From e359b146aa7cb3039676760ba08e508933270390 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Mon, 19 May 2014 23:42:08 +0200 Subject: [PATCH] Properly handle read-write/read-only windows<->posix (fixes #236) --- model/puller.go | 20 +++++++++++++++----- model/util.go | 2 ++ scanner/walk.go | 21 +++++++++++++++++++-- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/model/puller.go b/model/puller.go index 9636f1f4..0fc360b7 100644 --- a/model/puller.go +++ b/model/puller.go @@ -525,19 +525,29 @@ func (p *puller) handleEmptyBlock(b bqBlock) { l.Debugf("pull: delete %q", f.Name) } os.Remove(of.temp) - os.Remove(of.filepath) + os.Chmod(of.filepath, 0666) + if os.Remove(of.filepath) == nil { + p.model.updateLocal(p.repo, f) + } } else { if debug { l.Debugf("pull: no blocks to fetch and nothing to copy for %q / %q", p.repo, f.Name) } t := time.Unix(f.Modified, 0) - os.Chtimes(of.temp, t, t) - os.Chmod(of.temp, os.FileMode(f.Flags&0777)) + if os.Chtimes(of.temp, t, t) != nil { + delete(p.openFiles, f.Name) + return + } + if os.Chmod(of.temp, os.FileMode(f.Flags&0777)) != nil { + delete(p.openFiles, f.Name) + return + } defTempNamer.Show(of.temp) - Rename(of.temp, of.filepath) + if Rename(of.temp, of.filepath) == nil { + p.model.updateLocal(p.repo, f) + } } delete(p.openFiles, f.Name) - p.model.updateLocal(p.repo, f) } func (p *puller) queueNeededBlocks() { diff --git a/model/util.go b/model/util.go index 38235f6c..e9290531 100644 --- a/model/util.go +++ b/model/util.go @@ -12,11 +12,13 @@ import ( func Rename(from, to string) error { if runtime.GOOS == "windows" { + os.Chmod(to, 0666) // Make sure the file is user writeable err := os.Remove(to) if err != nil && !os.IsNotExist(err) { l.Warnln(err) } } + defer os.Remove(from) // Don't leave a dangling temp file in case of rename error return os.Rename(from, to) } diff --git a/scanner/walk.go b/scanner/walk.go index b4db3b4b..a9465009 100644 --- a/scanner/walk.go +++ b/scanner/walk.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "strings" "time" @@ -161,7 +162,7 @@ func (w *Walker) walkAndHashFiles(res *[]File, ign map[string][]string) filepath if info.Mode().IsDir() { if w.CurrentFiler != nil { cf := w.CurrentFiler.CurrentFile(rn) - if cf.Modified == info.ModTime().Unix() && cf.Flags == uint32(info.Mode()&os.ModePerm|protocol.FlagDirectory) { + if cf.Modified == info.ModTime().Unix() && cf.Flags&protocol.FlagDirectory != 0 && permsEqual(cf.Flags, uint32(info.Mode())) { if debug { l.Debugln("unchanged:", cf) } @@ -185,7 +186,7 @@ func (w *Walker) walkAndHashFiles(res *[]File, ign map[string][]string) filepath if info.Mode().IsRegular() { if w.CurrentFiler != nil { cf := w.CurrentFiler.CurrentFile(rn) - if cf.Flags&protocol.FlagDeleted == 0 && cf.Modified == info.ModTime().Unix() && cf.Flags == uint32(info.Mode()&os.ModePerm) { + if cf.Flags&protocol.FlagDeleted == 0 && cf.Modified == info.ModTime().Unix() && permsEqual(cf.Flags, uint32(info.Mode())) { if debug { l.Debugln("unchanged:", cf) } @@ -207,6 +208,10 @@ func (w *Walker) walkAndHashFiles(res *[]File, ign map[string][]string) filepath l.Infof("Changes to %q are no longer suppressed.", p) } } + + if debug { + l.Debugln("rescan:", cf, info.ModTime().Unix(), info.Mode()&os.ModePerm) + } } fd, err := os.Open(p) @@ -277,3 +282,15 @@ func checkDir(dir string) error { } return nil } + +func permsEqual(a, b uint32) bool { + switch runtime.GOOS { + case "windows": + // There is only writeable and read only, represented for user, group + // and other equally. We only compare against user. + return a&0600 == b&0600 + default: + // All bits count + return a&0777 == b&0777 + } +}