Mercurial > hg > mercurial-crew-with-dirclash
annotate hgext/imerge.py @ 5192:33015dac5df5
convert: fix mercurial_sink.putcommit
Changeset 4ebc8693ce72 added some code to putcommit to avoid creating a
revision that touches no files, but this can break regular conversions
from some repositories:
- conceptually, since we're converting a repo, we should try to make
the new hg repo as similar as possible to the original repo - we
should create a new changeset, even if the original revision didn't
touch any files (maybe the commit message had some important bit);
- even if a "regular" revision that doesn't touch any file may seem
weird (and maybe even broken), it's completely legitimate for a merge
revision to not touch any file, and, if we just skip it, the
converted repo will end up with wrong history and possibly an extra
head.
As an example, say the crew and main hg repos are sync'ed. Somebody
sends an important patch to the mailing list. Matt quickly applies
and pushes it. But at the same time somebody also applies it to crew
and pushes it. Suppose the commit message ended up being a bit
different (say, there was a typo and somebody didn't fix it) or that
the date ended up being different (because of different patch-applying
scripts): the changeset hashes will be different, but the manifests
will be the same.
Since both changesets were pushed to public repos, it's hard to recall
them. If both are merged, the manifest from the resulting merge
revision will have the exact same contents as its parents - i.e. the
merge revision really doesn't touch any file at all.
To keep the file filtering stuff "working", the generic code was changed
to skip empty revisions if we're filtering the repo, fixing a bug in the
process (we want parents[0] instead of tip).
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Fri, 17 Aug 2007 20:18:05 -0300 |
parents | ec24bfd852ab |
children | 8860f29447c1 |
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 * | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
10 from mercurial import commands, cmdutil, 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 | |
112 def filemerge(self, fn): | |
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] |
5063 | 116 p2 = self.wctx.parents()[1] |
117 return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) | |
5042 | 118 |
119 def start(self, rev=None): | |
120 _filemerge = merge.filemerge | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
121 def filemerge(repo, fw, fd, fo, wctx, mctx): |
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5042
diff
changeset
|
122 self.conflicts[fw] = (fd, fo) |
5042 | 123 |
124 merge.filemerge = filemerge | |
125 commands.merge(self.ui, self.repo, rev=rev) | |
126 merge.filemerge = _filemerge | |
127 | |
5063 | 128 self.wctx = self.repo.workingctx() |
5042 | 129 self.save() |
130 | |
131 def resume(self): | |
132 self.load() | |
133 | |
134 dp = self.repo.dirstate.parents() | |
5063 | 135 p1, p2 = self.wctx.parents() |
136 if p1.node() != dp[0] or p2.node() != dp[1]: | |
5042 | 137 raise util.Abort('imerge state does not match working directory') |
138 | |
139 def next(self): | |
140 remaining = self.remaining() | |
141 return remaining and remaining[0] | |
142 | |
143 def resolve(self, files): | |
144 resolved = dict.fromkeys(self.resolved) | |
145 for fn in files: | |
146 if fn not in self.conflicts: | |
147 raise util.Abort('%s is not in the merge set' % fn) | |
148 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
|
149 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
|
150 self.resolved.sort() |
5042 | 151 self.save() |
152 return 0 | |
153 | |
154 def unresolve(self, files): | |
155 resolved = dict.fromkeys(self.resolved) | |
156 for fn in files: | |
157 if fn not in resolved: | |
158 raise util.Abort('%s is not resolved' % fn) | |
159 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
|
160 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
|
161 self.resolved.sort() |
5042 | 162 self.save() |
163 return 0 | |
164 | |
165 def pickle(self, dest): | |
166 '''write current merge state to file to be resumed elsewhere''' | |
167 state = ImergeStateFile(self) | |
168 return state.save(dest) | |
169 | |
170 def unpickle(self, source): | |
171 '''read merge state from file''' | |
172 state = ImergeStateFile(self) | |
173 return state.load(source) | |
174 | |
175 def load(im, source): | |
176 if im.merging(): | |
177 raise util.Abort('there is already a merge in progress ' | |
178 '(update -C <rev> to abort it)' ) | |
179 m, a, r, d = im.repo.status()[:4] | |
180 if m or a or r or d: | |
181 raise util.Abort('working directory has uncommitted changes') | |
182 | |
183 rc = im.unpickle(source) | |
184 if not rc: | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
185 status(im) |
5042 | 186 return rc |
187 | |
188 def merge_(im, filename=None): | |
189 if not filename: | |
190 filename = im.next() | |
191 if not filename: | |
192 im.ui.write('all conflicts resolved\n') | |
193 return 0 | |
194 | |
195 rc = im.filemerge(filename) | |
196 if not rc: | |
197 im.resolve([filename]) | |
198 if not im.next(): | |
199 im.ui.write('all conflicts resolved\n') | |
200 return 0 | |
201 return rc | |
202 | |
203 def next(im): | |
204 n = im.next() | |
205 if n: | |
206 im.ui.write('%s\n' % n) | |
207 else: | |
208 im.ui.write('all conflicts resolved\n') | |
209 return 0 | |
210 | |
211 def resolve(im, *files): | |
212 if not files: | |
213 raise util.Abort('resolve requires at least one filename') | |
214 return im.resolve(files) | |
215 | |
216 def save(im, dest): | |
217 return im.pickle(dest) | |
218 | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
219 def status(im, **opts): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
220 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
|
221 opts['resolved'] = True |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
222 opts['unresolved'] = True |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
223 |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
224 if im.ui.verbose: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
225 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
|
226 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
|
227 |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
228 conflicts = im.conflicts.keys() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
229 conflicts.sort() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
230 remaining = dict.fromkeys(im.remaining()) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
231 st = [] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
232 for fn in conflicts: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
233 if opts.get('no_status'): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
234 mode = '' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
235 elif fn in remaining: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
236 mode = 'U ' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
237 else: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
238 mode = 'R ' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
239 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
|
240 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
|
241 st.append((mode, fn)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
242 st.sort() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
243 for (mode, fn) in st: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
244 if im.ui.verbose: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
245 fo, fd = im.conflicts[fn] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
246 if fd != fn: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
247 fn = '%s (%s)' % (fn, fd) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
248 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
|
249 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
|
250 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
|
251 |
5042 | 252 return 0 |
253 | |
254 def unresolve(im, *files): | |
255 if not files: | |
256 raise util.Abort('unresolve requires at least one filename') | |
257 return im.unresolve(files) | |
258 | |
259 subcmdtable = { | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
260 'load': (load, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
261 'merge': (merge_, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
262 'next': (next, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
263 'resolve': (resolve, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
264 'save': (save, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
265 'status': (status, |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
266 [('n', 'no-status', None, _('hide status prefix')), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
267 ('', 'resolved', None, _('only show resolved conflicts')), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
268 ('', 'unresolved', None, _('only show unresolved conflicts'))]), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
269 'unresolve': (unresolve, []) |
5042 | 270 } |
271 | |
272 def dispatch(im, args, opts): | |
273 def complete(s, choices): | |
274 candidates = [] | |
275 for choice in choices: | |
276 if choice.startswith(s): | |
277 candidates.append(choice) | |
278 return candidates | |
279 | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
280 c, args = args[0], list(args[1:]) |
5042 | 281 cmd = complete(c, subcmdtable.keys()) |
282 if not cmd: | |
283 raise cmdutil.UnknownCommand('imerge ' + c) | |
284 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
|
285 cmd.sort() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
286 raise cmdutil.AmbiguousCommand('imerge ' + c, cmd) |
5042 | 287 cmd = cmd[0] |
288 | |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
289 func, optlist = subcmdtable[cmd] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
290 opts = {} |
5042 | 291 try: |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
292 args = fancyopts.fancyopts(args, optlist, opts) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
293 return func(im, *args, **opts) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
294 except fancyopts.getopt.GetoptError, inst: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
295 raise cmdutil.ParseError('imerge', '%s: %s' % (cmd, inst)) |
5042 | 296 except TypeError: |
5065
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5064
diff
changeset
|
297 raise cmdutil.ParseError('imerge', _('%s: invalid arguments') % cmd) |
5042 | 298 |
299 def imerge(ui, repo, *args, **opts): | |
300 '''interactive merge | |
301 | |
302 imerge lets you split a merge into pieces. When you start a merge | |
303 with imerge, the names of all files with conflicts are recorded. | |
304 You can then merge any of these files, and if the merge is | |
305 successful, they will be marked as resolved. When all files are | |
306 resolved, the merge is complete. | |
307 | |
308 If no merge is in progress, hg imerge [rev] will merge the working | |
309 directory with rev (defaulting to the other head if the repository | |
310 only has two heads). You may also resume a saved merge with | |
311 hg imerge load <file>. | |
312 | |
313 If a merge is in progress, hg imerge will default to merging the | |
314 next unresolved file. | |
315 | |
316 The following subcommands are available: | |
317 | |
318 status: | |
319 show the current state of the merge | |
320 next: | |
321 show the next unresolved file merge | |
322 merge [<file>]: | |
323 merge <file>. If the file merge is successful, the file will be | |
324 recorded as resolved. If no file is given, the next unresolved | |
325 file will be merged. | |
326 resolve <file>...: | |
327 mark files as successfully merged | |
328 unresolve <file>...: | |
329 mark files as requiring merging. | |
330 save <file>: | |
331 save the state of the merge to a file to be resumed elsewhere | |
332 load <file>: | |
333 load the state of the merge from a file created by save | |
334 ''' | |
335 | |
336 im = Imerge(ui, repo) | |
337 | |
338 if im.merging(): | |
339 im.resume() | |
340 else: | |
341 rev = opts.get('rev') | |
342 if rev and args: | |
343 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
|
344 |
5042 | 345 if len(args) == 2 and args[0] == 'load': |
346 pass | |
347 else: | |
348 if args: | |
349 rev = args[0] | |
350 im.start(rev=rev) | |
351 args = ['status'] | |
352 | |
353 if not args: | |
354 args = ['merge'] | |
355 | |
356 return dispatch(im, args, opts) | |
357 | |
358 cmdtable = { | |
359 '^imerge': | |
360 (imerge, | |
361 [('r', 'rev', '', _('revision to merge'))], 'hg imerge [command]') | |
362 } |