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']: |