瀏覽代碼

Add linientMtimes workaround for Android brokenness (ref #831)

Jakob Borg 11 年之前
父節點
當前提交
5f52e0581d
共有 3 個文件被更改,包括 40 次插入17 次删除
  1. 1 0
      internal/config/config.go
  2. 10 5
      internal/model/model.go
  3. 29 12
      internal/model/puller.go

+ 1 - 0
internal/config/config.go

@@ -57,6 +57,7 @@ type FolderConfiguration struct {
 	RescanIntervalS int                         `xml:"rescanIntervalS,attr" default:"60"`
 	IgnorePerms     bool                        `xml:"ignorePerms,attr"`
 	Versioning      VersioningConfiguration     `xml:"versioning"`
+	LenientMtimes   bool                        `xml:"lenientMtimes"`
 
 	Invalid string `xml:"-"` // Set at runtime when there is an error, not saved
 

+ 10 - 5
internal/model/model.go

@@ -167,11 +167,12 @@ func (m *Model) StartFolderRW(folder string) {
 		panic("cannot start already running folder " + folder)
 	}
 	p := &Puller{
-		folder:      folder,
-		dir:         cfg.Path,
-		scanIntv:    time.Duration(cfg.RescanIntervalS) * time.Second,
-		model:       m,
-		ignorePerms: cfg.IgnorePerms,
+		folder:        folder,
+		dir:           cfg.Path,
+		scanIntv:      time.Duration(cfg.RescanIntervalS) * time.Second,
+		model:         m,
+		ignorePerms:   cfg.IgnorePerms,
+		lenientMtimes: cfg.LenientMtimes,
 	}
 	m.folderRunners[folder] = p
 	m.fmut.Unlock()
@@ -184,6 +185,10 @@ func (m *Model) StartFolderRW(folder string) {
 		p.versioner = factory(folder, cfg.Path, cfg.Versioning.Params)
 	}
 
+	if cfg.LenientMtimes {
+		l.Infof("Folder %q is running with LenientMtimes workaround. Syncing may not work properly.", folder)
+	}
+
 	go p.Serve()
 }
 

+ 29 - 12
internal/model/puller.go

@@ -62,13 +62,14 @@ var (
 )
 
 type Puller struct {
-	folder      string
-	dir         string
-	scanIntv    time.Duration
-	model       *Model
-	stop        chan struct{}
-	versioner   versioner.Versioner
-	ignorePerms bool
+	folder        string
+	dir           string
+	scanIntv      time.Duration
+	model         *Model
+	stop          chan struct{}
+	versioner     versioner.Versioner
+	ignorePerms   bool
+	lenientMtimes bool
 }
 
 // Serve will run scans and pulls. It will return when Stop()ed or on a
@@ -528,8 +529,16 @@ func (p *Puller) shortcutFile(file protocol.FileInfo) {
 	t := time.Unix(file.Modified, 0)
 	err := os.Chtimes(realName, t, t)
 	if err != nil {
-		l.Infof("Puller (folder %q, file %q): shortcut: %v", p.folder, file.Name, err)
-		return
+		if p.lenientMtimes {
+			// We accept the failure with a warning here and allow the sync to
+			// continue. We'll sync the new mtime back to the other devices later.
+			// If they have the same problem & setting, we might never get in
+			// sync.
+			l.Infof("Puller (folder %q, file %q): shortcut: %v (continuing anyway as requested)", p.folder, file.Name, err)
+		} else {
+			l.Infof("Puller (folder %q, file %q): shortcut: %v", p.folder, file.Name, err)
+			return
+		}
 	}
 
 	p.model.updateLocal(p.folder, file)
@@ -666,9 +675,17 @@ func (p *Puller) finisherRoutine(in <-chan *sharedPullerState) {
 			t := time.Unix(state.file.Modified, 0)
 			err = os.Chtimes(state.tempName, t, t)
 			if err != nil {
-				os.Remove(state.tempName)
-				l.Warnln("puller: final:", err)
-				continue
+				if p.lenientMtimes {
+					// We accept the failure with a warning here and allow the sync to
+					// continue. We'll sync the new mtime back to the other devices later.
+					// If they have the same problem & setting, we might never get in
+					// sync.
+					l.Infof("Puller (folder %q, file %q): final: %v (continuing anyway as requested)", p.folder, state.file.Name, err)
+				} else {
+					os.Remove(state.tempName)
+					l.Warnln("puller: final:", err)
+					continue
+				}
 			}
 
 			// If we should use versioning, let the versioner archive the old