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