mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Reimplement case-insensitivity move bug fix (#3047)
* Use eq for FindByPath for case sensitivity * Handle case sensitive moves
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/fsutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Opener provides an interface to open a file.
|
// Opener provides an interface to open a file.
|
||||||
@@ -26,6 +28,7 @@ type FS interface {
|
|||||||
Lstat(name string) (fs.FileInfo, error)
|
Lstat(name string) (fs.FileInfo, error)
|
||||||
Open(name string) (fs.ReadDirFile, error)
|
Open(name string) (fs.ReadDirFile, error)
|
||||||
OpenZip(name string) (*ZipFS, error)
|
OpenZip(name string) (*ZipFS, error)
|
||||||
|
IsPathCaseSensitive(path string) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OsFS is a file system backed by the OS.
|
// OsFS is a file system backed by the OS.
|
||||||
@@ -51,3 +54,7 @@ func (f *OsFS) OpenZip(name string) (*ZipFS, error) {
|
|||||||
|
|
||||||
return newZipFS(f, name, info)
|
return newZipFS(f, name, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *OsFS) IsPathCaseSensitive(path string) (bool, error) {
|
||||||
|
return fsutil.IsFsPathCaseSensitive(path)
|
||||||
|
}
|
||||||
|
|||||||
@@ -740,7 +740,6 @@ func (s *scanJob) handleRename(ctx context.Context, f File, fp []Fingerprint) (F
|
|||||||
|
|
||||||
for _, other := range others {
|
for _, other := range others {
|
||||||
// if file does not exist, then update it to the new path
|
// if file does not exist, then update it to the new path
|
||||||
// TODO - handle #1426 scenario
|
|
||||||
fs, err := s.getFileFS(other.Base())
|
fs, err := s.getFileFS(other.Base())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
missing = append(missing, other)
|
missing = append(missing, other)
|
||||||
@@ -749,6 +748,14 @@ func (s *scanJob) handleRename(ctx context.Context, f File, fp []Fingerprint) (F
|
|||||||
|
|
||||||
if _, err := fs.Lstat(other.Base().Path); err != nil {
|
if _, err := fs.Lstat(other.Base().Path); err != nil {
|
||||||
missing = append(missing, other)
|
missing = append(missing, other)
|
||||||
|
} else if strings.EqualFold(f.Base().Path, other.Base().Path) {
|
||||||
|
// #1426 - if file exists but is a case-insensitive match for the
|
||||||
|
// original filename, and the filesystem is case-insensitive
|
||||||
|
// then treat it as a move
|
||||||
|
if caseSensitive, _ := fs.IsPathCaseSensitive(other.Base().Path); !caseSensitive {
|
||||||
|
// treat as a move
|
||||||
|
missing = append(missing, other)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ func (f *ZipFS) OpenZip(name string) (*ZipFS, error) {
|
|||||||
return nil, errZipFSOpenZip
|
return nil, errZipFSOpenZip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *ZipFS) IsPathCaseSensitive(path string) (bool, error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
type zipReadDirFile struct {
|
type zipReadDirFile struct {
|
||||||
fs.File
|
fs.File
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -586,10 +586,20 @@ func (qb *FileStore) FindByPath(ctx context.Context, p string) (file.File, error
|
|||||||
table := qb.table()
|
table := qb.table()
|
||||||
folderTable := folderTableMgr.table
|
folderTable := folderTableMgr.table
|
||||||
|
|
||||||
q := qb.selectDataset().Prepared(true).Where(
|
// like uses case-insensitive matching. Only use like if wildcards are used
|
||||||
|
q := qb.selectDataset().Prepared(true)
|
||||||
|
|
||||||
|
if strings.Contains(basename, "%") || strings.Contains(dirName, "%") {
|
||||||
|
q = q.Where(
|
||||||
folderTable.Col("path").Like(dirName),
|
folderTable.Col("path").Like(dirName),
|
||||||
table.Col("basename").Like(basename),
|
table.Col("basename").Like(basename),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
q = q.Where(
|
||||||
|
folderTable.Col("path").Eq(dirName),
|
||||||
|
table.Col("basename").Eq(basename),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ret, err := qb.get(ctx, q)
|
ret, err := qb.get(ctx, q)
|
||||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||||
|
|||||||
Reference in New Issue
Block a user