##// END OF EJS Templates
share: fix typo to drop 'shared' requirement on unshare...
Yuya Nishihara -
r31211:ecbd378d default
parent child Browse files
Show More
@@ -1,220 +1,220 b''
1 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
1 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6 '''share a common history between several working directories
6 '''share a common history between several working directories
7
7
8 Automatic Pooled Storage for Clones
8 Automatic Pooled Storage for Clones
9 -----------------------------------
9 -----------------------------------
10
10
11 When this extension is active, :hg:`clone` can be configured to
11 When this extension is active, :hg:`clone` can be configured to
12 automatically share/pool storage across multiple clones. This
12 automatically share/pool storage across multiple clones. This
13 mode effectively converts :hg:`clone` to :hg:`clone` + :hg:`share`.
13 mode effectively converts :hg:`clone` to :hg:`clone` + :hg:`share`.
14 The benefit of using this mode is the automatic management of
14 The benefit of using this mode is the automatic management of
15 store paths and intelligent pooling of related repositories.
15 store paths and intelligent pooling of related repositories.
16
16
17 The following ``share.`` config options influence this feature:
17 The following ``share.`` config options influence this feature:
18
18
19 ``share.pool``
19 ``share.pool``
20 Filesystem path where shared repository data will be stored. When
20 Filesystem path where shared repository data will be stored. When
21 defined, :hg:`clone` will automatically use shared repository
21 defined, :hg:`clone` will automatically use shared repository
22 storage instead of creating a store inside each clone.
22 storage instead of creating a store inside each clone.
23
23
24 ``share.poolnaming``
24 ``share.poolnaming``
25 How directory names in ``share.pool`` are constructed.
25 How directory names in ``share.pool`` are constructed.
26
26
27 "identity" means the name is derived from the first changeset in the
27 "identity" means the name is derived from the first changeset in the
28 repository. In this mode, different remotes share storage if their
28 repository. In this mode, different remotes share storage if their
29 root/initial changeset is identical. In this mode, the local shared
29 root/initial changeset is identical. In this mode, the local shared
30 repository is an aggregate of all encountered remote repositories.
30 repository is an aggregate of all encountered remote repositories.
31
31
32 "remote" means the name is derived from the source repository's
32 "remote" means the name is derived from the source repository's
33 path or URL. In this mode, storage is only shared if the path or URL
33 path or URL. In this mode, storage is only shared if the path or URL
34 requested in the :hg:`clone` command matches exactly to a repository
34 requested in the :hg:`clone` command matches exactly to a repository
35 that was cloned before.
35 that was cloned before.
36
36
37 The default naming mode is "identity."
37 The default naming mode is "identity."
38 '''
38 '''
39
39
40 from __future__ import absolute_import
40 from __future__ import absolute_import
41
41
42 import errno
42 import errno
43 from mercurial.i18n import _
43 from mercurial.i18n import _
44 from mercurial import (
44 from mercurial import (
45 bookmarks,
45 bookmarks,
46 cmdutil,
46 cmdutil,
47 commands,
47 commands,
48 error,
48 error,
49 extensions,
49 extensions,
50 hg,
50 hg,
51 txnutil,
51 txnutil,
52 util,
52 util,
53 )
53 )
54
54
55 repository = hg.repository
55 repository = hg.repository
56 parseurl = hg.parseurl
56 parseurl = hg.parseurl
57
57
58 cmdtable = {}
58 cmdtable = {}
59 command = cmdutil.command(cmdtable)
59 command = cmdutil.command(cmdtable)
60 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
60 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
61 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
61 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
62 # be specifying the version(s) of Mercurial they are tested with, or
62 # be specifying the version(s) of Mercurial they are tested with, or
63 # leave the attribute unspecified.
63 # leave the attribute unspecified.
64 testedwith = 'ships-with-hg-core'
64 testedwith = 'ships-with-hg-core'
65
65
66 @command('share',
66 @command('share',
67 [('U', 'noupdate', None, _('do not create a working directory')),
67 [('U', 'noupdate', None, _('do not create a working directory')),
68 ('B', 'bookmarks', None, _('also share bookmarks')),
68 ('B', 'bookmarks', None, _('also share bookmarks')),
69 ('', 'relative', None, _('point to source using a relative path '
69 ('', 'relative', None, _('point to source using a relative path '
70 '(EXPERIMENTAL)')),
70 '(EXPERIMENTAL)')),
71 ],
71 ],
72 _('[-U] [-B] SOURCE [DEST]'),
72 _('[-U] [-B] SOURCE [DEST]'),
73 norepo=True)
73 norepo=True)
74 def share(ui, source, dest=None, noupdate=False, bookmarks=False,
74 def share(ui, source, dest=None, noupdate=False, bookmarks=False,
75 relative=False):
75 relative=False):
76 """create a new shared repository
76 """create a new shared repository
77
77
78 Initialize a new repository and working directory that shares its
78 Initialize a new repository and working directory that shares its
79 history (and optionally bookmarks) with another repository.
79 history (and optionally bookmarks) with another repository.
80
80
81 .. note::
81 .. note::
82
82
83 using rollback or extensions that destroy/modify history (mq,
83 using rollback or extensions that destroy/modify history (mq,
84 rebase, etc.) can cause considerable confusion with shared
84 rebase, etc.) can cause considerable confusion with shared
85 clones. In particular, if two shared clones are both updated to
85 clones. In particular, if two shared clones are both updated to
86 the same changeset, and one of them destroys that changeset
86 the same changeset, and one of them destroys that changeset
87 with rollback, the other clone will suddenly stop working: all
87 with rollback, the other clone will suddenly stop working: all
88 operations will fail with "abort: working directory has unknown
88 operations will fail with "abort: working directory has unknown
89 parent". The only known workaround is to use debugsetparents on
89 parent". The only known workaround is to use debugsetparents on
90 the broken clone to reset it to a changeset that still exists.
90 the broken clone to reset it to a changeset that still exists.
91 """
91 """
92
92
93 return hg.share(ui, source, dest=dest, update=not noupdate,
93 return hg.share(ui, source, dest=dest, update=not noupdate,
94 bookmarks=bookmarks, relative=relative)
94 bookmarks=bookmarks, relative=relative)
95
95
96 @command('unshare', [], '')
96 @command('unshare', [], '')
97 def unshare(ui, repo):
97 def unshare(ui, repo):
98 """convert a shared repository to a normal one
98 """convert a shared repository to a normal one
99
99
100 Copy the store data to the repo and remove the sharedpath data.
100 Copy the store data to the repo and remove the sharedpath data.
101 """
101 """
102
102
103 if not repo.shared():
103 if not repo.shared():
104 raise error.Abort(_("this is not a shared repo"))
104 raise error.Abort(_("this is not a shared repo"))
105
105
106 destlock = lock = None
106 destlock = lock = None
107 lock = repo.lock()
107 lock = repo.lock()
108 try:
108 try:
109 # we use locks here because if we race with commit, we
109 # we use locks here because if we race with commit, we
110 # can end up with extra data in the cloned revlogs that's
110 # can end up with extra data in the cloned revlogs that's
111 # not pointed to by changesets, thus causing verify to
111 # not pointed to by changesets, thus causing verify to
112 # fail
112 # fail
113
113
114 destlock = hg.copystore(ui, repo, repo.path)
114 destlock = hg.copystore(ui, repo, repo.path)
115
115
116 sharefile = repo.join('sharedpath')
116 sharefile = repo.join('sharedpath')
117 util.rename(sharefile, sharefile + '.old')
117 util.rename(sharefile, sharefile + '.old')
118
118
119 repo.requirements.discard('sharedpath')
119 repo.requirements.discard('shared')
120 repo._writerequirements()
120 repo._writerequirements()
121 finally:
121 finally:
122 destlock and destlock.release()
122 destlock and destlock.release()
123 lock and lock.release()
123 lock and lock.release()
124
124
125 # update store, spath, svfs and sjoin of repo
125 # update store, spath, svfs and sjoin of repo
126 repo.unfiltered().__init__(repo.baseui, repo.root)
126 repo.unfiltered().__init__(repo.baseui, repo.root)
127
127
128 # Wrap clone command to pass auto share options.
128 # Wrap clone command to pass auto share options.
129 def clone(orig, ui, source, *args, **opts):
129 def clone(orig, ui, source, *args, **opts):
130 pool = ui.config('share', 'pool', None)
130 pool = ui.config('share', 'pool', None)
131 if pool:
131 if pool:
132 pool = util.expandpath(pool)
132 pool = util.expandpath(pool)
133
133
134 opts['shareopts'] = dict(
134 opts['shareopts'] = dict(
135 pool=pool,
135 pool=pool,
136 mode=ui.config('share', 'poolnaming', 'identity'),
136 mode=ui.config('share', 'poolnaming', 'identity'),
137 )
137 )
138
138
139 return orig(ui, source, *args, **opts)
139 return orig(ui, source, *args, **opts)
140
140
141 def extsetup(ui):
141 def extsetup(ui):
142 extensions.wrapfunction(bookmarks, '_getbkfile', getbkfile)
142 extensions.wrapfunction(bookmarks, '_getbkfile', getbkfile)
143 extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
143 extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
144 extensions.wrapfunction(bookmarks.bmstore, '_writerepo', writerepo)
144 extensions.wrapfunction(bookmarks.bmstore, '_writerepo', writerepo)
145 extensions.wrapcommand(commands.table, 'clone', clone)
145 extensions.wrapcommand(commands.table, 'clone', clone)
146
146
147 def _hassharedbookmarks(repo):
147 def _hassharedbookmarks(repo):
148 """Returns whether this repo has shared bookmarks"""
148 """Returns whether this repo has shared bookmarks"""
149 try:
149 try:
150 shared = repo.vfs.read('shared').splitlines()
150 shared = repo.vfs.read('shared').splitlines()
151 except IOError as inst:
151 except IOError as inst:
152 if inst.errno != errno.ENOENT:
152 if inst.errno != errno.ENOENT:
153 raise
153 raise
154 return False
154 return False
155 return hg.sharedbookmarks in shared
155 return hg.sharedbookmarks in shared
156
156
157 def _getsrcrepo(repo):
157 def _getsrcrepo(repo):
158 """
158 """
159 Returns the source repository object for a given shared repository.
159 Returns the source repository object for a given shared repository.
160 If repo is not a shared repository, return None.
160 If repo is not a shared repository, return None.
161 """
161 """
162 if repo.sharedpath == repo.path:
162 if repo.sharedpath == repo.path:
163 return None
163 return None
164
164
165 if util.safehasattr(repo, 'srcrepo') and repo.srcrepo:
165 if util.safehasattr(repo, 'srcrepo') and repo.srcrepo:
166 return repo.srcrepo
166 return repo.srcrepo
167
167
168 # the sharedpath always ends in the .hg; we want the path to the repo
168 # the sharedpath always ends in the .hg; we want the path to the repo
169 source = repo.vfs.split(repo.sharedpath)[0]
169 source = repo.vfs.split(repo.sharedpath)[0]
170 srcurl, branches = parseurl(source)
170 srcurl, branches = parseurl(source)
171 srcrepo = repository(repo.ui, srcurl)
171 srcrepo = repository(repo.ui, srcurl)
172 repo.srcrepo = srcrepo
172 repo.srcrepo = srcrepo
173 return srcrepo
173 return srcrepo
174
174
175 def getbkfile(orig, repo):
175 def getbkfile(orig, repo):
176 if _hassharedbookmarks(repo):
176 if _hassharedbookmarks(repo):
177 srcrepo = _getsrcrepo(repo)
177 srcrepo = _getsrcrepo(repo)
178 if srcrepo is not None:
178 if srcrepo is not None:
179 # just orig(srcrepo) doesn't work as expected, because
179 # just orig(srcrepo) doesn't work as expected, because
180 # HG_PENDING refers repo.root.
180 # HG_PENDING refers repo.root.
181 try:
181 try:
182 fp, pending = txnutil.trypending(repo.root, repo.vfs,
182 fp, pending = txnutil.trypending(repo.root, repo.vfs,
183 'bookmarks')
183 'bookmarks')
184 if pending:
184 if pending:
185 # only in this case, bookmark information in repo
185 # only in this case, bookmark information in repo
186 # is up-to-date.
186 # is up-to-date.
187 return fp
187 return fp
188 fp.close()
188 fp.close()
189 except IOError as inst:
189 except IOError as inst:
190 if inst.errno != errno.ENOENT:
190 if inst.errno != errno.ENOENT:
191 raise
191 raise
192
192
193 # otherwise, we should read bookmarks from srcrepo,
193 # otherwise, we should read bookmarks from srcrepo,
194 # because .hg/bookmarks in srcrepo might be already
194 # because .hg/bookmarks in srcrepo might be already
195 # changed via another sharing repo
195 # changed via another sharing repo
196 repo = srcrepo
196 repo = srcrepo
197
197
198 # TODO: Pending changes in repo are still invisible in
198 # TODO: Pending changes in repo are still invisible in
199 # srcrepo, because bookmarks.pending is written only into repo.
199 # srcrepo, because bookmarks.pending is written only into repo.
200 # See also https://www.mercurial-scm.org/wiki/SharedRepository
200 # See also https://www.mercurial-scm.org/wiki/SharedRepository
201 return orig(repo)
201 return orig(repo)
202
202
203 def recordchange(orig, self, tr):
203 def recordchange(orig, self, tr):
204 # Continue with write to local bookmarks file as usual
204 # Continue with write to local bookmarks file as usual
205 orig(self, tr)
205 orig(self, tr)
206
206
207 if _hassharedbookmarks(self._repo):
207 if _hassharedbookmarks(self._repo):
208 srcrepo = _getsrcrepo(self._repo)
208 srcrepo = _getsrcrepo(self._repo)
209 if srcrepo is not None:
209 if srcrepo is not None:
210 category = 'share-bookmarks'
210 category = 'share-bookmarks'
211 tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
211 tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
212
212
213 def writerepo(orig, self, repo):
213 def writerepo(orig, self, repo):
214 # First write local bookmarks file in case we ever unshare
214 # First write local bookmarks file in case we ever unshare
215 orig(self, repo)
215 orig(self, repo)
216
216
217 if _hassharedbookmarks(self._repo):
217 if _hassharedbookmarks(self._repo):
218 srcrepo = _getsrcrepo(self._repo)
218 srcrepo = _getsrcrepo(self._repo)
219 if srcrepo is not None:
219 if srcrepo is not None:
220 orig(self, srcrepo)
220 orig(self, srcrepo)
@@ -1,399 +1,401 b''
1 #require killdaemons
1 #require killdaemons
2
2
3 $ echo "[extensions]" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
4 $ echo "share = " >> $HGRCPATH
4 $ echo "share = " >> $HGRCPATH
5
5
6 prepare repo1
6 prepare repo1
7
7
8 $ hg init repo1
8 $ hg init repo1
9 $ cd repo1
9 $ cd repo1
10 $ echo a > a
10 $ echo a > a
11 $ hg commit -A -m'init'
11 $ hg commit -A -m'init'
12 adding a
12 adding a
13
13
14 share it
14 share it
15
15
16 $ cd ..
16 $ cd ..
17 $ hg share repo1 repo2
17 $ hg share repo1 repo2
18 updating working directory
18 updating working directory
19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20
20
21 share shouldn't have a store dir
21 share shouldn't have a store dir
22
22
23 $ cd repo2
23 $ cd repo2
24 $ test -d .hg/store
24 $ test -d .hg/store
25 [1]
25 [1]
26
26
27 Some sed versions appends newline, some don't, and some just fails
27 Some sed versions appends newline, some don't, and some just fails
28
28
29 $ cat .hg/sharedpath; echo
29 $ cat .hg/sharedpath; echo
30 $TESTTMP/repo1/.hg (glob)
30 $TESTTMP/repo1/.hg (glob)
31
31
32 trailing newline on .hg/sharedpath is ok
32 trailing newline on .hg/sharedpath is ok
33 $ hg tip -q
33 $ hg tip -q
34 0:d3873e73d99e
34 0:d3873e73d99e
35 $ echo '' >> .hg/sharedpath
35 $ echo '' >> .hg/sharedpath
36 $ cat .hg/sharedpath
36 $ cat .hg/sharedpath
37 $TESTTMP/repo1/.hg (glob)
37 $TESTTMP/repo1/.hg (glob)
38 $ hg tip -q
38 $ hg tip -q
39 0:d3873e73d99e
39 0:d3873e73d99e
40
40
41 commit in shared clone
41 commit in shared clone
42
42
43 $ echo a >> a
43 $ echo a >> a
44 $ hg commit -m'change in shared clone'
44 $ hg commit -m'change in shared clone'
45
45
46 check original
46 check original
47
47
48 $ cd ../repo1
48 $ cd ../repo1
49 $ hg log
49 $ hg log
50 changeset: 1:8af4dc49db9e
50 changeset: 1:8af4dc49db9e
51 tag: tip
51 tag: tip
52 user: test
52 user: test
53 date: Thu Jan 01 00:00:00 1970 +0000
53 date: Thu Jan 01 00:00:00 1970 +0000
54 summary: change in shared clone
54 summary: change in shared clone
55
55
56 changeset: 0:d3873e73d99e
56 changeset: 0:d3873e73d99e
57 user: test
57 user: test
58 date: Thu Jan 01 00:00:00 1970 +0000
58 date: Thu Jan 01 00:00:00 1970 +0000
59 summary: init
59 summary: init
60
60
61 $ hg update
61 $ hg update
62 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 $ cat a # should be two lines of "a"
63 $ cat a # should be two lines of "a"
64 a
64 a
65 a
65 a
66
66
67 commit in original
67 commit in original
68
68
69 $ echo b > b
69 $ echo b > b
70 $ hg commit -A -m'another file'
70 $ hg commit -A -m'another file'
71 adding b
71 adding b
72
72
73 check in shared clone
73 check in shared clone
74
74
75 $ cd ../repo2
75 $ cd ../repo2
76 $ hg log
76 $ hg log
77 changeset: 2:c2e0ac586386
77 changeset: 2:c2e0ac586386
78 tag: tip
78 tag: tip
79 user: test
79 user: test
80 date: Thu Jan 01 00:00:00 1970 +0000
80 date: Thu Jan 01 00:00:00 1970 +0000
81 summary: another file
81 summary: another file
82
82
83 changeset: 1:8af4dc49db9e
83 changeset: 1:8af4dc49db9e
84 user: test
84 user: test
85 date: Thu Jan 01 00:00:00 1970 +0000
85 date: Thu Jan 01 00:00:00 1970 +0000
86 summary: change in shared clone
86 summary: change in shared clone
87
87
88 changeset: 0:d3873e73d99e
88 changeset: 0:d3873e73d99e
89 user: test
89 user: test
90 date: Thu Jan 01 00:00:00 1970 +0000
90 date: Thu Jan 01 00:00:00 1970 +0000
91 summary: init
91 summary: init
92
92
93 $ hg update
93 $ hg update
94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 $ cat b # should exist with one "b"
95 $ cat b # should exist with one "b"
96 b
96 b
97
97
98 hg serve shared clone
98 hg serve shared clone
99
99
100 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid
100 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid
101 $ cat hg.pid >> $DAEMON_PIDS
101 $ cat hg.pid >> $DAEMON_PIDS
102 $ get-with-headers.py localhost:$HGPORT 'raw-file/'
102 $ get-with-headers.py localhost:$HGPORT 'raw-file/'
103 200 Script output follows
103 200 Script output follows
104
104
105
105
106 -rw-r--r-- 4 a
106 -rw-r--r-- 4 a
107 -rw-r--r-- 2 b
107 -rw-r--r-- 2 b
108
108
109
109
110
110
111 test unshare command
111 test unshare command
112
112
113 $ hg unshare
113 $ hg unshare
114 $ test -d .hg/store
114 $ test -d .hg/store
115 $ test -f .hg/sharedpath
115 $ test -f .hg/sharedpath
116 [1]
116 [1]
117 $ grep shared .hg/requires
118 [1]
117 $ hg unshare
119 $ hg unshare
118 abort: this is not a shared repo
120 abort: this is not a shared repo
119 [255]
121 [255]
120
122
121 check that a change does not propagate
123 check that a change does not propagate
122
124
123 $ echo b >> b
125 $ echo b >> b
124 $ hg commit -m'change in unshared'
126 $ hg commit -m'change in unshared'
125 $ cd ../repo1
127 $ cd ../repo1
126 $ hg id -r tip
128 $ hg id -r tip
127 c2e0ac586386 tip
129 c2e0ac586386 tip
128
130
129 $ cd ..
131 $ cd ..
130
132
131
133
132 test sharing bookmarks
134 test sharing bookmarks
133
135
134 $ hg share -B repo1 repo3
136 $ hg share -B repo1 repo3
135 updating working directory
137 updating working directory
136 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 $ cd repo1
139 $ cd repo1
138 $ hg bookmark bm1
140 $ hg bookmark bm1
139 $ hg bookmarks
141 $ hg bookmarks
140 * bm1 2:c2e0ac586386
142 * bm1 2:c2e0ac586386
141 $ cd ../repo2
143 $ cd ../repo2
142 $ hg book bm2
144 $ hg book bm2
143 $ hg bookmarks
145 $ hg bookmarks
144 * bm2 3:0e6e70d1d5f1
146 * bm2 3:0e6e70d1d5f1
145 $ cd ../repo3
147 $ cd ../repo3
146 $ hg bookmarks
148 $ hg bookmarks
147 bm1 2:c2e0ac586386
149 bm1 2:c2e0ac586386
148 $ hg book bm3
150 $ hg book bm3
149 $ hg bookmarks
151 $ hg bookmarks
150 bm1 2:c2e0ac586386
152 bm1 2:c2e0ac586386
151 * bm3 2:c2e0ac586386
153 * bm3 2:c2e0ac586386
152 $ cd ../repo1
154 $ cd ../repo1
153 $ hg bookmarks
155 $ hg bookmarks
154 * bm1 2:c2e0ac586386
156 * bm1 2:c2e0ac586386
155 bm3 2:c2e0ac586386
157 bm3 2:c2e0ac586386
156
158
157 check whether HG_PENDING makes pending changes only in relatd
159 check whether HG_PENDING makes pending changes only in relatd
158 repositories visible to an external hook.
160 repositories visible to an external hook.
159
161
160 In "hg share" case, another transaction can't run in other
162 In "hg share" case, another transaction can't run in other
161 repositories sharing same source repository, because starting
163 repositories sharing same source repository, because starting
162 transaction requires locking store of source repository.
164 transaction requires locking store of source repository.
163
165
164 Therefore, this test scenario ignores checking visibility of
166 Therefore, this test scenario ignores checking visibility of
165 .hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks.
167 .hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks.
166
168
167 $ cat > $TESTTMP/checkbookmarks.sh <<EOF
169 $ cat > $TESTTMP/checkbookmarks.sh <<EOF
168 > echo "@repo1"
170 > echo "@repo1"
169 > hg -R $TESTTMP/repo1 bookmarks
171 > hg -R $TESTTMP/repo1 bookmarks
170 > echo "@repo2"
172 > echo "@repo2"
171 > hg -R $TESTTMP/repo2 bookmarks
173 > hg -R $TESTTMP/repo2 bookmarks
172 > echo "@repo3"
174 > echo "@repo3"
173 > hg -R $TESTTMP/repo3 bookmarks
175 > hg -R $TESTTMP/repo3 bookmarks
174 > exit 1 # to avoid adding new bookmark for subsequent tests
176 > exit 1 # to avoid adding new bookmark for subsequent tests
175 > EOF
177 > EOF
176
178
177 $ cd ../repo1
179 $ cd ../repo1
178 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
180 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
179 @repo1
181 @repo1
180 bm1 2:c2e0ac586386
182 bm1 2:c2e0ac586386
181 bm3 2:c2e0ac586386
183 bm3 2:c2e0ac586386
182 * bmX 2:c2e0ac586386
184 * bmX 2:c2e0ac586386
183 @repo2
185 @repo2
184 * bm2 3:0e6e70d1d5f1
186 * bm2 3:0e6e70d1d5f1
185 @repo3
187 @repo3
186 bm1 2:c2e0ac586386
188 bm1 2:c2e0ac586386
187 * bm3 2:c2e0ac586386
189 * bm3 2:c2e0ac586386
188 bmX 2:c2e0ac586386
190 bmX 2:c2e0ac586386
189 transaction abort!
191 transaction abort!
190 rollback completed
192 rollback completed
191 abort: pretxnclose hook exited with status 1
193 abort: pretxnclose hook exited with status 1
192 [255]
194 [255]
193 $ hg book bm1
195 $ hg book bm1
194
196
195 FYI, in contrast to above test, bmX is invisible in repo1 (= shared
197 FYI, in contrast to above test, bmX is invisible in repo1 (= shared
196 src), because (1) HG_PENDING refers only repo3 and (2)
198 src), because (1) HG_PENDING refers only repo3 and (2)
197 "bookmarks.pending" is written only into repo3.
199 "bookmarks.pending" is written only into repo3.
198
200
199 $ cd ../repo3
201 $ cd ../repo3
200 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
202 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
201 @repo1
203 @repo1
202 * bm1 2:c2e0ac586386
204 * bm1 2:c2e0ac586386
203 bm3 2:c2e0ac586386
205 bm3 2:c2e0ac586386
204 @repo2
206 @repo2
205 * bm2 3:0e6e70d1d5f1
207 * bm2 3:0e6e70d1d5f1
206 @repo3
208 @repo3
207 bm1 2:c2e0ac586386
209 bm1 2:c2e0ac586386
208 bm3 2:c2e0ac586386
210 bm3 2:c2e0ac586386
209 * bmX 2:c2e0ac586386
211 * bmX 2:c2e0ac586386
210 transaction abort!
212 transaction abort!
211 rollback completed
213 rollback completed
212 abort: pretxnclose hook exited with status 1
214 abort: pretxnclose hook exited with status 1
213 [255]
215 [255]
214 $ hg book bm3
216 $ hg book bm3
215
217
216 $ cd ../repo1
218 $ cd ../repo1
217
219
218 test that commits work
220 test that commits work
219
221
220 $ echo 'shared bookmarks' > a
222 $ echo 'shared bookmarks' > a
221 $ hg commit -m 'testing shared bookmarks'
223 $ hg commit -m 'testing shared bookmarks'
222 $ hg bookmarks
224 $ hg bookmarks
223 * bm1 3:b87954705719
225 * bm1 3:b87954705719
224 bm3 2:c2e0ac586386
226 bm3 2:c2e0ac586386
225 $ cd ../repo3
227 $ cd ../repo3
226 $ hg bookmarks
228 $ hg bookmarks
227 bm1 3:b87954705719
229 bm1 3:b87954705719
228 * bm3 2:c2e0ac586386
230 * bm3 2:c2e0ac586386
229 $ echo 'more shared bookmarks' > a
231 $ echo 'more shared bookmarks' > a
230 $ hg commit -m 'testing shared bookmarks'
232 $ hg commit -m 'testing shared bookmarks'
231 created new head
233 created new head
232 $ hg bookmarks
234 $ hg bookmarks
233 bm1 3:b87954705719
235 bm1 3:b87954705719
234 * bm3 4:62f4ded848e4
236 * bm3 4:62f4ded848e4
235 $ cd ../repo1
237 $ cd ../repo1
236 $ hg bookmarks
238 $ hg bookmarks
237 * bm1 3:b87954705719
239 * bm1 3:b87954705719
238 bm3 4:62f4ded848e4
240 bm3 4:62f4ded848e4
239 $ cd ..
241 $ cd ..
240
242
241 test pushing bookmarks works
243 test pushing bookmarks works
242
244
243 $ hg clone repo3 repo4
245 $ hg clone repo3 repo4
244 updating to branch default
246 updating to branch default
245 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
247 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 $ cd repo4
248 $ cd repo4
247 $ hg boo bm4
249 $ hg boo bm4
248 $ echo foo > b
250 $ echo foo > b
249 $ hg commit -m 'foo in b'
251 $ hg commit -m 'foo in b'
250 $ hg boo
252 $ hg boo
251 bm1 3:b87954705719
253 bm1 3:b87954705719
252 bm3 4:62f4ded848e4
254 bm3 4:62f4ded848e4
253 * bm4 5:92793bfc8cad
255 * bm4 5:92793bfc8cad
254 $ hg push -B bm4
256 $ hg push -B bm4
255 pushing to $TESTTMP/repo3 (glob)
257 pushing to $TESTTMP/repo3 (glob)
256 searching for changes
258 searching for changes
257 adding changesets
259 adding changesets
258 adding manifests
260 adding manifests
259 adding file changes
261 adding file changes
260 added 1 changesets with 1 changes to 1 files
262 added 1 changesets with 1 changes to 1 files
261 exporting bookmark bm4
263 exporting bookmark bm4
262 $ cd ../repo1
264 $ cd ../repo1
263 $ hg bookmarks
265 $ hg bookmarks
264 * bm1 3:b87954705719
266 * bm1 3:b87954705719
265 bm3 4:62f4ded848e4
267 bm3 4:62f4ded848e4
266 bm4 5:92793bfc8cad
268 bm4 5:92793bfc8cad
267 $ cd ../repo3
269 $ cd ../repo3
268 $ hg bookmarks
270 $ hg bookmarks
269 bm1 3:b87954705719
271 bm1 3:b87954705719
270 * bm3 4:62f4ded848e4
272 * bm3 4:62f4ded848e4
271 bm4 5:92793bfc8cad
273 bm4 5:92793bfc8cad
272 $ cd ..
274 $ cd ..
273
275
274 test behavior when sharing a shared repo
276 test behavior when sharing a shared repo
275
277
276 $ hg share -B repo3 repo5
278 $ hg share -B repo3 repo5
277 updating working directory
279 updating working directory
278 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 $ cd repo5
281 $ cd repo5
280 $ hg book
282 $ hg book
281 bm1 3:b87954705719
283 bm1 3:b87954705719
282 bm3 4:62f4ded848e4
284 bm3 4:62f4ded848e4
283 bm4 5:92793bfc8cad
285 bm4 5:92793bfc8cad
284 $ cd ..
286 $ cd ..
285
287
286 test what happens when an active bookmark is deleted
288 test what happens when an active bookmark is deleted
287
289
288 $ cd repo1
290 $ cd repo1
289 $ hg boo -d bm3
291 $ hg boo -d bm3
290 $ hg boo
292 $ hg boo
291 * bm1 3:b87954705719
293 * bm1 3:b87954705719
292 bm4 5:92793bfc8cad
294 bm4 5:92793bfc8cad
293 $ cd ../repo3
295 $ cd ../repo3
294 $ hg boo
296 $ hg boo
295 bm1 3:b87954705719
297 bm1 3:b87954705719
296 bm4 5:92793bfc8cad
298 bm4 5:92793bfc8cad
297 $ cd ..
299 $ cd ..
298
300
299 verify that bookmarks are not written on failed transaction
301 verify that bookmarks are not written on failed transaction
300
302
301 $ cat > failpullbookmarks.py << EOF
303 $ cat > failpullbookmarks.py << EOF
302 > """A small extension that makes bookmark pulls fail, for testing"""
304 > """A small extension that makes bookmark pulls fail, for testing"""
303 > from mercurial import extensions, exchange, error
305 > from mercurial import extensions, exchange, error
304 > def _pullbookmarks(orig, pullop):
306 > def _pullbookmarks(orig, pullop):
305 > orig(pullop)
307 > orig(pullop)
306 > raise error.HookAbort('forced failure by extension')
308 > raise error.HookAbort('forced failure by extension')
307 > def extsetup(ui):
309 > def extsetup(ui):
308 > extensions.wrapfunction(exchange, '_pullbookmarks', _pullbookmarks)
310 > extensions.wrapfunction(exchange, '_pullbookmarks', _pullbookmarks)
309 > EOF
311 > EOF
310 $ cd repo4
312 $ cd repo4
311 $ hg boo
313 $ hg boo
312 bm1 3:b87954705719
314 bm1 3:b87954705719
313 bm3 4:62f4ded848e4
315 bm3 4:62f4ded848e4
314 * bm4 5:92793bfc8cad
316 * bm4 5:92793bfc8cad
315 $ cd ../repo3
317 $ cd ../repo3
316 $ hg boo
318 $ hg boo
317 bm1 3:b87954705719
319 bm1 3:b87954705719
318 bm4 5:92793bfc8cad
320 bm4 5:92793bfc8cad
319 $ hg --config "extensions.failpullbookmarks=$TESTTMP/failpullbookmarks.py" pull $TESTTMP/repo4
321 $ hg --config "extensions.failpullbookmarks=$TESTTMP/failpullbookmarks.py" pull $TESTTMP/repo4
320 pulling from $TESTTMP/repo4 (glob)
322 pulling from $TESTTMP/repo4 (glob)
321 searching for changes
323 searching for changes
322 no changes found
324 no changes found
323 adding remote bookmark bm3
325 adding remote bookmark bm3
324 abort: forced failure by extension
326 abort: forced failure by extension
325 [255]
327 [255]
326 $ hg boo
328 $ hg boo
327 bm1 3:b87954705719
329 bm1 3:b87954705719
328 bm4 5:92793bfc8cad
330 bm4 5:92793bfc8cad
329 $ hg pull $TESTTMP/repo4
331 $ hg pull $TESTTMP/repo4
330 pulling from $TESTTMP/repo4 (glob)
332 pulling from $TESTTMP/repo4 (glob)
331 searching for changes
333 searching for changes
332 no changes found
334 no changes found
333 adding remote bookmark bm3
335 adding remote bookmark bm3
334 $ hg boo
336 $ hg boo
335 bm1 3:b87954705719
337 bm1 3:b87954705719
336 * bm3 4:62f4ded848e4
338 * bm3 4:62f4ded848e4
337 bm4 5:92793bfc8cad
339 bm4 5:92793bfc8cad
338 $ cd ..
340 $ cd ..
339
341
340 verify bookmark behavior after unshare
342 verify bookmark behavior after unshare
341
343
342 $ cd repo3
344 $ cd repo3
343 $ hg unshare
345 $ hg unshare
344 $ hg boo
346 $ hg boo
345 bm1 3:b87954705719
347 bm1 3:b87954705719
346 * bm3 4:62f4ded848e4
348 * bm3 4:62f4ded848e4
347 bm4 5:92793bfc8cad
349 bm4 5:92793bfc8cad
348 $ hg boo -d bm4
350 $ hg boo -d bm4
349 $ hg boo bm5
351 $ hg boo bm5
350 $ hg boo
352 $ hg boo
351 bm1 3:b87954705719
353 bm1 3:b87954705719
352 bm3 4:62f4ded848e4
354 bm3 4:62f4ded848e4
353 * bm5 4:62f4ded848e4
355 * bm5 4:62f4ded848e4
354 $ cd ../repo1
356 $ cd ../repo1
355 $ hg boo
357 $ hg boo
356 * bm1 3:b87954705719
358 * bm1 3:b87954705719
357 bm3 4:62f4ded848e4
359 bm3 4:62f4ded848e4
358 bm4 5:92793bfc8cad
360 bm4 5:92793bfc8cad
359 $ cd ..
361 $ cd ..
360
362
361 test shared clones using relative paths work
363 test shared clones using relative paths work
362
364
363 $ mkdir thisdir
365 $ mkdir thisdir
364 $ hg init thisdir/orig
366 $ hg init thisdir/orig
365 $ hg share -U thisdir/orig thisdir/abs
367 $ hg share -U thisdir/orig thisdir/abs
366 $ hg share -U --relative thisdir/abs thisdir/rel
368 $ hg share -U --relative thisdir/abs thisdir/rel
367 $ cat thisdir/rel/.hg/sharedpath
369 $ cat thisdir/rel/.hg/sharedpath
368 ../../orig/.hg (no-eol)
370 ../../orig/.hg (no-eol)
369 $ grep shared thisdir/*/.hg/requires
371 $ grep shared thisdir/*/.hg/requires
370 thisdir/abs/.hg/requires:shared
372 thisdir/abs/.hg/requires:shared
371 thisdir/rel/.hg/requires:shared
373 thisdir/rel/.hg/requires:shared
372 thisdir/rel/.hg/requires:relshared
374 thisdir/rel/.hg/requires:relshared
373
375
374 test that relative shared paths aren't relative to $PWD
376 test that relative shared paths aren't relative to $PWD
375
377
376 $ cd thisdir
378 $ cd thisdir
377 $ hg -R rel root
379 $ hg -R rel root
378 $TESTTMP/thisdir/rel
380 $TESTTMP/thisdir/rel
379 $ cd ..
381 $ cd ..
380
382
381 now test that relative paths really are relative, survive across
383 now test that relative paths really are relative, survive across
382 renames and changes of PWD
384 renames and changes of PWD
383
385
384 $ hg -R thisdir/abs root
386 $ hg -R thisdir/abs root
385 $TESTTMP/thisdir/abs
387 $TESTTMP/thisdir/abs
386 $ hg -R thisdir/rel root
388 $ hg -R thisdir/rel root
387 $TESTTMP/thisdir/rel
389 $TESTTMP/thisdir/rel
388 $ mv thisdir thatdir
390 $ mv thisdir thatdir
389 $ hg -R thatdir/abs root
391 $ hg -R thatdir/abs root
390 abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg!
392 abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg!
391 [255]
393 [255]
392 $ hg -R thatdir/rel root
394 $ hg -R thatdir/rel root
393 $TESTTMP/thatdir/rel
395 $TESTTMP/thatdir/rel
394 $ rm -r thatdir
396 $ rm -r thatdir
395
397
396 Explicitly kill daemons to let the test exit on Windows
398 Explicitly kill daemons to let the test exit on Windows
397
399
398 $ killdaemons.py
400 $ killdaemons.py
399
401
General Comments 0
You need to be logged in to leave comments. Login now