##// END OF EJS Templates
narrow: use diffmatcher to send only new filelogs in non-ellipses widening...
Pulkit Goyal -
r39701:c73c7653 default
parent child Browse files
Show More
@@ -1,335 +1,339 b''
1 1 # narrowbundle2.py - bundle2 extensions for narrow repository support
2 2 #
3 3 # Copyright 2017 Google, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import struct
12 12
13 13 from mercurial.i18n import _
14 14 from mercurial.node import (
15 15 bin,
16 16 nullid,
17 17 )
18 18 from mercurial import (
19 19 bundle2,
20 20 changegroup,
21 21 error,
22 22 exchange,
23 23 extensions,
24 match as matchmod,
24 25 narrowspec,
25 26 repair,
26 27 repository,
27 28 util,
28 29 wireprototypes,
29 30 )
30 31 from mercurial.utils import (
31 32 stringutil,
32 33 )
33 34
34 35 NARROWCAP = 'narrow'
35 36 _NARROWACL_SECTION = 'narrowhgacl'
36 37 _CHANGESPECPART = NARROWCAP + ':changespec'
37 38 _SPECPART = NARROWCAP + ':spec'
38 39 _SPECPART_INCLUDE = 'include'
39 40 _SPECPART_EXCLUDE = 'exclude'
40 41 _KILLNODESIGNAL = 'KILL'
41 42 _DONESIGNAL = 'DONE'
42 43 _ELIDEDCSHEADER = '>20s20s20sl' # cset id, p1, p2, len(text)
43 44 _ELIDEDMFHEADER = '>20s20s20s20sl' # manifest id, p1, p2, link id, len(text)
44 45 _CSHEADERSIZE = struct.calcsize(_ELIDEDCSHEADER)
45 46 _MFHEADERSIZE = struct.calcsize(_ELIDEDMFHEADER)
46 47
47 48 # When advertising capabilities, always include narrow clone support.
48 49 def getrepocaps_narrow(orig, repo, **kwargs):
49 50 caps = orig(repo, **kwargs)
50 51 caps[NARROWCAP] = ['v0']
51 52 return caps
52 53
53 54 def getbundlechangegrouppart_widen(bundler, repo, source, bundlecaps=None,
54 55 b2caps=None, heads=None, common=None,
55 56 **kwargs):
56 57 """Handling changegroup changegroup generation on the server when user
57 58 is widening their narrowspec"""
58 59
59 60 cgversions = b2caps.get('changegroup')
60 61 if cgversions: # 3.1 and 3.2 ship with an empty value
61 62 cgversions = [v for v in cgversions
62 63 if v in changegroup.supportedoutgoingversions(repo)]
63 64 if not cgversions:
64 65 raise ValueError(_('no common changegroup version'))
65 66 version = max(cgversions)
66 67 else:
67 68 raise ValueError(_("server does not advertise changegroup version,"
68 69 " can't negotiate support for ellipsis nodes"))
69 70
70 71 include = sorted(filter(bool, kwargs.get(r'includepats', [])))
71 72 exclude = sorted(filter(bool, kwargs.get(r'excludepats', [])))
72 73 newmatch = narrowspec.match(repo.root, include=include, exclude=exclude)
73 74 oldinclude = sorted(filter(bool, kwargs.get(r'oldincludepats', [])))
74 75 oldexclude = sorted(filter(bool, kwargs.get(r'oldexcludepats', [])))
76 oldmatch = narrowspec.match(repo.root, include=oldinclude,
77 exclude=oldexclude)
78 diffmatch = matchmod.differencematcher(newmatch, oldmatch)
75 79 common = set(common or [nullid])
76 80
77 81 if (oldinclude != include or oldexclude != exclude):
78 82 common = repo.revs("::%ln", common)
79 83 commonnodes = set()
80 84 cl = repo.changelog
81 85 for c in common:
82 86 commonnodes.add(cl.node(c))
83 87 if commonnodes:
84 88 # XXX: we should only send the filelogs (and treemanifest). user
85 89 # already has the changelog and manifest
86 90 packer = changegroup.getbundler(version, repo,
87 filematcher=newmatch,
91 filematcher=diffmatch,
88 92 fullnodes=commonnodes)
89 93 cgdata = packer.generate(set([nullid]), list(commonnodes), False,
90 94 source)
91 95
92 96 part = bundler.newpart('changegroup', data=cgdata)
93 97 part.addparam('version', version)
94 98 if 'treemanifest' in repo.requirements:
95 99 part.addparam('treemanifest', '1')
96 100
97 101 # Serve a changegroup for a client with a narrow clone.
98 102 def getbundlechangegrouppart_narrow(bundler, repo, source,
99 103 bundlecaps=None, b2caps=None, heads=None,
100 104 common=None, **kwargs):
101 105 assert repo.ui.configbool('experimental', 'narrowservebrokenellipses')
102 106
103 107 cgversions = b2caps.get('changegroup')
104 108 if cgversions: # 3.1 and 3.2 ship with an empty value
105 109 cgversions = [v for v in cgversions
106 110 if v in changegroup.supportedoutgoingversions(repo)]
107 111 if not cgversions:
108 112 raise ValueError(_('no common changegroup version'))
109 113 version = max(cgversions)
110 114 else:
111 115 raise ValueError(_("server does not advertise changegroup version,"
112 116 " can't negotiate support for ellipsis nodes"))
113 117
114 118 include = sorted(filter(bool, kwargs.get(r'includepats', [])))
115 119 exclude = sorted(filter(bool, kwargs.get(r'excludepats', [])))
116 120 newmatch = narrowspec.match(repo.root, include=include, exclude=exclude)
117 121
118 122 depth = kwargs.get(r'depth', None)
119 123 if depth is not None:
120 124 depth = int(depth)
121 125 if depth < 1:
122 126 raise error.Abort(_('depth must be positive, got %d') % depth)
123 127
124 128 heads = set(heads or repo.heads())
125 129 common = set(common or [nullid])
126 130 oldinclude = sorted(filter(bool, kwargs.get(r'oldincludepats', [])))
127 131 oldexclude = sorted(filter(bool, kwargs.get(r'oldexcludepats', [])))
128 132 known = {bin(n) for n in kwargs.get(r'known', [])}
129 133 if known and (oldinclude != include or oldexclude != exclude):
130 134 # Steps:
131 135 # 1. Send kill for "$known & ::common"
132 136 #
133 137 # 2. Send changegroup for ::common
134 138 #
135 139 # 3. Proceed.
136 140 #
137 141 # In the future, we can send kills for only the specific
138 142 # nodes we know should go away or change shape, and then
139 143 # send a data stream that tells the client something like this:
140 144 #
141 145 # a) apply this changegroup
142 146 # b) apply nodes XXX, YYY, ZZZ that you already have
143 147 # c) goto a
144 148 #
145 149 # until they've built up the full new state.
146 150 # Convert to revnums and intersect with "common". The client should
147 151 # have made it a subset of "common" already, but let's be safe.
148 152 known = set(repo.revs("%ln & ::%ln", known, common))
149 153 # TODO: we could send only roots() of this set, and the
150 154 # list of nodes in common, and the client could work out
151 155 # what to strip, instead of us explicitly sending every
152 156 # single node.
153 157 deadrevs = known
154 158 def genkills():
155 159 for r in deadrevs:
156 160 yield _KILLNODESIGNAL
157 161 yield repo.changelog.node(r)
158 162 yield _DONESIGNAL
159 163 bundler.newpart(_CHANGESPECPART, data=genkills())
160 164 newvisit, newfull, newellipsis = exchange._computeellipsis(
161 165 repo, set(), common, known, newmatch)
162 166 if newvisit:
163 167 packer = changegroup.getbundler(version, repo,
164 168 filematcher=newmatch,
165 169 ellipses=True,
166 170 shallow=depth is not None,
167 171 ellipsisroots=newellipsis,
168 172 fullnodes=newfull)
169 173 cgdata = packer.generate(common, newvisit, False, source)
170 174
171 175 part = bundler.newpart('changegroup', data=cgdata)
172 176 part.addparam('version', version)
173 177 if 'treemanifest' in repo.requirements:
174 178 part.addparam('treemanifest', '1')
175 179
176 180 visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
177 181 repo, common, heads, set(), newmatch, depth=depth)
178 182
179 183 repo.ui.debug('Found %d relevant revs\n' % len(relevant_nodes))
180 184 if visitnodes:
181 185 packer = changegroup.getbundler(version, repo,
182 186 filematcher=newmatch,
183 187 ellipses=True,
184 188 shallow=depth is not None,
185 189 ellipsisroots=ellipsisroots,
186 190 fullnodes=relevant_nodes)
187 191 cgdata = packer.generate(common, visitnodes, False, source)
188 192
189 193 part = bundler.newpart('changegroup', data=cgdata)
190 194 part.addparam('version', version)
191 195 if 'treemanifest' in repo.requirements:
192 196 part.addparam('treemanifest', '1')
193 197
194 198 @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
195 199 def _handlechangespec_2(op, inpart):
196 200 includepats = set(inpart.params.get(_SPECPART_INCLUDE, '').splitlines())
197 201 excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, '').splitlines())
198 202 narrowspec.validatepatterns(includepats)
199 203 narrowspec.validatepatterns(excludepats)
200 204
201 205 if not repository.NARROW_REQUIREMENT in op.repo.requirements:
202 206 op.repo.requirements.add(repository.NARROW_REQUIREMENT)
203 207 op.repo._writerequirements()
204 208 op.repo.setnarrowpats(includepats, excludepats)
205 209
206 210 @bundle2.parthandler(_CHANGESPECPART)
207 211 def _handlechangespec(op, inpart):
208 212 repo = op.repo
209 213 cl = repo.changelog
210 214
211 215 # changesets which need to be stripped entirely. either they're no longer
212 216 # needed in the new narrow spec, or the server is sending a replacement
213 217 # in the changegroup part.
214 218 clkills = set()
215 219
216 220 # A changespec part contains all the updates to ellipsis nodes
217 221 # that will happen as a result of widening or narrowing a
218 222 # repo. All the changes that this block encounters are ellipsis
219 223 # nodes or flags to kill an existing ellipsis.
220 224 chunksignal = changegroup.readexactly(inpart, 4)
221 225 while chunksignal != _DONESIGNAL:
222 226 if chunksignal == _KILLNODESIGNAL:
223 227 # a node used to be an ellipsis but isn't anymore
224 228 ck = changegroup.readexactly(inpart, 20)
225 229 if cl.hasnode(ck):
226 230 clkills.add(ck)
227 231 else:
228 232 raise error.Abort(
229 233 _('unexpected changespec node chunk type: %s') % chunksignal)
230 234 chunksignal = changegroup.readexactly(inpart, 4)
231 235
232 236 if clkills:
233 237 # preserve bookmarks that repair.strip() would otherwise strip
234 238 bmstore = repo._bookmarks
235 239 class dummybmstore(dict):
236 240 def applychanges(self, repo, tr, changes):
237 241 pass
238 242 def recordchange(self, tr): # legacy version
239 243 pass
240 244 repo._bookmarks = dummybmstore()
241 245 chgrpfile = repair.strip(op.ui, repo, list(clkills), backup=True,
242 246 topic='widen')
243 247 repo._bookmarks = bmstore
244 248 if chgrpfile:
245 249 op._widen_uninterr = repo.ui.uninterruptable()
246 250 op._widen_uninterr.__enter__()
247 251 # presence of _widen_bundle attribute activates widen handler later
248 252 op._widen_bundle = chgrpfile
249 253 # Set the new narrowspec if we're widening. The setnewnarrowpats() method
250 254 # will currently always be there when using the core+narrowhg server, but
251 255 # other servers may include a changespec part even when not widening (e.g.
252 256 # because we're deepening a shallow repo).
253 257 if util.safehasattr(repo, 'setnewnarrowpats'):
254 258 repo.setnewnarrowpats()
255 259
256 260 def handlechangegroup_widen(op, inpart):
257 261 """Changegroup exchange handler which restores temporarily-stripped nodes"""
258 262 # We saved a bundle with stripped node data we must now restore.
259 263 # This approach is based on mercurial/repair.py@6ee26a53c111.
260 264 repo = op.repo
261 265 ui = op.ui
262 266
263 267 chgrpfile = op._widen_bundle
264 268 del op._widen_bundle
265 269 vfs = repo.vfs
266 270
267 271 ui.note(_("adding branch\n"))
268 272 f = vfs.open(chgrpfile, "rb")
269 273 try:
270 274 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
271 275 if not ui.verbose:
272 276 # silence internal shuffling chatter
273 277 ui.pushbuffer()
274 278 if isinstance(gen, bundle2.unbundle20):
275 279 with repo.transaction('strip') as tr:
276 280 bundle2.processbundle(repo, gen, lambda: tr)
277 281 else:
278 282 gen.apply(repo, 'strip', 'bundle:' + vfs.join(chgrpfile), True)
279 283 if not ui.verbose:
280 284 ui.popbuffer()
281 285 finally:
282 286 f.close()
283 287
284 288 # remove undo files
285 289 for undovfs, undofile in repo.undofiles():
286 290 try:
287 291 undovfs.unlink(undofile)
288 292 except OSError as e:
289 293 if e.errno != errno.ENOENT:
290 294 ui.warn(_('error removing %s: %s\n') %
291 295 (undovfs.join(undofile), stringutil.forcebytestr(e)))
292 296
293 297 # Remove partial backup only if there were no exceptions
294 298 op._widen_uninterr.__exit__(None, None, None)
295 299 vfs.unlink(chgrpfile)
296 300
297 301 def setup():
298 302 """Enable narrow repo support in bundle2-related extension points."""
299 303 extensions.wrapfunction(bundle2, 'getrepocaps', getrepocaps_narrow)
300 304
301 305 getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS
302 306
303 307 getbundleargs['narrow'] = 'boolean'
304 308 getbundleargs['widen'] = 'boolean'
305 309 getbundleargs['depth'] = 'plain'
306 310 getbundleargs['oldincludepats'] = 'csv'
307 311 getbundleargs['oldexcludepats'] = 'csv'
308 312 getbundleargs['includepats'] = 'csv'
309 313 getbundleargs['excludepats'] = 'csv'
310 314 getbundleargs['known'] = 'csv'
311 315
312 316 # Extend changegroup serving to handle requests from narrow clients.
313 317 origcgfn = exchange.getbundle2partsmapping['changegroup']
314 318 def wrappedcgfn(*args, **kwargs):
315 319 repo = args[1]
316 320 if repo.ui.has_section(_NARROWACL_SECTION):
317 321 kwargs = exchange.applynarrowacl(repo, kwargs)
318 322
319 323 if (kwargs.get(r'narrow', False) and
320 324 repo.ui.configbool('experimental', 'narrowservebrokenellipses')):
321 325 getbundlechangegrouppart_narrow(*args, **kwargs)
322 326 elif kwargs.get(r'widen', False) and kwargs.get(r'narrow', False):
323 327 getbundlechangegrouppart_widen(*args, **kwargs)
324 328 else:
325 329 origcgfn(*args, **kwargs)
326 330 exchange.getbundle2partsmapping['changegroup'] = wrappedcgfn
327 331
328 332 # Extend changegroup receiver so client can fixup after widen requests.
329 333 origcghandler = bundle2.parthandlermapping['changegroup']
330 334 def wrappedcghandler(op, inpart):
331 335 origcghandler(op, inpart)
332 336 if util.safehasattr(op, '_widen_bundle'):
333 337 handlechangegroup_widen(op, inpart)
334 338 wrappedcghandler.params = origcghandler.params
335 339 bundle2.parthandlermapping['changegroup'] = wrappedcghandler
@@ -1,389 +1,389 b''
1 1 #testcases tree flat
2 2 $ . "$TESTDIR/narrow-library.sh"
3 3
4 4 #if tree
5 5 $ cat << EOF >> $HGRCPATH
6 6 > [experimental]
7 7 > treemanifest = 1
8 8 > EOF
9 9 #endif
10 10
11 11 $ hg init master
12 12 $ cd master
13 13
14 14 $ mkdir inside
15 15 $ echo 'inside' > inside/f
16 16 $ hg add inside/f
17 17 $ hg commit -m 'add inside'
18 18
19 19 $ mkdir widest
20 20 $ echo 'widest' > widest/f
21 21 $ hg add widest/f
22 22 $ hg commit -m 'add widest'
23 23
24 24 $ mkdir outside
25 25 $ echo 'outside' > outside/f
26 26 $ hg add outside/f
27 27 $ hg commit -m 'add outside'
28 28
29 29 $ cd ..
30 30
31 31 narrow clone the inside file
32 32
33 33 $ hg clone --narrow ssh://user@dummy/master narrow --include inside
34 34 requesting all changes
35 35 adding changesets
36 36 adding manifests
37 37 adding file changes
38 38 added 3 changesets with 1 changes to 1 files
39 39 new changesets *:* (glob)
40 40 updating to branch default
41 41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 $ cd narrow
43 43 $ hg tracked
44 44 I path:inside
45 45 $ ls
46 46 inside
47 47 $ cat inside/f
48 48 inside
49 49 $ cd ..
50 50
51 51 add more upstream files which we will include in a wider narrow spec
52 52
53 53 $ cd master
54 54
55 55 $ mkdir wider
56 56 $ echo 'wider' > wider/f
57 57 $ hg add wider/f
58 58 $ echo 'widest v2' > widest/f
59 59 $ hg commit -m 'add wider, update widest'
60 60
61 61 $ echo 'widest v3' > widest/f
62 62 $ hg commit -m 'update widest v3'
63 63
64 64 $ echo 'inside v2' > inside/f
65 65 $ hg commit -m 'update inside'
66 66
67 67 $ mkdir outside2
68 68 $ echo 'outside2' > outside2/f
69 69 $ hg add outside2/f
70 70 $ hg commit -m 'add outside2'
71 71
72 72 $ echo 'widest v4' > widest/f
73 73 $ hg commit -m 'update widest v4'
74 74
75 75 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
76 76 7: update widest v4
77 77 6: add outside2
78 78 5: update inside
79 79 4: update widest v3
80 80 3: add wider, update widest
81 81 2: add outside
82 82 1: add widest
83 83 0: add inside
84 84
85 85 $ cd ..
86 86
87 87 Widen the narrow spec to see the widest file. This should not get the newly
88 88 added upstream revisions.
89 89
90 90 $ cd narrow
91 91 $ hg tracked --addinclude widest/f
92 92 comparing with ssh://user@dummy/master
93 93 searching for changes
94 94 no changes found
95 95 adding changesets
96 96 adding manifests
97 97 adding file changes
98 added 0 changesets with 1 changes to 2 files
98 added 0 changesets with 1 changes to 1 files
99 99 3 local changesets published
100 100 $ hg tracked
101 101 I path:inside
102 102 I path:widest/f
103 103
104 104 $ cat widest/f
105 105 widest
106 106
107 107 Pull down the newly added upstream revision.
108 108
109 109 $ hg pull
110 110 pulling from ssh://user@dummy/master
111 111 searching for changes
112 112 adding changesets
113 113 adding manifests
114 114 adding file changes
115 115 added 5 changesets with 4 changes to 2 files
116 116 new changesets *:* (glob)
117 117 (run 'hg update' to get a working copy)
118 118 $ hg update -r 'desc("add wider")'
119 119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 120
121 121 $ cat widest/f
122 122 widest v2
123 123
124 124 $ hg update -r 'desc("update inside")'
125 125 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 126 $ cat widest/f
127 127 widest v3
128 128 $ cat inside/f
129 129 inside v2
130 130
131 131 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
132 132 7: update widest v4
133 133 6: add outside2
134 134 5: update inside
135 135 4: update widest v3
136 136 3: add wider, update widest
137 137 2: add outside
138 138 1: add widest
139 139 0: add inside
140 140
141 141 Check that widening with a newline fails
142 142
143 143 $ hg tracked --addinclude 'widest
144 144 > '
145 145 abort: newlines are not allowed in narrowspec paths
146 146 [255]
147 147
148 148 widen the narrow spec to include the wider file
149 149
150 150 $ hg tracked --addinclude wider
151 151 comparing with ssh://user@dummy/master
152 152 searching for changes
153 153 no changes found
154 154 adding changesets
155 155 adding manifests
156 156 adding file changes
157 added 0 changesets with 1 changes to 3 files
157 added 0 changesets with 1 changes to 1 files
158 158 5 local changesets published
159 159 $ hg tracked
160 160 I path:inside
161 161 I path:wider
162 162 I path:widest/f
163 163 $ hg update 'desc("add widest")'
164 164 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
165 165 $ cat widest/f
166 166 widest
167 167 $ hg update 'desc("add wider, update widest")'
168 168 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 169 $ cat wider/f
170 170 wider
171 171 $ cat widest/f
172 172 widest v2
173 173 $ hg update 'desc("update widest v3")'
174 174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 175 $ cat widest/f
176 176 widest v3
177 177 $ hg update 'desc("update widest v4")'
178 178 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 179 $ cat widest/f
180 180 widest v4
181 181
182 182 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
183 183 7: update widest v4
184 184 6: add outside2
185 185 5: update inside
186 186 4: update widest v3
187 187 3: add wider, update widest
188 188 2: add outside
189 189 1: add widest
190 190 0: add inside
191 191
192 192 separate suite of tests: files from 0-10 modified in changes 0-10. This allows
193 193 more obvious precise tests tickling particular corner cases.
194 194
195 195 $ cd ..
196 196 $ hg init upstream
197 197 $ cd upstream
198 198 $ for x in `$TESTDIR/seq.py 0 10`
199 199 > do
200 200 > mkdir d$x
201 201 > echo $x > d$x/f
202 202 > hg add d$x/f
203 203 > hg commit -m "add d$x/f"
204 204 > done
205 205 $ hg log -T "{rev}: {desc}\n"
206 206 10: add d10/f
207 207 9: add d9/f
208 208 8: add d8/f
209 209 7: add d7/f
210 210 6: add d6/f
211 211 5: add d5/f
212 212 4: add d4/f
213 213 3: add d3/f
214 214 2: add d2/f
215 215 1: add d1/f
216 216 0: add d0/f
217 217
218 218 make narrow clone with every third node.
219 219
220 220 $ cd ..
221 221 $ hg clone --narrow ssh://user@dummy/upstream narrow2 --include d0 --include d3 --include d6 --include d9
222 222 requesting all changes
223 223 adding changesets
224 224 adding manifests
225 225 adding file changes
226 226 added 11 changesets with 4 changes to 4 files
227 227 new changesets *:* (glob)
228 228 updating to branch default
229 229 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 230 $ cd narrow2
231 231 $ hg tracked
232 232 I path:d0
233 233 I path:d3
234 234 I path:d6
235 235 I path:d9
236 236 $ hg verify
237 237 checking changesets
238 238 checking manifests
239 239 checking directory manifests (tree !)
240 240 crosschecking files in changesets and manifests
241 241 checking files
242 242 checked 11 changesets with 4 changes to 4 files
243 243 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
244 244 10: add d10/f
245 245 9: add d9/f
246 246 8: add d8/f
247 247 7: add d7/f
248 248 6: add d6/f
249 249 5: add d5/f
250 250 4: add d4/f
251 251 3: add d3/f
252 252 2: add d2/f
253 253 1: add d1/f
254 254 0: add d0/f
255 255 $ hg tracked --addinclude d1
256 256 comparing with ssh://user@dummy/upstream
257 257 searching for changes
258 258 no changes found
259 259 adding changesets
260 260 adding manifests
261 261 adding file changes
262 added 0 changesets with 1 changes to 5 files
262 added 0 changesets with 1 changes to 1 files
263 263 11 local changesets published
264 264 $ hg tracked
265 265 I path:d0
266 266 I path:d1
267 267 I path:d3
268 268 I path:d6
269 269 I path:d9
270 270 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
271 271 10: add d10/f
272 272 9: add d9/f
273 273 8: add d8/f
274 274 7: add d7/f
275 275 6: add d6/f
276 276 5: add d5/f
277 277 4: add d4/f
278 278 3: add d3/f
279 279 2: add d2/f
280 280 1: add d1/f
281 281 0: add d0/f
282 282
283 283 Verify shouldn't claim the repo is corrupt after a widen.
284 284
285 285 $ hg verify
286 286 checking changesets
287 287 checking manifests
288 288 checking directory manifests (tree !)
289 289 crosschecking files in changesets and manifests
290 290 checking files
291 291 checked 11 changesets with 5 changes to 5 files
292 292
293 293 Widening preserves parent of local commit
294 294
295 295 $ cd ..
296 296 $ hg clone -q --narrow ssh://user@dummy/upstream narrow3 --include d2 -r 2
297 297 $ cd narrow3
298 298 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
299 299 2: add d2/f
300 300 1: add d1/f
301 301 0: add d0/f
302 302 $ hg pull -q -r 3
303 303 $ hg co -q tip
304 304 $ hg pull -q -r 4
305 305 $ echo local > d2/f
306 306 $ hg ci -m local
307 307 created new head
308 308 $ hg tracked -q --addinclude d0 --addinclude d9
309 309
310 310 Widening preserves bookmarks
311 311
312 312 $ cd ..
313 313 $ hg clone -q --narrow ssh://user@dummy/upstream narrow-bookmarks --include d4
314 314 $ cd narrow-bookmarks
315 315 $ echo local > d4/f
316 316 $ hg ci -m local
317 317 $ hg bookmarks bookmark
318 318 $ hg bookmarks
319 319 * bookmark 11:* (glob)
320 320 $ hg -q tracked --addinclude d2
321 321 $ hg bookmarks
322 322 * bookmark 11:* (glob)
323 323 $ hg log -r bookmark -T '{desc}\n'
324 324 local
325 325
326 326 Widening that fails can be recovered from
327 327
328 328 $ cd ..
329 329 $ hg clone -q --narrow ssh://user@dummy/upstream interrupted --include d0
330 330 $ cd interrupted
331 331 $ echo local > d0/f
332 332 $ hg ci -m local
333 333 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
334 334 11: local
335 335 10: add d10/f
336 336 9: add d9/f
337 337 8: add d8/f
338 338 7: add d7/f
339 339 6: add d6/f
340 340 5: add d5/f
341 341 4: add d4/f
342 342 3: add d3/f
343 343 2: add d2/f
344 344 1: add d1/f
345 345 0: add d0/f
346 346 $ hg bookmarks bookmark
347 347 $ hg --config hooks.pretxnchangegroup.bad=false tracked --addinclude d1
348 348 comparing with ssh://user@dummy/upstream
349 349 searching for changes
350 350 no changes found
351 351 adding changesets
352 352 adding manifests
353 353 adding file changes
354 added 0 changesets with 1 changes to 2 files
354 added 0 changesets with 1 changes to 1 files
355 355 11 local changesets published
356 356 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
357 357 11: local
358 358 10: add d10/f
359 359 9: add d9/f
360 360 8: add d8/f
361 361 7: add d7/f
362 362 6: add d6/f
363 363 5: add d5/f
364 364 4: add d4/f
365 365 3: add d3/f
366 366 2: add d2/f
367 367 1: add d1/f
368 368 0: add d0/f
369 369 $ hg bookmarks
370 370 * bookmark 11:* (glob)
371 371 $ hg unbundle .hg/strip-backup/*-widen.hg
372 372 abort: .hg/strip-backup/*-widen.hg: $ENOTDIR$ (windows !)
373 373 abort: $ENOENT$: .hg/strip-backup/*-widen.hg (no-windows !)
374 374 [255]
375 375 $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
376 376 11: local
377 377 10: add d10/f
378 378 9: add d9/f
379 379 8: add d8/f
380 380 7: add d7/f
381 381 6: add d6/f
382 382 5: add d5/f
383 383 4: add d4/f
384 384 3: add d3/f
385 385 2: add d2/f
386 386 1: add d1/f
387 387 0: add d0/f
388 388 $ hg bookmarks
389 389 * bookmark 11:* (glob)
General Comments 0
You need to be logged in to leave comments. Login now