hgext/extdiff.py
changeset 8064 5c7bc1aece9e
parent 7758 e81e6c996e99
child 8065 66d0a03d3afc
equal deleted inserted replaced
8063:ee8d9b93b316 8064:5c7bc1aece9e
    48 from mercurial.i18n import _
    48 from mercurial.i18n import _
    49 from mercurial.node import short
    49 from mercurial.node import short
    50 from mercurial import cmdutil, util, commands
    50 from mercurial import cmdutil, util, commands
    51 import os, shlex, shutil, tempfile
    51 import os, shlex, shutil, tempfile
    52 
    52 
    53 def snapshot_node(ui, repo, files, node, tmproot):
    53 def snapshot(ui, repo, files, node, tmproot):
    54     '''snapshot files as of some revision'''
    54     '''snapshot files as of some revision
       
    55     if not using snapshot, -I/-X does not work and recursive diff
       
    56     in tools like kdiff3 and meld displays too many files.'''
    55     dirname = os.path.basename(repo.root)
    57     dirname = os.path.basename(repo.root)
    56     if dirname == "":
    58     if dirname == "":
    57         dirname = "root"
    59         dirname = "root"
    58     dirname = '%s.%s' % (dirname, short(node))
    60     if node is not None:
       
    61         dirname = '%s.%s' % (dirname, short(node))
    59     base = os.path.join(tmproot, dirname)
    62     base = os.path.join(tmproot, dirname)
    60     os.mkdir(base)
    63     os.mkdir(base)
    61     ui.note(_('making snapshot of %d files from rev %s\n') %
    64     if node is not None:
    62             (len(files), short(node)))
    65         ui.note(_('making snapshot of %d files from rev %s\n') %
       
    66                 (len(files), short(node)))
       
    67     else:
       
    68         ui.note(_('making snapshot of %d files from working dir\n') %
       
    69             (len(files)))
       
    70         
       
    71     fns_and_mtime = []
    63     ctx = repo[node]
    72     ctx = repo[node]
    64     for fn in files:
    73     for fn in files:
    65         wfn = util.pconvert(fn)
    74         wfn = util.pconvert(fn)
    66         if not wfn in ctx:
    75         if not wfn in ctx:
    67             # skipping new file after a merge ?
    76             # skipping new file after a merge ?
    71         destdir = os.path.dirname(dest)
    80         destdir = os.path.dirname(dest)
    72         if not os.path.isdir(destdir):
    81         if not os.path.isdir(destdir):
    73             os.makedirs(destdir)
    82             os.makedirs(destdir)
    74         data = repo.wwritedata(wfn, ctx[wfn].data())
    83         data = repo.wwritedata(wfn, ctx[wfn].data())
    75         open(dest, 'wb').write(data)
    84         open(dest, 'wb').write(data)
    76     return dirname
    85         if node is None:
    77 
    86             fns_and_mtime.append((dest, repo.wjoin(fn), os.path.getmtime(dest)))
    78 
       
    79 def snapshot_wdir(ui, repo, files, tmproot):
       
    80     '''snapshot files from working directory.
       
    81     if not using snapshot, -I/-X does not work and recursive diff
       
    82     in tools like kdiff3 and meld displays too many files.'''
       
    83     dirname = os.path.basename(repo.root)
       
    84     if dirname == "":
       
    85         dirname = "root"
       
    86     base = os.path.join(tmproot, dirname)
       
    87     os.mkdir(base)
       
    88     ui.note(_('making snapshot of %d files from working dir\n') %
       
    89             (len(files)))
       
    90 
       
    91     fns_and_mtime = []
       
    92 
       
    93     for fn in files:
       
    94         wfn = util.pconvert(fn)
       
    95         ui.note('  %s\n' % wfn)
       
    96         dest = os.path.join(base, wfn)
       
    97         destdir = os.path.dirname(dest)
       
    98         if not os.path.isdir(destdir):
       
    99             os.makedirs(destdir)
       
   100 
       
   101         fp = open(dest, 'wb')
       
   102         for chunk in util.filechunkiter(repo.wopener(wfn)):
       
   103             fp.write(chunk)
       
   104         fp.close()
       
   105 
       
   106         fns_and_mtime.append((dest, repo.wjoin(fn), os.path.getmtime(dest)))
       
   107 
       
   108 
       
   109     return dirname, fns_and_mtime
    87     return dirname, fns_and_mtime
   110 
       
   111 
    88 
   112 def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
    89 def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
   113     '''Do the actuall diff:
    90     '''Do the actuall diff:
   114 
    91 
   115     - copy to a temp structure if diffing 2 internal revisions
    92     - copy to a temp structure if diffing 2 internal revisions
   137 
   114 
   138     tmproot = tempfile.mkdtemp(prefix='extdiff.')
   115     tmproot = tempfile.mkdtemp(prefix='extdiff.')
   139     dir2root = ''
   116     dir2root = ''
   140     try:
   117     try:
   141         # Always make a copy of node1
   118         # Always make a copy of node1
   142         dir1 = snapshot_node(ui, repo, modified + removed, node1, tmproot)
   119         dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0]
   143         changes = len(modified) + len(removed) + len(added)
   120         changes = len(modified) + len(removed) + len(added)
   144 
   121 
   145         fns_and_mtime = []
       
   146 
       
   147         # If node2 in not the wc or there is >1 change, copy it
   122         # If node2 in not the wc or there is >1 change, copy it
   148         if node2:
   123         if node2 or changes > 1:
   149             dir2 = snapshot_node(ui, repo, modified + added, node2, tmproot)
   124             dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot)
   150         elif changes > 1:
       
   151             #we only actually need to get the files to copy back to the working
       
   152             #dir in this case (because the other cases are: diffing 2 revisions
       
   153             #or single file -- in which case the file is already directly passed
       
   154             #to the diff tool).
       
   155             dir2, fns_and_mtime = snapshot_wdir(ui, repo, modified + added, tmproot)
       
   156         else:
   125         else:
   157             # This lets the diff tool open the changed file directly
   126             # This lets the diff tool open the changed file directly
   158             dir2 = ''
   127             dir2 = ''
   159             dir2root = repo.root
   128             dir2root = repo.root
       
   129             fns_and_mtime = []
   160 
   130 
   161         # If only one change, diff the files instead of the directories
   131         # If only one change, diff the files instead of the directories
   162         if changes == 1 :
   132         if changes == 1 :
   163             if len(modified):
   133             if len(modified):
   164                 dir1 = os.path.join(dir1, util.localpath(modified[0]))
   134                 dir1 = os.path.join(dir1, util.localpath(modified[0]))