Refactor: break out walkSymlink method

This commit is contained in:
Jakob Borg 2015-11-20 09:50:46 +01:00
parent dc96849718
commit 6dbb072d11

View File

@ -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) {