hgext/extdiff.py
changeset 32257 affd753ddaf1
parent 31460 53865692a354
child 32323 8a1ff5ed620e
equal deleted inserted replaced
32256:98bb992bef19 32257:affd753ddaf1
    99         dirname = "root"
    99         dirname = "root"
   100     if node is not None:
   100     if node is not None:
   101         dirname = '%s.%s' % (dirname, short(node))
   101         dirname = '%s.%s' % (dirname, short(node))
   102     base = os.path.join(tmproot, dirname)
   102     base = os.path.join(tmproot, dirname)
   103     os.mkdir(base)
   103     os.mkdir(base)
   104     fns_and_mtime = []
   104     fnsandstat = []
   105 
   105 
   106     if node is not None:
   106     if node is not None:
   107         ui.note(_('making snapshot of %d files from rev %s\n') %
   107         ui.note(_('making snapshot of %d files from rev %s\n') %
   108                 (len(files), short(node)))
   108                 (len(files), short(node)))
   109     else:
   109     else:
   122             ui.note('  %s\n' % wfn)
   122             ui.note('  %s\n' % wfn)
   123 
   123 
   124             if node is None:
   124             if node is None:
   125                 dest = os.path.join(base, wfn)
   125                 dest = os.path.join(base, wfn)
   126 
   126 
   127                 fns_and_mtime.append((dest, repo.wjoin(fn),
   127                 fnsandstat.append((dest, repo.wjoin(fn), os.lstat(dest)))
   128                                       os.lstat(dest).st_mtime))
   128     return dirname, fnsandstat
   129     return dirname, fns_and_mtime
       
   130 
   129 
   131 def dodiff(ui, repo, cmdline, pats, opts):
   130 def dodiff(ui, repo, cmdline, pats, opts):
   132     '''Do the actual diff:
   131     '''Do the actual diff:
   133 
   132 
   134     - copy to a temp structure if diffing 2 internal revisions
   133     - copy to a temp structure if diffing 2 internal revisions
   197                 rev1b = '@%d' % repo[node1b].rev()
   196                 rev1b = '@%d' % repo[node1b].rev()
   198             else:
   197             else:
   199                 dir1b = None
   198                 dir1b = None
   200                 rev1b = ''
   199                 rev1b = ''
   201 
   200 
   202             fns_and_mtime = []
   201             fnsandstat = []
   203 
   202 
   204             # If node2 in not the wc or there is >1 change, copy it
   203             # If node2 in not the wc or there is >1 change, copy it
   205             dir2root = ''
   204             dir2root = ''
   206             rev2 = ''
   205             rev2 = ''
   207             if node2:
   206             if node2:
   210             elif len(common) > 1:
   209             elif len(common) > 1:
   211                 #we only actually need to get the files to copy back to
   210                 #we only actually need to get the files to copy back to
   212                 #the working dir in this case (because the other cases
   211                 #the working dir in this case (because the other cases
   213                 #are: diffing 2 revisions or single file -- in which case
   212                 #are: diffing 2 revisions or single file -- in which case
   214                 #the file is already directly passed to the diff tool).
   213                 #the file is already directly passed to the diff tool).
   215                 dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot,
   214                 dir2, fnsandstat = snapshot(ui, repo, modadd, None, tmproot,
   216                                                subrepos)
   215                                             subrepos)
   217             else:
   216             else:
   218                 # This lets the diff tool open the changed file directly
   217                 # This lets the diff tool open the changed file directly
   219                 dir2 = ''
   218                 dir2 = ''
   220                 dir2root = repo.root
   219                 dir2root = repo.root
   221 
   220 
   247             label2 = cmdutil.makefilename(repo, template, node2)
   246             label2 = cmdutil.makefilename(repo, template, node2)
   248             dir1a = repo.vfs.reljoin(tmproot, label1a)
   247             dir1a = repo.vfs.reljoin(tmproot, label1a)
   249             dir2 = repo.vfs.reljoin(tmproot, label2)
   248             dir2 = repo.vfs.reljoin(tmproot, label2)
   250             dir1b = None
   249             dir1b = None
   251             label1b = None
   250             label1b = None
   252             fns_and_mtime = []
   251             fnsandstat = []
   253 
   252 
   254         # Function to quote file/dir names in the argument string.
   253         # Function to quote file/dir names in the argument string.
   255         # When not operating in 3-way mode, an empty string is
   254         # When not operating in 3-way mode, an empty string is
   256         # returned for parent2
   255         # returned for parent2
   257         replace = {'parent': dir1a, 'parent1': dir1a, 'parent2': dir1b,
   256         replace = {'parent': dir1a, 'parent1': dir1a, 'parent2': dir1b,
   273         cmdline = re.sub(regex, quote, cmdline)
   272         cmdline = re.sub(regex, quote, cmdline)
   274 
   273 
   275         ui.debug('running %r in %s\n' % (cmdline, tmproot))
   274         ui.debug('running %r in %s\n' % (cmdline, tmproot))
   276         ui.system(cmdline, cwd=tmproot, blockedtag='extdiff')
   275         ui.system(cmdline, cwd=tmproot, blockedtag='extdiff')
   277 
   276 
   278         for copy_fn, working_fn, mtime in fns_and_mtime:
   277         for copy_fn, working_fn, st in fnsandstat:
   279             if os.lstat(copy_fn).st_mtime != mtime:
   278             cpstat = os.lstat(copy_fn)
       
   279             # Some tools copy the file and attributes, so mtime may not detect
       
   280             # all changes.  A size check will detect more cases, but not all.
       
   281             # The only certain way to detect every case is to diff all files,
       
   282             # which could be expensive.
       
   283             if cpstat.st_mtime != st.st_mtime or cpstat.st_size != st.st_size:
   280                 ui.debug('file changed while diffing. '
   284                 ui.debug('file changed while diffing. '
   281                          'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
   285                          'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
   282                 util.copyfile(copy_fn, working_fn)
   286                 util.copyfile(copy_fn, working_fn)
   283 
   287 
   284         return 1
   288         return 1