mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +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
|
// Index wise symlinks are always files, regardless of what the target
|
||||||
// is, because symlinks carry their target path as their content.
|
// is, because symlinks carry their target path as their content.
|
||||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
// If the target is a directory, do NOT descend down there. This
|
if shouldSkip, err := w.walkSymlink(absPath, relPath, dchan); err != nil {
|
||||||
// will cause files to get tracked, and removing the symlink will
|
return err
|
||||||
// as a result remove files in their real location.
|
} else if shouldSkip {
|
||||||
if !symlinks.Supported {
|
|
||||||
return skip
|
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() {
|
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
|
// normalizePath returns the normalized relative path (possibly after fixing
|
||||||
// it on disk), or skip is true.
|
// it on disk), or skip is true.
|
||||||
func (w *Walker) normalizePath(absPath, relPath string) (normPath string, skip bool) {
|
func (w *Walker) normalizePath(absPath, relPath string) (normPath string, skip bool) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user