##// END OF EJS Templates
fetch: switch the default parent used for a merge...
Bryan O'Sullivan -
r6206:0b6f1249 default
parent child Browse files
Show More
@@ -1,102 +1,121
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.i18n import _
8 from mercurial.i18n import _
9 from mercurial.node import *
9 from mercurial.node import *
10 from mercurial import commands, cmdutil, hg, node, util
10 from mercurial import commands, cmdutil, hg, node, util
11
11
12 def fetch(ui, repo, source='default', **opts):
12 def fetch(ui, repo, source='default', **opts):
13 '''Pull changes from a remote repository, merge new changes if needed.
13 '''Pull changes from a remote repository, merge new changes if needed.
14
14
15 This finds all changes from the repository at the specified path
15 This finds all changes from the repository at the specified path
16 or URL and adds them to the local repository.
16 or URL and adds them to the local repository.
17
17
18 If the pulled changes add a new head, the head is automatically
18 If the pulled changes add a new head, the head is automatically
19 merged, and the result of the merge is committed. Otherwise, the
19 merged, and the result of the merge is committed. Otherwise, the
20 working directory is updated.
20 working directory is updated to include the new changes.
21
22 When a merge occurs, the newly pulled changes are assumed to be
23 "authoritative". The head of the new changes is used as the first
24 parent, with local changes as the second. To switch the merge
25 order, use --switch-parent.
21
26
22 See 'hg help dates' for a list of formats valid for -d/--date.
27 See 'hg help dates' for a list of formats valid for -d/--date.
23 '''
28 '''
24
29
25 def postincoming(other, modheads):
30 def postincoming(other, modheads):
26 if modheads == 0:
31 if modheads == 0:
27 return 0
32 return 0
28 if modheads == 1:
33 if modheads == 1:
29 return hg.clean(repo, repo.changelog.tip())
34 return hg.clean(repo, repo.changelog.tip())
30 newheads = repo.heads(parent)
35 newheads = repo.heads(parent)
31 newchildren = [n for n in repo.heads(parent) if n != parent]
36 newchildren = [n for n in repo.heads(parent) if n != parent]
32 newparent = parent
37 newparent = parent
33 if newchildren:
38 if newchildren:
34 newparent = newchildren[0]
39 newparent = newchildren[0]
35 hg.clean(repo, newparent)
40 hg.clean(repo, newparent)
36 newheads = [n for n in repo.heads() if n != newparent]
41 newheads = [n for n in repo.heads() if n != newparent]
37 err = False
42 if len(newheads) > 1:
38 if newheads:
39 ui.status(_('merging with new head %d:%s\n') %
40 (repo.changelog.rev(newheads[0]), short(newheads[0])))
41 err = hg.merge(repo, newheads[0], remind=False)
42 if not err and len(newheads) > 1:
43 ui.status(_('not merging with %d other new heads '
43 ui.status(_('not merging with %d other new heads '
44 '(use "hg heads" and "hg merge" to merge them)') %
44 '(use "hg heads" and "hg merge" to merge them)') %
45 (len(newheads) - 1))
45 (len(newheads) - 1))
46 return
47 err = False
48 if newheads:
49 # By default, we consider the repository we're pulling
50 # *from* as authoritative, so we merge our changes into
51 # theirs.
52 if opts['switch_parent']:
53 firstparent, secondparent = newparent, newheads[0]
54 else:
55 firstparent, secondparent = newheads[0], newparent
56 ui.status(_('updating to %d:%s\n') %
57 (repo.changelog.rev(firstparent),
58 short(firstparent)))
59 hg.clean(repo, firstparent)
60 ui.status(_('merging with %d:%s\n') %
61 (repo.changelog.rev(secondparent), short(secondparent)))
62 err = hg.merge(repo, secondparent, remind=False)
46 if not err:
63 if not err:
47 mod, add, rem = repo.status()[:3]
64 mod, add, rem = repo.status()[:3]
48 message = (cmdutil.logmessage(opts) or
65 message = (cmdutil.logmessage(opts) or
49 (_('Automated merge with %s') %
66 (_('Automated merge with %s') %
50 util.removeauth(other.url())))
67 util.removeauth(other.url())))
51 n = repo.commit(mod + add + rem, message,
68 n = repo.commit(mod + add + rem, message,
52 opts['user'], opts['date'],
69 opts['user'], opts['date'],
53 force_editor=opts.get('force_editor'))
70 force_editor=opts.get('force_editor'))
54 ui.status(_('new changeset %d:%s merges remote changes '
71 ui.status(_('new changeset %d:%s merges remote changes '
55 'with local\n') % (repo.changelog.rev(n),
72 'with local\n') % (repo.changelog.rev(n),
56 short(n)))
73 short(n)))
74
57 def pull():
75 def pull():
58 cmdutil.setremoteconfig(ui, opts)
76 cmdutil.setremoteconfig(ui, opts)
59
77
60 other = hg.repository(ui, ui.expandpath(source))
78 other = hg.repository(ui, ui.expandpath(source))
61 ui.status(_('pulling from %s\n') %
79 ui.status(_('pulling from %s\n') %
62 util.hidepassword(ui.expandpath(source)))
80 util.hidepassword(ui.expandpath(source)))
63 revs = None
81 revs = None
64 if opts['rev'] and not other.local():
82 if opts['rev'] and not other.local():
65 raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
83 raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
66 elif opts['rev']:
84 elif opts['rev']:
67 revs = [other.lookup(rev) for rev in opts['rev']]
85 revs = [other.lookup(rev) for rev in opts['rev']]
68 modheads = repo.pull(other, heads=revs)
86 modheads = repo.pull(other, heads=revs)
69 return postincoming(other, modheads)
87 return postincoming(other, modheads)
70
88
71 date = opts.get('date')
89 date = opts.get('date')
72 if date:
90 if date:
73 opts['date'] = util.parsedate(date)
91 opts['date'] = util.parsedate(date)
74
92
75 parent, p2 = repo.dirstate.parents()
93 parent, p2 = repo.dirstate.parents()
76 if parent != repo.changelog.tip():
94 if parent != repo.changelog.tip():
77 raise util.Abort(_('working dir not at tip '
95 raise util.Abort(_('working dir not at tip '
78 '(use "hg update" to check out tip)'))
96 '(use "hg update" to check out tip)'))
79 if p2 != nullid:
97 if p2 != nullid:
80 raise util.Abort(_('outstanding uncommitted merge'))
98 raise util.Abort(_('outstanding uncommitted merge'))
81 wlock = lock = None
99 wlock = lock = None
82 try:
100 try:
83 wlock = repo.wlock()
101 wlock = repo.wlock()
84 lock = repo.lock()
102 lock = repo.lock()
85 mod, add, rem = repo.status()[:3]
103 mod, add, rem = repo.status()[:3]
86 if mod or add or rem:
104 if mod or add or rem:
87 raise util.Abort(_('outstanding uncommitted changes'))
105 raise util.Abort(_('outstanding uncommitted changes'))
88 if len(repo.heads()) > 1:
106 if len(repo.heads()) > 1:
89 raise util.Abort(_('multiple heads in this repository '
107 raise util.Abort(_('multiple heads in this repository '
90 '(use "hg heads" and "hg merge" to merge)'))
108 '(use "hg heads" and "hg merge" to merge)'))
91 return pull()
109 return pull()
92 finally:
110 finally:
93 del lock, wlock
111 del lock, wlock
94
112
95 cmdtable = {
113 cmdtable = {
96 'fetch':
114 'fetch':
97 (fetch,
115 (fetch,
98 [('r', 'rev', [], _('a specific revision you would like to pull')),
116 [('r', 'rev', [], _('a specific revision you would like to pull')),
99 ('f', 'force-editor', None, _('edit commit message')),
117 ('f', 'force-editor', None, _('edit commit message')),
118 ('', 'switch-parent', None, _('switch parents when merging')),
100 ] + commands.commitopts + commands.commitopts2 + commands.remoteopts,
119 ] + commands.commitopts + commands.commitopts2 + commands.remoteopts,
101 _('hg fetch [SOURCE]')),
120 _('hg fetch [SOURCE]')),
102 }
121 }
@@ -1,39 +1,52
1 #!/bin/sh
1 #!/bin/sh
2
2
3 echo "[extensions]" >> $HGRCPATH
3 echo "[extensions]" >> $HGRCPATH
4 echo "fetch=" >> $HGRCPATH
4 echo "fetch=" >> $HGRCPATH
5
5
6 hg init a
6 hg init a
7 echo a > a/a
7 echo a > a/a
8 hg --cwd a commit -d '1 0' -Ama
8 hg --cwd a commit -d '1 0' -Ama
9
9
10 hg clone a b
10 hg clone a b
11 hg clone a c
11 hg clone a c
12
12
13 echo b > a/b
13 echo b > a/b
14 hg --cwd a commit -d '2 0' -Amb
14 hg --cwd a commit -d '2 0' -Amb
15 hg --cwd a parents -q
15 hg --cwd a parents -q
16
16
17 echo % should pull one change
17 echo % should pull one change
18 hg --cwd b fetch ../a
18 hg --cwd b fetch ../a
19 hg --cwd b parents -q
19 hg --cwd b parents -q
20
20
21 echo c > c/c
21 echo c > c/c
22 hg --cwd c commit -d '3 0' -Amc
22 hg --cwd c commit -d '3 0' -Amc
23
23
24 hg clone c d
24 hg clone c d
25 hg clone c e
25 hg clone c e
26
26
27 echo % should merge c into a
27 hg --cwd c fetch -d '4 0' -m 'automated merge' ../a
28 hg --cwd c fetch -d '4 0' -m 'automated merge' ../a
28 ls c
29 ls c
29
30
30 hg --cwd a serve -a localhost -p $HGPORT -d --pid-file=hg.pid
31 hg --cwd a serve -a localhost -p $HGPORT -d --pid-file=hg.pid
31 cat a/hg.pid >> "$DAEMON_PIDS"
32 cat a/hg.pid >> "$DAEMON_PIDS"
32
33
33 echo '% fetch over http, no auth'
34 echo '% fetch over http, no auth'
34 hg --cwd d fetch -d '5 0' http://localhost:$HGPORT/
35 hg --cwd d fetch -d '5 0' http://localhost:$HGPORT/
35 hg --cwd d tip --template '{desc}\n'
36 hg --cwd d tip --template '{desc}\n'
36
37
37 echo '% fetch over http with auth (should be hidden in desc)'
38 echo '% fetch over http with auth (should be hidden in desc)'
38 hg --cwd e fetch -d '5 0' http://user:password@localhost:$HGPORT/
39 hg --cwd e fetch -d '5 0' http://user:password@localhost:$HGPORT/
39 hg --cwd e tip --template '{desc}\n'
40 hg --cwd e tip --template '{desc}\n'
41
42 hg clone a f
43 hg clone a g
44
45 echo f > f/f
46 hg --cwd f ci -d '6 0' -Amf
47
48 echo g > g/g
49 hg --cwd g ci -d '6 0' -Amg
50
51 echo % should merge f into g
52 hg --cwd g fetch --switch ../f
@@ -1,51 +1,73
1 adding a
1 adding a
2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 adding b
4 adding b
5 1:97d72e5f12c7
5 1:97d72e5f12c7
6 % should pull one change
6 % should pull one change
7 pulling from ../a
7 pulling from ../a
8 searching for changes
8 searching for changes
9 adding changesets
9 adding changesets
10 adding manifests
10 adding manifests
11 adding file changes
11 adding file changes
12 added 1 changesets with 1 changes to 1 files
12 added 1 changesets with 1 changes to 1 files
13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 1:97d72e5f12c7
14 1:97d72e5f12c7
15 adding c
15 adding c
16 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 % should merge c into a
18 pulling from ../a
19 pulling from ../a
19 searching for changes
20 searching for changes
20 adding changesets
21 adding changesets
21 adding manifests
22 adding manifests
22 adding file changes
23 adding file changes
23 added 1 changesets with 1 changes to 1 files (+1 heads)
24 added 1 changesets with 1 changes to 1 files (+1 heads)
24 merging with new head 2:97d72e5f12c7
25 updating to 2:97d72e5f12c7
26 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 merging with 1:5e056962225c
25 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 new changeset 3:cd3a41621cf0 merges remote changes with local
29 new changeset 3:cd3a41621cf0 merges remote changes with local
27 a
30 a
28 b
31 b
29 c
32 c
30 % fetch over http, no auth
33 % fetch over http, no auth
31 pulling from http://localhost:20059/
34 pulling from http://localhost:20059/
32 searching for changes
35 searching for changes
33 adding changesets
36 adding changesets
34 adding manifests
37 adding manifests
35 adding file changes
38 adding file changes
36 added 1 changesets with 1 changes to 1 files (+1 heads)
39 added 1 changesets with 1 changes to 1 files (+1 heads)
37 merging with new head 2:97d72e5f12c7
40 updating to 2:97d72e5f12c7
41 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
42 merging with 1:5e056962225c
38 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
39 new changeset 3:0b6439e938f9 merges remote changes with local
44 new changeset 3:0b6439e938f9 merges remote changes with local
40 Automated merge with http://localhost:20059/
45 Automated merge with http://localhost:20059/
41 % fetch over http with auth (should be hidden in desc)
46 % fetch over http with auth (should be hidden in desc)
42 pulling from http://user:***@localhost:20059/
47 pulling from http://user:***@localhost:20059/
43 searching for changes
48 searching for changes
44 adding changesets
49 adding changesets
45 adding manifests
50 adding manifests
46 adding file changes
51 adding file changes
47 added 1 changesets with 1 changes to 1 files (+1 heads)
52 added 1 changesets with 1 changes to 1 files (+1 heads)
48 merging with new head 2:97d72e5f12c7
53 updating to 2:97d72e5f12c7
54 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
55 merging with 1:5e056962225c
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 new changeset 3:0b6439e938f9 merges remote changes with local
57 new changeset 3:0b6439e938f9 merges remote changes with local
51 Automated merge with http://localhost:20059/
58 Automated merge with http://localhost:20059/
59 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 adding f
62 adding g
63 % should merge f into g
64 pulling from ../f
65 searching for changes
66 adding changesets
67 adding manifests
68 adding file changes
69 added 1 changesets with 1 changes to 1 files (+1 heads)
70 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 merging with 3:cc6a3744834d
72 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 new changeset 4:96d2275e70b4 merges remote changes with local
General Comments 0
You need to be logged in to leave comments. Login now