Show More
@@ -0,0 +1,93 b'' | |||||
|
1 | # fetch.py - pull and merge remote changes | |||
|
2 | # | |||
|
3 | # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms | |||
|
6 | # of the GNU General Public License, incorporated herein by reference. | |||
|
7 | ||||
|
8 | from mercurial.demandload import * | |||
|
9 | from mercurial.i18n import gettext as _ | |||
|
10 | from mercurial.node import * | |||
|
11 | demandload(globals(), 'mercurial:commands,hg,node,util') | |||
|
12 | ||||
|
13 | def fetch(ui, repo, source='default', **opts): | |||
|
14 | '''Pull changes from a remote repository, merge new changes if needed. | |||
|
15 | ||||
|
16 | This finds all changes from the repository at the specified path | |||
|
17 | or URL and adds them to the local repository. | |||
|
18 | ||||
|
19 | If the pulled changes add a new head, the head is automatically | |||
|
20 | merged, and the result of the merge is committed. Otherwise, the | |||
|
21 | working directory is updated.''' | |||
|
22 | ||||
|
23 | def postincoming(other, modheads): | |||
|
24 | if modheads == 0: | |||
|
25 | return 0 | |||
|
26 | if modheads == 1: | |||
|
27 | return commands.doupdate(ui, repo) | |||
|
28 | newheads = repo.heads(parent) | |||
|
29 | newchildren = [n for n in repo.heads(parent) if n != parent] | |||
|
30 | newparent = parent | |||
|
31 | if newchildren: | |||
|
32 | commands.doupdate(ui, repo, node=hex(newchildren[0])) | |||
|
33 | newparent = newchildren[0] | |||
|
34 | newheads = [n for n in repo.heads() if n != newparent] | |||
|
35 | err = False | |||
|
36 | if newheads: | |||
|
37 | ui.status(_('merging with new head %d:%s\n') % | |||
|
38 | (repo.changelog.rev(newheads[0]), short(newheads[0]))) | |||
|
39 | err = repo.update(newheads[0], allow=True, remind=False) | |||
|
40 | if not err and len(newheads) > 1: | |||
|
41 | ui.status(_('not merging with %d other new heads ' | |||
|
42 | '(use "hg heads" and "hg merge" to merge them)') % | |||
|
43 | (len(newheads) - 1)) | |||
|
44 | if not err: | |||
|
45 | mod, add, rem = repo.status()[:3] | |||
|
46 | message = (commands.logmessage(opts) or | |||
|
47 | (_('Automated merge with %s') % other.url())) | |||
|
48 | n = repo.commit(mod + add + rem, message, | |||
|
49 | opts['user'], opts['date'], | |||
|
50 | force_editor=opts.get('force_editor')) | |||
|
51 | ui.status(_('new changeset %d:%s merges remote changes ' | |||
|
52 | 'with local\n') % (repo.changelog.rev(n), | |||
|
53 | short(n))) | |||
|
54 | def pull(): | |||
|
55 | commands.setremoteconfig(ui, opts) | |||
|
56 | ||||
|
57 | other = hg.repository(ui, ui.expandpath(source)) | |||
|
58 | ui.status(_('pulling from %s\n') % source) | |||
|
59 | revs = None | |||
|
60 | if opts['rev'] and not other.local(): | |||
|
61 | raise util.Abort(_("fetch -r doesn't work for remote repositories yet")) | |||
|
62 | elif opts['rev']: | |||
|
63 | revs = [other.lookup(rev) for rev in opts['rev']] | |||
|
64 | modheads = repo.pull(other, heads=revs) | |||
|
65 | return postincoming(other, modheads) | |||
|
66 | ||||
|
67 | parent, p2 = repo.dirstate.parents() | |||
|
68 | if parent != repo.changelog.tip(): | |||
|
69 | raise util.Abort(_('working dir not at tip ' | |||
|
70 | '(use "hg update" to check out tip)')) | |||
|
71 | if p2 != nullid: | |||
|
72 | raise util.Abort(_('outstanding uncommitted merge')) | |||
|
73 | mod, add, rem = repo.status()[:3] | |||
|
74 | if mod or add or rem: | |||
|
75 | raise util.Abort(_('outstanding uncommitted changes')) | |||
|
76 | if len(repo.heads()) > 1: | |||
|
77 | raise util.Abort(_('multiple heads in this repository ' | |||
|
78 | '(use "hg heads" and "hg merge" to merge them)')) | |||
|
79 | return pull() | |||
|
80 | ||||
|
81 | cmdtable = { | |||
|
82 | 'fetch': | |||
|
83 | (fetch, | |||
|
84 | [('e', 'ssh', '', _('specify ssh command to use')), | |||
|
85 | ('m', 'message', '', _('use <text> as commit message')), | |||
|
86 | ('l', 'logfile', '', _('read the commit message from <file>')), | |||
|
87 | ('d', 'date', '', _('record datecode as commit date')), | |||
|
88 | ('u', 'user', '', _('record user as commiter')), | |||
|
89 | ('r', 'rev', [], _('a specific revision you would like to pull')), | |||
|
90 | ('f', 'force-editor', None, _('edit commit message')), | |||
|
91 | ('', 'remotecmd', '', _('hg command to run on the remote side'))], | |||
|
92 | 'hg fetch [SOURCE]'), | |||
|
93 | } |
@@ -39,6 +39,16 b' versionstr = "0.45"' | |||||
39 |
|
39 | |||
40 | commands.norepo += " qclone qversion" |
|
40 | commands.norepo += " qclone qversion" | |
41 |
|
41 | |||
|
42 | class StatusEntry: | |||
|
43 | def __init__(self, rev, name=None): | |||
|
44 | if not name: | |||
|
45 | self.rev, self.name = rev.split(':') | |||
|
46 | else: | |||
|
47 | self.rev, self.name = rev, name | |||
|
48 | ||||
|
49 | def __str__(self): | |||
|
50 | return self.rev + ':' + self.name | |||
|
51 | ||||
42 | class queue: |
|
52 | class queue: | |
43 | def __init__(self, ui, path, patchdir=None): |
|
53 | def __init__(self, ui, path, patchdir=None): | |
44 | self.basepath = path |
|
54 | self.basepath = path | |
@@ -60,7 +70,8 b' class queue:' | |||||
60 | self.parse_series() |
|
70 | self.parse_series() | |
61 |
|
71 | |||
62 | if os.path.exists(os.path.join(self.path, self.status_path)): |
|
72 | if os.path.exists(os.path.join(self.path, self.status_path)): | |
63 | self.applied = self.opener(self.status_path).read().splitlines() |
|
73 | self.applied = [StatusEntry(l) | |
|
74 | for l in self.opener(self.status_path).read().splitlines()] | |||
64 |
|
75 | |||
65 | def find_series(self, patch): |
|
76 | def find_series(self, patch): | |
66 | pre = re.compile("(\s*)([^#]+)") |
|
77 | pre = re.compile("(\s*)([^#]+)") | |
@@ -88,7 +99,7 b' class queue:' | |||||
88 | for i in items: |
|
99 | for i in items: | |
89 | print >> fp, i |
|
100 | print >> fp, i | |
90 | fp.close() |
|
101 | fp.close() | |
91 | if self.applied_dirty: write_list(self.applied, self.status_path) |
|
102 | if self.applied_dirty: write_list(map(str, self.applied), self.status_path) | |
92 | if self.series_dirty: write_list(self.full_series, self.series_path) |
|
103 | if self.series_dirty: write_list(self.full_series, self.series_path) | |
93 |
|
104 | |||
94 | def readheaders(self, patch): |
|
105 | def readheaders(self, patch): | |
@@ -209,12 +220,10 b' class queue:' | |||||
209 | return p1 |
|
220 | return p1 | |
210 | if len(self.applied) == 0: |
|
221 | if len(self.applied) == 0: | |
211 | return None |
|
222 | return None | |
212 | (top, patch) = self.applied[-1].split(':') |
|
223 | return revlog.bin(self.applied[-1].rev) | |
213 | top = revlog.bin(top) |
|
|||
214 | return top |
|
|||
215 | pp = repo.changelog.parents(rev) |
|
224 | pp = repo.changelog.parents(rev) | |
216 | if pp[1] != revlog.nullid: |
|
225 | if pp[1] != revlog.nullid: | |
217 |
arevs = [ x. |
|
226 | arevs = [ x.rev for x in self.applied ] | |
218 | p0 = revlog.hex(pp[0]) |
|
227 | p0 = revlog.hex(pp[0]) | |
219 | p1 = revlog.hex(pp[1]) |
|
228 | p1 = revlog.hex(pp[1]) | |
220 | if p0 in arevs: |
|
229 | if p0 in arevs: | |
@@ -234,7 +243,7 b' class queue:' | |||||
234 | pname = ".hg.patches.merge.marker" |
|
243 | pname = ".hg.patches.merge.marker" | |
235 | n = repo.commit(None, '[mq]: merge marker', user=None, force=1, |
|
244 | n = repo.commit(None, '[mq]: merge marker', user=None, force=1, | |
236 | wlock=wlock) |
|
245 | wlock=wlock) | |
237 |
self.applied.append(revlog.hex(n) |
|
246 | self.applied.append(StatusEntry(revlog.hex(n), pname)) | |
238 | self.applied_dirty = 1 |
|
247 | self.applied_dirty = 1 | |
239 |
|
248 | |||
240 | head = self.qparents(repo) |
|
249 | head = self.qparents(repo) | |
@@ -252,7 +261,7 b' class queue:' | |||||
252 | rev = revlog.bin(info[1]) |
|
261 | rev = revlog.bin(info[1]) | |
253 | (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) |
|
262 | (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) | |
254 | if head: |
|
263 | if head: | |
255 |
self.applied.append(revlog.hex(head) |
|
264 | self.applied.append(StatusEntry(revlog.hex(head), patch)) | |
256 | self.applied_dirty = 1 |
|
265 | self.applied_dirty = 1 | |
257 | if err: |
|
266 | if err: | |
258 | return (err, head) |
|
267 | return (err, head) | |
@@ -263,8 +272,8 b' class queue:' | |||||
263 | patchfile: file name of patch''' |
|
272 | patchfile: file name of patch''' | |
264 | try: |
|
273 | try: | |
265 | pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
|
274 | pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') | |
266 |
f = os.popen("%s -d |
|
275 | f = os.popen("%s -d %s -p1 --no-backup-if-mismatch < %s" % | |
267 | (pp, repo.root, patchfile)) |
|
276 | (pp, util.shellquote(repo.root), util.shellquote(patchfile))) | |
268 | except: |
|
277 | except: | |
269 | self.ui.warn("patch failed, unable to continue (try -v)\n") |
|
278 | self.ui.warn("patch failed, unable to continue (try -v)\n") | |
270 | return (None, [], False) |
|
279 | return (None, [], False) | |
@@ -275,11 +284,7 b' class queue:' | |||||
275 | if self.ui.verbose: |
|
284 | if self.ui.verbose: | |
276 | self.ui.warn(l + "\n") |
|
285 | self.ui.warn(l + "\n") | |
277 | if l[:14] == 'patching file ': |
|
286 | if l[:14] == 'patching file ': | |
278 |
pf = os.path.normpath(l |
|
287 | pf = os.path.normpath(util.parse_patch_output(l)) | |
279 | # when patch finds a space in the file name, it puts |
|
|||
280 | # single quotes around the filename. strip them off |
|
|||
281 | if pf[0] == "'" and pf[-1] == "'": |
|
|||
282 | pf = pf[1:-1] |
|
|||
283 | if pf not in files: |
|
288 | if pf not in files: | |
284 | files.append(pf) |
|
289 | files.append(pf) | |
285 | printed_file = False |
|
290 | printed_file = False | |
@@ -351,7 +356,7 b' class queue:' | |||||
351 | raise util.Abort(_("repo commit failed")) |
|
356 | raise util.Abort(_("repo commit failed")) | |
352 |
|
357 | |||
353 | if update_status: |
|
358 | if update_status: | |
354 |
self.applied.append(revlog.hex(n) |
|
359 | self.applied.append(StatusEntry(revlog.hex(n), patch)) | |
355 |
|
360 | |||
356 | if patcherr: |
|
361 | if patcherr: | |
357 | if not patchfound: |
|
362 | if not patchfound: | |
@@ -389,8 +394,7 b' class queue:' | |||||
389 |
|
394 | |||
390 | def check_toppatch(self, repo): |
|
395 | def check_toppatch(self, repo): | |
391 | if len(self.applied) > 0: |
|
396 | if len(self.applied) > 0: | |
392 |
|
|
397 | top = revlog.bin(self.applied[-1].rev) | |
393 | top = revlog.bin(top) |
|
|||
394 | pp = repo.dirstate.parents() |
|
398 | pp = repo.dirstate.parents() | |
395 | if top not in pp: |
|
399 | if top not in pp: | |
396 | raise util.Abort(_("queue top not at same revision as working directory")) |
|
400 | raise util.Abort(_("queue top not at same revision as working directory")) | |
@@ -421,7 +425,7 b' class queue:' | |||||
421 | if n == None: |
|
425 | if n == None: | |
422 | raise util.Abort(_("repo commit failed")) |
|
426 | raise util.Abort(_("repo commit failed")) | |
423 | self.full_series[insert:insert] = [patch] |
|
427 | self.full_series[insert:insert] = [patch] | |
424 |
self.applied.append(revlog.hex(n) |
|
428 | self.applied.append(StatusEntry(revlog.hex(n), patch)) | |
425 | self.parse_series() |
|
429 | self.parse_series() | |
426 | self.series_dirty = 1 |
|
430 | self.series_dirty = 1 | |
427 | self.applied_dirty = 1 |
|
431 | self.applied_dirty = 1 | |
@@ -501,9 +505,9 b' class queue:' | |||||
501 | # we go in two steps here so the strip loop happens in a |
|
505 | # we go in two steps here so the strip loop happens in a | |
502 | # sensible order. When stripping many files, this helps keep |
|
506 | # sensible order. When stripping many files, this helps keep | |
503 | # our disk access patterns under control. |
|
507 | # our disk access patterns under control. | |
504 | list = seen.keys() |
|
508 | seen_list = seen.keys() | |
505 | list.sort() |
|
509 | seen_list.sort() | |
506 | for f in list: |
|
510 | for f in seen_list: | |
507 | ff = repo.file(f) |
|
511 | ff = repo.file(f) | |
508 | filerev = seen[f] |
|
512 | filerev = seen[f] | |
509 | if filerev != 0: |
|
513 | if filerev != 0: | |
@@ -535,7 +539,6 b' class queue:' | |||||
535 | saveheads = [] |
|
539 | saveheads = [] | |
536 | savebases = {} |
|
540 | savebases = {} | |
537 |
|
541 | |||
538 | tip = chlog.tip() |
|
|||
539 | heads = limitheads(chlog, rev) |
|
542 | heads = limitheads(chlog, rev) | |
540 | seen = {} |
|
543 | seen = {} | |
541 |
|
544 | |||
@@ -566,7 +569,7 b' class queue:' | |||||
566 | savebases[x] = 1 |
|
569 | savebases[x] = 1 | |
567 |
|
570 | |||
568 | # create a changegroup for all the branches we need to keep |
|
571 | # create a changegroup for all the branches we need to keep | |
569 |
if backup |
|
572 | if backup == "all": | |
570 | backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip') |
|
573 | backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip') | |
571 | bundle(backupch) |
|
574 | bundle(backupch) | |
572 | if saveheads: |
|
575 | if saveheads: | |
@@ -581,16 +584,15 b' class queue:' | |||||
581 | if saveheads: |
|
584 | if saveheads: | |
582 | self.ui.status("adding branch\n") |
|
585 | self.ui.status("adding branch\n") | |
583 | commands.unbundle(self.ui, repo, chgrpfile, update=False) |
|
586 | commands.unbundle(self.ui, repo, chgrpfile, update=False) | |
584 |
if backup |
|
587 | if backup != "strip": | |
585 | os.unlink(chgrpfile) |
|
588 | os.unlink(chgrpfile) | |
586 |
|
589 | |||
587 | def isapplied(self, patch): |
|
590 | def isapplied(self, patch): | |
588 | """returns (index, rev, patch)""" |
|
591 | """returns (index, rev, patch)""" | |
589 | for i in xrange(len(self.applied)): |
|
592 | for i in xrange(len(self.applied)): | |
590 |
|
|
593 | a = self.applied[i] | |
591 |
a = p |
|
594 | if a.name == patch: | |
592 | if a[1] == patch: |
|
595 | return (i, a.rev, a.name) | |
593 | return (i, a[0], a[1]) |
|
|||
594 | return None |
|
596 | return None | |
595 |
|
597 | |||
596 | # if the exact patch name does not exist, we try a few |
|
598 | # if the exact patch name does not exist, we try a few | |
@@ -693,7 +695,7 b' class queue:' | |||||
693 | ret = self.mergepatch(repo, mergeq, s, wlock) |
|
695 | ret = self.mergepatch(repo, mergeq, s, wlock) | |
694 | else: |
|
696 | else: | |
695 | ret = self.apply(repo, s, list, wlock=wlock) |
|
697 | ret = self.apply(repo, s, list, wlock=wlock) | |
696 |
top = self.applied[-1]. |
|
698 | top = self.applied[-1].name | |
697 | if ret[0]: |
|
699 | if ret[0]: | |
698 | self.ui.write("Errors during apply, please fix and refresh %s\n" % |
|
700 | self.ui.write("Errors during apply, please fix and refresh %s\n" % | |
699 | top) |
|
701 | top) | |
@@ -730,7 +732,7 b' class queue:' | |||||
730 |
|
732 | |||
731 | if not update: |
|
733 | if not update: | |
732 | parents = repo.dirstate.parents() |
|
734 | parents = repo.dirstate.parents() | |
733 |
rr = [ revlog.bin(x. |
|
735 | rr = [ revlog.bin(x.rev) for x in self.applied ] | |
734 | for p in parents: |
|
736 | for p in parents: | |
735 | if p in rr: |
|
737 | if p in rr: | |
736 | self.ui.warn("qpop: forcing dirstate update\n") |
|
738 | self.ui.warn("qpop: forcing dirstate update\n") | |
@@ -751,7 +753,7 b' class queue:' | |||||
751 | if popi >= end: |
|
753 | if popi >= end: | |
752 | self.ui.warn("qpop: %s is already at the top\n" % patch) |
|
754 | self.ui.warn("qpop: %s is already at the top\n" % patch) | |
753 | return |
|
755 | return | |
754 |
info = [ popi ] + self.applied[popi]. |
|
756 | info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name] | |
755 |
|
757 | |||
756 | start = info[0] |
|
758 | start = info[0] | |
757 | rev = revlog.bin(info[1]) |
|
759 | rev = revlog.bin(info[1]) | |
@@ -784,7 +786,7 b' class queue:' | |||||
784 | self.strip(repo, rev, update=False, backup='strip', wlock=wlock) |
|
786 | self.strip(repo, rev, update=False, backup='strip', wlock=wlock) | |
785 | del self.applied[start:end] |
|
787 | del self.applied[start:end] | |
786 | if len(self.applied): |
|
788 | if len(self.applied): | |
787 |
self.ui.write("Now at: %s\n" % self.applied[-1]. |
|
789 | self.ui.write("Now at: %s\n" % self.applied[-1].name) | |
788 | else: |
|
790 | else: | |
789 | self.ui.write("Patch queue now empty\n") |
|
791 | self.ui.write("Patch queue now empty\n") | |
790 |
|
792 | |||
@@ -802,8 +804,7 b' class queue:' | |||||
802 | return |
|
804 | return | |
803 | wlock = repo.wlock() |
|
805 | wlock = repo.wlock() | |
804 | self.check_toppatch(repo) |
|
806 | self.check_toppatch(repo) | |
805 | qp = self.qparents(repo) |
|
807 | (top, patch) = (self.applied[-1].rev, self.applied[-1].name) | |
806 | (top, patch) = self.applied[-1].split(':') |
|
|||
807 | top = revlog.bin(top) |
|
808 | top = revlog.bin(top) | |
808 | cparents = repo.changelog.parents(top) |
|
809 | cparents = repo.changelog.parents(top) | |
809 | patchparent = self.qparents(repo, top) |
|
810 | patchparent = self.qparents(repo, top) | |
@@ -899,7 +900,7 b' class queue:' | |||||
899 |
|
900 | |||
900 | self.strip(repo, top, update=False, backup='strip', wlock=wlock) |
|
901 | self.strip(repo, top, update=False, backup='strip', wlock=wlock) | |
901 | n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) |
|
902 | n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) | |
902 |
self.applied[-1] = revlog.hex(n) |
|
903 | self.applied[-1] = StatusEntry(revlog.hex(n), patch) | |
903 | self.applied_dirty = 1 |
|
904 | self.applied_dirty = 1 | |
904 | else: |
|
905 | else: | |
905 | commands.dodiff(patchf, self.ui, repo, patchparent, None) |
|
906 | commands.dodiff(patchf, self.ui, repo, patchparent, None) | |
@@ -921,10 +922,7 b' class queue:' | |||||
921 | start = self.series_end() |
|
922 | start = self.series_end() | |
922 | else: |
|
923 | else: | |
923 | start = self.series.index(patch) + 1 |
|
924 | start = self.series.index(patch) + 1 | |
924 | for p in self.series[start:]: |
|
925 | return [(i, self.series[i]) for i in xrange(start, len(self.series))] | |
925 | if self.ui.verbose: |
|
|||
926 | self.ui.write("%d " % self.series.index(p)) |
|
|||
927 | self.ui.write("%s\n" % p) |
|
|||
928 |
|
926 | |||
929 | def qseries(self, repo, missing=None, summary=False): |
|
927 | def qseries(self, repo, missing=None, summary=False): | |
930 | start = self.series_end() |
|
928 | start = self.series_end() | |
@@ -944,7 +942,7 b' class queue:' | |||||
944 | msg = '' |
|
942 | msg = '' | |
945 | self.ui.write('%s%s\n' % (patch, msg)) |
|
943 | self.ui.write('%s%s\n' % (patch, msg)) | |
946 | else: |
|
944 | else: | |
947 | list = [] |
|
945 | msng_list = [] | |
948 | for root, dirs, files in os.walk(self.path): |
|
946 | for root, dirs, files in os.walk(self.path): | |
949 | d = root[len(self.path) + 1:] |
|
947 | d = root[len(self.path) + 1:] | |
950 | for f in files: |
|
948 | for f in files: | |
@@ -952,13 +950,12 b' class queue:' | |||||
952 | if (fl not in self.series and |
|
950 | if (fl not in self.series and | |
953 | fl not in (self.status_path, self.series_path) |
|
951 | fl not in (self.status_path, self.series_path) | |
954 | and not fl.startswith('.')): |
|
952 | and not fl.startswith('.')): | |
955 | list.append(fl) |
|
953 | msng_list.append(fl) | |
956 | list.sort() |
|
954 | msng_list.sort() | |
957 |
|
|
955 | for x in msng_list: | |
958 |
f |
|
956 | if self.ui.verbose: | |
959 |
|
|
957 | self.ui.write("D ") | |
960 |
|
|
958 | self.ui.write("%s\n" % x) | |
961 | self.ui.write("%s\n" % x) |
|
|||
962 |
|
959 | |||
963 | def issaveline(self, l): |
|
960 | def issaveline(self, l): | |
964 | name = l.split(':')[1] |
|
961 | name = l.split(':')[1] | |
@@ -987,12 +984,11 b' class queue:' | |||||
987 | qpp = [ hg.bin(x) for x in l ] |
|
984 | qpp = [ hg.bin(x) for x in l ] | |
988 | elif datastart != None: |
|
985 | elif datastart != None: | |
989 | l = lines[i].rstrip() |
|
986 | l = lines[i].rstrip() | |
990 |
|
|
987 | se = StatusEntry(l) | |
991 |
|
|
988 | file_ = se.name | |
992 |
|
|
989 | if se.rev: | |
993 |
|
|
990 | applied.append(se) | |
994 |
|
|
991 | series.append(file_) | |
995 | series.append(file) |
|
|||
996 | if datastart == None: |
|
992 | if datastart == None: | |
997 | self.ui.warn("No saved patch data found\n") |
|
993 | self.ui.warn("No saved patch data found\n") | |
998 | return 1 |
|
994 | return 1 | |
@@ -1043,18 +1039,18 b' class queue:' | |||||
1043 | pp = r.dirstate.parents() |
|
1039 | pp = r.dirstate.parents() | |
1044 | msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) |
|
1040 | msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) | |
1045 | msg += "\n\nPatch Data:\n" |
|
1041 | msg += "\n\nPatch Data:\n" | |
1046 | text = msg + "\n".join(self.applied) + '\n' + (ar and "\n".join(ar) |
|
1042 | text = msg + "\n".join(str(self.applied)) + '\n' + (ar and "\n".join(ar) | |
1047 | + '\n' or "") |
|
1043 | + '\n' or "") | |
1048 | n = repo.commit(None, text, user=None, force=1) |
|
1044 | n = repo.commit(None, text, user=None, force=1) | |
1049 | if not n: |
|
1045 | if not n: | |
1050 | self.ui.warn("repo commit failed\n") |
|
1046 | self.ui.warn("repo commit failed\n") | |
1051 | return 1 |
|
1047 | return 1 | |
1052 |
self.applied.append(revlog.hex(n) |
|
1048 | self.applied.append(StatusEntry(revlog.hex(n),'.hg.patches.save.line')) | |
1053 | self.applied_dirty = 1 |
|
1049 | self.applied_dirty = 1 | |
1054 |
|
1050 | |||
1055 | def full_series_end(self): |
|
1051 | def full_series_end(self): | |
1056 | if len(self.applied) > 0: |
|
1052 | if len(self.applied) > 0: | |
1057 |
|
|
1053 | p = self.applied[-1].name | |
1058 | end = self.find_series(p) |
|
1054 | end = self.find_series(p) | |
1059 | if end == None: |
|
1055 | if end == None: | |
1060 | return len(self.full_series) |
|
1056 | return len(self.full_series) | |
@@ -1064,7 +1060,7 b' class queue:' | |||||
1064 | def series_end(self): |
|
1060 | def series_end(self): | |
1065 | end = 0 |
|
1061 | end = 0 | |
1066 | if len(self.applied) > 0: |
|
1062 | if len(self.applied) > 0: | |
1067 |
|
|
1063 | p = self.applied[-1].name | |
1068 | try: |
|
1064 | try: | |
1069 | end = self.series.index(p) |
|
1065 | end = self.series.index(p) | |
1070 | except ValueError: |
|
1066 | except ValueError: | |
@@ -1084,8 +1080,7 b' class queue:' | |||||
1084 | self.ui.write("%s\n" % p) |
|
1080 | self.ui.write("%s\n" % p) | |
1085 |
|
1081 | |||
1086 | def appliedname(self, index): |
|
1082 | def appliedname(self, index): | |
1087 | p = self.applied[index] |
|
1083 | pname = self.applied[index].name | |
1088 | pname = p.split(':')[1] |
|
|||
1089 | if not self.ui.verbose: |
|
1084 | if not self.ui.verbose: | |
1090 | p = pname |
|
1085 | p = pname | |
1091 | else: |
|
1086 | else: | |
@@ -1173,8 +1168,10 b' def applied(ui, repo, patch=None, **opts' | |||||
1173 |
|
1168 | |||
1174 | def unapplied(ui, repo, patch=None, **opts): |
|
1169 | def unapplied(ui, repo, patch=None, **opts): | |
1175 | """print the patches not yet applied""" |
|
1170 | """print the patches not yet applied""" | |
1176 | repo.mq.unapplied(repo, patch) |
|
1171 | for i, p in repo.mq.unapplied(repo, patch): | |
1177 | return 0 |
|
1172 | if ui.verbose: | |
|
1173 | ui.write("%d " % i) | |||
|
1174 | ui.write("%s\n" % p) | |||
1178 |
|
1175 | |||
1179 | def qimport(ui, repo, *filename, **opts): |
|
1176 | def qimport(ui, repo, *filename, **opts): | |
1180 | """import a patch""" |
|
1177 | """import a patch""" | |
@@ -1223,7 +1220,7 b' def clone(ui, source, dest=None, **opts)' | |||||
1223 | if sr.local(): |
|
1220 | if sr.local(): | |
1224 | reposetup(ui, sr) |
|
1221 | reposetup(ui, sr) | |
1225 | if sr.mq.applied: |
|
1222 | if sr.mq.applied: | |
1226 |
qbase = revlog.bin(sr.mq.applied[0]. |
|
1223 | qbase = revlog.bin(sr.mq.applied[0].rev) | |
1227 | if not hg.islocal(dest): |
|
1224 | if not hg.islocal(dest): | |
1228 | destrev = sr.parents(qbase)[0] |
|
1225 | destrev = sr.parents(qbase)[0] | |
1229 | ui.note(_('cloning main repo\n')) |
|
1226 | ui.note(_('cloning main repo\n')) | |
@@ -1286,7 +1283,7 b' def new(ui, repo, patch, **opts):' | |||||
1286 | If neither is specified, the patch header is empty and the |
|
1283 | If neither is specified, the patch header is empty and the | |
1287 | commit message is 'New patch: PATCH'""" |
|
1284 | commit message is 'New patch: PATCH'""" | |
1288 | q = repo.mq |
|
1285 | q = repo.mq | |
1289 | message=commands.logmessage(**opts) |
|
1286 | message = commands.logmessage(**opts) | |
1290 | q.new(repo, patch, msg=message, force=opts['force']) |
|
1287 | q.new(repo, patch, msg=message, force=opts['force']) | |
1291 | q.save_dirty() |
|
1288 | q.save_dirty() | |
1292 | return 0 |
|
1289 | return 0 | |
@@ -1294,11 +1291,11 b' def new(ui, repo, patch, **opts):' | |||||
1294 | def refresh(ui, repo, **opts): |
|
1291 | def refresh(ui, repo, **opts): | |
1295 | """update the current patch""" |
|
1292 | """update the current patch""" | |
1296 | q = repo.mq |
|
1293 | q = repo.mq | |
1297 | message=commands.logmessage(**opts) |
|
1294 | message = commands.logmessage(**opts) | |
1298 | if opts['edit']: |
|
1295 | if opts['edit']: | |
1299 | if message: |
|
1296 | if message: | |
1300 | raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
|
1297 | raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | |
1301 |
patch = q.applied[-1]. |
|
1298 | patch = q.applied[-1].name | |
1302 | (message, comment, user, date, hasdiff) = q.readheaders(patch) |
|
1299 | (message, comment, user, date, hasdiff) = q.readheaders(patch) | |
1303 | message = ui.edit('\n'.join(message), user or ui.username()) |
|
1300 | message = ui.edit('\n'.join(message), user or ui.username()) | |
1304 | q.refresh(repo, msg=message, short=opts['short']) |
|
1301 | q.refresh(repo, msg=message, short=opts['short']) | |
@@ -1331,7 +1328,7 b' def fold(ui, repo, *files, **opts):' | |||||
1331 | if not q.check_toppatch(repo): |
|
1328 | if not q.check_toppatch(repo): | |
1332 | raise util.Abort(_('No patches applied\n')) |
|
1329 | raise util.Abort(_('No patches applied\n')) | |
1333 |
|
1330 | |||
1334 | message=commands.logmessage(**opts) |
|
1331 | message = commands.logmessage(**opts) | |
1335 | if opts['edit']: |
|
1332 | if opts['edit']: | |
1336 | if message: |
|
1333 | if message: | |
1337 | raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
|
1334 | raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | |
@@ -1342,7 +1339,7 b' def fold(ui, repo, *files, **opts):' | |||||
1342 | for f in files: |
|
1339 | for f in files: | |
1343 | patch = q.lookup(f) |
|
1340 | patch = q.lookup(f) | |
1344 | if patch in patches or patch == parent: |
|
1341 | if patch in patches or patch == parent: | |
1345 |
|
|
1342 | ui.warn(_('Skipping already folded patch %s') % patch) | |
1346 | if q.isapplied(patch): |
|
1343 | if q.isapplied(patch): | |
1347 | raise util.Abort(_('qfold cannot fold already applied patch %s') % patch) |
|
1344 | raise util.Abort(_('qfold cannot fold already applied patch %s') % patch) | |
1348 | patches.append(patch) |
|
1345 | patches.append(patch) | |
@@ -1388,20 +1385,20 b' def header(ui, repo, patch=None):' | |||||
1388 | ui.write('\n'.join(message) + '\n') |
|
1385 | ui.write('\n'.join(message) + '\n') | |
1389 |
|
1386 | |||
1390 | def lastsavename(path): |
|
1387 | def lastsavename(path): | |
1391 | (dir, base) = os.path.split(path) |
|
1388 | (directory, base) = os.path.split(path) | |
1392 | names = os.listdir(dir) |
|
1389 | names = os.listdir(directory) | |
1393 | namere = re.compile("%s.([0-9]+)" % base) |
|
1390 | namere = re.compile("%s.([0-9]+)" % base) | |
1394 | max = None |
|
1391 | maxindex = None | |
1395 | maxname = None |
|
1392 | maxname = None | |
1396 | for f in names: |
|
1393 | for f in names: | |
1397 | m = namere.match(f) |
|
1394 | m = namere.match(f) | |
1398 | if m: |
|
1395 | if m: | |
1399 | index = int(m.group(1)) |
|
1396 | index = int(m.group(1)) | |
1400 | if max == None or index > max: |
|
1397 | if maxindex == None or index > maxindex: | |
1401 | max = index |
|
1398 | maxindex = index | |
1402 | maxname = f |
|
1399 | maxname = f | |
1403 | if maxname: |
|
1400 | if maxname: | |
1404 | return (os.path.join(dir, maxname), max) |
|
1401 | return (os.path.join(directory, maxname), maxindex) | |
1405 | return (None, None) |
|
1402 | return (None, None) | |
1406 |
|
1403 | |||
1407 | def savename(path): |
|
1404 | def savename(path): | |
@@ -1482,7 +1479,7 b' def rename(ui, repo, patch, name=None, *' | |||||
1482 |
|
1479 | |||
1483 | info = q.isapplied(patch) |
|
1480 | info = q.isapplied(patch) | |
1484 | if info: |
|
1481 | if info: | |
1485 |
q.applied[info[0]] = info[1] |
|
1482 | q.applied[info[0]] = StatusEntry(info[1], name) | |
1486 | q.applied_dirty = 1 |
|
1483 | q.applied_dirty = 1 | |
1487 |
|
1484 | |||
1488 | util.rename(os.path.join(q.path, patch), absdest) |
|
1485 | util.rename(os.path.join(q.path, patch), absdest) | |
@@ -1508,7 +1505,7 b' def restore(ui, repo, rev, **opts):' | |||||
1508 | def save(ui, repo, **opts): |
|
1505 | def save(ui, repo, **opts): | |
1509 | """save current queue state""" |
|
1506 | """save current queue state""" | |
1510 | q = repo.mq |
|
1507 | q = repo.mq | |
1511 | message=commands.logmessage(**opts) |
|
1508 | message = commands.logmessage(**opts) | |
1512 | ret = q.save(repo, msg=message) |
|
1509 | ret = q.save(repo, msg=message) | |
1513 | if ret: |
|
1510 | if ret: | |
1514 | return ret |
|
1511 | return ret | |
@@ -1563,7 +1560,7 b' def reposetup(ui, repo):' | |||||
1563 | if not q.applied: |
|
1560 | if not q.applied: | |
1564 | return tagscache |
|
1561 | return tagscache | |
1565 |
|
1562 | |||
1566 |
mqtags = [patch. |
|
1563 | mqtags = [(patch.rev, patch.name) for patch in q.applied] | |
1567 | mqtags.append((mqtags[-1][0], 'qtip')) |
|
1564 | mqtags.append((mqtags[-1][0], 'qtip')) | |
1568 | mqtags.append((mqtags[0][0], 'qbase')) |
|
1565 | mqtags.append((mqtags[0][0], 'qbase')) | |
1569 | for patch in mqtags: |
|
1566 | for patch in mqtags: |
@@ -255,7 +255,7 b' def hook(ui, repo, hooktype, node=None, ' | |||||
255 | changegroup. else send one email per changeset.''' |
|
255 | changegroup. else send one email per changeset.''' | |
256 | n = notifier(ui, repo, hooktype) |
|
256 | n = notifier(ui, repo, hooktype) | |
257 | if not n.subs: |
|
257 | if not n.subs: | |
258 |
ui.debug(_('notify: no subscribers to |
|
258 | ui.debug(_('notify: no subscribers to repo %s\n' % n.root)) | |
259 | return |
|
259 | return | |
260 | if n.skipsource(source): |
|
260 | if n.skipsource(source): | |
261 | ui.debug(_('notify: changes have source "%s" - skipping\n') % |
|
261 | ui.debug(_('notify: changes have source "%s" - skipping\n') % |
@@ -288,7 +288,8 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
288 | fp.close() |
|
288 | fp.close() | |
289 | else: |
|
289 | else: | |
290 | ui.status('Sending ', m['Subject'], ' ...\n') |
|
290 | ui.status('Sending ', m['Subject'], ' ...\n') | |
291 | m.__delitem__('bcc') |
|
291 | # Exim does not remove the Bcc field | |
|
292 | del m['Bcc'] | |||
292 | mail.sendmail(sender, to + bcc + cc, m.as_string(0)) |
|
293 | mail.sendmail(sender, to + bcc + cc, m.as_string(0)) | |
293 |
|
294 | |||
294 | cmdtable = { |
|
295 | cmdtable = { |
@@ -40,7 +40,7 b' def relpath(repo, args):' | |||||
40 | return [util.normpath(os.path.join(cwd, x)) for x in args] |
|
40 | return [util.normpath(os.path.join(cwd, x)) for x in args] | |
41 | return args |
|
41 | return args | |
42 |
|
42 | |||
43 |
def logmessage( |
|
43 | def logmessage(opts): | |
44 | """ get the log message according to -m and -l option """ |
|
44 | """ get the log message according to -m and -l option """ | |
45 | message = opts['message'] |
|
45 | message = opts['message'] | |
46 | logfile = opts['logfile'] |
|
46 | logfile = opts['logfile'] | |
@@ -125,12 +125,22 b' def walkchangerevs(ui, repo, pats, opts)' | |||||
125 |
|
125 | |||
126 |
|
126 | |||
127 | files, matchfn, anypats = matchpats(repo, pats, opts) |
|
127 | files, matchfn, anypats = matchpats(repo, pats, opts) | |
128 | follow = opts.get('follow') |
|
128 | follow = opts.get('follow') or opts.get('follow_first') | |
129 |
|
129 | |||
130 | if repo.changelog.count() == 0: |
|
130 | if repo.changelog.count() == 0: | |
131 | return [], False, matchfn |
|
131 | return [], False, matchfn | |
132 |
|
132 | |||
133 | revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0'])) |
|
133 | if follow: | |
|
134 | p = repo.dirstate.parents()[0] | |||
|
135 | if p == nullid: | |||
|
136 | ui.warn(_('No working directory revision; defaulting to tip\n')) | |||
|
137 | start = 'tip' | |||
|
138 | else: | |||
|
139 | start = repo.changelog.rev(p) | |||
|
140 | defrange = '%s:0' % start | |||
|
141 | else: | |||
|
142 | defrange = 'tip:0' | |||
|
143 | revs = map(int, revrange(ui, repo, opts['rev'] or [defrange])) | |||
134 | wanted = {} |
|
144 | wanted = {} | |
135 | slowpath = anypats |
|
145 | slowpath = anypats | |
136 | fncache = {} |
|
146 | fncache = {} | |
@@ -206,10 +216,55 b' def walkchangerevs(ui, repo, pats, opts)' | |||||
206 | wanted[rev] = 1 |
|
216 | wanted[rev] = 1 | |
207 |
|
217 | |||
208 | def iterate(): |
|
218 | def iterate(): | |
|
219 | class followfilter: | |||
|
220 | def __init__(self, onlyfirst=False): | |||
|
221 | self.startrev = -1 | |||
|
222 | self.roots = [] | |||
|
223 | self.onlyfirst = onlyfirst | |||
|
224 | ||||
|
225 | def match(self, rev): | |||
|
226 | def realparents(rev): | |||
|
227 | if self.onlyfirst: | |||
|
228 | return repo.changelog.parentrevs(rev)[0:1] | |||
|
229 | else: | |||
|
230 | return filter(lambda x: x != -1, repo.changelog.parentrevs(rev)) | |||
|
231 | ||||
|
232 | if self.startrev == -1: | |||
|
233 | self.startrev = rev | |||
|
234 | return True | |||
|
235 | ||||
|
236 | if rev > self.startrev: | |||
|
237 | # forward: all descendants | |||
|
238 | if not self.roots: | |||
|
239 | self.roots.append(self.startrev) | |||
|
240 | for parent in realparents(rev): | |||
|
241 | if parent in self.roots: | |||
|
242 | self.roots.append(rev) | |||
|
243 | return True | |||
|
244 | else: | |||
|
245 | # backwards: all parents | |||
|
246 | if not self.roots: | |||
|
247 | self.roots.extend(realparents(self.startrev)) | |||
|
248 | if rev in self.roots: | |||
|
249 | self.roots.remove(rev) | |||
|
250 | self.roots.extend(realparents(rev)) | |||
|
251 | return True | |||
|
252 | ||||
|
253 | return False | |||
|
254 | ||||
|
255 | if follow and not files: | |||
|
256 | ff = followfilter(onlyfirst=opts.get('follow_first')) | |||
|
257 | def want(rev): | |||
|
258 | if rev not in wanted: | |||
|
259 | return False | |||
|
260 | return ff.match(rev) | |||
|
261 | else: | |||
|
262 | def want(rev): | |||
|
263 | return rev in wanted | |||
|
264 | ||||
209 | for i, window in increasing_windows(0, len(revs)): |
|
265 | for i, window in increasing_windows(0, len(revs)): | |
210 | yield 'window', revs[0] < revs[-1], revs[-1] |
|
266 | yield 'window', revs[0] < revs[-1], revs[-1] | |
211 | nrevs = [rev for rev in revs[i:i+window] |
|
267 | nrevs = [rev for rev in revs[i:i+window] if want(rev)] | |
212 | if rev in wanted] |
|
|||
213 | srevs = list(nrevs) |
|
268 | srevs = list(nrevs) | |
214 | srevs.sort() |
|
269 | srevs.sort() | |
215 | for rev in srevs: |
|
270 | for rev in srevs: | |
@@ -1041,7 +1096,7 b' def commit(ui, repo, *pats, **opts):' | |||||
1041 | If no commit message is specified, the editor configured in your hgrc |
|
1096 | If no commit message is specified, the editor configured in your hgrc | |
1042 | or in the EDITOR environment variable is started to enter a message. |
|
1097 | or in the EDITOR environment variable is started to enter a message. | |
1043 | """ |
|
1098 | """ | |
1044 |
message = logmessage( |
|
1099 | message = logmessage(opts) | |
1045 |
|
1100 | |||
1046 | if opts['addremove']: |
|
1101 | if opts['addremove']: | |
1047 | addremove_lock(ui, repo, pats, opts) |
|
1102 | addremove_lock(ui, repo, pats, opts) | |
@@ -1972,8 +2027,14 b' def log(ui, repo, *pats, **opts):' | |||||
1972 | project. |
|
2027 | project. | |
1973 |
|
2028 | |||
1974 | File history is shown without following rename or copy history of |
|
2029 | File history is shown without following rename or copy history of | |
1975 |
files. Use -f/--follow to follow history across |
|
2030 | files. Use -f/--follow with a file name to follow history across | |
1976 | copies. |
|
2031 | renames and copies. --follow without a file name will only show | |
|
2032 | ancestors or descendants of the starting revision. --follow-first | |||
|
2033 | only follows the first parent of merge revisions. | |||
|
2034 | ||||
|
2035 | If no revision range is specified, the default is tip:0 unless | |||
|
2036 | --follow is set, in which case the working directory parent is | |||
|
2037 | used as the starting revision. | |||
1977 |
|
2038 | |||
1978 | By default this command outputs: changeset id and hash, tags, |
|
2039 | By default this command outputs: changeset id and hash, tags, | |
1979 | non-trivial parents, user, date and time, and a summary for each |
|
2040 | non-trivial parents, user, date and time, and a summary for each | |
@@ -2728,8 +2789,8 b' def tag(ui, repo, name, rev_=None, **opt' | |||||
2728 | necessary. The file '.hg/localtags' is used for local tags (not |
|
2789 | necessary. The file '.hg/localtags' is used for local tags (not | |
2729 | shared among repositories). |
|
2790 | shared among repositories). | |
2730 | """ |
|
2791 | """ | |
2731 |
if name |
|
2792 | if name in ['tip', '.']: | |
2732 |
raise util.Abort(_("the name ' |
|
2793 | raise util.Abort(_("the name '%s' is reserved") % name) | |
2733 | if rev_ is not None: |
|
2794 | if rev_ is not None: | |
2734 | ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, " |
|
2795 | ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, " | |
2735 | "please use 'hg tag [-r REV] NAME' instead\n")) |
|
2796 | "please use 'hg tag [-r REV] NAME' instead\n")) | |
@@ -3087,7 +3148,9 b' table = {' | |||||
3087 | (log, |
|
3148 | (log, | |
3088 | [('b', 'branches', None, _('show branches')), |
|
3149 | [('b', 'branches', None, _('show branches')), | |
3089 | ('f', 'follow', None, |
|
3150 | ('f', 'follow', None, | |
3090 | _('follow file history across copies and renames')), |
|
3151 | _('follow changeset history, or file history across copies and renames')), | |
|
3152 | ('', 'follow-first', None, | |||
|
3153 | _('only follow the first parent of merge changesets')), | |||
3091 | ('k', 'keyword', [], _('search for a keyword')), |
|
3154 | ('k', 'keyword', [], _('search for a keyword')), | |
3092 | ('l', 'limit', '', _('limit number of changes displayed')), |
|
3155 | ('l', 'limit', '', _('limit number of changes displayed')), | |
3093 | ('r', 'rev', [], _('show the specified revision or range')), |
|
3156 | ('r', 'rev', [], _('show the specified revision or range')), |
@@ -292,6 +292,10 b' class localrepository(repo.repository):' | |||||
292 | try: |
|
292 | try: | |
293 | return self.tags()[key] |
|
293 | return self.tags()[key] | |
294 | except KeyError: |
|
294 | except KeyError: | |
|
295 | if key == '.': | |||
|
296 | key = self.dirstate.parents()[0] | |||
|
297 | if key == nullid: | |||
|
298 | raise repo.RepoError(_("no revision checked out")) | |||
295 | try: |
|
299 | try: | |
296 | return self.changelog.lookup(key) |
|
300 | return self.changelog.lookup(key) | |
297 | except: |
|
301 | except: | |
@@ -1693,6 +1697,7 b' class localrepository(repo.repository):' | |||||
1693 |
|
1697 | |||
1694 | return newheads - oldheads + 1 |
|
1698 | return newheads - oldheads + 1 | |
1695 |
|
1699 | |||
|
1700 | ||||
1696 | def stream_in(self, remote): |
|
1701 | def stream_in(self, remote): | |
1697 | fp = remote.stream_out() |
|
1702 | fp = remote.stream_out() | |
1698 | resp = int(fp.readline()) |
|
1703 | resp = int(fp.readline()) |
@@ -48,7 +48,8 b' def merge3(repo, fn, my, other, p1, p2):' | |||||
48 | return r |
|
48 | return r | |
49 |
|
49 | |||
50 | def update(repo, node, allow=False, force=False, choose=None, |
|
50 | def update(repo, node, allow=False, force=False, choose=None, | |
51 |
moddirstate=True, forcemerge=False, wlock=None, show_stats=True |
|
51 | moddirstate=True, forcemerge=False, wlock=None, show_stats=True, | |
|
52 | remind=True): | |||
52 | pl = repo.dirstate.parents() |
|
53 | pl = repo.dirstate.parents() | |
53 | if not force and pl[1] != nullid: |
|
54 | if not force and pl[1] != nullid: | |
54 | raise util.Abort(_("outstanding uncommitted merges")) |
|
55 | raise util.Abort(_("outstanding uncommitted merges")) | |
@@ -337,7 +338,7 b' def update(repo, node, allow=False, forc' | |||||
337 | " hg merge %s\n" |
|
338 | " hg merge %s\n" | |
338 | % (repo.changelog.rev(p1), |
|
339 | % (repo.changelog.rev(p1), | |
339 | repo.changelog.rev(p2)))) |
|
340 | repo.changelog.rev(p2)))) | |
340 |
el |
|
341 | elif remind: | |
341 | repo.ui.status(_("(branch merge, don't forget to commit)\n")) |
|
342 | repo.ui.status(_("(branch merge, don't forget to commit)\n")) | |
342 | elif failedmerge: |
|
343 | elif failedmerge: | |
343 | repo.ui.status(_("There are unresolved merges with" |
|
344 | repo.ui.status(_("There are unresolved merges with" |
@@ -99,9 +99,9 b' def patch(strip, patchname, ui, cwd=None' | |||||
99 | patcher = find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
|
99 | patcher = find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') | |
100 | args = [] |
|
100 | args = [] | |
101 | if cwd: |
|
101 | if cwd: | |
102 |
args.append('-d |
|
102 | args.append('-d %s' % shellquote(cwd)) | |
103 |
fp = os.popen('%s %s -p%d < |
|
103 | fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip, | |
104 |
|
|
104 | shellquote(patchname))) | |
105 | files = {} |
|
105 | files = {} | |
106 | for line in fp: |
|
106 | for line in fp: | |
107 | line = line.rstrip() |
|
107 | line = line.rstrip() | |
@@ -611,6 +611,9 b" if os.name == 'nt':" | |||||
611 | def samestat(s1, s2): |
|
611 | def samestat(s1, s2): | |
612 | return False |
|
612 | return False | |
613 |
|
613 | |||
|
614 | def shellquote(s): | |||
|
615 | return '"%s"' % s.replace('"', '\\"') | |||
|
616 | ||||
614 | def explain_exit(code): |
|
617 | def explain_exit(code): | |
615 | return _("exited with status %d") % code, code |
|
618 | return _("exited with status %d") % code, code | |
616 |
|
619 | |||
@@ -700,6 +703,9 b' else:' | |||||
700 | else: |
|
703 | else: | |
701 | raise |
|
704 | raise | |
702 |
|
705 | |||
|
706 | def shellquote(s): | |||
|
707 | return "'%s'" % s.replace("'", "'\\''") | |||
|
708 | ||||
703 | def testpid(pid): |
|
709 | def testpid(pid): | |
704 | '''return False if pid dead, True if running or not sure''' |
|
710 | '''return False if pid dead, True if running or not sure''' | |
705 | try: |
|
711 | try: |
@@ -28,3 +28,38 b' echo % one rename' | |||||
28 | hg log -vf a |
|
28 | hg log -vf a | |
29 | echo % many renames |
|
29 | echo % many renames | |
30 | hg log -vf e |
|
30 | hg log -vf e | |
|
31 | ||||
|
32 | # log --follow tests | |||
|
33 | hg init ../follow | |||
|
34 | cd ../follow | |||
|
35 | echo base > base | |||
|
36 | hg ci -Ambase -d '1 0' | |||
|
37 | ||||
|
38 | echo r1 >> base | |||
|
39 | hg ci -Amr1 -d '1 0' | |||
|
40 | echo r2 >> base | |||
|
41 | hg ci -Amr2 -d '1 0' | |||
|
42 | ||||
|
43 | hg up -C 1 | |||
|
44 | echo b1 > b1 | |||
|
45 | hg ci -Amb1 -d '1 0' | |||
|
46 | ||||
|
47 | echo % log -f | |||
|
48 | hg log -f | |||
|
49 | ||||
|
50 | hg up -C 0 | |||
|
51 | echo b2 > b2 | |||
|
52 | hg ci -Amb2 -d '1 0' | |||
|
53 | ||||
|
54 | echo % log -f -r 1:tip | |||
|
55 | hg log -f -r 1:tip | |||
|
56 | ||||
|
57 | hg up -C 3 | |||
|
58 | hg merge tip | |||
|
59 | hg ci -mm12 -d '1 0' | |||
|
60 | ||||
|
61 | echo postm >> b1 | |||
|
62 | hg ci -Amb1.1 -d'1 0' | |||
|
63 | ||||
|
64 | echo % log --follow-first | |||
|
65 | hg log --follow-first |
@@ -76,3 +76,76 b' description:' | |||||
76 | a |
|
76 | a | |
77 |
|
77 | |||
78 |
|
78 | |||
|
79 | adding base | |||
|
80 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
81 | adding b1 | |||
|
82 | % log -f | |||
|
83 | changeset: 3:e62f78d544b4 | |||
|
84 | tag: tip | |||
|
85 | parent: 1:3d5bf5654eda | |||
|
86 | user: test | |||
|
87 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
88 | summary: b1 | |||
|
89 | ||||
|
90 | changeset: 1:3d5bf5654eda | |||
|
91 | user: test | |||
|
92 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
93 | summary: r1 | |||
|
94 | ||||
|
95 | changeset: 0:67e992f2c4f3 | |||
|
96 | user: test | |||
|
97 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
98 | summary: base | |||
|
99 | ||||
|
100 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
101 | adding b2 | |||
|
102 | % log -f -r 1:tip | |||
|
103 | changeset: 1:3d5bf5654eda | |||
|
104 | user: test | |||
|
105 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
106 | summary: r1 | |||
|
107 | ||||
|
108 | changeset: 2:60c670bf5b30 | |||
|
109 | user: test | |||
|
110 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
111 | summary: r2 | |||
|
112 | ||||
|
113 | changeset: 3:e62f78d544b4 | |||
|
114 | parent: 1:3d5bf5654eda | |||
|
115 | user: test | |||
|
116 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
117 | summary: b1 | |||
|
118 | ||||
|
119 | 2 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
120 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
121 | (branch merge, don't forget to commit) | |||
|
122 | % log --follow-first | |||
|
123 | changeset: 6:2404bbcab562 | |||
|
124 | tag: tip | |||
|
125 | user: test | |||
|
126 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
127 | summary: b1.1 | |||
|
128 | ||||
|
129 | changeset: 5:302e9dd6890d | |||
|
130 | parent: 3:e62f78d544b4 | |||
|
131 | parent: 4:ddb82e70d1a1 | |||
|
132 | user: test | |||
|
133 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
134 | summary: m12 | |||
|
135 | ||||
|
136 | changeset: 3:e62f78d544b4 | |||
|
137 | parent: 1:3d5bf5654eda | |||
|
138 | user: test | |||
|
139 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
140 | summary: b1 | |||
|
141 | ||||
|
142 | changeset: 1:3d5bf5654eda | |||
|
143 | user: test | |||
|
144 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
145 | summary: r1 | |||
|
146 | ||||
|
147 | changeset: 0:67e992f2c4f3 | |||
|
148 | user: test | |||
|
149 | date: Thu Jan 01 00:00:01 1970 +0000 | |||
|
150 | summary: base | |||
|
151 |
General Comments 0
You need to be logged in to leave comments.
Login now