##// END OF EJS Templates
fetch: lock repo across pull and commit
Vadim Gelfer -
r2825:0496cfb0 default
parent child Browse files
Show More
@@ -1,93 +1,97
1 # fetch.py - pull and merge remote changes
1 # fetch.py - pull and merge remote changes
2 #
2 #
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from mercurial.demandload import *
8 from mercurial.demandload import *
9 from mercurial.i18n import gettext as _
9 from mercurial.i18n import gettext as _
10 from mercurial.node import *
10 from mercurial.node import *
11 demandload(globals(), 'mercurial:commands,hg,node,util')
11 demandload(globals(), 'mercurial:commands,hg,node,util')
12
12
13 def fetch(ui, repo, source='default', **opts):
13 def fetch(ui, repo, source='default', **opts):
14 '''Pull changes from a remote repository, merge new changes if needed.
14 '''Pull changes from a remote repository, merge new changes if needed.
15
15
16 This finds all changes from the repository at the specified path
16 This finds all changes from the repository at the specified path
17 or URL and adds them to the local repository.
17 or URL and adds them to the local repository.
18
18
19 If the pulled changes add a new head, the head is automatically
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
20 merged, and the result of the merge is committed. Otherwise, the
21 working directory is updated.'''
21 working directory is updated.'''
22
22
23 def postincoming(other, modheads):
23 def postincoming(other, modheads):
24 if modheads == 0:
24 if modheads == 0:
25 return 0
25 return 0
26 if modheads == 1:
26 if modheads == 1:
27 return hg.update(repo, repo.changelog.tip())
27 return hg.update(repo, repo.changelog.tip())
28 newheads = repo.heads(parent)
28 newheads = repo.heads(parent)
29 newchildren = [n for n in repo.heads(parent) if n != parent]
29 newchildren = [n for n in repo.heads(parent) if n != parent]
30 newparent = parent
30 newparent = parent
31 if newchildren:
31 if newchildren:
32 newparent = newchildren[0]
32 newparent = newchildren[0]
33 hg.update(repo, newparent)
33 hg.update(repo, newparent)
34 newheads = [n for n in repo.heads() if n != newparent]
34 newheads = [n for n in repo.heads() if n != newparent]
35 err = False
35 err = False
36 if newheads:
36 if newheads:
37 ui.status(_('merging with new head %d:%s\n') %
37 ui.status(_('merging with new head %d:%s\n') %
38 (repo.changelog.rev(newheads[0]), short(newheads[0])))
38 (repo.changelog.rev(newheads[0]), short(newheads[0])))
39 err = hg.update(repo, newheads[0], allow=True, remind=False)
39 err = hg.update(repo, newheads[0], allow=True, remind=False)
40 if not err and len(newheads) > 1:
40 if not err and len(newheads) > 1:
41 ui.status(_('not merging with %d other new heads '
41 ui.status(_('not merging with %d other new heads '
42 '(use "hg heads" and "hg merge" to merge them)') %
42 '(use "hg heads" and "hg merge" to merge them)') %
43 (len(newheads) - 1))
43 (len(newheads) - 1))
44 if not err:
44 if not err:
45 mod, add, rem = repo.status()[:3]
45 mod, add, rem = repo.status()[:3]
46 message = (commands.logmessage(opts) or
46 message = (commands.logmessage(opts) or
47 (_('Automated merge with %s') % other.url()))
47 (_('Automated merge with %s') % other.url()))
48 n = repo.commit(mod + add + rem, message,
48 n = repo.commit(mod + add + rem, message,
49 opts['user'], opts['date'],
49 opts['user'], opts['date'], lock=lock,
50 force_editor=opts.get('force_editor'))
50 force_editor=opts.get('force_editor'))
51 ui.status(_('new changeset %d:%s merges remote changes '
51 ui.status(_('new changeset %d:%s merges remote changes '
52 'with local\n') % (repo.changelog.rev(n),
52 'with local\n') % (repo.changelog.rev(n),
53 short(n)))
53 short(n)))
54 def pull():
54 def pull():
55 commands.setremoteconfig(ui, opts)
55 commands.setremoteconfig(ui, opts)
56
56
57 other = hg.repository(ui, ui.expandpath(source))
57 other = hg.repository(ui, ui.expandpath(source))
58 ui.status(_('pulling from %s\n') % source)
58 ui.status(_('pulling from %s\n') % source)
59 revs = None
59 revs = None
60 if opts['rev'] and not other.local():
60 if opts['rev'] and not other.local():
61 raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
61 raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
62 elif opts['rev']:
62 elif opts['rev']:
63 revs = [other.lookup(rev) for rev in opts['rev']]
63 revs = [other.lookup(rev) for rev in opts['rev']]
64 modheads = repo.pull(other, heads=revs)
64 modheads = repo.pull(other, heads=revs, lock=lock)
65 return postincoming(other, modheads)
65 return postincoming(other, modheads)
66
66
67 parent, p2 = repo.dirstate.parents()
67 parent, p2 = repo.dirstate.parents()
68 if parent != repo.changelog.tip():
68 if parent != repo.changelog.tip():
69 raise util.Abort(_('working dir not at tip '
69 raise util.Abort(_('working dir not at tip '
70 '(use "hg update" to check out tip)'))
70 '(use "hg update" to check out tip)'))
71 if p2 != nullid:
71 if p2 != nullid:
72 raise util.Abort(_('outstanding uncommitted merge'))
72 raise util.Abort(_('outstanding uncommitted merge'))
73 mod, add, rem = repo.status()[:3]
73 mod, add, rem = repo.status()[:3]
74 if mod or add or rem:
74 if mod or add or rem:
75 raise util.Abort(_('outstanding uncommitted changes'))
75 raise util.Abort(_('outstanding uncommitted changes'))
76 if len(repo.heads()) > 1:
76 if len(repo.heads()) > 1:
77 raise util.Abort(_('multiple heads in this repository '
77 raise util.Abort(_('multiple heads in this repository '
78 '(use "hg heads" and "hg merge" to merge them)'))
78 '(use "hg heads" and "hg merge" to merge them)'))
79 lock = repo.lock()
80 try:
79 return pull()
81 return pull()
82 finally:
83 lock.release()
80
84
81 cmdtable = {
85 cmdtable = {
82 'fetch':
86 'fetch':
83 (fetch,
87 (fetch,
84 [('e', 'ssh', '', _('specify ssh command to use')),
88 [('e', 'ssh', '', _('specify ssh command to use')),
85 ('m', 'message', '', _('use <text> as commit message')),
89 ('m', 'message', '', _('use <text> as commit message')),
86 ('l', 'logfile', '', _('read the commit message from <file>')),
90 ('l', 'logfile', '', _('read the commit message from <file>')),
87 ('d', 'date', '', _('record datecode as commit date')),
91 ('d', 'date', '', _('record datecode as commit date')),
88 ('u', 'user', '', _('record user as commiter')),
92 ('u', 'user', '', _('record user as commiter')),
89 ('r', 'rev', [], _('a specific revision you would like to pull')),
93 ('r', 'rev', [], _('a specific revision you would like to pull')),
90 ('f', 'force-editor', None, _('edit commit message')),
94 ('f', 'force-editor', None, _('edit commit message')),
91 ('', 'remotecmd', '', _('hg command to run on the remote side'))],
95 ('', 'remotecmd', '', _('hg command to run on the remote side'))],
92 'hg fetch [SOURCE]'),
96 'hg fetch [SOURCE]'),
93 }
97 }
General Comments 0
You need to be logged in to leave comments. Login now