mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-22 14:48:30 +00:00
Refactor: break out walkSymlink method
This commit is contained in:
parent
dc96849718
commit
6dbb072d11
@ -263,61 +263,11 @@ func (w *Walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.
|
||||
// Index wise symlinks are always files, regardless of what the target
|
||||
// is, because symlinks carry their target path as their content.
|
||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
// If the target is a directory, do NOT descend down there. This
|
||||
// will cause files to get tracked, and removing the symlink will
|
||||
// as a result remove files in their real location.
|
||||
if !symlinks.Supported {
|
||||
if shouldSkip, err := w.walkSymlink(absPath, relPath, dchan); err != nil {
|
||||
return err
|
||||
} else if shouldSkip {
|
||||
return skip
|
||||
}
|
||||
|
||||
// We always rehash symlinks as they have no modtime or
|
||||
// permissions. We check if they point to the old target by
|
||||
// checking that their existing blocks match with the blocks in
|
||||
// the index.
|
||||
|
||||
target, targetType, err := symlinks.Read(absPath)
|
||||
if err != nil {
|
||||
l.Debugln("readlink error:", absPath, err)
|
||||
return skip
|
||||
}
|
||||
|
||||
blocks, err := Blocks(strings.NewReader(target), w.BlockSize, 0, nil)
|
||||
if err != nil {
|
||||
l.Debugln("hash link error:", absPath, err)
|
||||
return skip
|
||||
}
|
||||
|
||||
if w.CurrentFiler != nil {
|
||||
// A symlink is "unchanged", if
|
||||
// - it exists
|
||||
// - it wasn't deleted (because it isn't now)
|
||||
// - it was a symlink
|
||||
// - it wasn't invalid
|
||||
// - the symlink type (file/dir) was the same
|
||||
// - the block list (i.e. hash of target) was the same
|
||||
cf, ok = w.CurrentFiler.CurrentFile(relPath)
|
||||
if ok && !cf.IsDeleted() && cf.IsSymlink() && !cf.IsInvalid() && SymlinkTypeEqual(targetType, cf) && BlocksEqual(cf.Blocks, blocks) {
|
||||
return skip
|
||||
}
|
||||
}
|
||||
|
||||
f := protocol.FileInfo{
|
||||
Name: relPath,
|
||||
Version: cf.Version.Update(w.ShortID),
|
||||
Flags: uint32(protocol.FlagSymlink | protocol.FlagNoPermBits | 0666 | SymlinkFlags(targetType)),
|
||||
Modified: 0,
|
||||
Blocks: blocks,
|
||||
}
|
||||
|
||||
l.Debugln("symlink changedb:", absPath, f)
|
||||
|
||||
select {
|
||||
case dchan <- f:
|
||||
case <-w.Cancel:
|
||||
return errors.New("cancelled")
|
||||
}
|
||||
|
||||
return skip
|
||||
}
|
||||
|
||||
if info.Mode().IsDir() {
|
||||
@ -410,6 +360,68 @@ func (w *Walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.
|
||||
}
|
||||
}
|
||||
|
||||
// walkSymlinks returns true if the symlink should be skipped, or an error if
|
||||
// we should stop walking altogether.
|
||||
func (w *Walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileInfo) (skip bool, err error) {
|
||||
// If the target is a directory, do NOT descend down there. This
|
||||
// will cause files to get tracked, and removing the symlink will
|
||||
// as a result remove files in their real location.
|
||||
if !symlinks.Supported {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// We always rehash symlinks as they have no modtime or
|
||||
// permissions. We check if they point to the old target by
|
||||
// checking that their existing blocks match with the blocks in
|
||||
// the index.
|
||||
|
||||
target, targetType, err := symlinks.Read(absPath)
|
||||
if err != nil {
|
||||
l.Debugln("readlink error:", absPath, err)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
blocks, err := Blocks(strings.NewReader(target), w.BlockSize, 0, nil)
|
||||
if err != nil {
|
||||
l.Debugln("hash link error:", absPath, err)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var currentVersion protocol.Vector
|
||||
if w.CurrentFiler != nil {
|
||||
// A symlink is "unchanged", if
|
||||
// - it exists
|
||||
// - it wasn't deleted (because it isn't now)
|
||||
// - it was a symlink
|
||||
// - it wasn't invalid
|
||||
// - the symlink type (file/dir) was the same
|
||||
// - the block list (i.e. hash of target) was the same
|
||||
cf, ok := w.CurrentFiler.CurrentFile(relPath)
|
||||
if ok && !cf.IsDeleted() && cf.IsSymlink() && !cf.IsInvalid() && SymlinkTypeEqual(targetType, cf) && BlocksEqual(cf.Blocks, blocks) {
|
||||
return true, nil
|
||||
}
|
||||
currentVersion = cf.Version
|
||||
}
|
||||
|
||||
f := protocol.FileInfo{
|
||||
Name: relPath,
|
||||
Version: currentVersion.Update(w.ShortID),
|
||||
Flags: uint32(protocol.FlagSymlink | protocol.FlagNoPermBits | 0666 | SymlinkFlags(targetType)),
|
||||
Modified: 0,
|
||||
Blocks: blocks,
|
||||
}
|
||||
|
||||
l.Debugln("symlink changedb:", absPath, f)
|
||||
|
||||
select {
|
||||
case dchan <- f:
|
||||
case <-w.Cancel:
|
||||
return false, errors.New("cancelled")
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// normalizePath returns the normalized relative path (possibly after fixing
|
||||
// it on disk), or skip is true.
|
||||
func (w *Walker) normalizePath(absPath, relPath string) (normPath string, skip bool) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user