hgext/extdiff.py
changeset 32217 affd753ddaf1
parent 31451 53865692a354
child 32283 8a1ff5ed620e
--- a/hgext/extdiff.py	Sat May 06 22:48:06 2017 -0400
+++ b/hgext/extdiff.py	Sat May 06 23:00:57 2017 -0400
@@ -101,7 +101,7 @@
         dirname = '%s.%s' % (dirname, short(node))
     base = os.path.join(tmproot, dirname)
     os.mkdir(base)
-    fns_and_mtime = []
+    fnsandstat = []
 
     if node is not None:
         ui.note(_('making snapshot of %d files from rev %s\n') %
@@ -124,9 +124,8 @@
             if node is None:
                 dest = os.path.join(base, wfn)
 
-                fns_and_mtime.append((dest, repo.wjoin(fn),
-                                      os.lstat(dest).st_mtime))
-    return dirname, fns_and_mtime
+                fnsandstat.append((dest, repo.wjoin(fn), os.lstat(dest)))
+    return dirname, fnsandstat
 
 def dodiff(ui, repo, cmdline, pats, opts):
     '''Do the actual diff:
@@ -199,7 +198,7 @@
                 dir1b = None
                 rev1b = ''
 
-            fns_and_mtime = []
+            fnsandstat = []
 
             # If node2 in not the wc or there is >1 change, copy it
             dir2root = ''
@@ -212,8 +211,8 @@
                 #the working dir in this case (because the other cases
                 #are: diffing 2 revisions or single file -- in which case
                 #the file is already directly passed to the diff tool).
-                dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot,
-                                               subrepos)
+                dir2, fnsandstat = snapshot(ui, repo, modadd, None, tmproot,
+                                            subrepos)
             else:
                 # This lets the diff tool open the changed file directly
                 dir2 = ''
@@ -249,7 +248,7 @@
             dir2 = repo.vfs.reljoin(tmproot, label2)
             dir1b = None
             label1b = None
-            fns_and_mtime = []
+            fnsandstat = []
 
         # Function to quote file/dir names in the argument string.
         # When not operating in 3-way mode, an empty string is
@@ -275,8 +274,13 @@
         ui.debug('running %r in %s\n' % (cmdline, tmproot))
         ui.system(cmdline, cwd=tmproot, blockedtag='extdiff')
 
-        for copy_fn, working_fn, mtime in fns_and_mtime:
-            if os.lstat(copy_fn).st_mtime != mtime:
+        for copy_fn, working_fn, st in fnsandstat:
+            cpstat = os.lstat(copy_fn)
+            # Some tools copy the file and attributes, so mtime may not detect
+            # all changes.  A size check will detect more cases, but not all.
+            # The only certain way to detect every case is to diff all files,
+            # which could be expensive.
+            if cpstat.st_mtime != st.st_mtime or cpstat.st_size != st.st_size:
                 ui.debug('file changed while diffing. '
                          'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
                 util.copyfile(copy_fn, working_fn)