Mercurial > hg
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])) |