Show More
@@ -1,6 +1,3 b'' | |||
|
1 | Integration with the share extension needs improvement. Right now | |
|
2 | we've seen some odd bugs. | |
|
3 | ||
|
4 | 1 |
|
|
5 | 2 | specifically we should improve the collaboration with core so that |
|
6 | 3 | add() never gets called on an excluded directory and we can improve |
@@ -339,6 +339,8 b' def _widen(ui, repo, remote, commoninc, ' | |||
|
339 | 339 | ('', 'clear', False, _('whether to replace the existing narrowspec')), |
|
340 | 340 | ('', 'force-delete-local-changes', False, |
|
341 | 341 | _('forces deletion of local changes when narrowing')), |
|
342 | ('', 'update-working-copy', False, | |
|
343 | _('update working copy when the store has changed')), | |
|
342 | 344 | ] + commands.remoteopts, |
|
343 | 345 | _('[OPTIONS]... [REMOTE]'), |
|
344 | 346 | inferrepo=True) |
@@ -398,8 +400,9 b' def trackedcmd(ui, repo, remotepath=None' | |||
|
398 | 400 | addedexcludes = narrowspec.parsepatterns(opts['addexclude']) |
|
399 | 401 | removedexcludes = narrowspec.parsepatterns(opts['removeexclude']) |
|
400 | 402 | |
|
403 | update_working_copy = opts['update_working_copy'] | |
|
401 | 404 | only_show = not (addedincludes or removedincludes or addedexcludes or |
|
402 | removedexcludes or newrules) | |
|
405 | removedexcludes or newrules or update_working_copy) | |
|
403 | 406 | |
|
404 | 407 | oldincludes, oldexcludes = repo.narrowpats |
|
405 | 408 | |
@@ -428,6 +431,12 b' def trackedcmd(ui, repo, remotepath=None' | |||
|
428 | 431 | fm.end() |
|
429 | 432 | return 0 |
|
430 | 433 | |
|
434 | if update_working_copy: | |
|
435 | with repo.wlock(), repo.lock(), repo.transaction('narrow-wc') as tr: | |
|
436 | narrowspec.updateworkingcopy(repo, tr) | |
|
437 | narrowspec.copytoworkingcopy(repo, tr) | |
|
438 | return 0 | |
|
439 | ||
|
431 | 440 | if not widening and not narrowing: |
|
432 | 441 | ui.status(_("nothing to widen or narrow\n")) |
|
433 | 442 | return 0 |
@@ -38,6 +38,7 b' from . import (' | |||
|
38 | 38 | narrowspec, |
|
39 | 39 | node, |
|
40 | 40 | phases, |
|
41 | repository as repositorymod, | |
|
41 | 42 | scmutil, |
|
42 | 43 | sshpeer, |
|
43 | 44 | statichttprepo, |
@@ -331,6 +332,9 b' def postshare(sourcerepo, destrepo, defa' | |||
|
331 | 332 | template = ('[paths]\n' |
|
332 | 333 | 'default = %s\n') |
|
333 | 334 | destrepo.vfs.write('hgrc', util.tonativeeol(template % default)) |
|
335 | if repositorymod.NARROW_REQUIREMENT in sourcerepo.requirements: | |
|
336 | with destrepo.wlock(): | |
|
337 | narrowspec.copytoworkingcopy(destrepo, None) | |
|
334 | 338 | |
|
335 | 339 | def _postshareupdate(repo, update, checkout=None): |
|
336 | 340 | """Maybe perform a working directory update after a shared repo is created. |
@@ -731,7 +735,7 b' def clone(ui, peeropts, source, dest=Non' | |||
|
731 | 735 | local = destpeer.local() |
|
732 | 736 | if local: |
|
733 | 737 | if narrow: |
|
734 | with local.lock(): | |
|
738 | with local.wlock(), local.lock(): | |
|
735 | 739 | local.setnarrowpats(storeincludepats, storeexcludepats) |
|
736 | 740 | |
|
737 | 741 | u = util.url(abspath) |
@@ -1227,6 +1227,7 b' class localrepository(object):' | |||
|
1227 | 1227 | def _narrowmatch(self): |
|
1228 | 1228 | if repository.NARROW_REQUIREMENT not in self.requirements: |
|
1229 | 1229 | return matchmod.always(self.root, '') |
|
1230 | narrowspec.checkworkingcopynarrowspec(self) | |
|
1230 | 1231 | include, exclude = self.narrowpats |
|
1231 | 1232 | return narrowspec.match(self.root, include=include, exclude=exclude) |
|
1232 | 1233 | |
@@ -1251,7 +1252,14 b' class localrepository(object):' | |||
|
1251 | 1252 | |
|
1252 | 1253 | def setnarrowpats(self, newincludes, newexcludes): |
|
1253 | 1254 | narrowspec.save(self, newincludes, newexcludes) |
|
1255 | narrowspec.copytoworkingcopy(self, self.currenttransaction()) | |
|
1254 | 1256 | self.invalidate(clearfilecache=True) |
|
1257 | # So the next access won't be considered a conflict | |
|
1258 | # TODO: It seems like there should be a way of doing this that | |
|
1259 | # doesn't involve replacing these attributes. | |
|
1260 | self.narrowpats = newincludes, newexcludes | |
|
1261 | self._narrowmatch = narrowspec.match(self.root, include=newincludes, | |
|
1262 | exclude=newexcludes) | |
|
1255 | 1263 | |
|
1256 | 1264 | def __getitem__(self, changeid): |
|
1257 | 1265 | if changeid is None: |
@@ -13,12 +13,16 b' from .i18n import _' | |||
|
13 | 13 | from . import ( |
|
14 | 14 | error, |
|
15 | 15 | match as matchmod, |
|
16 | merge, | |
|
16 | 17 | repository, |
|
17 | 18 | sparse, |
|
18 | 19 | util, |
|
19 | 20 | ) |
|
20 | 21 | |
|
22 | # The file in .hg/store/ that indicates which paths exit in the store | |
|
21 | 23 | FILENAME = 'narrowspec' |
|
24 | # The file in .hg/ that indicates which paths exit in the dirstate | |
|
25 | DIRSTATE_FILENAME = 'narrowspec.dirstate' | |
|
22 | 26 | |
|
23 | 27 | # Pattern prefixes that are allowed in narrow patterns. This list MUST |
|
24 | 28 | # only contain patterns that are fast and safe to evaluate. Keep in mind |
@@ -157,6 +161,18 b' def save(repo, includepats, excludepats)' | |||
|
157 | 161 | spec = format(includepats, excludepats) |
|
158 | 162 | repo.svfs.write(FILENAME, spec) |
|
159 | 163 | |
|
164 | def copytoworkingcopy(repo, tr): | |
|
165 | if tr: | |
|
166 | def write(file): | |
|
167 | spec = repo.svfs.read(FILENAME) | |
|
168 | file.write(spec) | |
|
169 | file.close() | |
|
170 | tr.addfilegenerator('narrowspec', (DIRSTATE_FILENAME,), write, | |
|
171 | location='plain') | |
|
172 | else: | |
|
173 | spec = repo.svfs.read(FILENAME) | |
|
174 | repo.vfs.write(DIRSTATE_FILENAME, spec) | |
|
175 | ||
|
160 | 176 | def savebackup(repo, backupname): |
|
161 | 177 | if repository.NARROW_REQUIREMENT not in repo.requirements: |
|
162 | 178 | return |
@@ -226,3 +242,57 b' def restrictpatterns(req_includes, req_e' | |||
|
226 | 242 | else: |
|
227 | 243 | res_includes = set(req_includes) |
|
228 | 244 | return res_includes, res_excludes, invalid_includes |
|
245 | ||
|
246 | # These two are extracted for extensions (specifically for Google's CitC file | |
|
247 | # system) | |
|
248 | def _deletecleanfiles(repo, files): | |
|
249 | for f in files: | |
|
250 | repo.wvfs.unlinkpath(f) | |
|
251 | ||
|
252 | def _writeaddedfiles(repo, pctx, files): | |
|
253 | actions = merge.emptyactions() | |
|
254 | addgaction = actions['g'].append | |
|
255 | mf = repo['.'].manifest() | |
|
256 | for f in files: | |
|
257 | if not repo.wvfs.exists(f): | |
|
258 | addgaction((f, (mf.flags(f), False), "narrowspec updated")) | |
|
259 | merge.applyupdates(repo, actions, wctx=repo[None], | |
|
260 | mctx=repo['.'], overwrite=False) | |
|
261 | ||
|
262 | def checkworkingcopynarrowspec(repo): | |
|
263 | storespec = repo.svfs.tryread(FILENAME) | |
|
264 | wcspec = repo.vfs.tryread(DIRSTATE_FILENAME) | |
|
265 | if wcspec != storespec: | |
|
266 | raise error.Abort(_("working copy's narrowspec is stale"), | |
|
267 | hint=_("run 'hg tracked --update-working-copy'")) | |
|
268 | ||
|
269 | def updateworkingcopy(repo, tr): | |
|
270 | oldspec = repo.vfs.tryread(DIRSTATE_FILENAME) | |
|
271 | newspec = repo.svfs.tryread(FILENAME) | |
|
272 | ||
|
273 | oldincludes, oldexcludes = parseconfig(repo.ui, oldspec) | |
|
274 | newincludes, newexcludes = parseconfig(repo.ui, newspec) | |
|
275 | oldmatch = match(repo.root, include=oldincludes, exclude=oldexcludes) | |
|
276 | newmatch = match(repo.root, include=newincludes, exclude=newexcludes) | |
|
277 | addedmatch = matchmod.differencematcher(newmatch, oldmatch) | |
|
278 | removedmatch = matchmod.differencematcher(oldmatch, newmatch) | |
|
279 | ||
|
280 | ds = repo.dirstate | |
|
281 | lookup, status = ds.status(removedmatch, subrepos=[], ignored=False, | |
|
282 | clean=True, unknown=False) | |
|
283 | _deletecleanfiles(repo, status.clean) | |
|
284 | trackeddirty = lookup + status.modified + status.added | |
|
285 | for f in sorted(trackeddirty): | |
|
286 | repo.ui.status(_('not deleting possibly dirty file %s\n') % f) | |
|
287 | for f in status.clean + trackeddirty: | |
|
288 | ds.drop(f) | |
|
289 | ||
|
290 | repo.narrowpats = newincludes, newexcludes | |
|
291 | repo._narrowmatch = newmatch | |
|
292 | pctx = repo['.'] | |
|
293 | newfiles = [f for f in pctx.manifest().walk(addedmatch) if f not in ds] | |
|
294 | for f in newfiles: | |
|
295 | ds.normallookup(f) | |
|
296 | _writeaddedfiles(repo, pctx, newfiles) | |
|
297 | ||
|
298 | ds.write(tr) |
@@ -6,6 +6,7 b'' | |||
|
6 | 6 | > path:foo |
|
7 | 7 | > [exclude] |
|
8 | 8 | > EOF |
|
9 | $ cp .hg/store/narrowspec .hg/narrowspec.dirstate | |
|
9 | 10 | $ echo treemanifest >> .hg/requires |
|
10 | 11 | $ echo narrowhg-experimental >> .hg/requires |
|
11 | 12 | $ mkdir -p foo/bar |
@@ -75,13 +75,20 b' Narrow the share and check that the main' | |||
|
75 | 75 | deleting meta/d5/00manifest.i (tree !) |
|
76 | 76 | $ hg -R main tracked |
|
77 | 77 | I path:d7 |
|
78 | $ hg -R main files | |
|
79 | abort: working copy's narrowspec is stale | |
|
80 | (run 'hg tracked --update-working-copy') | |
|
81 | [255] | |
|
82 | $ hg -R main tracked --update-working-copy | |
|
83 | not deleting possibly dirty file d3/f | |
|
84 | not deleting possibly dirty file d3/g | |
|
85 | not deleting possibly dirty file d5/f | |
|
78 | 86 |
|
|
79 | 87 | $ hg -R main files |
|
80 | 88 | main/d7/f |
|
81 | 89 |
|
|
82 | 90 |
|
|
83 | 91 | $ find main/d* -type f | sort |
|
84 | main/d1/f | |
|
85 | 92 | main/d3/f |
|
86 | 93 | main/d3/g |
|
87 | 94 | main/d5/f |
@@ -102,16 +109,20 b' Widen the share and check that the main ' | |||
|
102 | 109 | I path:d1 |
|
103 | 110 | I path:d3 |
|
104 | 111 | I path:d7 |
|
112 | $ hg -R main files | |
|
113 | abort: working copy's narrowspec is stale | |
|
114 | (run 'hg tracked --update-working-copy') | |
|
115 | [255] | |
|
116 | $ hg -R main tracked --update-working-copy | |
|
105 | 117 | # d1/f, d3/f should be back |
|
106 | 118 | $ hg -R main files |
|
107 | 119 | main/d1/f |
|
108 | 120 | main/d3/f |
|
109 | main/d3/g | |
|
110 | 121 | main/d7/f |
|
111 | 122 | # d3/f should be modified (not clobbered by the widening), and d3/g should be untracked |
|
112 | 123 | $ hg -R main st --all |
|
113 | 124 | M d3/f |
|
114 |
|
|
|
125 | ? d3/g | |
|
115 | 126 | C d1/f |
|
116 | 127 | C d7/f |
|
117 | 128 | |
@@ -130,3 +141,30 b' We should also be able to unshare withou' | |||
|
130 | 141 | checking files |
|
131 | 142 | checked 11 changesets with 3 changes to 3 files |
|
132 | 143 | $ cd .. |
|
144 | ||
|
145 | Dirstate should be left alone when upgrading from version of hg that didn't support narrow+share | |
|
146 | ||
|
147 | $ hg share main share-upgrade | |
|
148 | updating working directory | |
|
149 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
150 | $ cd share-upgrade | |
|
151 | $ echo x >> d1/f | |
|
152 | $ echo y >> d3/g | |
|
153 | $ hg add d3/g | |
|
154 | $ hg rm d7/f | |
|
155 | $ hg st | |
|
156 | M d1/f | |
|
157 | A d3/g | |
|
158 | R d7/f | |
|
159 | Make it look like a repo from before narrow+share was supported | |
|
160 | $ rm .hg/narrowspec.dirstate | |
|
161 | $ hg st | |
|
162 | abort: working copy's narrowspec is stale | |
|
163 | (run 'hg tracked --update-working-copy') | |
|
164 | [255] | |
|
165 | $ hg tracked --update-working-copy | |
|
166 | $ hg st | |
|
167 | M d1/f | |
|
168 | A d3/g | |
|
169 | R d7/f | |
|
170 | $ cd .. |
@@ -107,6 +107,8 b' Testing the --import-rules flag of `hg t' | |||
|
107 | 107 | --clear whether to replace the existing narrowspec |
|
108 | 108 | --force-delete-local-changes forces deletion of local changes when |
|
109 | 109 | narrowing |
|
110 | --update-working-copy update working copy when the store has | |
|
111 | changed | |
|
110 | 112 | -e --ssh CMD specify ssh command to use |
|
111 | 113 | --remotecmd CMD specify hg command to run on the remote side |
|
112 | 114 | --insecure do not verify server certificate (ignoring |
General Comments 0
You need to be logged in to leave comments.
Login now