##// END OF EJS Templates
share: use dict literal instead of dict(key=value)...
Yuya Nishihara -
r33021:24c0a9a7 default
parent child Browse files
Show More
@@ -1,221 +1,221
1 1 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5
6 6 '''share a common history between several working directories
7 7
8 8 Automatic Pooled Storage for Clones
9 9 -----------------------------------
10 10
11 11 When this extension is active, :hg:`clone` can be configured to
12 12 automatically share/pool storage across multiple clones. This
13 13 mode effectively converts :hg:`clone` to :hg:`clone` + :hg:`share`.
14 14 The benefit of using this mode is the automatic management of
15 15 store paths and intelligent pooling of related repositories.
16 16
17 17 The following ``share.`` config options influence this feature:
18 18
19 19 ``share.pool``
20 20 Filesystem path where shared repository data will be stored. When
21 21 defined, :hg:`clone` will automatically use shared repository
22 22 storage instead of creating a store inside each clone.
23 23
24 24 ``share.poolnaming``
25 25 How directory names in ``share.pool`` are constructed.
26 26
27 27 "identity" means the name is derived from the first changeset in the
28 28 repository. In this mode, different remotes share storage if their
29 29 root/initial changeset is identical. In this mode, the local shared
30 30 repository is an aggregate of all encountered remote repositories.
31 31
32 32 "remote" means the name is derived from the source repository's
33 33 path or URL. In this mode, storage is only shared if the path or URL
34 34 requested in the :hg:`clone` command matches exactly to a repository
35 35 that was cloned before.
36 36
37 37 The default naming mode is "identity."
38 38 '''
39 39
40 40 from __future__ import absolute_import
41 41
42 42 import errno
43 43 from mercurial.i18n import _
44 44 from mercurial import (
45 45 bookmarks,
46 46 commands,
47 47 error,
48 48 extensions,
49 49 hg,
50 50 registrar,
51 51 txnutil,
52 52 util,
53 53 )
54 54
55 55 repository = hg.repository
56 56 parseurl = hg.parseurl
57 57
58 58 cmdtable = {}
59 59 command = registrar.command(cmdtable)
60 60 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
61 61 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
62 62 # be specifying the version(s) of Mercurial they are tested with, or
63 63 # leave the attribute unspecified.
64 64 testedwith = 'ships-with-hg-core'
65 65
66 66 @command('share',
67 67 [('U', 'noupdate', None, _('do not create a working directory')),
68 68 ('B', 'bookmarks', None, _('also share bookmarks')),
69 69 ('', 'relative', None, _('point to source using a relative path '
70 70 '(EXPERIMENTAL)')),
71 71 ],
72 72 _('[-U] [-B] SOURCE [DEST]'),
73 73 norepo=True)
74 74 def share(ui, source, dest=None, noupdate=False, bookmarks=False,
75 75 relative=False):
76 76 """create a new shared repository
77 77
78 78 Initialize a new repository and working directory that shares its
79 79 history (and optionally bookmarks) with another repository.
80 80
81 81 .. note::
82 82
83 83 using rollback or extensions that destroy/modify history (mq,
84 84 rebase, etc.) can cause considerable confusion with shared
85 85 clones. In particular, if two shared clones are both updated to
86 86 the same changeset, and one of them destroys that changeset
87 87 with rollback, the other clone will suddenly stop working: all
88 88 operations will fail with "abort: working directory has unknown
89 89 parent". The only known workaround is to use debugsetparents on
90 90 the broken clone to reset it to a changeset that still exists.
91 91 """
92 92
93 93 return hg.share(ui, source, dest=dest, update=not noupdate,
94 94 bookmarks=bookmarks, relative=relative)
95 95
96 96 @command('unshare', [], '')
97 97 def unshare(ui, repo):
98 98 """convert a shared repository to a normal one
99 99
100 100 Copy the store data to the repo and remove the sharedpath data.
101 101 """
102 102
103 103 if not repo.shared():
104 104 raise error.Abort(_("this is not a shared repo"))
105 105
106 106 destlock = lock = None
107 107 lock = repo.lock()
108 108 try:
109 109 # we use locks here because if we race with commit, we
110 110 # can end up with extra data in the cloned revlogs that's
111 111 # not pointed to by changesets, thus causing verify to
112 112 # fail
113 113
114 114 destlock = hg.copystore(ui, repo, repo.path)
115 115
116 116 sharefile = repo.vfs.join('sharedpath')
117 117 util.rename(sharefile, sharefile + '.old')
118 118
119 119 repo.requirements.discard('shared')
120 120 repo.requirements.discard('relshared')
121 121 repo._writerequirements()
122 122 finally:
123 123 destlock and destlock.release()
124 124 lock and lock.release()
125 125
126 126 # update store, spath, svfs and sjoin of repo
127 127 repo.unfiltered().__init__(repo.baseui, repo.root)
128 128
129 129 # Wrap clone command to pass auto share options.
130 130 def clone(orig, ui, source, *args, **opts):
131 131 pool = ui.config('share', 'pool', None)
132 132 if pool:
133 133 pool = util.expandpath(pool)
134 134
135 opts[r'shareopts'] = dict(
136 pool=pool,
137 mode=ui.config('share', 'poolnaming', 'identity'),
138 )
135 opts[r'shareopts'] = {
136 'pool': pool,
137 'mode': ui.config('share', 'poolnaming', 'identity'),
138 }
139 139
140 140 return orig(ui, source, *args, **opts)
141 141
142 142 def extsetup(ui):
143 143 extensions.wrapfunction(bookmarks, '_getbkfile', getbkfile)
144 144 extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
145 145 extensions.wrapfunction(bookmarks.bmstore, '_writerepo', writerepo)
146 146 extensions.wrapcommand(commands.table, 'clone', clone)
147 147
148 148 def _hassharedbookmarks(repo):
149 149 """Returns whether this repo has shared bookmarks"""
150 150 try:
151 151 shared = repo.vfs.read('shared').splitlines()
152 152 except IOError as inst:
153 153 if inst.errno != errno.ENOENT:
154 154 raise
155 155 return False
156 156 return hg.sharedbookmarks in shared
157 157
158 158 def _getsrcrepo(repo):
159 159 """
160 160 Returns the source repository object for a given shared repository.
161 161 If repo is not a shared repository, return None.
162 162 """
163 163 if repo.sharedpath == repo.path:
164 164 return None
165 165
166 166 if util.safehasattr(repo, 'srcrepo') and repo.srcrepo:
167 167 return repo.srcrepo
168 168
169 169 # the sharedpath always ends in the .hg; we want the path to the repo
170 170 source = repo.vfs.split(repo.sharedpath)[0]
171 171 srcurl, branches = parseurl(source)
172 172 srcrepo = repository(repo.ui, srcurl)
173 173 repo.srcrepo = srcrepo
174 174 return srcrepo
175 175
176 176 def getbkfile(orig, repo):
177 177 if _hassharedbookmarks(repo):
178 178 srcrepo = _getsrcrepo(repo)
179 179 if srcrepo is not None:
180 180 # just orig(srcrepo) doesn't work as expected, because
181 181 # HG_PENDING refers repo.root.
182 182 try:
183 183 fp, pending = txnutil.trypending(repo.root, repo.vfs,
184 184 'bookmarks')
185 185 if pending:
186 186 # only in this case, bookmark information in repo
187 187 # is up-to-date.
188 188 return fp
189 189 fp.close()
190 190 except IOError as inst:
191 191 if inst.errno != errno.ENOENT:
192 192 raise
193 193
194 194 # otherwise, we should read bookmarks from srcrepo,
195 195 # because .hg/bookmarks in srcrepo might be already
196 196 # changed via another sharing repo
197 197 repo = srcrepo
198 198
199 199 # TODO: Pending changes in repo are still invisible in
200 200 # srcrepo, because bookmarks.pending is written only into repo.
201 201 # See also https://www.mercurial-scm.org/wiki/SharedRepository
202 202 return orig(repo)
203 203
204 204 def recordchange(orig, self, tr):
205 205 # Continue with write to local bookmarks file as usual
206 206 orig(self, tr)
207 207
208 208 if _hassharedbookmarks(self._repo):
209 209 srcrepo = _getsrcrepo(self._repo)
210 210 if srcrepo is not None:
211 211 category = 'share-bookmarks'
212 212 tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
213 213
214 214 def writerepo(orig, self, repo):
215 215 # First write local bookmarks file in case we ever unshare
216 216 orig(self, repo)
217 217
218 218 if _hassharedbookmarks(self._repo):
219 219 srcrepo = _getsrcrepo(self._repo)
220 220 if srcrepo is not None:
221 221 orig(self, srcrepo)
General Comments 0
You need to be logged in to leave comments. Login now