comparison hgext/extdiff.py @ 8064:5c7bc1aece9e

extdiff: merge node and working dir snapshot modes
author Patrick Mezard <pmezard@gmail.com>
date Mon, 13 Apr 2009 21:21:01 +0200
parents e81e6c996e99
children 66d0a03d3afc
comparison
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]))