|
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') |
|
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 if len(repo.heads()) > 1: |
|
74 raise util.Abort(_('multiple heads in this repository ' |
|
75 '(use "hg heads" and "hg merge" to merge them)')) |
|
76 return pull() |
|
77 |
|
78 cmdtable = { |
|
79 'fetch': |
|
80 (fetch, |
|
81 [('e', 'ssh', '', _('specify ssh command to use')), |
|
82 ('m', 'message', '', _('use <text> as commit message')), |
|
83 ('l', 'logfile', '', _('read the commit message from <file>')), |
|
84 ('d', 'date', '', _('record datecode as commit date')), |
|
85 ('u', 'user', '', _('record user as commiter')), |
|
86 ('r', 'rev', [], _('a specific revision you would like to pull')), |
|
87 ('f', 'force-editor', None, _('edit commit message')), |
|
88 ('', 'remotecmd', '', _('hg command to run on the remote side'))], |
|
89 'hg fetch [SOURCE]'), |
|
90 } |