Mercurial > hg > mercurial-crew-with-dirclash
annotate hgext/imerge.py @ 5390:36c46e20976a
merge: provide *_ISLINK environment vars to merge helper
Sets HG_MY_ISLINK, HG_OTHER_ISLINK, HG_BASE_ISLINK in environment. Without these variables, it's impossible for the merge application to know whether the 'other' and 'base' files were symlinks in their original contexts. For the purposes of the merge they are always emitted as small text files.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Wed, 03 Oct 2007 23:09:36 +0200 |
parents | 3786ef8877d5 |
children |
rev | line source |
---|---|
5042 | 1 # Copyright (C) 2007 Brendan Cully <brendan@kublai.com> |
2 # Published under the GNU GPL | |
3 | |
4 ''' | |
5 imerge - interactive merge | |
6 ''' | |
7 | |
8 from mercurial.i18n import _ | |
9 from mercurial.node import * | |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
10 from mercurial import commands, cmdutil, dispatch, fancyopts, hg, merge, util |
5042 | 11 import os, tarfile |
12 | |
13 class InvalidStateFileException(Exception): pass | |
14 | |
15 class ImergeStateFile(object): | |
16 def __init__(self, im): | |
17 self.im = im | |
18 | |
19 def save(self, dest): | |
20 tf = tarfile.open(dest, 'w:gz') | |
21 | |
22 st = os.path.join(self.im.path, 'status') | |
23 tf.add(st, os.path.join('.hg', 'imerge', 'status')) | |
24 | |
25 for f in self.im.resolved: | |
5063 | 26 (fd, fo) = self.im.conflicts[f] |
27 abssrc = self.im.repo.wjoin(fd) | |
28 tf.add(abssrc, fd) | |
5042 | 29 |
30 tf.close() | |
31 | |
32 def load(self, source): | |
33 wlock = self.im.repo.wlock() | |
34 lock = self.im.repo.lock() | |
35 | |
36 tf = tarfile.open(source, 'r') | |
37 contents = tf.getnames() | |
5153
1d5ebb0d366f
imerge: fix status file lookups
Patrick Mezard <pmezard@gmail.com>
parents:
5117
diff
changeset
|
38 # tarfile normalizes path separators to '/' |
5154
ec24bfd852ab
imerge: simplify 1d5ebb0d366f
Brendan Cully <brendan@kublai.com>
parents:
5153
diff
changeset
|
39 statusfile = '.hg/imerge/status' |
5042 | 40 if statusfile not in contents: |
41 raise InvalidStateFileException('no status file') | |
42 | |
43 tf.extract(statusfile, self.im.repo.root) | |
5063 | 44 p1, p2 = self.im.load() |
45 if self.im.repo.dirstate.parents()[0] != p1.node(): | |
46 hg.clean(self.im.repo, p1.node()) | |
47 self.im.start(p2.node()) | |
5055
56d48aed1f69
imerge: tarfile.extractall is only available in python2.5
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
5054
diff
changeset
|
48 for tarinfo in tf: |
56d48aed1f69
imerge: tarfile.extractall is only available in python2.5
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
5054
diff
changeset
|
49 tf.extract(tarinfo, self.im.repo.root) |
5042 | 50 self.im.load() |
51 | |
52 class Imerge(object): | |
53 def __init__(self, ui, repo): | |
54 self.ui = ui | |
55 self.repo = repo | |
56 | |
57 self.path = repo.join('imerge') | |
58 self.opener = util.opener(self.path) | |
59 | |
5063 | 60 self.wctx = self.repo.workingctx() |
5042 | 61 self.conflicts = {} |
62 self.resolved = [] | |
63 | |
64 def merging(self): | |
5063 | 65 return len(self.wctx.parents()) > 1 |
5042 | 66 |
67 def load(self): | |
68 # status format. \0-delimited file, fields are | |
69 # p1, p2, conflict count, conflict filenames, resolved filenames | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
70 # conflict filenames are tuples of localname, remoteorig, remotenew |
5042 | 71 |
72 statusfile = self.opener('status') | |
73 | |
74 status = statusfile.read().split('\0') | |
75 if len(status) < 3: | |
76 raise util.Abort('invalid imerge status file') | |
77 | |
78 try: | |
5063 | 79 parents = [self.repo.changectx(n) for n in status[:2]] |
5042 | 80 except LookupError: |
81 raise util.Abort('merge parent %s not in repository' % short(p)) | |
82 | |
83 status = status[2:] | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
84 conflicts = int(status.pop(0)) * 3 |
5042 | 85 self.resolved = status[conflicts:] |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
86 for i in xrange(0, conflicts, 3): |
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
87 self.conflicts[status[i]] = (status[i+1], status[i+2]) |
5042 | 88 |
5063 | 89 return parents |
90 | |
5042 | 91 def save(self): |
92 lock = self.repo.lock() | |
93 | |
94 if not os.path.isdir(self.path): | |
95 os.mkdir(self.path) | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
96 statusfile = self.opener('status', 'wb') |
5042 | 97 |
5063 | 98 out = [hex(n.node()) for n in self.wctx.parents()] |
5042 | 99 out.append(str(len(self.conflicts))) |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
100 conflicts = self.conflicts.items() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
101 conflicts.sort() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
102 for fw, fd_fo in conflicts: |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
103 out.append(fw) |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
104 out.extend(fd_fo) |
5042 | 105 out.extend(self.resolved) |
106 | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
107 statusfile.write('\0'.join(out)) |
5042 | 108 |
109 def remaining(self): | |
110 return [f for f in self.conflicts if f not in self.resolved] | |
111 | |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
112 def filemerge(self, fn, interactive=True): |
5042 | 113 wlock = self.repo.wlock() |
114 | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
115 (fd, fo) = self.conflicts[fn] |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
116 p1, p2 = self.wctx.parents() |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
117 |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
118 # this could be greatly improved |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
119 realmerge = os.environ.get('HGMERGE') |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
120 if not interactive: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
121 os.environ['HGMERGE'] = 'merge' |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
122 |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
123 # The filemerge ancestor algorithm does not work if self.wctx |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
124 # already has two parents (in normal merge it doesn't yet). But |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
125 # this is very dirty. |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
126 self.wctx._parents.pop() |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
127 try: |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
128 # TODO: we should probably revert the file if merge fails |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
129 return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
130 finally: |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
131 self.wctx._parents.append(p2) |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
132 if realmerge: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
133 os.environ['HGMERGE'] = realmerge |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
134 elif not interactive: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
135 del os.environ['HGMERGE'] |
5042 | 136 |
137 def start(self, rev=None): | |
138 _filemerge = merge.filemerge | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
139 def filemerge(repo, fw, fd, fo, wctx, mctx): |
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
140 self.conflicts[fw] = (fd, fo) |
5042 | 141 |
142 merge.filemerge = filemerge | |
143 commands.merge(self.ui, self.repo, rev=rev) | |
144 merge.filemerge = _filemerge | |
145 | |
5063 | 146 self.wctx = self.repo.workingctx() |
5042 | 147 self.save() |
148 | |
149 def resume(self): | |
150 self.load() | |
151 | |
152 dp = self.repo.dirstate.parents() | |
5063 | 153 p1, p2 = self.wctx.parents() |
154 if p1.node() != dp[0] or p2.node() != dp[1]: | |
5042 | 155 raise util.Abort('imerge state does not match working directory') |
156 | |
157 def next(self): | |
158 remaining = self.remaining() | |
159 return remaining and remaining[0] | |
160 | |
161 def resolve(self, files): | |
162 resolved = dict.fromkeys(self.resolved) | |
163 for fn in files: | |
164 if fn not in self.conflicts: | |
165 raise util.Abort('%s is not in the merge set' % fn) | |
166 resolved[fn] = True | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
167 self.resolved = resolved.keys() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
168 self.resolved.sort() |
5042 | 169 self.save() |
170 return 0 | |
171 | |
172 def unresolve(self, files): | |
173 resolved = dict.fromkeys(self.resolved) | |
174 for fn in files: | |
175 if fn not in resolved: | |
176 raise util.Abort('%s is not resolved' % fn) | |
177 del resolved[fn] | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
178 self.resolved = resolved.keys() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
179 self.resolved.sort() |
5042 | 180 self.save() |
181 return 0 | |
182 | |
183 def pickle(self, dest): | |
184 '''write current merge state to file to be resumed elsewhere''' | |
185 state = ImergeStateFile(self) | |
186 return state.save(dest) | |
187 | |
188 def unpickle(self, source): | |
189 '''read merge state from file''' | |
190 state = ImergeStateFile(self) | |
191 return state.load(source) | |
192 | |
193 def load(im, source): | |
194 if im.merging(): | |
195 raise util.Abort('there is already a merge in progress ' | |
196 '(update -C <rev> to abort it)' ) | |
197 m, a, r, d = im.repo.status()[:4] | |
198 if m or a or r or d: | |
199 raise util.Abort('working directory has uncommitted changes') | |
200 | |
201 rc = im.unpickle(source) | |
202 if not rc: | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
203 status(im) |
5042 | 204 return rc |
205 | |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
206 def merge_(im, filename=None, auto=False): |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
207 success = True |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
208 if auto and not filename: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
209 for fn in im.remaining(): |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
210 rc = im.filemerge(fn, interactive=False) |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
211 if rc: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
212 success = False |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
213 else: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
214 im.resolve([fn]) |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
215 if success: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
216 im.ui.write('all conflicts resolved\n') |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
217 else: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
218 status(im) |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
219 return 0 |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
220 |
5042 | 221 if not filename: |
222 filename = im.next() | |
223 if not filename: | |
224 im.ui.write('all conflicts resolved\n') | |
225 return 0 | |
226 | |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
227 rc = im.filemerge(filename, interactive=not auto) |
5042 | 228 if not rc: |
229 im.resolve([filename]) | |
230 if not im.next(): | |
231 im.ui.write('all conflicts resolved\n') | |
232 return rc | |
233 | |
234 def next(im): | |
235 n = im.next() | |
236 if n: | |
237 im.ui.write('%s\n' % n) | |
238 else: | |
239 im.ui.write('all conflicts resolved\n') | |
240 return 0 | |
241 | |
242 def resolve(im, *files): | |
243 if not files: | |
244 raise util.Abort('resolve requires at least one filename') | |
245 return im.resolve(files) | |
246 | |
247 def save(im, dest): | |
248 return im.pickle(dest) | |
249 | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
250 def status(im, **opts): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
251 if not opts.get('resolved') and not opts.get('unresolved'): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
252 opts['resolved'] = True |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
253 opts['unresolved'] = True |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
254 |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
255 if im.ui.verbose: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
256 p1, p2 = [short(p.node()) for p in im.wctx.parents()] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
257 im.ui.note(_('merging %s and %s\n') % (p1, p2)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
258 |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
259 conflicts = im.conflicts.keys() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
260 conflicts.sort() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
261 remaining = dict.fromkeys(im.remaining()) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
262 st = [] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
263 for fn in conflicts: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
264 if opts.get('no_status'): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
265 mode = '' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
266 elif fn in remaining: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
267 mode = 'U ' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
268 else: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
269 mode = 'R ' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
270 if ((opts.get('resolved') and fn not in remaining) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
271 or (opts.get('unresolved') and fn in remaining)): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
272 st.append((mode, fn)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
273 st.sort() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
274 for (mode, fn) in st: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
275 if im.ui.verbose: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
276 fo, fd = im.conflicts[fn] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
277 if fd != fn: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
278 fn = '%s (%s)' % (fn, fd) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
279 im.ui.write('%s%s\n' % (mode, fn)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
280 if opts.get('unresolved') and not remaining: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
281 im.ui.write(_('all conflicts resolved\n')) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
282 |
5042 | 283 return 0 |
284 | |
285 def unresolve(im, *files): | |
286 if not files: | |
287 raise util.Abort('unresolve requires at least one filename') | |
288 return im.unresolve(files) | |
289 | |
290 subcmdtable = { | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
291 'load': (load, []), |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
292 'merge': |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
293 (merge_, |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
294 [('a', 'auto', None, _('automatically resolve if possible'))]), |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
295 'next': (next, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
296 'resolve': (resolve, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
297 'save': (save, []), |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
298 'status': |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
299 (status, |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
300 [('n', 'no-status', None, _('hide status prefix')), |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
301 ('', 'resolved', None, _('only show resolved conflicts')), |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
302 ('', 'unresolved', None, _('only show unresolved conflicts'))]), |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
303 'unresolve': (unresolve, []) |
5042 | 304 } |
305 | |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
306 def dispatch_(im, args, opts): |
5042 | 307 def complete(s, choices): |
308 candidates = [] | |
309 for choice in choices: | |
310 if choice.startswith(s): | |
311 candidates.append(choice) | |
312 return candidates | |
313 | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
314 c, args = args[0], list(args[1:]) |
5042 | 315 cmd = complete(c, subcmdtable.keys()) |
316 if not cmd: | |
317 raise cmdutil.UnknownCommand('imerge ' + c) | |
318 if len(cmd) > 1: | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
319 cmd.sort() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
320 raise cmdutil.AmbiguousCommand('imerge ' + c, cmd) |
5042 | 321 cmd = cmd[0] |
322 | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
323 func, optlist = subcmdtable[cmd] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
324 opts = {} |
5042 | 325 try: |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
326 args = fancyopts.fancyopts(args, optlist, opts) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
327 return func(im, *args, **opts) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
328 except fancyopts.getopt.GetoptError, inst: |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
329 raise dispatch.ParseError('imerge', '%s: %s' % (cmd, inst)) |
5042 | 330 except TypeError: |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
331 raise dispatch.ParseError('imerge', _('%s: invalid arguments') % cmd) |
5042 | 332 |
333 def imerge(ui, repo, *args, **opts): | |
334 '''interactive merge | |
335 | |
336 imerge lets you split a merge into pieces. When you start a merge | |
337 with imerge, the names of all files with conflicts are recorded. | |
338 You can then merge any of these files, and if the merge is | |
339 successful, they will be marked as resolved. When all files are | |
340 resolved, the merge is complete. | |
341 | |
342 If no merge is in progress, hg imerge [rev] will merge the working | |
343 directory with rev (defaulting to the other head if the repository | |
344 only has two heads). You may also resume a saved merge with | |
345 hg imerge load <file>. | |
346 | |
347 If a merge is in progress, hg imerge will default to merging the | |
348 next unresolved file. | |
349 | |
350 The following subcommands are available: | |
351 | |
352 status: | |
353 show the current state of the merge | |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
354 options: |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
355 -n --no-status: do not print the status prefix |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
356 --resolved: only print resolved conflicts |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
357 --unresolved: only print unresolved conflicts |
5042 | 358 next: |
359 show the next unresolved file merge | |
360 merge [<file>]: | |
361 merge <file>. If the file merge is successful, the file will be | |
362 recorded as resolved. If no file is given, the next unresolved | |
363 file will be merged. | |
364 resolve <file>...: | |
365 mark files as successfully merged | |
366 unresolve <file>...: | |
367 mark files as requiring merging. | |
368 save <file>: | |
369 save the state of the merge to a file to be resumed elsewhere | |
370 load <file>: | |
371 load the state of the merge from a file created by save | |
372 ''' | |
373 | |
374 im = Imerge(ui, repo) | |
375 | |
376 if im.merging(): | |
377 im.resume() | |
378 else: | |
379 rev = opts.get('rev') | |
380 if rev and args: | |
381 raise util.Abort('please specify just one revision') | |
5117
d4fa6bafc43a
Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5065
diff
changeset
|
382 |
5042 | 383 if len(args) == 2 and args[0] == 'load': |
384 pass | |
385 else: | |
386 if args: | |
387 rev = args[0] | |
388 im.start(rev=rev) | |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
389 if opts.get('auto'): |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
390 args = ['merge', '--auto'] |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
391 else: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
392 args = ['status'] |
5042 | 393 |
394 if not args: | |
395 args = ['merge'] | |
396 | |
5221
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5154
diff
changeset
|
397 return dispatch_(im, args, opts) |
5042 | 398 |
399 cmdtable = { | |
400 '^imerge': | |
401 (imerge, | |
5223
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
402 [('r', 'rev', '', _('revision to merge')), |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
403 ('a', 'auto', None, _('automatically merge where possible'))], |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5221
diff
changeset
|
404 'hg imerge [command]') |
5042 | 405 } |