##// END OF EJS Templates
share: drop 'relshared' requirement as well
Yuya Nishihara -
r31212:344121b3 default
parent child Browse files
Show More
@@ -1,220 +1,221 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('shared')
119 repo.requirements.discard('shared')
120 repo.requirements.discard('relshared')
120 repo._writerequirements()
121 repo._writerequirements()
121 finally:
122 finally:
122 destlock and destlock.release()
123 destlock and destlock.release()
123 lock and lock.release()
124 lock and lock.release()
124
125
125 # update store, spath, svfs and sjoin of repo
126 # update store, spath, svfs and sjoin of repo
126 repo.unfiltered().__init__(repo.baseui, repo.root)
127 repo.unfiltered().__init__(repo.baseui, repo.root)
127
128
128 # Wrap clone command to pass auto share options.
129 # Wrap clone command to pass auto share options.
129 def clone(orig, ui, source, *args, **opts):
130 def clone(orig, ui, source, *args, **opts):
130 pool = ui.config('share', 'pool', None)
131 pool = ui.config('share', 'pool', None)
131 if pool:
132 if pool:
132 pool = util.expandpath(pool)
133 pool = util.expandpath(pool)
133
134
134 opts['shareopts'] = dict(
135 opts['shareopts'] = dict(
135 pool=pool,
136 pool=pool,
136 mode=ui.config('share', 'poolnaming', 'identity'),
137 mode=ui.config('share', 'poolnaming', 'identity'),
137 )
138 )
138
139
139 return orig(ui, source, *args, **opts)
140 return orig(ui, source, *args, **opts)
140
141
141 def extsetup(ui):
142 def extsetup(ui):
142 extensions.wrapfunction(bookmarks, '_getbkfile', getbkfile)
143 extensions.wrapfunction(bookmarks, '_getbkfile', getbkfile)
143 extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
144 extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
144 extensions.wrapfunction(bookmarks.bmstore, '_writerepo', writerepo)
145 extensions.wrapfunction(bookmarks.bmstore, '_writerepo', writerepo)
145 extensions.wrapcommand(commands.table, 'clone', clone)
146 extensions.wrapcommand(commands.table, 'clone', clone)
146
147
147 def _hassharedbookmarks(repo):
148 def _hassharedbookmarks(repo):
148 """Returns whether this repo has shared bookmarks"""
149 """Returns whether this repo has shared bookmarks"""
149 try:
150 try:
150 shared = repo.vfs.read('shared').splitlines()
151 shared = repo.vfs.read('shared').splitlines()
151 except IOError as inst:
152 except IOError as inst:
152 if inst.errno != errno.ENOENT:
153 if inst.errno != errno.ENOENT:
153 raise
154 raise
154 return False
155 return False
155 return hg.sharedbookmarks in shared
156 return hg.sharedbookmarks in shared
156
157
157 def _getsrcrepo(repo):
158 def _getsrcrepo(repo):
158 """
159 """
159 Returns the source repository object for a given shared repository.
160 Returns the source repository object for a given shared repository.
160 If repo is not a shared repository, return None.
161 If repo is not a shared repository, return None.
161 """
162 """
162 if repo.sharedpath == repo.path:
163 if repo.sharedpath == repo.path:
163 return None
164 return None
164
165
165 if util.safehasattr(repo, 'srcrepo') and repo.srcrepo:
166 if util.safehasattr(repo, 'srcrepo') and repo.srcrepo:
166 return repo.srcrepo
167 return repo.srcrepo
167
168
168 # the sharedpath always ends in the .hg; we want the path to the repo
169 # the sharedpath always ends in the .hg; we want the path to the repo
169 source = repo.vfs.split(repo.sharedpath)[0]
170 source = repo.vfs.split(repo.sharedpath)[0]
170 srcurl, branches = parseurl(source)
171 srcurl, branches = parseurl(source)
171 srcrepo = repository(repo.ui, srcurl)
172 srcrepo = repository(repo.ui, srcurl)
172 repo.srcrepo = srcrepo
173 repo.srcrepo = srcrepo
173 return srcrepo
174 return srcrepo
174
175
175 def getbkfile(orig, repo):
176 def getbkfile(orig, repo):
176 if _hassharedbookmarks(repo):
177 if _hassharedbookmarks(repo):
177 srcrepo = _getsrcrepo(repo)
178 srcrepo = _getsrcrepo(repo)
178 if srcrepo is not None:
179 if srcrepo is not None:
179 # just orig(srcrepo) doesn't work as expected, because
180 # just orig(srcrepo) doesn't work as expected, because
180 # HG_PENDING refers repo.root.
181 # HG_PENDING refers repo.root.
181 try:
182 try:
182 fp, pending = txnutil.trypending(repo.root, repo.vfs,
183 fp, pending = txnutil.trypending(repo.root, repo.vfs,
183 'bookmarks')
184 'bookmarks')
184 if pending:
185 if pending:
185 # only in this case, bookmark information in repo
186 # only in this case, bookmark information in repo
186 # is up-to-date.
187 # is up-to-date.
187 return fp
188 return fp
188 fp.close()
189 fp.close()
189 except IOError as inst:
190 except IOError as inst:
190 if inst.errno != errno.ENOENT:
191 if inst.errno != errno.ENOENT:
191 raise
192 raise
192
193
193 # otherwise, we should read bookmarks from srcrepo,
194 # otherwise, we should read bookmarks from srcrepo,
194 # because .hg/bookmarks in srcrepo might be already
195 # because .hg/bookmarks in srcrepo might be already
195 # changed via another sharing repo
196 # changed via another sharing repo
196 repo = srcrepo
197 repo = srcrepo
197
198
198 # TODO: Pending changes in repo are still invisible in
199 # TODO: Pending changes in repo are still invisible in
199 # srcrepo, because bookmarks.pending is written only into repo.
200 # srcrepo, because bookmarks.pending is written only into repo.
200 # See also https://www.mercurial-scm.org/wiki/SharedRepository
201 # See also https://www.mercurial-scm.org/wiki/SharedRepository
201 return orig(repo)
202 return orig(repo)
202
203
203 def recordchange(orig, self, tr):
204 def recordchange(orig, self, tr):
204 # Continue with write to local bookmarks file as usual
205 # Continue with write to local bookmarks file as usual
205 orig(self, tr)
206 orig(self, tr)
206
207
207 if _hassharedbookmarks(self._repo):
208 if _hassharedbookmarks(self._repo):
208 srcrepo = _getsrcrepo(self._repo)
209 srcrepo = _getsrcrepo(self._repo)
209 if srcrepo is not None:
210 if srcrepo is not None:
210 category = 'share-bookmarks'
211 category = 'share-bookmarks'
211 tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
212 tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
212
213
213 def writerepo(orig, self, repo):
214 def writerepo(orig, self, repo):
214 # First write local bookmarks file in case we ever unshare
215 # First write local bookmarks file in case we ever unshare
215 orig(self, repo)
216 orig(self, repo)
216
217
217 if _hassharedbookmarks(self._repo):
218 if _hassharedbookmarks(self._repo):
218 srcrepo = _getsrcrepo(self._repo)
219 srcrepo = _getsrcrepo(self._repo)
219 if srcrepo is not None:
220 if srcrepo is not None:
220 orig(self, srcrepo)
221 orig(self, srcrepo)
@@ -1,401 +1,416 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
117 $ grep shared .hg/requires
118 [1]
118 [1]
119 $ hg unshare
119 $ hg unshare
120 abort: this is not a shared repo
120 abort: this is not a shared repo
121 [255]
121 [255]
122
122
123 check that a change does not propagate
123 check that a change does not propagate
124
124
125 $ echo b >> b
125 $ echo b >> b
126 $ hg commit -m'change in unshared'
126 $ hg commit -m'change in unshared'
127 $ cd ../repo1
127 $ cd ../repo1
128 $ hg id -r tip
128 $ hg id -r tip
129 c2e0ac586386 tip
129 c2e0ac586386 tip
130
130
131 $ cd ..
131 $ cd ..
132
132
133
133
134 test sharing bookmarks
134 test sharing bookmarks
135
135
136 $ hg share -B repo1 repo3
136 $ hg share -B repo1 repo3
137 updating working directory
137 updating working directory
138 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
139 $ cd repo1
139 $ cd repo1
140 $ hg bookmark bm1
140 $ hg bookmark bm1
141 $ hg bookmarks
141 $ hg bookmarks
142 * bm1 2:c2e0ac586386
142 * bm1 2:c2e0ac586386
143 $ cd ../repo2
143 $ cd ../repo2
144 $ hg book bm2
144 $ hg book bm2
145 $ hg bookmarks
145 $ hg bookmarks
146 * bm2 3:0e6e70d1d5f1
146 * bm2 3:0e6e70d1d5f1
147 $ cd ../repo3
147 $ cd ../repo3
148 $ hg bookmarks
148 $ hg bookmarks
149 bm1 2:c2e0ac586386
149 bm1 2:c2e0ac586386
150 $ hg book bm3
150 $ hg book bm3
151 $ hg bookmarks
151 $ hg bookmarks
152 bm1 2:c2e0ac586386
152 bm1 2:c2e0ac586386
153 * bm3 2:c2e0ac586386
153 * bm3 2:c2e0ac586386
154 $ cd ../repo1
154 $ cd ../repo1
155 $ hg bookmarks
155 $ hg bookmarks
156 * bm1 2:c2e0ac586386
156 * bm1 2:c2e0ac586386
157 bm3 2:c2e0ac586386
157 bm3 2:c2e0ac586386
158
158
159 check whether HG_PENDING makes pending changes only in relatd
159 check whether HG_PENDING makes pending changes only in relatd
160 repositories visible to an external hook.
160 repositories visible to an external hook.
161
161
162 In "hg share" case, another transaction can't run in other
162 In "hg share" case, another transaction can't run in other
163 repositories sharing same source repository, because starting
163 repositories sharing same source repository, because starting
164 transaction requires locking store of source repository.
164 transaction requires locking store of source repository.
165
165
166 Therefore, this test scenario ignores checking visibility of
166 Therefore, this test scenario ignores checking visibility of
167 .hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks.
167 .hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks.
168
168
169 $ cat > $TESTTMP/checkbookmarks.sh <<EOF
169 $ cat > $TESTTMP/checkbookmarks.sh <<EOF
170 > echo "@repo1"
170 > echo "@repo1"
171 > hg -R $TESTTMP/repo1 bookmarks
171 > hg -R $TESTTMP/repo1 bookmarks
172 > echo "@repo2"
172 > echo "@repo2"
173 > hg -R $TESTTMP/repo2 bookmarks
173 > hg -R $TESTTMP/repo2 bookmarks
174 > echo "@repo3"
174 > echo "@repo3"
175 > hg -R $TESTTMP/repo3 bookmarks
175 > hg -R $TESTTMP/repo3 bookmarks
176 > exit 1 # to avoid adding new bookmark for subsequent tests
176 > exit 1 # to avoid adding new bookmark for subsequent tests
177 > EOF
177 > EOF
178
178
179 $ cd ../repo1
179 $ cd ../repo1
180 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
180 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
181 @repo1
181 @repo1
182 bm1 2:c2e0ac586386
182 bm1 2:c2e0ac586386
183 bm3 2:c2e0ac586386
183 bm3 2:c2e0ac586386
184 * bmX 2:c2e0ac586386
184 * bmX 2:c2e0ac586386
185 @repo2
185 @repo2
186 * bm2 3:0e6e70d1d5f1
186 * bm2 3:0e6e70d1d5f1
187 @repo3
187 @repo3
188 bm1 2:c2e0ac586386
188 bm1 2:c2e0ac586386
189 * bm3 2:c2e0ac586386
189 * bm3 2:c2e0ac586386
190 bmX 2:c2e0ac586386
190 bmX 2:c2e0ac586386
191 transaction abort!
191 transaction abort!
192 rollback completed
192 rollback completed
193 abort: pretxnclose hook exited with status 1
193 abort: pretxnclose hook exited with status 1
194 [255]
194 [255]
195 $ hg book bm1
195 $ hg book bm1
196
196
197 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
198 src), because (1) HG_PENDING refers only repo3 and (2)
198 src), because (1) HG_PENDING refers only repo3 and (2)
199 "bookmarks.pending" is written only into repo3.
199 "bookmarks.pending" is written only into repo3.
200
200
201 $ cd ../repo3
201 $ cd ../repo3
202 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
202 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
203 @repo1
203 @repo1
204 * bm1 2:c2e0ac586386
204 * bm1 2:c2e0ac586386
205 bm3 2:c2e0ac586386
205 bm3 2:c2e0ac586386
206 @repo2
206 @repo2
207 * bm2 3:0e6e70d1d5f1
207 * bm2 3:0e6e70d1d5f1
208 @repo3
208 @repo3
209 bm1 2:c2e0ac586386
209 bm1 2:c2e0ac586386
210 bm3 2:c2e0ac586386
210 bm3 2:c2e0ac586386
211 * bmX 2:c2e0ac586386
211 * bmX 2:c2e0ac586386
212 transaction abort!
212 transaction abort!
213 rollback completed
213 rollback completed
214 abort: pretxnclose hook exited with status 1
214 abort: pretxnclose hook exited with status 1
215 [255]
215 [255]
216 $ hg book bm3
216 $ hg book bm3
217
217
218 $ cd ../repo1
218 $ cd ../repo1
219
219
220 test that commits work
220 test that commits work
221
221
222 $ echo 'shared bookmarks' > a
222 $ echo 'shared bookmarks' > a
223 $ hg commit -m 'testing shared bookmarks'
223 $ hg commit -m 'testing shared bookmarks'
224 $ hg bookmarks
224 $ hg bookmarks
225 * bm1 3:b87954705719
225 * bm1 3:b87954705719
226 bm3 2:c2e0ac586386
226 bm3 2:c2e0ac586386
227 $ cd ../repo3
227 $ cd ../repo3
228 $ hg bookmarks
228 $ hg bookmarks
229 bm1 3:b87954705719
229 bm1 3:b87954705719
230 * bm3 2:c2e0ac586386
230 * bm3 2:c2e0ac586386
231 $ echo 'more shared bookmarks' > a
231 $ echo 'more shared bookmarks' > a
232 $ hg commit -m 'testing shared bookmarks'
232 $ hg commit -m 'testing shared bookmarks'
233 created new head
233 created new head
234 $ hg bookmarks
234 $ hg bookmarks
235 bm1 3:b87954705719
235 bm1 3:b87954705719
236 * bm3 4:62f4ded848e4
236 * bm3 4:62f4ded848e4
237 $ cd ../repo1
237 $ cd ../repo1
238 $ hg bookmarks
238 $ hg bookmarks
239 * bm1 3:b87954705719
239 * bm1 3:b87954705719
240 bm3 4:62f4ded848e4
240 bm3 4:62f4ded848e4
241 $ cd ..
241 $ cd ..
242
242
243 test pushing bookmarks works
243 test pushing bookmarks works
244
244
245 $ hg clone repo3 repo4
245 $ hg clone repo3 repo4
246 updating to branch default
246 updating to branch default
247 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
248 $ cd repo4
248 $ cd repo4
249 $ hg boo bm4
249 $ hg boo bm4
250 $ echo foo > b
250 $ echo foo > b
251 $ hg commit -m 'foo in b'
251 $ hg commit -m 'foo in b'
252 $ hg boo
252 $ hg boo
253 bm1 3:b87954705719
253 bm1 3:b87954705719
254 bm3 4:62f4ded848e4
254 bm3 4:62f4ded848e4
255 * bm4 5:92793bfc8cad
255 * bm4 5:92793bfc8cad
256 $ hg push -B bm4
256 $ hg push -B bm4
257 pushing to $TESTTMP/repo3 (glob)
257 pushing to $TESTTMP/repo3 (glob)
258 searching for changes
258 searching for changes
259 adding changesets
259 adding changesets
260 adding manifests
260 adding manifests
261 adding file changes
261 adding file changes
262 added 1 changesets with 1 changes to 1 files
262 added 1 changesets with 1 changes to 1 files
263 exporting bookmark bm4
263 exporting bookmark bm4
264 $ cd ../repo1
264 $ cd ../repo1
265 $ hg bookmarks
265 $ hg bookmarks
266 * bm1 3:b87954705719
266 * bm1 3:b87954705719
267 bm3 4:62f4ded848e4
267 bm3 4:62f4ded848e4
268 bm4 5:92793bfc8cad
268 bm4 5:92793bfc8cad
269 $ cd ../repo3
269 $ cd ../repo3
270 $ hg bookmarks
270 $ hg bookmarks
271 bm1 3:b87954705719
271 bm1 3:b87954705719
272 * bm3 4:62f4ded848e4
272 * bm3 4:62f4ded848e4
273 bm4 5:92793bfc8cad
273 bm4 5:92793bfc8cad
274 $ cd ..
274 $ cd ..
275
275
276 test behavior when sharing a shared repo
276 test behavior when sharing a shared repo
277
277
278 $ hg share -B repo3 repo5
278 $ hg share -B repo3 repo5
279 updating working directory
279 updating working directory
280 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
281 $ cd repo5
281 $ cd repo5
282 $ hg book
282 $ hg book
283 bm1 3:b87954705719
283 bm1 3:b87954705719
284 bm3 4:62f4ded848e4
284 bm3 4:62f4ded848e4
285 bm4 5:92793bfc8cad
285 bm4 5:92793bfc8cad
286 $ cd ..
286 $ cd ..
287
287
288 test what happens when an active bookmark is deleted
288 test what happens when an active bookmark is deleted
289
289
290 $ cd repo1
290 $ cd repo1
291 $ hg boo -d bm3
291 $ hg boo -d bm3
292 $ hg boo
292 $ hg boo
293 * bm1 3:b87954705719
293 * bm1 3:b87954705719
294 bm4 5:92793bfc8cad
294 bm4 5:92793bfc8cad
295 $ cd ../repo3
295 $ cd ../repo3
296 $ hg boo
296 $ hg boo
297 bm1 3:b87954705719
297 bm1 3:b87954705719
298 bm4 5:92793bfc8cad
298 bm4 5:92793bfc8cad
299 $ cd ..
299 $ cd ..
300
300
301 verify that bookmarks are not written on failed transaction
301 verify that bookmarks are not written on failed transaction
302
302
303 $ cat > failpullbookmarks.py << EOF
303 $ cat > failpullbookmarks.py << EOF
304 > """A small extension that makes bookmark pulls fail, for testing"""
304 > """A small extension that makes bookmark pulls fail, for testing"""
305 > from mercurial import extensions, exchange, error
305 > from mercurial import extensions, exchange, error
306 > def _pullbookmarks(orig, pullop):
306 > def _pullbookmarks(orig, pullop):
307 > orig(pullop)
307 > orig(pullop)
308 > raise error.HookAbort('forced failure by extension')
308 > raise error.HookAbort('forced failure by extension')
309 > def extsetup(ui):
309 > def extsetup(ui):
310 > extensions.wrapfunction(exchange, '_pullbookmarks', _pullbookmarks)
310 > extensions.wrapfunction(exchange, '_pullbookmarks', _pullbookmarks)
311 > EOF
311 > EOF
312 $ cd repo4
312 $ cd repo4
313 $ hg boo
313 $ hg boo
314 bm1 3:b87954705719
314 bm1 3:b87954705719
315 bm3 4:62f4ded848e4
315 bm3 4:62f4ded848e4
316 * bm4 5:92793bfc8cad
316 * bm4 5:92793bfc8cad
317 $ cd ../repo3
317 $ cd ../repo3
318 $ hg boo
318 $ hg boo
319 bm1 3:b87954705719
319 bm1 3:b87954705719
320 bm4 5:92793bfc8cad
320 bm4 5:92793bfc8cad
321 $ hg --config "extensions.failpullbookmarks=$TESTTMP/failpullbookmarks.py" pull $TESTTMP/repo4
321 $ hg --config "extensions.failpullbookmarks=$TESTTMP/failpullbookmarks.py" pull $TESTTMP/repo4
322 pulling from $TESTTMP/repo4 (glob)
322 pulling from $TESTTMP/repo4 (glob)
323 searching for changes
323 searching for changes
324 no changes found
324 no changes found
325 adding remote bookmark bm3
325 adding remote bookmark bm3
326 abort: forced failure by extension
326 abort: forced failure by extension
327 [255]
327 [255]
328 $ hg boo
328 $ hg boo
329 bm1 3:b87954705719
329 bm1 3:b87954705719
330 bm4 5:92793bfc8cad
330 bm4 5:92793bfc8cad
331 $ hg pull $TESTTMP/repo4
331 $ hg pull $TESTTMP/repo4
332 pulling from $TESTTMP/repo4 (glob)
332 pulling from $TESTTMP/repo4 (glob)
333 searching for changes
333 searching for changes
334 no changes found
334 no changes found
335 adding remote bookmark bm3
335 adding remote bookmark bm3
336 $ hg boo
336 $ hg boo
337 bm1 3:b87954705719
337 bm1 3:b87954705719
338 * bm3 4:62f4ded848e4
338 * bm3 4:62f4ded848e4
339 bm4 5:92793bfc8cad
339 bm4 5:92793bfc8cad
340 $ cd ..
340 $ cd ..
341
341
342 verify bookmark behavior after unshare
342 verify bookmark behavior after unshare
343
343
344 $ cd repo3
344 $ cd repo3
345 $ hg unshare
345 $ hg unshare
346 $ hg boo
346 $ hg boo
347 bm1 3:b87954705719
347 bm1 3:b87954705719
348 * bm3 4:62f4ded848e4
348 * bm3 4:62f4ded848e4
349 bm4 5:92793bfc8cad
349 bm4 5:92793bfc8cad
350 $ hg boo -d bm4
350 $ hg boo -d bm4
351 $ hg boo bm5
351 $ hg boo bm5
352 $ hg boo
352 $ hg boo
353 bm1 3:b87954705719
353 bm1 3:b87954705719
354 bm3 4:62f4ded848e4
354 bm3 4:62f4ded848e4
355 * bm5 4:62f4ded848e4
355 * bm5 4:62f4ded848e4
356 $ cd ../repo1
356 $ cd ../repo1
357 $ hg boo
357 $ hg boo
358 * bm1 3:b87954705719
358 * bm1 3:b87954705719
359 bm3 4:62f4ded848e4
359 bm3 4:62f4ded848e4
360 bm4 5:92793bfc8cad
360 bm4 5:92793bfc8cad
361 $ cd ..
361 $ cd ..
362
362
363 test shared clones using relative paths work
363 test shared clones using relative paths work
364
364
365 $ mkdir thisdir
365 $ mkdir thisdir
366 $ hg init thisdir/orig
366 $ hg init thisdir/orig
367 $ hg share -U thisdir/orig thisdir/abs
367 $ hg share -U thisdir/orig thisdir/abs
368 $ hg share -U --relative thisdir/abs thisdir/rel
368 $ hg share -U --relative thisdir/abs thisdir/rel
369 $ cat thisdir/rel/.hg/sharedpath
369 $ cat thisdir/rel/.hg/sharedpath
370 ../../orig/.hg (no-eol)
370 ../../orig/.hg (no-eol)
371 $ grep shared thisdir/*/.hg/requires
371 $ grep shared thisdir/*/.hg/requires
372 thisdir/abs/.hg/requires:shared
372 thisdir/abs/.hg/requires:shared
373 thisdir/rel/.hg/requires:shared
373 thisdir/rel/.hg/requires:shared
374 thisdir/rel/.hg/requires:relshared
374 thisdir/rel/.hg/requires:relshared
375
375
376 test that relative shared paths aren't relative to $PWD
376 test that relative shared paths aren't relative to $PWD
377
377
378 $ cd thisdir
378 $ cd thisdir
379 $ hg -R rel root
379 $ hg -R rel root
380 $TESTTMP/thisdir/rel
380 $TESTTMP/thisdir/rel
381 $ cd ..
381 $ cd ..
382
382
383 now test that relative paths really are relative, survive across
383 now test that relative paths really are relative, survive across
384 renames and changes of PWD
384 renames and changes of PWD
385
385
386 $ hg -R thisdir/abs root
386 $ hg -R thisdir/abs root
387 $TESTTMP/thisdir/abs
387 $TESTTMP/thisdir/abs
388 $ hg -R thisdir/rel root
388 $ hg -R thisdir/rel root
389 $TESTTMP/thisdir/rel
389 $TESTTMP/thisdir/rel
390 $ mv thisdir thatdir
390 $ mv thisdir thatdir
391 $ hg -R thatdir/abs root
391 $ hg -R thatdir/abs root
392 abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg!
392 abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg!
393 [255]
393 [255]
394 $ hg -R thatdir/rel root
394 $ hg -R thatdir/rel root
395 $TESTTMP/thatdir/rel
395 $TESTTMP/thatdir/rel
396
397 test unshare relshared repo
398
399 $ cd thatdir/rel
400 $ hg unshare
401 $ test -d .hg/store
402 $ test -f .hg/sharedpath
403 [1]
404 $ grep shared .hg/requires
405 [1]
406 $ hg unshare
407 abort: this is not a shared repo
408 [255]
409 $ cd ../..
410
396 $ rm -r thatdir
411 $ rm -r thatdir
397
412
398 Explicitly kill daemons to let the test exit on Windows
413 Explicitly kill daemons to let the test exit on Windows
399
414
400 $ killdaemons.py
415 $ killdaemons.py
401
416
General Comments 0
You need to be logged in to leave comments. Login now