comparison hgext/fetch.py @ 7007:a6b74fbb5ce0

fetch: added support for named branches Previously, fetch didn't really work when there were multiple named branches in the repository. Now it tries to do the right thing(tm) in all situations.
author Sune Foldager <cryo@cyanite.org>
date Mon, 08 Sep 2008 12:55:46 +0200
parents b2bc2d984bac
children 6489ee64b522
comparison
equal deleted inserted replaced
7006:92d44ec32430 7007:a6b74fbb5ce0
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 branch 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 to include the new changes. 21 working directory is updated to include the new changes.
22 22
23 When a merge occurs, the newly pulled changes are assumed to be 23 When a merge occurs, the newly pulled changes are assumed to be
24 "authoritative". The head of the new changes is used as the first 24 "authoritative". The head of the new changes is used as the first
31 date = opts.get('date') 31 date = opts.get('date')
32 if date: 32 if date:
33 opts['date'] = util.parsedate(date) 33 opts['date'] = util.parsedate(date)
34 34
35 parent, p2 = repo.dirstate.parents() 35 parent, p2 = repo.dirstate.parents()
36 if parent != repo.changelog.tip(): 36 branch = repo[parent].branch()
37 raise util.Abort(_('working dir not at tip ' 37 if parent != repo[branch].node():
38 '(use "hg update" to check out tip)')) 38 raise util.Abort(_('working dir not at branch tip '
39 '(use "hg update" to check out branch tip)'))
39 40
40 if p2 != nullid: 41 if p2 != nullid:
41 raise util.Abort(_('outstanding uncommitted merge')) 42 raise util.Abort(_('outstanding uncommitted merge'))
42 43
43 wlock = lock = None 44 wlock = lock = None
48 49
49 if mod or add or rem: 50 if mod or add or rem:
50 raise util.Abort(_('outstanding uncommitted changes')) 51 raise util.Abort(_('outstanding uncommitted changes'))
51 if del_: 52 if del_:
52 raise util.Abort(_('working directory is missing some files')) 53 raise util.Abort(_('working directory is missing some files'))
53 if len(repo.heads()) > 1: 54 if len(repo.branchheads(branch)) > 1:
54 raise util.Abort(_('multiple heads in this repository ' 55 raise util.Abort(_('multiple heads in this branch '
55 '(use "hg heads" and "hg merge" to merge)')) 56 '(use "hg heads ." and "hg merge" to merge)'))
56 57
57 cmdutil.setremoteconfig(ui, opts) 58 cmdutil.setremoteconfig(ui, opts)
58 59
59 other = hg.repository(ui, ui.expandpath(source)) 60 other = hg.repository(ui, ui.expandpath(source))
60 ui.status(_('pulling from %s\n') % 61 ui.status(_('pulling from %s\n') %
65 raise util.Abort(_("fetch -r doesn't work for remote " 66 raise util.Abort(_("fetch -r doesn't work for remote "
66 "repositories yet")) 67 "repositories yet"))
67 else: 68 else:
68 revs = [other.lookup(rev) for rev in opts['rev']] 69 revs = [other.lookup(rev) for rev in opts['rev']]
69 70
71 # Are there any changes at all?
70 modheads = repo.pull(other, heads=revs) 72 modheads = repo.pull(other, heads=revs)
71 if modheads == 0: 73 if modheads == 0:
72 return 0 74 return 0
73 if modheads == 1:
74 return hg.clean(repo, repo.changelog.tip())
75 75
76 newheads = repo.heads(parent) 76 # Is this a simple fast-forward along the current branch?
77 newchildren = [n for n in repo.heads(parent) if n != parent] 77 newheads = repo.branchheads(branch)
78 newchildren = repo.changelog.nodesbetween([parent], newheads)[2]
79 if len(newheads) == 1:
80 if newchildren[0] != parent:
81 return hg.clean(repo, newchildren[0])
82 else:
83 return
84
85 # Are there more than one additional branch heads?
86 newchildren = [n for n in newchildren if n != parent]
78 newparent = parent 87 newparent = parent
79 if newchildren: 88 if newchildren:
80 newparent = newchildren[0] 89 newparent = newchildren[0]
81 hg.clean(repo, newparent) 90 hg.clean(repo, newparent)
82 91 newheads = [n for n in newheads if n != newparent]
83 newheads = [n for n in repo.heads() if n != newparent]
84 if len(newheads) > 1: 92 if len(newheads) > 1:
85 ui.status(_('not merging with %d other new heads ' 93 ui.status(_('not merging with %d other new branch heads '
86 '(use "hg heads" and "hg merge" to merge them)') % 94 '(use "hg heads ." and "hg merge" to merge them)\n') %
87 (len(newheads) - 1)) 95 (len(newheads) - 1))
88 return 96 return
97
98 # Otherwise, let's merge.
89 err = False 99 err = False
90
91 if newheads: 100 if newheads:
92 # By default, we consider the repository we're pulling 101 # By default, we consider the repository we're pulling
93 # *from* as authoritative, so we merge our changes into 102 # *from* as authoritative, so we merge our changes into
94 # theirs. 103 # theirs.
95 if opts['switch_parent']: 104 if opts['switch_parent']: