In ignores, normalize the input when parsing it. When scanning, normalize earlier such that the path is already normalized when checking ignores. This requires splitting normalization of the string from normalization of the file, as we don't want to attempt the latter if the file is ignored. Closes #9598 --------- Co-authored-by: Jakob Borg <jakob@kastelo.net>
This commit is contained in:
+37
-34
@@ -293,6 +293,11 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
|
||||
return skip
|
||||
}
|
||||
|
||||
// Just in case the filesystem doesn't produce the normalization the OS
|
||||
// uses, and we use internally.
|
||||
nonNormPath := path
|
||||
path = normalizePath(path)
|
||||
|
||||
if m := w.Matcher.Match(path); m.IsIgnored() {
|
||||
l.Debugln(w, "ignored (patterns):", path)
|
||||
// Only descend if matcher says so and the current file is not a symlink.
|
||||
@@ -319,9 +324,23 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
|
||||
return nil
|
||||
}
|
||||
|
||||
if path != nonNormPath {
|
||||
if !w.AutoNormalize {
|
||||
// We're not authorized to do anything about it, so complain and skip.
|
||||
handleError(ctx, "normalizing path", nonNormPath, errUTF8Normalization, finishedChan)
|
||||
return skip
|
||||
}
|
||||
|
||||
path, err = w.applyNormalization(nonNormPath, path, info)
|
||||
if err != nil {
|
||||
handleError(ctx, "normalizing path", nonNormPath, err, finishedChan)
|
||||
return skip
|
||||
}
|
||||
}
|
||||
|
||||
if ignoredParent == "" {
|
||||
// parent isn't ignored, nothing special
|
||||
return w.handleItem(ctx, path, info, toHashChan, finishedChan, skip)
|
||||
return w.handleItem(ctx, path, info, toHashChan, finishedChan)
|
||||
}
|
||||
|
||||
// Part of current path below the ignored (potential) parent
|
||||
@@ -330,7 +349,7 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
|
||||
// ignored path isn't actually a parent of the current path
|
||||
if rel == path {
|
||||
ignoredParent = ""
|
||||
return w.handleItem(ctx, path, info, toHashChan, finishedChan, skip)
|
||||
return w.handleItem(ctx, path, info, toHashChan, finishedChan)
|
||||
}
|
||||
|
||||
// The previously ignored parent directories of the current, not
|
||||
@@ -345,7 +364,7 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
|
||||
handleError(ctx, "scan", ignoredParent, err, finishedChan)
|
||||
return skip
|
||||
}
|
||||
if err = w.handleItem(ctx, ignoredParent, info, toHashChan, finishedChan, skip); err != nil {
|
||||
if err = w.handleItem(ctx, ignoredParent, info, toHashChan, finishedChan); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -355,14 +374,7 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
|
||||
}
|
||||
}
|
||||
|
||||
func (w *walker) handleItem(ctx context.Context, path string, info fs.FileInfo, toHashChan chan<- protocol.FileInfo, finishedChan chan<- ScanResult, skip error) error {
|
||||
oldPath := path
|
||||
path, err := w.normalizePath(path, info)
|
||||
if err != nil {
|
||||
handleError(ctx, "normalizing path", oldPath, err, finishedChan)
|
||||
return skip
|
||||
}
|
||||
|
||||
func (w *walker) handleItem(ctx context.Context, path string, info fs.FileInfo, toHashChan chan<- protocol.FileInfo, finishedChan chan<- ScanResult) error {
|
||||
switch {
|
||||
case info.IsSymlink():
|
||||
if err := w.walkSymlink(ctx, path, info, finishedChan); err != nil {
|
||||
@@ -375,13 +387,13 @@ func (w *walker) handleItem(ctx context.Context, path string, info fs.FileInfo,
|
||||
return nil
|
||||
|
||||
case info.IsDir():
|
||||
err = w.walkDir(ctx, path, info, finishedChan)
|
||||
return w.walkDir(ctx, path, info, finishedChan)
|
||||
|
||||
case info.IsRegular():
|
||||
err = w.walkRegular(ctx, path, info, toHashChan)
|
||||
return w.walkRegular(ctx, path, info, toHashChan)
|
||||
}
|
||||
|
||||
return err
|
||||
return fmt.Errorf("bug: file info for %v is neither symlink, dir nor regular", path)
|
||||
}
|
||||
|
||||
func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileInfo, toHashChan chan<- protocol.FileInfo) error {
|
||||
@@ -550,30 +562,21 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, info fs.FileIn
|
||||
return nil
|
||||
}
|
||||
|
||||
// normalizePath returns the normalized relative path (possibly after fixing
|
||||
// it on disk), or skip is true.
|
||||
func (w *walker) normalizePath(path string, info fs.FileInfo) (normPath string, err error) {
|
||||
func normalizePath(path string) string {
|
||||
if build.IsDarwin || build.IsIOS {
|
||||
// Mac OS X file names should always be NFD normalized.
|
||||
normPath = norm.NFD.String(path)
|
||||
} else {
|
||||
// Every other OS in the known universe uses NFC or just plain
|
||||
// doesn't bother to define an encoding. In our case *we* do care,
|
||||
// so we enforce NFC regardless.
|
||||
normPath = norm.NFC.String(path)
|
||||
}
|
||||
|
||||
if path == normPath {
|
||||
// The file name is already normalized: nothing to do
|
||||
return path, nil
|
||||
}
|
||||
|
||||
if !w.AutoNormalize {
|
||||
// We're not authorized to do anything about it, so complain and skip.
|
||||
|
||||
return "", errUTF8Normalization
|
||||
return norm.NFD.String(path)
|
||||
}
|
||||
// Every other OS in the known universe uses NFC or just plain
|
||||
// doesn't bother to define an encoding. In our case *we* do care,
|
||||
// so we enforce NFC regardless.
|
||||
return norm.NFC.String(path)
|
||||
}
|
||||
|
||||
// applyNormalization fixes the normalization of the file on disk, i.e. ensures
|
||||
// the file at path ends up named normPath. It shouldn't but may happen that the
|
||||
// file ends up with a different name, in which case that one should be scanned.
|
||||
func (w *walker) applyNormalization(path, normPath string, info fs.FileInfo) (string, error) {
|
||||
// We will attempt to normalize it.
|
||||
normInfo, err := w.Filesystem.Lstat(normPath)
|
||||
if fs.IsNotExist(err) {
|
||||
|
||||
Reference in New Issue
Block a user