##// END OF EJS Templates
revlogv2: allow upgrading to v2...
Raphaël Gomès -
r47439:fd55a9eb default
parent child Browse files
Show More
@@ -1,2627 +1,2633 b''
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import functools
10 import functools
11 import re
11 import re
12
12
13 from . import (
13 from . import (
14 encoding,
14 encoding,
15 error,
15 error,
16 )
16 )
17
17
18
18
19 def loadconfigtable(ui, extname, configtable):
19 def loadconfigtable(ui, extname, configtable):
20 """update config item known to the ui with the extension ones"""
20 """update config item known to the ui with the extension ones"""
21 for section, items in sorted(configtable.items()):
21 for section, items in sorted(configtable.items()):
22 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 knownitems = ui._knownconfig.setdefault(section, itemregister())
23 knownkeys = set(knownitems)
23 knownkeys = set(knownitems)
24 newkeys = set(items)
24 newkeys = set(items)
25 for key in sorted(knownkeys & newkeys):
25 for key in sorted(knownkeys & newkeys):
26 msg = b"extension '%s' overwrite config item '%s.%s'"
26 msg = b"extension '%s' overwrite config item '%s.%s'"
27 msg %= (extname, section, key)
27 msg %= (extname, section, key)
28 ui.develwarn(msg, config=b'warn-config')
28 ui.develwarn(msg, config=b'warn-config')
29
29
30 knownitems.update(items)
30 knownitems.update(items)
31
31
32
32
33 class configitem(object):
33 class configitem(object):
34 """represent a known config item
34 """represent a known config item
35
35
36 :section: the official config section where to find this item,
36 :section: the official config section where to find this item,
37 :name: the official name within the section,
37 :name: the official name within the section,
38 :default: default value for this item,
38 :default: default value for this item,
39 :alias: optional list of tuples as alternatives,
39 :alias: optional list of tuples as alternatives,
40 :generic: this is a generic definition, match name using regular expression.
40 :generic: this is a generic definition, match name using regular expression.
41 """
41 """
42
42
43 def __init__(
43 def __init__(
44 self,
44 self,
45 section,
45 section,
46 name,
46 name,
47 default=None,
47 default=None,
48 alias=(),
48 alias=(),
49 generic=False,
49 generic=False,
50 priority=0,
50 priority=0,
51 experimental=False,
51 experimental=False,
52 ):
52 ):
53 self.section = section
53 self.section = section
54 self.name = name
54 self.name = name
55 self.default = default
55 self.default = default
56 self.alias = list(alias)
56 self.alias = list(alias)
57 self.generic = generic
57 self.generic = generic
58 self.priority = priority
58 self.priority = priority
59 self.experimental = experimental
59 self.experimental = experimental
60 self._re = None
60 self._re = None
61 if generic:
61 if generic:
62 self._re = re.compile(self.name)
62 self._re = re.compile(self.name)
63
63
64
64
65 class itemregister(dict):
65 class itemregister(dict):
66 """A specialized dictionary that can handle wild-card selection"""
66 """A specialized dictionary that can handle wild-card selection"""
67
67
68 def __init__(self):
68 def __init__(self):
69 super(itemregister, self).__init__()
69 super(itemregister, self).__init__()
70 self._generics = set()
70 self._generics = set()
71
71
72 def update(self, other):
72 def update(self, other):
73 super(itemregister, self).update(other)
73 super(itemregister, self).update(other)
74 self._generics.update(other._generics)
74 self._generics.update(other._generics)
75
75
76 def __setitem__(self, key, item):
76 def __setitem__(self, key, item):
77 super(itemregister, self).__setitem__(key, item)
77 super(itemregister, self).__setitem__(key, item)
78 if item.generic:
78 if item.generic:
79 self._generics.add(item)
79 self._generics.add(item)
80
80
81 def get(self, key):
81 def get(self, key):
82 baseitem = super(itemregister, self).get(key)
82 baseitem = super(itemregister, self).get(key)
83 if baseitem is not None and not baseitem.generic:
83 if baseitem is not None and not baseitem.generic:
84 return baseitem
84 return baseitem
85
85
86 # search for a matching generic item
86 # search for a matching generic item
87 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
87 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
88 for item in generics:
88 for item in generics:
89 # we use 'match' instead of 'search' to make the matching simpler
89 # we use 'match' instead of 'search' to make the matching simpler
90 # for people unfamiliar with regular expression. Having the match
90 # for people unfamiliar with regular expression. Having the match
91 # rooted to the start of the string will produce less surprising
91 # rooted to the start of the string will produce less surprising
92 # result for user writing simple regex for sub-attribute.
92 # result for user writing simple regex for sub-attribute.
93 #
93 #
94 # For example using "color\..*" match produces an unsurprising
94 # For example using "color\..*" match produces an unsurprising
95 # result, while using search could suddenly match apparently
95 # result, while using search could suddenly match apparently
96 # unrelated configuration that happens to contains "color."
96 # unrelated configuration that happens to contains "color."
97 # anywhere. This is a tradeoff where we favor requiring ".*" on
97 # anywhere. This is a tradeoff where we favor requiring ".*" on
98 # some match to avoid the need to prefix most pattern with "^".
98 # some match to avoid the need to prefix most pattern with "^".
99 # The "^" seems more error prone.
99 # The "^" seems more error prone.
100 if item._re.match(key):
100 if item._re.match(key):
101 return item
101 return item
102
102
103 return None
103 return None
104
104
105
105
106 coreitems = {}
106 coreitems = {}
107
107
108
108
109 def _register(configtable, *args, **kwargs):
109 def _register(configtable, *args, **kwargs):
110 item = configitem(*args, **kwargs)
110 item = configitem(*args, **kwargs)
111 section = configtable.setdefault(item.section, itemregister())
111 section = configtable.setdefault(item.section, itemregister())
112 if item.name in section:
112 if item.name in section:
113 msg = b"duplicated config item registration for '%s.%s'"
113 msg = b"duplicated config item registration for '%s.%s'"
114 raise error.ProgrammingError(msg % (item.section, item.name))
114 raise error.ProgrammingError(msg % (item.section, item.name))
115 section[item.name] = item
115 section[item.name] = item
116
116
117
117
118 # special value for case where the default is derived from other values
118 # special value for case where the default is derived from other values
119 dynamicdefault = object()
119 dynamicdefault = object()
120
120
121 # Registering actual config items
121 # Registering actual config items
122
122
123
123
124 def getitemregister(configtable):
124 def getitemregister(configtable):
125 f = functools.partial(_register, configtable)
125 f = functools.partial(_register, configtable)
126 # export pseudo enum as configitem.*
126 # export pseudo enum as configitem.*
127 f.dynamicdefault = dynamicdefault
127 f.dynamicdefault = dynamicdefault
128 return f
128 return f
129
129
130
130
131 coreconfigitem = getitemregister(coreitems)
131 coreconfigitem = getitemregister(coreitems)
132
132
133
133
134 def _registerdiffopts(section, configprefix=b''):
134 def _registerdiffopts(section, configprefix=b''):
135 coreconfigitem(
135 coreconfigitem(
136 section,
136 section,
137 configprefix + b'nodates',
137 configprefix + b'nodates',
138 default=False,
138 default=False,
139 )
139 )
140 coreconfigitem(
140 coreconfigitem(
141 section,
141 section,
142 configprefix + b'showfunc',
142 configprefix + b'showfunc',
143 default=False,
143 default=False,
144 )
144 )
145 coreconfigitem(
145 coreconfigitem(
146 section,
146 section,
147 configprefix + b'unified',
147 configprefix + b'unified',
148 default=None,
148 default=None,
149 )
149 )
150 coreconfigitem(
150 coreconfigitem(
151 section,
151 section,
152 configprefix + b'git',
152 configprefix + b'git',
153 default=False,
153 default=False,
154 )
154 )
155 coreconfigitem(
155 coreconfigitem(
156 section,
156 section,
157 configprefix + b'ignorews',
157 configprefix + b'ignorews',
158 default=False,
158 default=False,
159 )
159 )
160 coreconfigitem(
160 coreconfigitem(
161 section,
161 section,
162 configprefix + b'ignorewsamount',
162 configprefix + b'ignorewsamount',
163 default=False,
163 default=False,
164 )
164 )
165 coreconfigitem(
165 coreconfigitem(
166 section,
166 section,
167 configprefix + b'ignoreblanklines',
167 configprefix + b'ignoreblanklines',
168 default=False,
168 default=False,
169 )
169 )
170 coreconfigitem(
170 coreconfigitem(
171 section,
171 section,
172 configprefix + b'ignorewseol',
172 configprefix + b'ignorewseol',
173 default=False,
173 default=False,
174 )
174 )
175 coreconfigitem(
175 coreconfigitem(
176 section,
176 section,
177 configprefix + b'nobinary',
177 configprefix + b'nobinary',
178 default=False,
178 default=False,
179 )
179 )
180 coreconfigitem(
180 coreconfigitem(
181 section,
181 section,
182 configprefix + b'noprefix',
182 configprefix + b'noprefix',
183 default=False,
183 default=False,
184 )
184 )
185 coreconfigitem(
185 coreconfigitem(
186 section,
186 section,
187 configprefix + b'word-diff',
187 configprefix + b'word-diff',
188 default=False,
188 default=False,
189 )
189 )
190
190
191
191
192 coreconfigitem(
192 coreconfigitem(
193 b'alias',
193 b'alias',
194 b'.*',
194 b'.*',
195 default=dynamicdefault,
195 default=dynamicdefault,
196 generic=True,
196 generic=True,
197 )
197 )
198 coreconfigitem(
198 coreconfigitem(
199 b'auth',
199 b'auth',
200 b'cookiefile',
200 b'cookiefile',
201 default=None,
201 default=None,
202 )
202 )
203 _registerdiffopts(section=b'annotate')
203 _registerdiffopts(section=b'annotate')
204 # bookmarks.pushing: internal hack for discovery
204 # bookmarks.pushing: internal hack for discovery
205 coreconfigitem(
205 coreconfigitem(
206 b'bookmarks',
206 b'bookmarks',
207 b'pushing',
207 b'pushing',
208 default=list,
208 default=list,
209 )
209 )
210 # bundle.mainreporoot: internal hack for bundlerepo
210 # bundle.mainreporoot: internal hack for bundlerepo
211 coreconfigitem(
211 coreconfigitem(
212 b'bundle',
212 b'bundle',
213 b'mainreporoot',
213 b'mainreporoot',
214 default=b'',
214 default=b'',
215 )
215 )
216 coreconfigitem(
216 coreconfigitem(
217 b'censor',
217 b'censor',
218 b'policy',
218 b'policy',
219 default=b'abort',
219 default=b'abort',
220 experimental=True,
220 experimental=True,
221 )
221 )
222 coreconfigitem(
222 coreconfigitem(
223 b'chgserver',
223 b'chgserver',
224 b'idletimeout',
224 b'idletimeout',
225 default=3600,
225 default=3600,
226 )
226 )
227 coreconfigitem(
227 coreconfigitem(
228 b'chgserver',
228 b'chgserver',
229 b'skiphash',
229 b'skiphash',
230 default=False,
230 default=False,
231 )
231 )
232 coreconfigitem(
232 coreconfigitem(
233 b'cmdserver',
233 b'cmdserver',
234 b'log',
234 b'log',
235 default=None,
235 default=None,
236 )
236 )
237 coreconfigitem(
237 coreconfigitem(
238 b'cmdserver',
238 b'cmdserver',
239 b'max-log-files',
239 b'max-log-files',
240 default=7,
240 default=7,
241 )
241 )
242 coreconfigitem(
242 coreconfigitem(
243 b'cmdserver',
243 b'cmdserver',
244 b'max-log-size',
244 b'max-log-size',
245 default=b'1 MB',
245 default=b'1 MB',
246 )
246 )
247 coreconfigitem(
247 coreconfigitem(
248 b'cmdserver',
248 b'cmdserver',
249 b'max-repo-cache',
249 b'max-repo-cache',
250 default=0,
250 default=0,
251 experimental=True,
251 experimental=True,
252 )
252 )
253 coreconfigitem(
253 coreconfigitem(
254 b'cmdserver',
254 b'cmdserver',
255 b'message-encodings',
255 b'message-encodings',
256 default=list,
256 default=list,
257 )
257 )
258 coreconfigitem(
258 coreconfigitem(
259 b'cmdserver',
259 b'cmdserver',
260 b'track-log',
260 b'track-log',
261 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
261 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
262 )
262 )
263 coreconfigitem(
263 coreconfigitem(
264 b'cmdserver',
264 b'cmdserver',
265 b'shutdown-on-interrupt',
265 b'shutdown-on-interrupt',
266 default=True,
266 default=True,
267 )
267 )
268 coreconfigitem(
268 coreconfigitem(
269 b'color',
269 b'color',
270 b'.*',
270 b'.*',
271 default=None,
271 default=None,
272 generic=True,
272 generic=True,
273 )
273 )
274 coreconfigitem(
274 coreconfigitem(
275 b'color',
275 b'color',
276 b'mode',
276 b'mode',
277 default=b'auto',
277 default=b'auto',
278 )
278 )
279 coreconfigitem(
279 coreconfigitem(
280 b'color',
280 b'color',
281 b'pagermode',
281 b'pagermode',
282 default=dynamicdefault,
282 default=dynamicdefault,
283 )
283 )
284 coreconfigitem(
284 coreconfigitem(
285 b'command-templates',
285 b'command-templates',
286 b'graphnode',
286 b'graphnode',
287 default=None,
287 default=None,
288 alias=[(b'ui', b'graphnodetemplate')],
288 alias=[(b'ui', b'graphnodetemplate')],
289 )
289 )
290 coreconfigitem(
290 coreconfigitem(
291 b'command-templates',
291 b'command-templates',
292 b'log',
292 b'log',
293 default=None,
293 default=None,
294 alias=[(b'ui', b'logtemplate')],
294 alias=[(b'ui', b'logtemplate')],
295 )
295 )
296 coreconfigitem(
296 coreconfigitem(
297 b'command-templates',
297 b'command-templates',
298 b'mergemarker',
298 b'mergemarker',
299 default=(
299 default=(
300 b'{node|short} '
300 b'{node|short} '
301 b'{ifeq(tags, "tip", "", '
301 b'{ifeq(tags, "tip", "", '
302 b'ifeq(tags, "", "", "{tags} "))}'
302 b'ifeq(tags, "", "", "{tags} "))}'
303 b'{if(bookmarks, "{bookmarks} ")}'
303 b'{if(bookmarks, "{bookmarks} ")}'
304 b'{ifeq(branch, "default", "", "{branch} ")}'
304 b'{ifeq(branch, "default", "", "{branch} ")}'
305 b'- {author|user}: {desc|firstline}'
305 b'- {author|user}: {desc|firstline}'
306 ),
306 ),
307 alias=[(b'ui', b'mergemarkertemplate')],
307 alias=[(b'ui', b'mergemarkertemplate')],
308 )
308 )
309 coreconfigitem(
309 coreconfigitem(
310 b'command-templates',
310 b'command-templates',
311 b'pre-merge-tool-output',
311 b'pre-merge-tool-output',
312 default=None,
312 default=None,
313 alias=[(b'ui', b'pre-merge-tool-output-template')],
313 alias=[(b'ui', b'pre-merge-tool-output-template')],
314 )
314 )
315 coreconfigitem(
315 coreconfigitem(
316 b'command-templates',
316 b'command-templates',
317 b'oneline-summary',
317 b'oneline-summary',
318 default=None,
318 default=None,
319 )
319 )
320 coreconfigitem(
320 coreconfigitem(
321 b'command-templates',
321 b'command-templates',
322 b'oneline-summary.*',
322 b'oneline-summary.*',
323 default=dynamicdefault,
323 default=dynamicdefault,
324 generic=True,
324 generic=True,
325 )
325 )
326 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
326 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
327 coreconfigitem(
327 coreconfigitem(
328 b'commands',
328 b'commands',
329 b'commit.post-status',
329 b'commit.post-status',
330 default=False,
330 default=False,
331 )
331 )
332 coreconfigitem(
332 coreconfigitem(
333 b'commands',
333 b'commands',
334 b'grep.all-files',
334 b'grep.all-files',
335 default=False,
335 default=False,
336 experimental=True,
336 experimental=True,
337 )
337 )
338 coreconfigitem(
338 coreconfigitem(
339 b'commands',
339 b'commands',
340 b'merge.require-rev',
340 b'merge.require-rev',
341 default=False,
341 default=False,
342 )
342 )
343 coreconfigitem(
343 coreconfigitem(
344 b'commands',
344 b'commands',
345 b'push.require-revs',
345 b'push.require-revs',
346 default=False,
346 default=False,
347 )
347 )
348 coreconfigitem(
348 coreconfigitem(
349 b'commands',
349 b'commands',
350 b'resolve.confirm',
350 b'resolve.confirm',
351 default=False,
351 default=False,
352 )
352 )
353 coreconfigitem(
353 coreconfigitem(
354 b'commands',
354 b'commands',
355 b'resolve.explicit-re-merge',
355 b'resolve.explicit-re-merge',
356 default=False,
356 default=False,
357 )
357 )
358 coreconfigitem(
358 coreconfigitem(
359 b'commands',
359 b'commands',
360 b'resolve.mark-check',
360 b'resolve.mark-check',
361 default=b'none',
361 default=b'none',
362 )
362 )
363 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
363 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
364 coreconfigitem(
364 coreconfigitem(
365 b'commands',
365 b'commands',
366 b'show.aliasprefix',
366 b'show.aliasprefix',
367 default=list,
367 default=list,
368 )
368 )
369 coreconfigitem(
369 coreconfigitem(
370 b'commands',
370 b'commands',
371 b'status.relative',
371 b'status.relative',
372 default=False,
372 default=False,
373 )
373 )
374 coreconfigitem(
374 coreconfigitem(
375 b'commands',
375 b'commands',
376 b'status.skipstates',
376 b'status.skipstates',
377 default=[],
377 default=[],
378 experimental=True,
378 experimental=True,
379 )
379 )
380 coreconfigitem(
380 coreconfigitem(
381 b'commands',
381 b'commands',
382 b'status.terse',
382 b'status.terse',
383 default=b'',
383 default=b'',
384 )
384 )
385 coreconfigitem(
385 coreconfigitem(
386 b'commands',
386 b'commands',
387 b'status.verbose',
387 b'status.verbose',
388 default=False,
388 default=False,
389 )
389 )
390 coreconfigitem(
390 coreconfigitem(
391 b'commands',
391 b'commands',
392 b'update.check',
392 b'update.check',
393 default=None,
393 default=None,
394 )
394 )
395 coreconfigitem(
395 coreconfigitem(
396 b'commands',
396 b'commands',
397 b'update.requiredest',
397 b'update.requiredest',
398 default=False,
398 default=False,
399 )
399 )
400 coreconfigitem(
400 coreconfigitem(
401 b'committemplate',
401 b'committemplate',
402 b'.*',
402 b'.*',
403 default=None,
403 default=None,
404 generic=True,
404 generic=True,
405 )
405 )
406 coreconfigitem(
406 coreconfigitem(
407 b'convert',
407 b'convert',
408 b'bzr.saverev',
408 b'bzr.saverev',
409 default=True,
409 default=True,
410 )
410 )
411 coreconfigitem(
411 coreconfigitem(
412 b'convert',
412 b'convert',
413 b'cvsps.cache',
413 b'cvsps.cache',
414 default=True,
414 default=True,
415 )
415 )
416 coreconfigitem(
416 coreconfigitem(
417 b'convert',
417 b'convert',
418 b'cvsps.fuzz',
418 b'cvsps.fuzz',
419 default=60,
419 default=60,
420 )
420 )
421 coreconfigitem(
421 coreconfigitem(
422 b'convert',
422 b'convert',
423 b'cvsps.logencoding',
423 b'cvsps.logencoding',
424 default=None,
424 default=None,
425 )
425 )
426 coreconfigitem(
426 coreconfigitem(
427 b'convert',
427 b'convert',
428 b'cvsps.mergefrom',
428 b'cvsps.mergefrom',
429 default=None,
429 default=None,
430 )
430 )
431 coreconfigitem(
431 coreconfigitem(
432 b'convert',
432 b'convert',
433 b'cvsps.mergeto',
433 b'cvsps.mergeto',
434 default=None,
434 default=None,
435 )
435 )
436 coreconfigitem(
436 coreconfigitem(
437 b'convert',
437 b'convert',
438 b'git.committeractions',
438 b'git.committeractions',
439 default=lambda: [b'messagedifferent'],
439 default=lambda: [b'messagedifferent'],
440 )
440 )
441 coreconfigitem(
441 coreconfigitem(
442 b'convert',
442 b'convert',
443 b'git.extrakeys',
443 b'git.extrakeys',
444 default=list,
444 default=list,
445 )
445 )
446 coreconfigitem(
446 coreconfigitem(
447 b'convert',
447 b'convert',
448 b'git.findcopiesharder',
448 b'git.findcopiesharder',
449 default=False,
449 default=False,
450 )
450 )
451 coreconfigitem(
451 coreconfigitem(
452 b'convert',
452 b'convert',
453 b'git.remoteprefix',
453 b'git.remoteprefix',
454 default=b'remote',
454 default=b'remote',
455 )
455 )
456 coreconfigitem(
456 coreconfigitem(
457 b'convert',
457 b'convert',
458 b'git.renamelimit',
458 b'git.renamelimit',
459 default=400,
459 default=400,
460 )
460 )
461 coreconfigitem(
461 coreconfigitem(
462 b'convert',
462 b'convert',
463 b'git.saverev',
463 b'git.saverev',
464 default=True,
464 default=True,
465 )
465 )
466 coreconfigitem(
466 coreconfigitem(
467 b'convert',
467 b'convert',
468 b'git.similarity',
468 b'git.similarity',
469 default=50,
469 default=50,
470 )
470 )
471 coreconfigitem(
471 coreconfigitem(
472 b'convert',
472 b'convert',
473 b'git.skipsubmodules',
473 b'git.skipsubmodules',
474 default=False,
474 default=False,
475 )
475 )
476 coreconfigitem(
476 coreconfigitem(
477 b'convert',
477 b'convert',
478 b'hg.clonebranches',
478 b'hg.clonebranches',
479 default=False,
479 default=False,
480 )
480 )
481 coreconfigitem(
481 coreconfigitem(
482 b'convert',
482 b'convert',
483 b'hg.ignoreerrors',
483 b'hg.ignoreerrors',
484 default=False,
484 default=False,
485 )
485 )
486 coreconfigitem(
486 coreconfigitem(
487 b'convert',
487 b'convert',
488 b'hg.preserve-hash',
488 b'hg.preserve-hash',
489 default=False,
489 default=False,
490 )
490 )
491 coreconfigitem(
491 coreconfigitem(
492 b'convert',
492 b'convert',
493 b'hg.revs',
493 b'hg.revs',
494 default=None,
494 default=None,
495 )
495 )
496 coreconfigitem(
496 coreconfigitem(
497 b'convert',
497 b'convert',
498 b'hg.saverev',
498 b'hg.saverev',
499 default=False,
499 default=False,
500 )
500 )
501 coreconfigitem(
501 coreconfigitem(
502 b'convert',
502 b'convert',
503 b'hg.sourcename',
503 b'hg.sourcename',
504 default=None,
504 default=None,
505 )
505 )
506 coreconfigitem(
506 coreconfigitem(
507 b'convert',
507 b'convert',
508 b'hg.startrev',
508 b'hg.startrev',
509 default=None,
509 default=None,
510 )
510 )
511 coreconfigitem(
511 coreconfigitem(
512 b'convert',
512 b'convert',
513 b'hg.tagsbranch',
513 b'hg.tagsbranch',
514 default=b'default',
514 default=b'default',
515 )
515 )
516 coreconfigitem(
516 coreconfigitem(
517 b'convert',
517 b'convert',
518 b'hg.usebranchnames',
518 b'hg.usebranchnames',
519 default=True,
519 default=True,
520 )
520 )
521 coreconfigitem(
521 coreconfigitem(
522 b'convert',
522 b'convert',
523 b'ignoreancestorcheck',
523 b'ignoreancestorcheck',
524 default=False,
524 default=False,
525 experimental=True,
525 experimental=True,
526 )
526 )
527 coreconfigitem(
527 coreconfigitem(
528 b'convert',
528 b'convert',
529 b'localtimezone',
529 b'localtimezone',
530 default=False,
530 default=False,
531 )
531 )
532 coreconfigitem(
532 coreconfigitem(
533 b'convert',
533 b'convert',
534 b'p4.encoding',
534 b'p4.encoding',
535 default=dynamicdefault,
535 default=dynamicdefault,
536 )
536 )
537 coreconfigitem(
537 coreconfigitem(
538 b'convert',
538 b'convert',
539 b'p4.startrev',
539 b'p4.startrev',
540 default=0,
540 default=0,
541 )
541 )
542 coreconfigitem(
542 coreconfigitem(
543 b'convert',
543 b'convert',
544 b'skiptags',
544 b'skiptags',
545 default=False,
545 default=False,
546 )
546 )
547 coreconfigitem(
547 coreconfigitem(
548 b'convert',
548 b'convert',
549 b'svn.debugsvnlog',
549 b'svn.debugsvnlog',
550 default=True,
550 default=True,
551 )
551 )
552 coreconfigitem(
552 coreconfigitem(
553 b'convert',
553 b'convert',
554 b'svn.trunk',
554 b'svn.trunk',
555 default=None,
555 default=None,
556 )
556 )
557 coreconfigitem(
557 coreconfigitem(
558 b'convert',
558 b'convert',
559 b'svn.tags',
559 b'svn.tags',
560 default=None,
560 default=None,
561 )
561 )
562 coreconfigitem(
562 coreconfigitem(
563 b'convert',
563 b'convert',
564 b'svn.branches',
564 b'svn.branches',
565 default=None,
565 default=None,
566 )
566 )
567 coreconfigitem(
567 coreconfigitem(
568 b'convert',
568 b'convert',
569 b'svn.startrev',
569 b'svn.startrev',
570 default=0,
570 default=0,
571 )
571 )
572 coreconfigitem(
572 coreconfigitem(
573 b'convert',
573 b'convert',
574 b'svn.dangerous-set-commit-dates',
574 b'svn.dangerous-set-commit-dates',
575 default=False,
575 default=False,
576 )
576 )
577 coreconfigitem(
577 coreconfigitem(
578 b'debug',
578 b'debug',
579 b'dirstate.delaywrite',
579 b'dirstate.delaywrite',
580 default=0,
580 default=0,
581 )
581 )
582 coreconfigitem(
582 coreconfigitem(
583 b'debug',
583 b'debug',
584 b'revlog.verifyposition.changelog',
584 b'revlog.verifyposition.changelog',
585 default=b'',
585 default=b'',
586 )
586 )
587 coreconfigitem(
587 coreconfigitem(
588 b'defaults',
588 b'defaults',
589 b'.*',
589 b'.*',
590 default=None,
590 default=None,
591 generic=True,
591 generic=True,
592 )
592 )
593 coreconfigitem(
593 coreconfigitem(
594 b'devel',
594 b'devel',
595 b'all-warnings',
595 b'all-warnings',
596 default=False,
596 default=False,
597 )
597 )
598 coreconfigitem(
598 coreconfigitem(
599 b'devel',
599 b'devel',
600 b'bundle2.debug',
600 b'bundle2.debug',
601 default=False,
601 default=False,
602 )
602 )
603 coreconfigitem(
603 coreconfigitem(
604 b'devel',
604 b'devel',
605 b'bundle.delta',
605 b'bundle.delta',
606 default=b'',
606 default=b'',
607 )
607 )
608 coreconfigitem(
608 coreconfigitem(
609 b'devel',
609 b'devel',
610 b'cache-vfs',
610 b'cache-vfs',
611 default=None,
611 default=None,
612 )
612 )
613 coreconfigitem(
613 coreconfigitem(
614 b'devel',
614 b'devel',
615 b'check-locks',
615 b'check-locks',
616 default=False,
616 default=False,
617 )
617 )
618 coreconfigitem(
618 coreconfigitem(
619 b'devel',
619 b'devel',
620 b'check-relroot',
620 b'check-relroot',
621 default=False,
621 default=False,
622 )
622 )
623 # Track copy information for all file, not just "added" one (very slow)
623 # Track copy information for all file, not just "added" one (very slow)
624 coreconfigitem(
624 coreconfigitem(
625 b'devel',
625 b'devel',
626 b'copy-tracing.trace-all-files',
626 b'copy-tracing.trace-all-files',
627 default=False,
627 default=False,
628 )
628 )
629 coreconfigitem(
629 coreconfigitem(
630 b'devel',
630 b'devel',
631 b'default-date',
631 b'default-date',
632 default=None,
632 default=None,
633 )
633 )
634 coreconfigitem(
634 coreconfigitem(
635 b'devel',
635 b'devel',
636 b'deprec-warn',
636 b'deprec-warn',
637 default=False,
637 default=False,
638 )
638 )
639 coreconfigitem(
639 coreconfigitem(
640 b'devel',
640 b'devel',
641 b'disableloaddefaultcerts',
641 b'disableloaddefaultcerts',
642 default=False,
642 default=False,
643 )
643 )
644 coreconfigitem(
644 coreconfigitem(
645 b'devel',
645 b'devel',
646 b'warn-empty-changegroup',
646 b'warn-empty-changegroup',
647 default=False,
647 default=False,
648 )
648 )
649 coreconfigitem(
649 coreconfigitem(
650 b'devel',
650 b'devel',
651 b'legacy.exchange',
651 b'legacy.exchange',
652 default=list,
652 default=list,
653 )
653 )
654 # When True, revlogs use a special reference version of the nodemap, that is not
654 # When True, revlogs use a special reference version of the nodemap, that is not
655 # performant but is "known" to behave properly.
655 # performant but is "known" to behave properly.
656 coreconfigitem(
656 coreconfigitem(
657 b'devel',
657 b'devel',
658 b'persistent-nodemap',
658 b'persistent-nodemap',
659 default=False,
659 default=False,
660 )
660 )
661 coreconfigitem(
661 coreconfigitem(
662 b'devel',
662 b'devel',
663 b'servercafile',
663 b'servercafile',
664 default=b'',
664 default=b'',
665 )
665 )
666 coreconfigitem(
666 coreconfigitem(
667 b'devel',
667 b'devel',
668 b'serverexactprotocol',
668 b'serverexactprotocol',
669 default=b'',
669 default=b'',
670 )
670 )
671 coreconfigitem(
671 coreconfigitem(
672 b'devel',
672 b'devel',
673 b'serverrequirecert',
673 b'serverrequirecert',
674 default=False,
674 default=False,
675 )
675 )
676 coreconfigitem(
676 coreconfigitem(
677 b'devel',
677 b'devel',
678 b'strip-obsmarkers',
678 b'strip-obsmarkers',
679 default=True,
679 default=True,
680 )
680 )
681 coreconfigitem(
681 coreconfigitem(
682 b'devel',
682 b'devel',
683 b'warn-config',
683 b'warn-config',
684 default=None,
684 default=None,
685 )
685 )
686 coreconfigitem(
686 coreconfigitem(
687 b'devel',
687 b'devel',
688 b'warn-config-default',
688 b'warn-config-default',
689 default=None,
689 default=None,
690 )
690 )
691 coreconfigitem(
691 coreconfigitem(
692 b'devel',
692 b'devel',
693 b'user.obsmarker',
693 b'user.obsmarker',
694 default=None,
694 default=None,
695 )
695 )
696 coreconfigitem(
696 coreconfigitem(
697 b'devel',
697 b'devel',
698 b'warn-config-unknown',
698 b'warn-config-unknown',
699 default=None,
699 default=None,
700 )
700 )
701 coreconfigitem(
701 coreconfigitem(
702 b'devel',
702 b'devel',
703 b'debug.copies',
703 b'debug.copies',
704 default=False,
704 default=False,
705 )
705 )
706 coreconfigitem(
706 coreconfigitem(
707 b'devel',
707 b'devel',
708 b'copy-tracing.multi-thread',
708 b'copy-tracing.multi-thread',
709 default=True,
709 default=True,
710 )
710 )
711 coreconfigitem(
711 coreconfigitem(
712 b'devel',
712 b'devel',
713 b'debug.extensions',
713 b'debug.extensions',
714 default=False,
714 default=False,
715 )
715 )
716 coreconfigitem(
716 coreconfigitem(
717 b'devel',
717 b'devel',
718 b'debug.repo-filters',
718 b'debug.repo-filters',
719 default=False,
719 default=False,
720 )
720 )
721 coreconfigitem(
721 coreconfigitem(
722 b'devel',
722 b'devel',
723 b'debug.peer-request',
723 b'debug.peer-request',
724 default=False,
724 default=False,
725 )
725 )
726 # If discovery.exchange-heads is False, the discovery will not start with
726 # If discovery.exchange-heads is False, the discovery will not start with
727 # remote head fetching and local head querying.
727 # remote head fetching and local head querying.
728 coreconfigitem(
728 coreconfigitem(
729 b'devel',
729 b'devel',
730 b'discovery.exchange-heads',
730 b'discovery.exchange-heads',
731 default=True,
731 default=True,
732 )
732 )
733 # If discovery.grow-sample is False, the sample size used in set discovery will
733 # If discovery.grow-sample is False, the sample size used in set discovery will
734 # not be increased through the process
734 # not be increased through the process
735 coreconfigitem(
735 coreconfigitem(
736 b'devel',
736 b'devel',
737 b'discovery.grow-sample',
737 b'discovery.grow-sample',
738 default=True,
738 default=True,
739 )
739 )
740 # discovery.grow-sample.rate control the rate at which the sample grow
740 # discovery.grow-sample.rate control the rate at which the sample grow
741 coreconfigitem(
741 coreconfigitem(
742 b'devel',
742 b'devel',
743 b'discovery.grow-sample.rate',
743 b'discovery.grow-sample.rate',
744 default=1.05,
744 default=1.05,
745 )
745 )
746 # If discovery.randomize is False, random sampling during discovery are
746 # If discovery.randomize is False, random sampling during discovery are
747 # deterministic. It is meant for integration tests.
747 # deterministic. It is meant for integration tests.
748 coreconfigitem(
748 coreconfigitem(
749 b'devel',
749 b'devel',
750 b'discovery.randomize',
750 b'discovery.randomize',
751 default=True,
751 default=True,
752 )
752 )
753 # Control the initial size of the discovery sample
753 # Control the initial size of the discovery sample
754 coreconfigitem(
754 coreconfigitem(
755 b'devel',
755 b'devel',
756 b'discovery.sample-size',
756 b'discovery.sample-size',
757 default=200,
757 default=200,
758 )
758 )
759 # Control the initial size of the discovery for initial change
759 # Control the initial size of the discovery for initial change
760 coreconfigitem(
760 coreconfigitem(
761 b'devel',
761 b'devel',
762 b'discovery.sample-size.initial',
762 b'discovery.sample-size.initial',
763 default=100,
763 default=100,
764 )
764 )
765 _registerdiffopts(section=b'diff')
765 _registerdiffopts(section=b'diff')
766 coreconfigitem(
766 coreconfigitem(
767 b'diff',
767 b'diff',
768 b'merge',
768 b'merge',
769 default=False,
769 default=False,
770 experimental=True,
770 experimental=True,
771 )
771 )
772 coreconfigitem(
772 coreconfigitem(
773 b'email',
773 b'email',
774 b'bcc',
774 b'bcc',
775 default=None,
775 default=None,
776 )
776 )
777 coreconfigitem(
777 coreconfigitem(
778 b'email',
778 b'email',
779 b'cc',
779 b'cc',
780 default=None,
780 default=None,
781 )
781 )
782 coreconfigitem(
782 coreconfigitem(
783 b'email',
783 b'email',
784 b'charsets',
784 b'charsets',
785 default=list,
785 default=list,
786 )
786 )
787 coreconfigitem(
787 coreconfigitem(
788 b'email',
788 b'email',
789 b'from',
789 b'from',
790 default=None,
790 default=None,
791 )
791 )
792 coreconfigitem(
792 coreconfigitem(
793 b'email',
793 b'email',
794 b'method',
794 b'method',
795 default=b'smtp',
795 default=b'smtp',
796 )
796 )
797 coreconfigitem(
797 coreconfigitem(
798 b'email',
798 b'email',
799 b'reply-to',
799 b'reply-to',
800 default=None,
800 default=None,
801 )
801 )
802 coreconfigitem(
802 coreconfigitem(
803 b'email',
803 b'email',
804 b'to',
804 b'to',
805 default=None,
805 default=None,
806 )
806 )
807 coreconfigitem(
807 coreconfigitem(
808 b'experimental',
808 b'experimental',
809 b'archivemetatemplate',
809 b'archivemetatemplate',
810 default=dynamicdefault,
810 default=dynamicdefault,
811 )
811 )
812 coreconfigitem(
812 coreconfigitem(
813 b'experimental',
813 b'experimental',
814 b'auto-publish',
814 b'auto-publish',
815 default=b'publish',
815 default=b'publish',
816 )
816 )
817 coreconfigitem(
817 coreconfigitem(
818 b'experimental',
818 b'experimental',
819 b'bundle-phases',
819 b'bundle-phases',
820 default=False,
820 default=False,
821 )
821 )
822 coreconfigitem(
822 coreconfigitem(
823 b'experimental',
823 b'experimental',
824 b'bundle2-advertise',
824 b'bundle2-advertise',
825 default=True,
825 default=True,
826 )
826 )
827 coreconfigitem(
827 coreconfigitem(
828 b'experimental',
828 b'experimental',
829 b'bundle2-output-capture',
829 b'bundle2-output-capture',
830 default=False,
830 default=False,
831 )
831 )
832 coreconfigitem(
832 coreconfigitem(
833 b'experimental',
833 b'experimental',
834 b'bundle2.pushback',
834 b'bundle2.pushback',
835 default=False,
835 default=False,
836 )
836 )
837 coreconfigitem(
837 coreconfigitem(
838 b'experimental',
838 b'experimental',
839 b'bundle2lazylocking',
839 b'bundle2lazylocking',
840 default=False,
840 default=False,
841 )
841 )
842 coreconfigitem(
842 coreconfigitem(
843 b'experimental',
843 b'experimental',
844 b'bundlecomplevel',
844 b'bundlecomplevel',
845 default=None,
845 default=None,
846 )
846 )
847 coreconfigitem(
847 coreconfigitem(
848 b'experimental',
848 b'experimental',
849 b'bundlecomplevel.bzip2',
849 b'bundlecomplevel.bzip2',
850 default=None,
850 default=None,
851 )
851 )
852 coreconfigitem(
852 coreconfigitem(
853 b'experimental',
853 b'experimental',
854 b'bundlecomplevel.gzip',
854 b'bundlecomplevel.gzip',
855 default=None,
855 default=None,
856 )
856 )
857 coreconfigitem(
857 coreconfigitem(
858 b'experimental',
858 b'experimental',
859 b'bundlecomplevel.none',
859 b'bundlecomplevel.none',
860 default=None,
860 default=None,
861 )
861 )
862 coreconfigitem(
862 coreconfigitem(
863 b'experimental',
863 b'experimental',
864 b'bundlecomplevel.zstd',
864 b'bundlecomplevel.zstd',
865 default=None,
865 default=None,
866 )
866 )
867 coreconfigitem(
867 coreconfigitem(
868 b'experimental',
868 b'experimental',
869 b'changegroup3',
869 b'changegroup3',
870 default=False,
870 default=False,
871 )
871 )
872 coreconfigitem(
872 coreconfigitem(
873 b'experimental',
873 b'experimental',
874 b'cleanup-as-archived',
874 b'cleanup-as-archived',
875 default=False,
875 default=False,
876 )
876 )
877 coreconfigitem(
877 coreconfigitem(
878 b'experimental',
878 b'experimental',
879 b'clientcompressionengines',
879 b'clientcompressionengines',
880 default=list,
880 default=list,
881 )
881 )
882 coreconfigitem(
882 coreconfigitem(
883 b'experimental',
883 b'experimental',
884 b'copytrace',
884 b'copytrace',
885 default=b'on',
885 default=b'on',
886 )
886 )
887 coreconfigitem(
887 coreconfigitem(
888 b'experimental',
888 b'experimental',
889 b'copytrace.movecandidateslimit',
889 b'copytrace.movecandidateslimit',
890 default=100,
890 default=100,
891 )
891 )
892 coreconfigitem(
892 coreconfigitem(
893 b'experimental',
893 b'experimental',
894 b'copytrace.sourcecommitlimit',
894 b'copytrace.sourcecommitlimit',
895 default=100,
895 default=100,
896 )
896 )
897 coreconfigitem(
897 coreconfigitem(
898 b'experimental',
898 b'experimental',
899 b'copies.read-from',
899 b'copies.read-from',
900 default=b"filelog-only",
900 default=b"filelog-only",
901 )
901 )
902 coreconfigitem(
902 coreconfigitem(
903 b'experimental',
903 b'experimental',
904 b'copies.write-to',
904 b'copies.write-to',
905 default=b'filelog-only',
905 default=b'filelog-only',
906 )
906 )
907 coreconfigitem(
907 coreconfigitem(
908 b'experimental',
908 b'experimental',
909 b'crecordtest',
909 b'crecordtest',
910 default=None,
910 default=None,
911 )
911 )
912 coreconfigitem(
912 coreconfigitem(
913 b'experimental',
913 b'experimental',
914 b'directaccess',
914 b'directaccess',
915 default=False,
915 default=False,
916 )
916 )
917 coreconfigitem(
917 coreconfigitem(
918 b'experimental',
918 b'experimental',
919 b'directaccess.revnums',
919 b'directaccess.revnums',
920 default=False,
920 default=False,
921 )
921 )
922 coreconfigitem(
922 coreconfigitem(
923 b'experimental',
923 b'experimental',
924 b'editortmpinhg',
924 b'editortmpinhg',
925 default=False,
925 default=False,
926 )
926 )
927 coreconfigitem(
927 coreconfigitem(
928 b'experimental',
928 b'experimental',
929 b'evolution',
929 b'evolution',
930 default=list,
930 default=list,
931 )
931 )
932 coreconfigitem(
932 coreconfigitem(
933 b'experimental',
933 b'experimental',
934 b'evolution.allowdivergence',
934 b'evolution.allowdivergence',
935 default=False,
935 default=False,
936 alias=[(b'experimental', b'allowdivergence')],
936 alias=[(b'experimental', b'allowdivergence')],
937 )
937 )
938 coreconfigitem(
938 coreconfigitem(
939 b'experimental',
939 b'experimental',
940 b'evolution.allowunstable',
940 b'evolution.allowunstable',
941 default=None,
941 default=None,
942 )
942 )
943 coreconfigitem(
943 coreconfigitem(
944 b'experimental',
944 b'experimental',
945 b'evolution.createmarkers',
945 b'evolution.createmarkers',
946 default=None,
946 default=None,
947 )
947 )
948 coreconfigitem(
948 coreconfigitem(
949 b'experimental',
949 b'experimental',
950 b'evolution.effect-flags',
950 b'evolution.effect-flags',
951 default=True,
951 default=True,
952 alias=[(b'experimental', b'effect-flags')],
952 alias=[(b'experimental', b'effect-flags')],
953 )
953 )
954 coreconfigitem(
954 coreconfigitem(
955 b'experimental',
955 b'experimental',
956 b'evolution.exchange',
956 b'evolution.exchange',
957 default=None,
957 default=None,
958 )
958 )
959 coreconfigitem(
959 coreconfigitem(
960 b'experimental',
960 b'experimental',
961 b'evolution.bundle-obsmarker',
961 b'evolution.bundle-obsmarker',
962 default=False,
962 default=False,
963 )
963 )
964 coreconfigitem(
964 coreconfigitem(
965 b'experimental',
965 b'experimental',
966 b'evolution.bundle-obsmarker:mandatory',
966 b'evolution.bundle-obsmarker:mandatory',
967 default=True,
967 default=True,
968 )
968 )
969 coreconfigitem(
969 coreconfigitem(
970 b'experimental',
970 b'experimental',
971 b'log.topo',
971 b'log.topo',
972 default=False,
972 default=False,
973 )
973 )
974 coreconfigitem(
974 coreconfigitem(
975 b'experimental',
975 b'experimental',
976 b'evolution.report-instabilities',
976 b'evolution.report-instabilities',
977 default=True,
977 default=True,
978 )
978 )
979 coreconfigitem(
979 coreconfigitem(
980 b'experimental',
980 b'experimental',
981 b'evolution.track-operation',
981 b'evolution.track-operation',
982 default=True,
982 default=True,
983 )
983 )
984 # repo-level config to exclude a revset visibility
984 # repo-level config to exclude a revset visibility
985 #
985 #
986 # The target use case is to use `share` to expose different subset of the same
986 # The target use case is to use `share` to expose different subset of the same
987 # repository, especially server side. See also `server.view`.
987 # repository, especially server side. See also `server.view`.
988 coreconfigitem(
988 coreconfigitem(
989 b'experimental',
989 b'experimental',
990 b'extra-filter-revs',
990 b'extra-filter-revs',
991 default=None,
991 default=None,
992 )
992 )
993 coreconfigitem(
993 coreconfigitem(
994 b'experimental',
994 b'experimental',
995 b'maxdeltachainspan',
995 b'maxdeltachainspan',
996 default=-1,
996 default=-1,
997 )
997 )
998 # tracks files which were undeleted (merge might delete them but we explicitly
998 # tracks files which were undeleted (merge might delete them but we explicitly
999 # kept/undeleted them) and creates new filenodes for them
999 # kept/undeleted them) and creates new filenodes for them
1000 coreconfigitem(
1000 coreconfigitem(
1001 b'experimental',
1001 b'experimental',
1002 b'merge-track-salvaged',
1002 b'merge-track-salvaged',
1003 default=False,
1003 default=False,
1004 )
1004 )
1005 coreconfigitem(
1005 coreconfigitem(
1006 b'experimental',
1006 b'experimental',
1007 b'mergetempdirprefix',
1007 b'mergetempdirprefix',
1008 default=None,
1008 default=None,
1009 )
1009 )
1010 coreconfigitem(
1010 coreconfigitem(
1011 b'experimental',
1011 b'experimental',
1012 b'mmapindexthreshold',
1012 b'mmapindexthreshold',
1013 default=None,
1013 default=None,
1014 )
1014 )
1015 coreconfigitem(
1015 coreconfigitem(
1016 b'experimental',
1016 b'experimental',
1017 b'narrow',
1017 b'narrow',
1018 default=False,
1018 default=False,
1019 )
1019 )
1020 coreconfigitem(
1020 coreconfigitem(
1021 b'experimental',
1021 b'experimental',
1022 b'nonnormalparanoidcheck',
1022 b'nonnormalparanoidcheck',
1023 default=False,
1023 default=False,
1024 )
1024 )
1025 coreconfigitem(
1025 coreconfigitem(
1026 b'experimental',
1026 b'experimental',
1027 b'exportableenviron',
1027 b'exportableenviron',
1028 default=list,
1028 default=list,
1029 )
1029 )
1030 coreconfigitem(
1030 coreconfigitem(
1031 b'experimental',
1031 b'experimental',
1032 b'extendedheader.index',
1032 b'extendedheader.index',
1033 default=None,
1033 default=None,
1034 )
1034 )
1035 coreconfigitem(
1035 coreconfigitem(
1036 b'experimental',
1036 b'experimental',
1037 b'extendedheader.similarity',
1037 b'extendedheader.similarity',
1038 default=False,
1038 default=False,
1039 )
1039 )
1040 coreconfigitem(
1040 coreconfigitem(
1041 b'experimental',
1041 b'experimental',
1042 b'graphshorten',
1042 b'graphshorten',
1043 default=False,
1043 default=False,
1044 )
1044 )
1045 coreconfigitem(
1045 coreconfigitem(
1046 b'experimental',
1046 b'experimental',
1047 b'graphstyle.parent',
1047 b'graphstyle.parent',
1048 default=dynamicdefault,
1048 default=dynamicdefault,
1049 )
1049 )
1050 coreconfigitem(
1050 coreconfigitem(
1051 b'experimental',
1051 b'experimental',
1052 b'graphstyle.missing',
1052 b'graphstyle.missing',
1053 default=dynamicdefault,
1053 default=dynamicdefault,
1054 )
1054 )
1055 coreconfigitem(
1055 coreconfigitem(
1056 b'experimental',
1056 b'experimental',
1057 b'graphstyle.grandparent',
1057 b'graphstyle.grandparent',
1058 default=dynamicdefault,
1058 default=dynamicdefault,
1059 )
1059 )
1060 coreconfigitem(
1060 coreconfigitem(
1061 b'experimental',
1061 b'experimental',
1062 b'hook-track-tags',
1062 b'hook-track-tags',
1063 default=False,
1063 default=False,
1064 )
1064 )
1065 coreconfigitem(
1065 coreconfigitem(
1066 b'experimental',
1066 b'experimental',
1067 b'httppeer.advertise-v2',
1067 b'httppeer.advertise-v2',
1068 default=False,
1068 default=False,
1069 )
1069 )
1070 coreconfigitem(
1070 coreconfigitem(
1071 b'experimental',
1071 b'experimental',
1072 b'httppeer.v2-encoder-order',
1072 b'httppeer.v2-encoder-order',
1073 default=None,
1073 default=None,
1074 )
1074 )
1075 coreconfigitem(
1075 coreconfigitem(
1076 b'experimental',
1076 b'experimental',
1077 b'httppostargs',
1077 b'httppostargs',
1078 default=False,
1078 default=False,
1079 )
1079 )
1080 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1080 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1081 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1081 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1082
1082
1083 coreconfigitem(
1083 coreconfigitem(
1084 b'experimental',
1084 b'experimental',
1085 b'obsmarkers-exchange-debug',
1085 b'obsmarkers-exchange-debug',
1086 default=False,
1086 default=False,
1087 )
1087 )
1088 coreconfigitem(
1088 coreconfigitem(
1089 b'experimental',
1089 b'experimental',
1090 b'remotenames',
1090 b'remotenames',
1091 default=False,
1091 default=False,
1092 )
1092 )
1093 coreconfigitem(
1093 coreconfigitem(
1094 b'experimental',
1094 b'experimental',
1095 b'removeemptydirs',
1095 b'removeemptydirs',
1096 default=True,
1096 default=True,
1097 )
1097 )
1098 coreconfigitem(
1098 coreconfigitem(
1099 b'experimental',
1099 b'experimental',
1100 b'revert.interactive.select-to-keep',
1100 b'revert.interactive.select-to-keep',
1101 default=False,
1101 default=False,
1102 )
1102 )
1103 coreconfigitem(
1103 coreconfigitem(
1104 b'experimental',
1104 b'experimental',
1105 b'revisions.prefixhexnode',
1105 b'revisions.prefixhexnode',
1106 default=False,
1106 default=False,
1107 )
1107 )
1108 coreconfigitem(
1108 coreconfigitem(
1109 b'experimental',
1109 b'experimental',
1110 b'revlogv2',
1110 b'revlogv2',
1111 default=None,
1111 default=None,
1112 )
1112 )
1113 coreconfigitem(
1113 coreconfigitem(
1114 b'experimental',
1114 b'experimental',
1115 b'revisions.disambiguatewithin',
1115 b'revisions.disambiguatewithin',
1116 default=None,
1116 default=None,
1117 )
1117 )
1118 coreconfigitem(
1118 coreconfigitem(
1119 b'experimental',
1119 b'experimental',
1120 b'rust.index',
1120 b'rust.index',
1121 default=False,
1121 default=False,
1122 )
1122 )
1123 coreconfigitem(
1123 coreconfigitem(
1124 b'experimental',
1124 b'experimental',
1125 b'server.filesdata.recommended-batch-size',
1125 b'server.filesdata.recommended-batch-size',
1126 default=50000,
1126 default=50000,
1127 )
1127 )
1128 coreconfigitem(
1128 coreconfigitem(
1129 b'experimental',
1129 b'experimental',
1130 b'server.manifestdata.recommended-batch-size',
1130 b'server.manifestdata.recommended-batch-size',
1131 default=100000,
1131 default=100000,
1132 )
1132 )
1133 coreconfigitem(
1133 coreconfigitem(
1134 b'experimental',
1134 b'experimental',
1135 b'server.stream-narrow-clones',
1135 b'server.stream-narrow-clones',
1136 default=False,
1136 default=False,
1137 )
1137 )
1138 coreconfigitem(
1138 coreconfigitem(
1139 b'experimental',
1139 b'experimental',
1140 b'single-head-per-branch',
1140 b'single-head-per-branch',
1141 default=False,
1141 default=False,
1142 )
1142 )
1143 coreconfigitem(
1143 coreconfigitem(
1144 b'experimental',
1144 b'experimental',
1145 b'single-head-per-branch:account-closed-heads',
1145 b'single-head-per-branch:account-closed-heads',
1146 default=False,
1146 default=False,
1147 )
1147 )
1148 coreconfigitem(
1148 coreconfigitem(
1149 b'experimental',
1149 b'experimental',
1150 b'single-head-per-branch:public-changes-only',
1150 b'single-head-per-branch:public-changes-only',
1151 default=False,
1151 default=False,
1152 )
1152 )
1153 coreconfigitem(
1153 coreconfigitem(
1154 b'experimental',
1154 b'experimental',
1155 b'sshserver.support-v2',
1155 b'sshserver.support-v2',
1156 default=False,
1156 default=False,
1157 )
1157 )
1158 coreconfigitem(
1158 coreconfigitem(
1159 b'experimental',
1159 b'experimental',
1160 b'sparse-read',
1160 b'sparse-read',
1161 default=False,
1161 default=False,
1162 )
1162 )
1163 coreconfigitem(
1163 coreconfigitem(
1164 b'experimental',
1164 b'experimental',
1165 b'sparse-read.density-threshold',
1165 b'sparse-read.density-threshold',
1166 default=0.50,
1166 default=0.50,
1167 )
1167 )
1168 coreconfigitem(
1168 coreconfigitem(
1169 b'experimental',
1169 b'experimental',
1170 b'sparse-read.min-gap-size',
1170 b'sparse-read.min-gap-size',
1171 default=b'65K',
1171 default=b'65K',
1172 )
1172 )
1173 coreconfigitem(
1173 coreconfigitem(
1174 b'experimental',
1174 b'experimental',
1175 b'treemanifest',
1175 b'treemanifest',
1176 default=False,
1176 default=False,
1177 )
1177 )
1178 coreconfigitem(
1178 coreconfigitem(
1179 b'experimental',
1179 b'experimental',
1180 b'update.atomic-file',
1180 b'update.atomic-file',
1181 default=False,
1181 default=False,
1182 )
1182 )
1183 coreconfigitem(
1183 coreconfigitem(
1184 b'experimental',
1184 b'experimental',
1185 b'sshpeer.advertise-v2',
1185 b'sshpeer.advertise-v2',
1186 default=False,
1186 default=False,
1187 )
1187 )
1188 coreconfigitem(
1188 coreconfigitem(
1189 b'experimental',
1189 b'experimental',
1190 b'web.apiserver',
1190 b'web.apiserver',
1191 default=False,
1191 default=False,
1192 )
1192 )
1193 coreconfigitem(
1193 coreconfigitem(
1194 b'experimental',
1194 b'experimental',
1195 b'web.api.http-v2',
1195 b'web.api.http-v2',
1196 default=False,
1196 default=False,
1197 )
1197 )
1198 coreconfigitem(
1198 coreconfigitem(
1199 b'experimental',
1199 b'experimental',
1200 b'web.api.debugreflect',
1200 b'web.api.debugreflect',
1201 default=False,
1201 default=False,
1202 )
1202 )
1203 coreconfigitem(
1203 coreconfigitem(
1204 b'experimental',
1204 b'experimental',
1205 b'worker.wdir-get-thread-safe',
1205 b'worker.wdir-get-thread-safe',
1206 default=False,
1206 default=False,
1207 )
1207 )
1208 coreconfigitem(
1208 coreconfigitem(
1209 b'experimental',
1209 b'experimental',
1210 b'worker.repository-upgrade',
1210 b'worker.repository-upgrade',
1211 default=False,
1211 default=False,
1212 )
1212 )
1213 coreconfigitem(
1213 coreconfigitem(
1214 b'experimental',
1214 b'experimental',
1215 b'xdiff',
1215 b'xdiff',
1216 default=False,
1216 default=False,
1217 )
1217 )
1218 coreconfigitem(
1218 coreconfigitem(
1219 b'extensions',
1219 b'extensions',
1220 b'.*',
1220 b'.*',
1221 default=None,
1221 default=None,
1222 generic=True,
1222 generic=True,
1223 )
1223 )
1224 coreconfigitem(
1224 coreconfigitem(
1225 b'extdata',
1225 b'extdata',
1226 b'.*',
1226 b'.*',
1227 default=None,
1227 default=None,
1228 generic=True,
1228 generic=True,
1229 )
1229 )
1230 coreconfigitem(
1230 coreconfigitem(
1231 b'format',
1231 b'format',
1232 b'bookmarks-in-store',
1232 b'bookmarks-in-store',
1233 default=False,
1233 default=False,
1234 )
1234 )
1235 coreconfigitem(
1235 coreconfigitem(
1236 b'format',
1236 b'format',
1237 b'chunkcachesize',
1237 b'chunkcachesize',
1238 default=None,
1238 default=None,
1239 experimental=True,
1239 experimental=True,
1240 )
1240 )
1241 coreconfigitem(
1241 coreconfigitem(
1242 b'format',
1242 b'format',
1243 b'dotencode',
1243 b'dotencode',
1244 default=True,
1244 default=True,
1245 )
1245 )
1246 coreconfigitem(
1246 coreconfigitem(
1247 b'format',
1247 b'format',
1248 b'generaldelta',
1248 b'generaldelta',
1249 default=False,
1249 default=False,
1250 experimental=True,
1250 experimental=True,
1251 )
1251 )
1252 coreconfigitem(
1252 coreconfigitem(
1253 b'format',
1253 b'format',
1254 b'manifestcachesize',
1254 b'manifestcachesize',
1255 default=None,
1255 default=None,
1256 experimental=True,
1256 experimental=True,
1257 )
1257 )
1258 coreconfigitem(
1258 coreconfigitem(
1259 b'format',
1259 b'format',
1260 b'maxchainlen',
1260 b'maxchainlen',
1261 default=dynamicdefault,
1261 default=dynamicdefault,
1262 experimental=True,
1262 experimental=True,
1263 )
1263 )
1264 coreconfigitem(
1264 coreconfigitem(
1265 b'format',
1265 b'format',
1266 b'obsstore-version',
1266 b'obsstore-version',
1267 default=None,
1267 default=None,
1268 )
1268 )
1269 coreconfigitem(
1269 coreconfigitem(
1270 b'format',
1270 b'format',
1271 b'sparse-revlog',
1271 b'sparse-revlog',
1272 default=True,
1272 default=True,
1273 )
1273 )
1274 coreconfigitem(
1274 coreconfigitem(
1275 b'format',
1275 b'format',
1276 b'revlog-compression',
1276 b'revlog-compression',
1277 default=lambda: [b'zlib'],
1277 default=lambda: [b'zlib'],
1278 alias=[(b'experimental', b'format.compression')],
1278 alias=[(b'experimental', b'format.compression')],
1279 )
1279 )
1280 coreconfigitem(
1280 coreconfigitem(
1281 b'format',
1281 b'format',
1282 b'usefncache',
1282 b'usefncache',
1283 default=True,
1283 default=True,
1284 )
1284 )
1285 coreconfigitem(
1285 coreconfigitem(
1286 b'format',
1286 b'format',
1287 b'usegeneraldelta',
1287 b'usegeneraldelta',
1288 default=True,
1288 default=True,
1289 )
1289 )
1290 coreconfigitem(
1290 coreconfigitem(
1291 b'format',
1291 b'format',
1292 b'usestore',
1292 b'usestore',
1293 default=True,
1293 default=True,
1294 )
1294 )
1295 coreconfigitem(
1295 coreconfigitem(
1296 b'format',
1296 b'format',
1297 b'use-persistent-nodemap',
1297 b'use-persistent-nodemap',
1298 default=False,
1298 default=False,
1299 )
1299 )
1300 coreconfigitem(
1300 coreconfigitem(
1301 b'format',
1301 b'format',
1302 b'exp-revlogv2.2',
1303 default=False,
1304 experimental=True,
1305 )
1306 coreconfigitem(
1307 b'format',
1302 b'exp-use-copies-side-data-changeset',
1308 b'exp-use-copies-side-data-changeset',
1303 default=False,
1309 default=False,
1304 experimental=True,
1310 experimental=True,
1305 )
1311 )
1306 coreconfigitem(
1312 coreconfigitem(
1307 b'format',
1313 b'format',
1308 b'exp-use-side-data',
1314 b'exp-use-side-data',
1309 default=False,
1315 default=False,
1310 experimental=True,
1316 experimental=True,
1311 )
1317 )
1312 coreconfigitem(
1318 coreconfigitem(
1313 b'format',
1319 b'format',
1314 b'use-share-safe',
1320 b'use-share-safe',
1315 default=False,
1321 default=False,
1316 )
1322 )
1317 coreconfigitem(
1323 coreconfigitem(
1318 b'format',
1324 b'format',
1319 b'internal-phase',
1325 b'internal-phase',
1320 default=False,
1326 default=False,
1321 experimental=True,
1327 experimental=True,
1322 )
1328 )
1323 coreconfigitem(
1329 coreconfigitem(
1324 b'fsmonitor',
1330 b'fsmonitor',
1325 b'warn_when_unused',
1331 b'warn_when_unused',
1326 default=True,
1332 default=True,
1327 )
1333 )
1328 coreconfigitem(
1334 coreconfigitem(
1329 b'fsmonitor',
1335 b'fsmonitor',
1330 b'warn_update_file_count',
1336 b'warn_update_file_count',
1331 default=50000,
1337 default=50000,
1332 )
1338 )
1333 coreconfigitem(
1339 coreconfigitem(
1334 b'fsmonitor',
1340 b'fsmonitor',
1335 b'warn_update_file_count_rust',
1341 b'warn_update_file_count_rust',
1336 default=400000,
1342 default=400000,
1337 )
1343 )
1338 coreconfigitem(
1344 coreconfigitem(
1339 b'help',
1345 b'help',
1340 br'hidden-command\..*',
1346 br'hidden-command\..*',
1341 default=False,
1347 default=False,
1342 generic=True,
1348 generic=True,
1343 )
1349 )
1344 coreconfigitem(
1350 coreconfigitem(
1345 b'help',
1351 b'help',
1346 br'hidden-topic\..*',
1352 br'hidden-topic\..*',
1347 default=False,
1353 default=False,
1348 generic=True,
1354 generic=True,
1349 )
1355 )
1350 coreconfigitem(
1356 coreconfigitem(
1351 b'hooks',
1357 b'hooks',
1352 b'[^:]*',
1358 b'[^:]*',
1353 default=dynamicdefault,
1359 default=dynamicdefault,
1354 generic=True,
1360 generic=True,
1355 )
1361 )
1356 coreconfigitem(
1362 coreconfigitem(
1357 b'hooks',
1363 b'hooks',
1358 b'.*:run-with-plain',
1364 b'.*:run-with-plain',
1359 default=True,
1365 default=True,
1360 generic=True,
1366 generic=True,
1361 )
1367 )
1362 coreconfigitem(
1368 coreconfigitem(
1363 b'hgweb-paths',
1369 b'hgweb-paths',
1364 b'.*',
1370 b'.*',
1365 default=list,
1371 default=list,
1366 generic=True,
1372 generic=True,
1367 )
1373 )
1368 coreconfigitem(
1374 coreconfigitem(
1369 b'hostfingerprints',
1375 b'hostfingerprints',
1370 b'.*',
1376 b'.*',
1371 default=list,
1377 default=list,
1372 generic=True,
1378 generic=True,
1373 )
1379 )
1374 coreconfigitem(
1380 coreconfigitem(
1375 b'hostsecurity',
1381 b'hostsecurity',
1376 b'ciphers',
1382 b'ciphers',
1377 default=None,
1383 default=None,
1378 )
1384 )
1379 coreconfigitem(
1385 coreconfigitem(
1380 b'hostsecurity',
1386 b'hostsecurity',
1381 b'minimumprotocol',
1387 b'minimumprotocol',
1382 default=dynamicdefault,
1388 default=dynamicdefault,
1383 )
1389 )
1384 coreconfigitem(
1390 coreconfigitem(
1385 b'hostsecurity',
1391 b'hostsecurity',
1386 b'.*:minimumprotocol$',
1392 b'.*:minimumprotocol$',
1387 default=dynamicdefault,
1393 default=dynamicdefault,
1388 generic=True,
1394 generic=True,
1389 )
1395 )
1390 coreconfigitem(
1396 coreconfigitem(
1391 b'hostsecurity',
1397 b'hostsecurity',
1392 b'.*:ciphers$',
1398 b'.*:ciphers$',
1393 default=dynamicdefault,
1399 default=dynamicdefault,
1394 generic=True,
1400 generic=True,
1395 )
1401 )
1396 coreconfigitem(
1402 coreconfigitem(
1397 b'hostsecurity',
1403 b'hostsecurity',
1398 b'.*:fingerprints$',
1404 b'.*:fingerprints$',
1399 default=list,
1405 default=list,
1400 generic=True,
1406 generic=True,
1401 )
1407 )
1402 coreconfigitem(
1408 coreconfigitem(
1403 b'hostsecurity',
1409 b'hostsecurity',
1404 b'.*:verifycertsfile$',
1410 b'.*:verifycertsfile$',
1405 default=None,
1411 default=None,
1406 generic=True,
1412 generic=True,
1407 )
1413 )
1408
1414
1409 coreconfigitem(
1415 coreconfigitem(
1410 b'http_proxy',
1416 b'http_proxy',
1411 b'always',
1417 b'always',
1412 default=False,
1418 default=False,
1413 )
1419 )
1414 coreconfigitem(
1420 coreconfigitem(
1415 b'http_proxy',
1421 b'http_proxy',
1416 b'host',
1422 b'host',
1417 default=None,
1423 default=None,
1418 )
1424 )
1419 coreconfigitem(
1425 coreconfigitem(
1420 b'http_proxy',
1426 b'http_proxy',
1421 b'no',
1427 b'no',
1422 default=list,
1428 default=list,
1423 )
1429 )
1424 coreconfigitem(
1430 coreconfigitem(
1425 b'http_proxy',
1431 b'http_proxy',
1426 b'passwd',
1432 b'passwd',
1427 default=None,
1433 default=None,
1428 )
1434 )
1429 coreconfigitem(
1435 coreconfigitem(
1430 b'http_proxy',
1436 b'http_proxy',
1431 b'user',
1437 b'user',
1432 default=None,
1438 default=None,
1433 )
1439 )
1434
1440
1435 coreconfigitem(
1441 coreconfigitem(
1436 b'http',
1442 b'http',
1437 b'timeout',
1443 b'timeout',
1438 default=None,
1444 default=None,
1439 )
1445 )
1440
1446
1441 coreconfigitem(
1447 coreconfigitem(
1442 b'logtoprocess',
1448 b'logtoprocess',
1443 b'commandexception',
1449 b'commandexception',
1444 default=None,
1450 default=None,
1445 )
1451 )
1446 coreconfigitem(
1452 coreconfigitem(
1447 b'logtoprocess',
1453 b'logtoprocess',
1448 b'commandfinish',
1454 b'commandfinish',
1449 default=None,
1455 default=None,
1450 )
1456 )
1451 coreconfigitem(
1457 coreconfigitem(
1452 b'logtoprocess',
1458 b'logtoprocess',
1453 b'command',
1459 b'command',
1454 default=None,
1460 default=None,
1455 )
1461 )
1456 coreconfigitem(
1462 coreconfigitem(
1457 b'logtoprocess',
1463 b'logtoprocess',
1458 b'develwarn',
1464 b'develwarn',
1459 default=None,
1465 default=None,
1460 )
1466 )
1461 coreconfigitem(
1467 coreconfigitem(
1462 b'logtoprocess',
1468 b'logtoprocess',
1463 b'uiblocked',
1469 b'uiblocked',
1464 default=None,
1470 default=None,
1465 )
1471 )
1466 coreconfigitem(
1472 coreconfigitem(
1467 b'merge',
1473 b'merge',
1468 b'checkunknown',
1474 b'checkunknown',
1469 default=b'abort',
1475 default=b'abort',
1470 )
1476 )
1471 coreconfigitem(
1477 coreconfigitem(
1472 b'merge',
1478 b'merge',
1473 b'checkignored',
1479 b'checkignored',
1474 default=b'abort',
1480 default=b'abort',
1475 )
1481 )
1476 coreconfigitem(
1482 coreconfigitem(
1477 b'experimental',
1483 b'experimental',
1478 b'merge.checkpathconflicts',
1484 b'merge.checkpathconflicts',
1479 default=False,
1485 default=False,
1480 )
1486 )
1481 coreconfigitem(
1487 coreconfigitem(
1482 b'merge',
1488 b'merge',
1483 b'followcopies',
1489 b'followcopies',
1484 default=True,
1490 default=True,
1485 )
1491 )
1486 coreconfigitem(
1492 coreconfigitem(
1487 b'merge',
1493 b'merge',
1488 b'on-failure',
1494 b'on-failure',
1489 default=b'continue',
1495 default=b'continue',
1490 )
1496 )
1491 coreconfigitem(
1497 coreconfigitem(
1492 b'merge',
1498 b'merge',
1493 b'preferancestor',
1499 b'preferancestor',
1494 default=lambda: [b'*'],
1500 default=lambda: [b'*'],
1495 experimental=True,
1501 experimental=True,
1496 )
1502 )
1497 coreconfigitem(
1503 coreconfigitem(
1498 b'merge',
1504 b'merge',
1499 b'strict-capability-check',
1505 b'strict-capability-check',
1500 default=False,
1506 default=False,
1501 )
1507 )
1502 coreconfigitem(
1508 coreconfigitem(
1503 b'merge-tools',
1509 b'merge-tools',
1504 b'.*',
1510 b'.*',
1505 default=None,
1511 default=None,
1506 generic=True,
1512 generic=True,
1507 )
1513 )
1508 coreconfigitem(
1514 coreconfigitem(
1509 b'merge-tools',
1515 b'merge-tools',
1510 br'.*\.args$',
1516 br'.*\.args$',
1511 default=b"$local $base $other",
1517 default=b"$local $base $other",
1512 generic=True,
1518 generic=True,
1513 priority=-1,
1519 priority=-1,
1514 )
1520 )
1515 coreconfigitem(
1521 coreconfigitem(
1516 b'merge-tools',
1522 b'merge-tools',
1517 br'.*\.binary$',
1523 br'.*\.binary$',
1518 default=False,
1524 default=False,
1519 generic=True,
1525 generic=True,
1520 priority=-1,
1526 priority=-1,
1521 )
1527 )
1522 coreconfigitem(
1528 coreconfigitem(
1523 b'merge-tools',
1529 b'merge-tools',
1524 br'.*\.check$',
1530 br'.*\.check$',
1525 default=list,
1531 default=list,
1526 generic=True,
1532 generic=True,
1527 priority=-1,
1533 priority=-1,
1528 )
1534 )
1529 coreconfigitem(
1535 coreconfigitem(
1530 b'merge-tools',
1536 b'merge-tools',
1531 br'.*\.checkchanged$',
1537 br'.*\.checkchanged$',
1532 default=False,
1538 default=False,
1533 generic=True,
1539 generic=True,
1534 priority=-1,
1540 priority=-1,
1535 )
1541 )
1536 coreconfigitem(
1542 coreconfigitem(
1537 b'merge-tools',
1543 b'merge-tools',
1538 br'.*\.executable$',
1544 br'.*\.executable$',
1539 default=dynamicdefault,
1545 default=dynamicdefault,
1540 generic=True,
1546 generic=True,
1541 priority=-1,
1547 priority=-1,
1542 )
1548 )
1543 coreconfigitem(
1549 coreconfigitem(
1544 b'merge-tools',
1550 b'merge-tools',
1545 br'.*\.fixeol$',
1551 br'.*\.fixeol$',
1546 default=False,
1552 default=False,
1547 generic=True,
1553 generic=True,
1548 priority=-1,
1554 priority=-1,
1549 )
1555 )
1550 coreconfigitem(
1556 coreconfigitem(
1551 b'merge-tools',
1557 b'merge-tools',
1552 br'.*\.gui$',
1558 br'.*\.gui$',
1553 default=False,
1559 default=False,
1554 generic=True,
1560 generic=True,
1555 priority=-1,
1561 priority=-1,
1556 )
1562 )
1557 coreconfigitem(
1563 coreconfigitem(
1558 b'merge-tools',
1564 b'merge-tools',
1559 br'.*\.mergemarkers$',
1565 br'.*\.mergemarkers$',
1560 default=b'basic',
1566 default=b'basic',
1561 generic=True,
1567 generic=True,
1562 priority=-1,
1568 priority=-1,
1563 )
1569 )
1564 coreconfigitem(
1570 coreconfigitem(
1565 b'merge-tools',
1571 b'merge-tools',
1566 br'.*\.mergemarkertemplate$',
1572 br'.*\.mergemarkertemplate$',
1567 default=dynamicdefault, # take from command-templates.mergemarker
1573 default=dynamicdefault, # take from command-templates.mergemarker
1568 generic=True,
1574 generic=True,
1569 priority=-1,
1575 priority=-1,
1570 )
1576 )
1571 coreconfigitem(
1577 coreconfigitem(
1572 b'merge-tools',
1578 b'merge-tools',
1573 br'.*\.priority$',
1579 br'.*\.priority$',
1574 default=0,
1580 default=0,
1575 generic=True,
1581 generic=True,
1576 priority=-1,
1582 priority=-1,
1577 )
1583 )
1578 coreconfigitem(
1584 coreconfigitem(
1579 b'merge-tools',
1585 b'merge-tools',
1580 br'.*\.premerge$',
1586 br'.*\.premerge$',
1581 default=dynamicdefault,
1587 default=dynamicdefault,
1582 generic=True,
1588 generic=True,
1583 priority=-1,
1589 priority=-1,
1584 )
1590 )
1585 coreconfigitem(
1591 coreconfigitem(
1586 b'merge-tools',
1592 b'merge-tools',
1587 br'.*\.symlink$',
1593 br'.*\.symlink$',
1588 default=False,
1594 default=False,
1589 generic=True,
1595 generic=True,
1590 priority=-1,
1596 priority=-1,
1591 )
1597 )
1592 coreconfigitem(
1598 coreconfigitem(
1593 b'pager',
1599 b'pager',
1594 b'attend-.*',
1600 b'attend-.*',
1595 default=dynamicdefault,
1601 default=dynamicdefault,
1596 generic=True,
1602 generic=True,
1597 )
1603 )
1598 coreconfigitem(
1604 coreconfigitem(
1599 b'pager',
1605 b'pager',
1600 b'ignore',
1606 b'ignore',
1601 default=list,
1607 default=list,
1602 )
1608 )
1603 coreconfigitem(
1609 coreconfigitem(
1604 b'pager',
1610 b'pager',
1605 b'pager',
1611 b'pager',
1606 default=dynamicdefault,
1612 default=dynamicdefault,
1607 )
1613 )
1608 coreconfigitem(
1614 coreconfigitem(
1609 b'patch',
1615 b'patch',
1610 b'eol',
1616 b'eol',
1611 default=b'strict',
1617 default=b'strict',
1612 )
1618 )
1613 coreconfigitem(
1619 coreconfigitem(
1614 b'patch',
1620 b'patch',
1615 b'fuzz',
1621 b'fuzz',
1616 default=2,
1622 default=2,
1617 )
1623 )
1618 coreconfigitem(
1624 coreconfigitem(
1619 b'paths',
1625 b'paths',
1620 b'default',
1626 b'default',
1621 default=None,
1627 default=None,
1622 )
1628 )
1623 coreconfigitem(
1629 coreconfigitem(
1624 b'paths',
1630 b'paths',
1625 b'default-push',
1631 b'default-push',
1626 default=None,
1632 default=None,
1627 )
1633 )
1628 coreconfigitem(
1634 coreconfigitem(
1629 b'paths',
1635 b'paths',
1630 b'.*',
1636 b'.*',
1631 default=None,
1637 default=None,
1632 generic=True,
1638 generic=True,
1633 )
1639 )
1634 coreconfigitem(
1640 coreconfigitem(
1635 b'phases',
1641 b'phases',
1636 b'checksubrepos',
1642 b'checksubrepos',
1637 default=b'follow',
1643 default=b'follow',
1638 )
1644 )
1639 coreconfigitem(
1645 coreconfigitem(
1640 b'phases',
1646 b'phases',
1641 b'new-commit',
1647 b'new-commit',
1642 default=b'draft',
1648 default=b'draft',
1643 )
1649 )
1644 coreconfigitem(
1650 coreconfigitem(
1645 b'phases',
1651 b'phases',
1646 b'publish',
1652 b'publish',
1647 default=True,
1653 default=True,
1648 )
1654 )
1649 coreconfigitem(
1655 coreconfigitem(
1650 b'profiling',
1656 b'profiling',
1651 b'enabled',
1657 b'enabled',
1652 default=False,
1658 default=False,
1653 )
1659 )
1654 coreconfigitem(
1660 coreconfigitem(
1655 b'profiling',
1661 b'profiling',
1656 b'format',
1662 b'format',
1657 default=b'text',
1663 default=b'text',
1658 )
1664 )
1659 coreconfigitem(
1665 coreconfigitem(
1660 b'profiling',
1666 b'profiling',
1661 b'freq',
1667 b'freq',
1662 default=1000,
1668 default=1000,
1663 )
1669 )
1664 coreconfigitem(
1670 coreconfigitem(
1665 b'profiling',
1671 b'profiling',
1666 b'limit',
1672 b'limit',
1667 default=30,
1673 default=30,
1668 )
1674 )
1669 coreconfigitem(
1675 coreconfigitem(
1670 b'profiling',
1676 b'profiling',
1671 b'nested',
1677 b'nested',
1672 default=0,
1678 default=0,
1673 )
1679 )
1674 coreconfigitem(
1680 coreconfigitem(
1675 b'profiling',
1681 b'profiling',
1676 b'output',
1682 b'output',
1677 default=None,
1683 default=None,
1678 )
1684 )
1679 coreconfigitem(
1685 coreconfigitem(
1680 b'profiling',
1686 b'profiling',
1681 b'showmax',
1687 b'showmax',
1682 default=0.999,
1688 default=0.999,
1683 )
1689 )
1684 coreconfigitem(
1690 coreconfigitem(
1685 b'profiling',
1691 b'profiling',
1686 b'showmin',
1692 b'showmin',
1687 default=dynamicdefault,
1693 default=dynamicdefault,
1688 )
1694 )
1689 coreconfigitem(
1695 coreconfigitem(
1690 b'profiling',
1696 b'profiling',
1691 b'showtime',
1697 b'showtime',
1692 default=True,
1698 default=True,
1693 )
1699 )
1694 coreconfigitem(
1700 coreconfigitem(
1695 b'profiling',
1701 b'profiling',
1696 b'sort',
1702 b'sort',
1697 default=b'inlinetime',
1703 default=b'inlinetime',
1698 )
1704 )
1699 coreconfigitem(
1705 coreconfigitem(
1700 b'profiling',
1706 b'profiling',
1701 b'statformat',
1707 b'statformat',
1702 default=b'hotpath',
1708 default=b'hotpath',
1703 )
1709 )
1704 coreconfigitem(
1710 coreconfigitem(
1705 b'profiling',
1711 b'profiling',
1706 b'time-track',
1712 b'time-track',
1707 default=dynamicdefault,
1713 default=dynamicdefault,
1708 )
1714 )
1709 coreconfigitem(
1715 coreconfigitem(
1710 b'profiling',
1716 b'profiling',
1711 b'type',
1717 b'type',
1712 default=b'stat',
1718 default=b'stat',
1713 )
1719 )
1714 coreconfigitem(
1720 coreconfigitem(
1715 b'progress',
1721 b'progress',
1716 b'assume-tty',
1722 b'assume-tty',
1717 default=False,
1723 default=False,
1718 )
1724 )
1719 coreconfigitem(
1725 coreconfigitem(
1720 b'progress',
1726 b'progress',
1721 b'changedelay',
1727 b'changedelay',
1722 default=1,
1728 default=1,
1723 )
1729 )
1724 coreconfigitem(
1730 coreconfigitem(
1725 b'progress',
1731 b'progress',
1726 b'clear-complete',
1732 b'clear-complete',
1727 default=True,
1733 default=True,
1728 )
1734 )
1729 coreconfigitem(
1735 coreconfigitem(
1730 b'progress',
1736 b'progress',
1731 b'debug',
1737 b'debug',
1732 default=False,
1738 default=False,
1733 )
1739 )
1734 coreconfigitem(
1740 coreconfigitem(
1735 b'progress',
1741 b'progress',
1736 b'delay',
1742 b'delay',
1737 default=3,
1743 default=3,
1738 )
1744 )
1739 coreconfigitem(
1745 coreconfigitem(
1740 b'progress',
1746 b'progress',
1741 b'disable',
1747 b'disable',
1742 default=False,
1748 default=False,
1743 )
1749 )
1744 coreconfigitem(
1750 coreconfigitem(
1745 b'progress',
1751 b'progress',
1746 b'estimateinterval',
1752 b'estimateinterval',
1747 default=60.0,
1753 default=60.0,
1748 )
1754 )
1749 coreconfigitem(
1755 coreconfigitem(
1750 b'progress',
1756 b'progress',
1751 b'format',
1757 b'format',
1752 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1758 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1753 )
1759 )
1754 coreconfigitem(
1760 coreconfigitem(
1755 b'progress',
1761 b'progress',
1756 b'refresh',
1762 b'refresh',
1757 default=0.1,
1763 default=0.1,
1758 )
1764 )
1759 coreconfigitem(
1765 coreconfigitem(
1760 b'progress',
1766 b'progress',
1761 b'width',
1767 b'width',
1762 default=dynamicdefault,
1768 default=dynamicdefault,
1763 )
1769 )
1764 coreconfigitem(
1770 coreconfigitem(
1765 b'pull',
1771 b'pull',
1766 b'confirm',
1772 b'confirm',
1767 default=False,
1773 default=False,
1768 )
1774 )
1769 coreconfigitem(
1775 coreconfigitem(
1770 b'push',
1776 b'push',
1771 b'pushvars.server',
1777 b'pushvars.server',
1772 default=False,
1778 default=False,
1773 )
1779 )
1774 coreconfigitem(
1780 coreconfigitem(
1775 b'rewrite',
1781 b'rewrite',
1776 b'backup-bundle',
1782 b'backup-bundle',
1777 default=True,
1783 default=True,
1778 alias=[(b'ui', b'history-editing-backup')],
1784 alias=[(b'ui', b'history-editing-backup')],
1779 )
1785 )
1780 coreconfigitem(
1786 coreconfigitem(
1781 b'rewrite',
1787 b'rewrite',
1782 b'update-timestamp',
1788 b'update-timestamp',
1783 default=False,
1789 default=False,
1784 )
1790 )
1785 coreconfigitem(
1791 coreconfigitem(
1786 b'rewrite',
1792 b'rewrite',
1787 b'empty-successor',
1793 b'empty-successor',
1788 default=b'skip',
1794 default=b'skip',
1789 experimental=True,
1795 experimental=True,
1790 )
1796 )
1791 coreconfigitem(
1797 coreconfigitem(
1792 b'storage',
1798 b'storage',
1793 b'new-repo-backend',
1799 b'new-repo-backend',
1794 default=b'revlogv1',
1800 default=b'revlogv1',
1795 experimental=True,
1801 experimental=True,
1796 )
1802 )
1797 coreconfigitem(
1803 coreconfigitem(
1798 b'storage',
1804 b'storage',
1799 b'revlog.optimize-delta-parent-choice',
1805 b'revlog.optimize-delta-parent-choice',
1800 default=True,
1806 default=True,
1801 alias=[(b'format', b'aggressivemergedeltas')],
1807 alias=[(b'format', b'aggressivemergedeltas')],
1802 )
1808 )
1803 # experimental as long as rust is experimental (or a C version is implemented)
1809 # experimental as long as rust is experimental (or a C version is implemented)
1804 coreconfigitem(
1810 coreconfigitem(
1805 b'storage',
1811 b'storage',
1806 b'revlog.persistent-nodemap.mmap',
1812 b'revlog.persistent-nodemap.mmap',
1807 default=True,
1813 default=True,
1808 )
1814 )
1809 # experimental as long as format.use-persistent-nodemap is.
1815 # experimental as long as format.use-persistent-nodemap is.
1810 coreconfigitem(
1816 coreconfigitem(
1811 b'storage',
1817 b'storage',
1812 b'revlog.persistent-nodemap.slow-path',
1818 b'revlog.persistent-nodemap.slow-path',
1813 default=b"abort",
1819 default=b"abort",
1814 )
1820 )
1815
1821
1816 coreconfigitem(
1822 coreconfigitem(
1817 b'storage',
1823 b'storage',
1818 b'revlog.reuse-external-delta',
1824 b'revlog.reuse-external-delta',
1819 default=True,
1825 default=True,
1820 )
1826 )
1821 coreconfigitem(
1827 coreconfigitem(
1822 b'storage',
1828 b'storage',
1823 b'revlog.reuse-external-delta-parent',
1829 b'revlog.reuse-external-delta-parent',
1824 default=None,
1830 default=None,
1825 )
1831 )
1826 coreconfigitem(
1832 coreconfigitem(
1827 b'storage',
1833 b'storage',
1828 b'revlog.zlib.level',
1834 b'revlog.zlib.level',
1829 default=None,
1835 default=None,
1830 )
1836 )
1831 coreconfigitem(
1837 coreconfigitem(
1832 b'storage',
1838 b'storage',
1833 b'revlog.zstd.level',
1839 b'revlog.zstd.level',
1834 default=None,
1840 default=None,
1835 )
1841 )
1836 coreconfigitem(
1842 coreconfigitem(
1837 b'server',
1843 b'server',
1838 b'bookmarks-pushkey-compat',
1844 b'bookmarks-pushkey-compat',
1839 default=True,
1845 default=True,
1840 )
1846 )
1841 coreconfigitem(
1847 coreconfigitem(
1842 b'server',
1848 b'server',
1843 b'bundle1',
1849 b'bundle1',
1844 default=True,
1850 default=True,
1845 )
1851 )
1846 coreconfigitem(
1852 coreconfigitem(
1847 b'server',
1853 b'server',
1848 b'bundle1gd',
1854 b'bundle1gd',
1849 default=None,
1855 default=None,
1850 )
1856 )
1851 coreconfigitem(
1857 coreconfigitem(
1852 b'server',
1858 b'server',
1853 b'bundle1.pull',
1859 b'bundle1.pull',
1854 default=None,
1860 default=None,
1855 )
1861 )
1856 coreconfigitem(
1862 coreconfigitem(
1857 b'server',
1863 b'server',
1858 b'bundle1gd.pull',
1864 b'bundle1gd.pull',
1859 default=None,
1865 default=None,
1860 )
1866 )
1861 coreconfigitem(
1867 coreconfigitem(
1862 b'server',
1868 b'server',
1863 b'bundle1.push',
1869 b'bundle1.push',
1864 default=None,
1870 default=None,
1865 )
1871 )
1866 coreconfigitem(
1872 coreconfigitem(
1867 b'server',
1873 b'server',
1868 b'bundle1gd.push',
1874 b'bundle1gd.push',
1869 default=None,
1875 default=None,
1870 )
1876 )
1871 coreconfigitem(
1877 coreconfigitem(
1872 b'server',
1878 b'server',
1873 b'bundle2.stream',
1879 b'bundle2.stream',
1874 default=True,
1880 default=True,
1875 alias=[(b'experimental', b'bundle2.stream')],
1881 alias=[(b'experimental', b'bundle2.stream')],
1876 )
1882 )
1877 coreconfigitem(
1883 coreconfigitem(
1878 b'server',
1884 b'server',
1879 b'compressionengines',
1885 b'compressionengines',
1880 default=list,
1886 default=list,
1881 )
1887 )
1882 coreconfigitem(
1888 coreconfigitem(
1883 b'server',
1889 b'server',
1884 b'concurrent-push-mode',
1890 b'concurrent-push-mode',
1885 default=b'check-related',
1891 default=b'check-related',
1886 )
1892 )
1887 coreconfigitem(
1893 coreconfigitem(
1888 b'server',
1894 b'server',
1889 b'disablefullbundle',
1895 b'disablefullbundle',
1890 default=False,
1896 default=False,
1891 )
1897 )
1892 coreconfigitem(
1898 coreconfigitem(
1893 b'server',
1899 b'server',
1894 b'maxhttpheaderlen',
1900 b'maxhttpheaderlen',
1895 default=1024,
1901 default=1024,
1896 )
1902 )
1897 coreconfigitem(
1903 coreconfigitem(
1898 b'server',
1904 b'server',
1899 b'pullbundle',
1905 b'pullbundle',
1900 default=False,
1906 default=False,
1901 )
1907 )
1902 coreconfigitem(
1908 coreconfigitem(
1903 b'server',
1909 b'server',
1904 b'preferuncompressed',
1910 b'preferuncompressed',
1905 default=False,
1911 default=False,
1906 )
1912 )
1907 coreconfigitem(
1913 coreconfigitem(
1908 b'server',
1914 b'server',
1909 b'streamunbundle',
1915 b'streamunbundle',
1910 default=False,
1916 default=False,
1911 )
1917 )
1912 coreconfigitem(
1918 coreconfigitem(
1913 b'server',
1919 b'server',
1914 b'uncompressed',
1920 b'uncompressed',
1915 default=True,
1921 default=True,
1916 )
1922 )
1917 coreconfigitem(
1923 coreconfigitem(
1918 b'server',
1924 b'server',
1919 b'uncompressedallowsecret',
1925 b'uncompressedallowsecret',
1920 default=False,
1926 default=False,
1921 )
1927 )
1922 coreconfigitem(
1928 coreconfigitem(
1923 b'server',
1929 b'server',
1924 b'view',
1930 b'view',
1925 default=b'served',
1931 default=b'served',
1926 )
1932 )
1927 coreconfigitem(
1933 coreconfigitem(
1928 b'server',
1934 b'server',
1929 b'validate',
1935 b'validate',
1930 default=False,
1936 default=False,
1931 )
1937 )
1932 coreconfigitem(
1938 coreconfigitem(
1933 b'server',
1939 b'server',
1934 b'zliblevel',
1940 b'zliblevel',
1935 default=-1,
1941 default=-1,
1936 )
1942 )
1937 coreconfigitem(
1943 coreconfigitem(
1938 b'server',
1944 b'server',
1939 b'zstdlevel',
1945 b'zstdlevel',
1940 default=3,
1946 default=3,
1941 )
1947 )
1942 coreconfigitem(
1948 coreconfigitem(
1943 b'share',
1949 b'share',
1944 b'pool',
1950 b'pool',
1945 default=None,
1951 default=None,
1946 )
1952 )
1947 coreconfigitem(
1953 coreconfigitem(
1948 b'share',
1954 b'share',
1949 b'poolnaming',
1955 b'poolnaming',
1950 default=b'identity',
1956 default=b'identity',
1951 )
1957 )
1952 coreconfigitem(
1958 coreconfigitem(
1953 b'share',
1959 b'share',
1954 b'safe-mismatch.source-not-safe',
1960 b'safe-mismatch.source-not-safe',
1955 default=b'abort',
1961 default=b'abort',
1956 )
1962 )
1957 coreconfigitem(
1963 coreconfigitem(
1958 b'share',
1964 b'share',
1959 b'safe-mismatch.source-safe',
1965 b'safe-mismatch.source-safe',
1960 default=b'abort',
1966 default=b'abort',
1961 )
1967 )
1962 coreconfigitem(
1968 coreconfigitem(
1963 b'share',
1969 b'share',
1964 b'safe-mismatch.source-not-safe.warn',
1970 b'safe-mismatch.source-not-safe.warn',
1965 default=True,
1971 default=True,
1966 )
1972 )
1967 coreconfigitem(
1973 coreconfigitem(
1968 b'share',
1974 b'share',
1969 b'safe-mismatch.source-safe.warn',
1975 b'safe-mismatch.source-safe.warn',
1970 default=True,
1976 default=True,
1971 )
1977 )
1972 coreconfigitem(
1978 coreconfigitem(
1973 b'shelve',
1979 b'shelve',
1974 b'maxbackups',
1980 b'maxbackups',
1975 default=10,
1981 default=10,
1976 )
1982 )
1977 coreconfigitem(
1983 coreconfigitem(
1978 b'smtp',
1984 b'smtp',
1979 b'host',
1985 b'host',
1980 default=None,
1986 default=None,
1981 )
1987 )
1982 coreconfigitem(
1988 coreconfigitem(
1983 b'smtp',
1989 b'smtp',
1984 b'local_hostname',
1990 b'local_hostname',
1985 default=None,
1991 default=None,
1986 )
1992 )
1987 coreconfigitem(
1993 coreconfigitem(
1988 b'smtp',
1994 b'smtp',
1989 b'password',
1995 b'password',
1990 default=None,
1996 default=None,
1991 )
1997 )
1992 coreconfigitem(
1998 coreconfigitem(
1993 b'smtp',
1999 b'smtp',
1994 b'port',
2000 b'port',
1995 default=dynamicdefault,
2001 default=dynamicdefault,
1996 )
2002 )
1997 coreconfigitem(
2003 coreconfigitem(
1998 b'smtp',
2004 b'smtp',
1999 b'tls',
2005 b'tls',
2000 default=b'none',
2006 default=b'none',
2001 )
2007 )
2002 coreconfigitem(
2008 coreconfigitem(
2003 b'smtp',
2009 b'smtp',
2004 b'username',
2010 b'username',
2005 default=None,
2011 default=None,
2006 )
2012 )
2007 coreconfigitem(
2013 coreconfigitem(
2008 b'sparse',
2014 b'sparse',
2009 b'missingwarning',
2015 b'missingwarning',
2010 default=True,
2016 default=True,
2011 experimental=True,
2017 experimental=True,
2012 )
2018 )
2013 coreconfigitem(
2019 coreconfigitem(
2014 b'subrepos',
2020 b'subrepos',
2015 b'allowed',
2021 b'allowed',
2016 default=dynamicdefault, # to make backporting simpler
2022 default=dynamicdefault, # to make backporting simpler
2017 )
2023 )
2018 coreconfigitem(
2024 coreconfigitem(
2019 b'subrepos',
2025 b'subrepos',
2020 b'hg:allowed',
2026 b'hg:allowed',
2021 default=dynamicdefault,
2027 default=dynamicdefault,
2022 )
2028 )
2023 coreconfigitem(
2029 coreconfigitem(
2024 b'subrepos',
2030 b'subrepos',
2025 b'git:allowed',
2031 b'git:allowed',
2026 default=dynamicdefault,
2032 default=dynamicdefault,
2027 )
2033 )
2028 coreconfigitem(
2034 coreconfigitem(
2029 b'subrepos',
2035 b'subrepos',
2030 b'svn:allowed',
2036 b'svn:allowed',
2031 default=dynamicdefault,
2037 default=dynamicdefault,
2032 )
2038 )
2033 coreconfigitem(
2039 coreconfigitem(
2034 b'templates',
2040 b'templates',
2035 b'.*',
2041 b'.*',
2036 default=None,
2042 default=None,
2037 generic=True,
2043 generic=True,
2038 )
2044 )
2039 coreconfigitem(
2045 coreconfigitem(
2040 b'templateconfig',
2046 b'templateconfig',
2041 b'.*',
2047 b'.*',
2042 default=dynamicdefault,
2048 default=dynamicdefault,
2043 generic=True,
2049 generic=True,
2044 )
2050 )
2045 coreconfigitem(
2051 coreconfigitem(
2046 b'trusted',
2052 b'trusted',
2047 b'groups',
2053 b'groups',
2048 default=list,
2054 default=list,
2049 )
2055 )
2050 coreconfigitem(
2056 coreconfigitem(
2051 b'trusted',
2057 b'trusted',
2052 b'users',
2058 b'users',
2053 default=list,
2059 default=list,
2054 )
2060 )
2055 coreconfigitem(
2061 coreconfigitem(
2056 b'ui',
2062 b'ui',
2057 b'_usedassubrepo',
2063 b'_usedassubrepo',
2058 default=False,
2064 default=False,
2059 )
2065 )
2060 coreconfigitem(
2066 coreconfigitem(
2061 b'ui',
2067 b'ui',
2062 b'allowemptycommit',
2068 b'allowemptycommit',
2063 default=False,
2069 default=False,
2064 )
2070 )
2065 coreconfigitem(
2071 coreconfigitem(
2066 b'ui',
2072 b'ui',
2067 b'archivemeta',
2073 b'archivemeta',
2068 default=True,
2074 default=True,
2069 )
2075 )
2070 coreconfigitem(
2076 coreconfigitem(
2071 b'ui',
2077 b'ui',
2072 b'askusername',
2078 b'askusername',
2073 default=False,
2079 default=False,
2074 )
2080 )
2075 coreconfigitem(
2081 coreconfigitem(
2076 b'ui',
2082 b'ui',
2077 b'available-memory',
2083 b'available-memory',
2078 default=None,
2084 default=None,
2079 )
2085 )
2080
2086
2081 coreconfigitem(
2087 coreconfigitem(
2082 b'ui',
2088 b'ui',
2083 b'clonebundlefallback',
2089 b'clonebundlefallback',
2084 default=False,
2090 default=False,
2085 )
2091 )
2086 coreconfigitem(
2092 coreconfigitem(
2087 b'ui',
2093 b'ui',
2088 b'clonebundleprefers',
2094 b'clonebundleprefers',
2089 default=list,
2095 default=list,
2090 )
2096 )
2091 coreconfigitem(
2097 coreconfigitem(
2092 b'ui',
2098 b'ui',
2093 b'clonebundles',
2099 b'clonebundles',
2094 default=True,
2100 default=True,
2095 )
2101 )
2096 coreconfigitem(
2102 coreconfigitem(
2097 b'ui',
2103 b'ui',
2098 b'color',
2104 b'color',
2099 default=b'auto',
2105 default=b'auto',
2100 )
2106 )
2101 coreconfigitem(
2107 coreconfigitem(
2102 b'ui',
2108 b'ui',
2103 b'commitsubrepos',
2109 b'commitsubrepos',
2104 default=False,
2110 default=False,
2105 )
2111 )
2106 coreconfigitem(
2112 coreconfigitem(
2107 b'ui',
2113 b'ui',
2108 b'debug',
2114 b'debug',
2109 default=False,
2115 default=False,
2110 )
2116 )
2111 coreconfigitem(
2117 coreconfigitem(
2112 b'ui',
2118 b'ui',
2113 b'debugger',
2119 b'debugger',
2114 default=None,
2120 default=None,
2115 )
2121 )
2116 coreconfigitem(
2122 coreconfigitem(
2117 b'ui',
2123 b'ui',
2118 b'editor',
2124 b'editor',
2119 default=dynamicdefault,
2125 default=dynamicdefault,
2120 )
2126 )
2121 coreconfigitem(
2127 coreconfigitem(
2122 b'ui',
2128 b'ui',
2123 b'detailed-exit-code',
2129 b'detailed-exit-code',
2124 default=False,
2130 default=False,
2125 experimental=True,
2131 experimental=True,
2126 )
2132 )
2127 coreconfigitem(
2133 coreconfigitem(
2128 b'ui',
2134 b'ui',
2129 b'fallbackencoding',
2135 b'fallbackencoding',
2130 default=None,
2136 default=None,
2131 )
2137 )
2132 coreconfigitem(
2138 coreconfigitem(
2133 b'ui',
2139 b'ui',
2134 b'forcecwd',
2140 b'forcecwd',
2135 default=None,
2141 default=None,
2136 )
2142 )
2137 coreconfigitem(
2143 coreconfigitem(
2138 b'ui',
2144 b'ui',
2139 b'forcemerge',
2145 b'forcemerge',
2140 default=None,
2146 default=None,
2141 )
2147 )
2142 coreconfigitem(
2148 coreconfigitem(
2143 b'ui',
2149 b'ui',
2144 b'formatdebug',
2150 b'formatdebug',
2145 default=False,
2151 default=False,
2146 )
2152 )
2147 coreconfigitem(
2153 coreconfigitem(
2148 b'ui',
2154 b'ui',
2149 b'formatjson',
2155 b'formatjson',
2150 default=False,
2156 default=False,
2151 )
2157 )
2152 coreconfigitem(
2158 coreconfigitem(
2153 b'ui',
2159 b'ui',
2154 b'formatted',
2160 b'formatted',
2155 default=None,
2161 default=None,
2156 )
2162 )
2157 coreconfigitem(
2163 coreconfigitem(
2158 b'ui',
2164 b'ui',
2159 b'interactive',
2165 b'interactive',
2160 default=None,
2166 default=None,
2161 )
2167 )
2162 coreconfigitem(
2168 coreconfigitem(
2163 b'ui',
2169 b'ui',
2164 b'interface',
2170 b'interface',
2165 default=None,
2171 default=None,
2166 )
2172 )
2167 coreconfigitem(
2173 coreconfigitem(
2168 b'ui',
2174 b'ui',
2169 b'interface.chunkselector',
2175 b'interface.chunkselector',
2170 default=None,
2176 default=None,
2171 )
2177 )
2172 coreconfigitem(
2178 coreconfigitem(
2173 b'ui',
2179 b'ui',
2174 b'large-file-limit',
2180 b'large-file-limit',
2175 default=10000000,
2181 default=10000000,
2176 )
2182 )
2177 coreconfigitem(
2183 coreconfigitem(
2178 b'ui',
2184 b'ui',
2179 b'logblockedtimes',
2185 b'logblockedtimes',
2180 default=False,
2186 default=False,
2181 )
2187 )
2182 coreconfigitem(
2188 coreconfigitem(
2183 b'ui',
2189 b'ui',
2184 b'merge',
2190 b'merge',
2185 default=None,
2191 default=None,
2186 )
2192 )
2187 coreconfigitem(
2193 coreconfigitem(
2188 b'ui',
2194 b'ui',
2189 b'mergemarkers',
2195 b'mergemarkers',
2190 default=b'basic',
2196 default=b'basic',
2191 )
2197 )
2192 coreconfigitem(
2198 coreconfigitem(
2193 b'ui',
2199 b'ui',
2194 b'message-output',
2200 b'message-output',
2195 default=b'stdio',
2201 default=b'stdio',
2196 )
2202 )
2197 coreconfigitem(
2203 coreconfigitem(
2198 b'ui',
2204 b'ui',
2199 b'nontty',
2205 b'nontty',
2200 default=False,
2206 default=False,
2201 )
2207 )
2202 coreconfigitem(
2208 coreconfigitem(
2203 b'ui',
2209 b'ui',
2204 b'origbackuppath',
2210 b'origbackuppath',
2205 default=None,
2211 default=None,
2206 )
2212 )
2207 coreconfigitem(
2213 coreconfigitem(
2208 b'ui',
2214 b'ui',
2209 b'paginate',
2215 b'paginate',
2210 default=True,
2216 default=True,
2211 )
2217 )
2212 coreconfigitem(
2218 coreconfigitem(
2213 b'ui',
2219 b'ui',
2214 b'patch',
2220 b'patch',
2215 default=None,
2221 default=None,
2216 )
2222 )
2217 coreconfigitem(
2223 coreconfigitem(
2218 b'ui',
2224 b'ui',
2219 b'portablefilenames',
2225 b'portablefilenames',
2220 default=b'warn',
2226 default=b'warn',
2221 )
2227 )
2222 coreconfigitem(
2228 coreconfigitem(
2223 b'ui',
2229 b'ui',
2224 b'promptecho',
2230 b'promptecho',
2225 default=False,
2231 default=False,
2226 )
2232 )
2227 coreconfigitem(
2233 coreconfigitem(
2228 b'ui',
2234 b'ui',
2229 b'quiet',
2235 b'quiet',
2230 default=False,
2236 default=False,
2231 )
2237 )
2232 coreconfigitem(
2238 coreconfigitem(
2233 b'ui',
2239 b'ui',
2234 b'quietbookmarkmove',
2240 b'quietbookmarkmove',
2235 default=False,
2241 default=False,
2236 )
2242 )
2237 coreconfigitem(
2243 coreconfigitem(
2238 b'ui',
2244 b'ui',
2239 b'relative-paths',
2245 b'relative-paths',
2240 default=b'legacy',
2246 default=b'legacy',
2241 )
2247 )
2242 coreconfigitem(
2248 coreconfigitem(
2243 b'ui',
2249 b'ui',
2244 b'remotecmd',
2250 b'remotecmd',
2245 default=b'hg',
2251 default=b'hg',
2246 )
2252 )
2247 coreconfigitem(
2253 coreconfigitem(
2248 b'ui',
2254 b'ui',
2249 b'report_untrusted',
2255 b'report_untrusted',
2250 default=True,
2256 default=True,
2251 )
2257 )
2252 coreconfigitem(
2258 coreconfigitem(
2253 b'ui',
2259 b'ui',
2254 b'rollback',
2260 b'rollback',
2255 default=True,
2261 default=True,
2256 )
2262 )
2257 coreconfigitem(
2263 coreconfigitem(
2258 b'ui',
2264 b'ui',
2259 b'signal-safe-lock',
2265 b'signal-safe-lock',
2260 default=True,
2266 default=True,
2261 )
2267 )
2262 coreconfigitem(
2268 coreconfigitem(
2263 b'ui',
2269 b'ui',
2264 b'slash',
2270 b'slash',
2265 default=False,
2271 default=False,
2266 )
2272 )
2267 coreconfigitem(
2273 coreconfigitem(
2268 b'ui',
2274 b'ui',
2269 b'ssh',
2275 b'ssh',
2270 default=b'ssh',
2276 default=b'ssh',
2271 )
2277 )
2272 coreconfigitem(
2278 coreconfigitem(
2273 b'ui',
2279 b'ui',
2274 b'ssherrorhint',
2280 b'ssherrorhint',
2275 default=None,
2281 default=None,
2276 )
2282 )
2277 coreconfigitem(
2283 coreconfigitem(
2278 b'ui',
2284 b'ui',
2279 b'statuscopies',
2285 b'statuscopies',
2280 default=False,
2286 default=False,
2281 )
2287 )
2282 coreconfigitem(
2288 coreconfigitem(
2283 b'ui',
2289 b'ui',
2284 b'strict',
2290 b'strict',
2285 default=False,
2291 default=False,
2286 )
2292 )
2287 coreconfigitem(
2293 coreconfigitem(
2288 b'ui',
2294 b'ui',
2289 b'style',
2295 b'style',
2290 default=b'',
2296 default=b'',
2291 )
2297 )
2292 coreconfigitem(
2298 coreconfigitem(
2293 b'ui',
2299 b'ui',
2294 b'supportcontact',
2300 b'supportcontact',
2295 default=None,
2301 default=None,
2296 )
2302 )
2297 coreconfigitem(
2303 coreconfigitem(
2298 b'ui',
2304 b'ui',
2299 b'textwidth',
2305 b'textwidth',
2300 default=78,
2306 default=78,
2301 )
2307 )
2302 coreconfigitem(
2308 coreconfigitem(
2303 b'ui',
2309 b'ui',
2304 b'timeout',
2310 b'timeout',
2305 default=b'600',
2311 default=b'600',
2306 )
2312 )
2307 coreconfigitem(
2313 coreconfigitem(
2308 b'ui',
2314 b'ui',
2309 b'timeout.warn',
2315 b'timeout.warn',
2310 default=0,
2316 default=0,
2311 )
2317 )
2312 coreconfigitem(
2318 coreconfigitem(
2313 b'ui',
2319 b'ui',
2314 b'timestamp-output',
2320 b'timestamp-output',
2315 default=False,
2321 default=False,
2316 )
2322 )
2317 coreconfigitem(
2323 coreconfigitem(
2318 b'ui',
2324 b'ui',
2319 b'traceback',
2325 b'traceback',
2320 default=False,
2326 default=False,
2321 )
2327 )
2322 coreconfigitem(
2328 coreconfigitem(
2323 b'ui',
2329 b'ui',
2324 b'tweakdefaults',
2330 b'tweakdefaults',
2325 default=False,
2331 default=False,
2326 )
2332 )
2327 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2333 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2328 coreconfigitem(
2334 coreconfigitem(
2329 b'ui',
2335 b'ui',
2330 b'verbose',
2336 b'verbose',
2331 default=False,
2337 default=False,
2332 )
2338 )
2333 coreconfigitem(
2339 coreconfigitem(
2334 b'verify',
2340 b'verify',
2335 b'skipflags',
2341 b'skipflags',
2336 default=None,
2342 default=None,
2337 )
2343 )
2338 coreconfigitem(
2344 coreconfigitem(
2339 b'web',
2345 b'web',
2340 b'allowbz2',
2346 b'allowbz2',
2341 default=False,
2347 default=False,
2342 )
2348 )
2343 coreconfigitem(
2349 coreconfigitem(
2344 b'web',
2350 b'web',
2345 b'allowgz',
2351 b'allowgz',
2346 default=False,
2352 default=False,
2347 )
2353 )
2348 coreconfigitem(
2354 coreconfigitem(
2349 b'web',
2355 b'web',
2350 b'allow-pull',
2356 b'allow-pull',
2351 alias=[(b'web', b'allowpull')],
2357 alias=[(b'web', b'allowpull')],
2352 default=True,
2358 default=True,
2353 )
2359 )
2354 coreconfigitem(
2360 coreconfigitem(
2355 b'web',
2361 b'web',
2356 b'allow-push',
2362 b'allow-push',
2357 alias=[(b'web', b'allow_push')],
2363 alias=[(b'web', b'allow_push')],
2358 default=list,
2364 default=list,
2359 )
2365 )
2360 coreconfigitem(
2366 coreconfigitem(
2361 b'web',
2367 b'web',
2362 b'allowzip',
2368 b'allowzip',
2363 default=False,
2369 default=False,
2364 )
2370 )
2365 coreconfigitem(
2371 coreconfigitem(
2366 b'web',
2372 b'web',
2367 b'archivesubrepos',
2373 b'archivesubrepos',
2368 default=False,
2374 default=False,
2369 )
2375 )
2370 coreconfigitem(
2376 coreconfigitem(
2371 b'web',
2377 b'web',
2372 b'cache',
2378 b'cache',
2373 default=True,
2379 default=True,
2374 )
2380 )
2375 coreconfigitem(
2381 coreconfigitem(
2376 b'web',
2382 b'web',
2377 b'comparisoncontext',
2383 b'comparisoncontext',
2378 default=5,
2384 default=5,
2379 )
2385 )
2380 coreconfigitem(
2386 coreconfigitem(
2381 b'web',
2387 b'web',
2382 b'contact',
2388 b'contact',
2383 default=None,
2389 default=None,
2384 )
2390 )
2385 coreconfigitem(
2391 coreconfigitem(
2386 b'web',
2392 b'web',
2387 b'deny_push',
2393 b'deny_push',
2388 default=list,
2394 default=list,
2389 )
2395 )
2390 coreconfigitem(
2396 coreconfigitem(
2391 b'web',
2397 b'web',
2392 b'guessmime',
2398 b'guessmime',
2393 default=False,
2399 default=False,
2394 )
2400 )
2395 coreconfigitem(
2401 coreconfigitem(
2396 b'web',
2402 b'web',
2397 b'hidden',
2403 b'hidden',
2398 default=False,
2404 default=False,
2399 )
2405 )
2400 coreconfigitem(
2406 coreconfigitem(
2401 b'web',
2407 b'web',
2402 b'labels',
2408 b'labels',
2403 default=list,
2409 default=list,
2404 )
2410 )
2405 coreconfigitem(
2411 coreconfigitem(
2406 b'web',
2412 b'web',
2407 b'logoimg',
2413 b'logoimg',
2408 default=b'hglogo.png',
2414 default=b'hglogo.png',
2409 )
2415 )
2410 coreconfigitem(
2416 coreconfigitem(
2411 b'web',
2417 b'web',
2412 b'logourl',
2418 b'logourl',
2413 default=b'https://mercurial-scm.org/',
2419 default=b'https://mercurial-scm.org/',
2414 )
2420 )
2415 coreconfigitem(
2421 coreconfigitem(
2416 b'web',
2422 b'web',
2417 b'accesslog',
2423 b'accesslog',
2418 default=b'-',
2424 default=b'-',
2419 )
2425 )
2420 coreconfigitem(
2426 coreconfigitem(
2421 b'web',
2427 b'web',
2422 b'address',
2428 b'address',
2423 default=b'',
2429 default=b'',
2424 )
2430 )
2425 coreconfigitem(
2431 coreconfigitem(
2426 b'web',
2432 b'web',
2427 b'allow-archive',
2433 b'allow-archive',
2428 alias=[(b'web', b'allow_archive')],
2434 alias=[(b'web', b'allow_archive')],
2429 default=list,
2435 default=list,
2430 )
2436 )
2431 coreconfigitem(
2437 coreconfigitem(
2432 b'web',
2438 b'web',
2433 b'allow_read',
2439 b'allow_read',
2434 default=list,
2440 default=list,
2435 )
2441 )
2436 coreconfigitem(
2442 coreconfigitem(
2437 b'web',
2443 b'web',
2438 b'baseurl',
2444 b'baseurl',
2439 default=None,
2445 default=None,
2440 )
2446 )
2441 coreconfigitem(
2447 coreconfigitem(
2442 b'web',
2448 b'web',
2443 b'cacerts',
2449 b'cacerts',
2444 default=None,
2450 default=None,
2445 )
2451 )
2446 coreconfigitem(
2452 coreconfigitem(
2447 b'web',
2453 b'web',
2448 b'certificate',
2454 b'certificate',
2449 default=None,
2455 default=None,
2450 )
2456 )
2451 coreconfigitem(
2457 coreconfigitem(
2452 b'web',
2458 b'web',
2453 b'collapse',
2459 b'collapse',
2454 default=False,
2460 default=False,
2455 )
2461 )
2456 coreconfigitem(
2462 coreconfigitem(
2457 b'web',
2463 b'web',
2458 b'csp',
2464 b'csp',
2459 default=None,
2465 default=None,
2460 )
2466 )
2461 coreconfigitem(
2467 coreconfigitem(
2462 b'web',
2468 b'web',
2463 b'deny_read',
2469 b'deny_read',
2464 default=list,
2470 default=list,
2465 )
2471 )
2466 coreconfigitem(
2472 coreconfigitem(
2467 b'web',
2473 b'web',
2468 b'descend',
2474 b'descend',
2469 default=True,
2475 default=True,
2470 )
2476 )
2471 coreconfigitem(
2477 coreconfigitem(
2472 b'web',
2478 b'web',
2473 b'description',
2479 b'description',
2474 default=b"",
2480 default=b"",
2475 )
2481 )
2476 coreconfigitem(
2482 coreconfigitem(
2477 b'web',
2483 b'web',
2478 b'encoding',
2484 b'encoding',
2479 default=lambda: encoding.encoding,
2485 default=lambda: encoding.encoding,
2480 )
2486 )
2481 coreconfigitem(
2487 coreconfigitem(
2482 b'web',
2488 b'web',
2483 b'errorlog',
2489 b'errorlog',
2484 default=b'-',
2490 default=b'-',
2485 )
2491 )
2486 coreconfigitem(
2492 coreconfigitem(
2487 b'web',
2493 b'web',
2488 b'ipv6',
2494 b'ipv6',
2489 default=False,
2495 default=False,
2490 )
2496 )
2491 coreconfigitem(
2497 coreconfigitem(
2492 b'web',
2498 b'web',
2493 b'maxchanges',
2499 b'maxchanges',
2494 default=10,
2500 default=10,
2495 )
2501 )
2496 coreconfigitem(
2502 coreconfigitem(
2497 b'web',
2503 b'web',
2498 b'maxfiles',
2504 b'maxfiles',
2499 default=10,
2505 default=10,
2500 )
2506 )
2501 coreconfigitem(
2507 coreconfigitem(
2502 b'web',
2508 b'web',
2503 b'maxshortchanges',
2509 b'maxshortchanges',
2504 default=60,
2510 default=60,
2505 )
2511 )
2506 coreconfigitem(
2512 coreconfigitem(
2507 b'web',
2513 b'web',
2508 b'motd',
2514 b'motd',
2509 default=b'',
2515 default=b'',
2510 )
2516 )
2511 coreconfigitem(
2517 coreconfigitem(
2512 b'web',
2518 b'web',
2513 b'name',
2519 b'name',
2514 default=dynamicdefault,
2520 default=dynamicdefault,
2515 )
2521 )
2516 coreconfigitem(
2522 coreconfigitem(
2517 b'web',
2523 b'web',
2518 b'port',
2524 b'port',
2519 default=8000,
2525 default=8000,
2520 )
2526 )
2521 coreconfigitem(
2527 coreconfigitem(
2522 b'web',
2528 b'web',
2523 b'prefix',
2529 b'prefix',
2524 default=b'',
2530 default=b'',
2525 )
2531 )
2526 coreconfigitem(
2532 coreconfigitem(
2527 b'web',
2533 b'web',
2528 b'push_ssl',
2534 b'push_ssl',
2529 default=True,
2535 default=True,
2530 )
2536 )
2531 coreconfigitem(
2537 coreconfigitem(
2532 b'web',
2538 b'web',
2533 b'refreshinterval',
2539 b'refreshinterval',
2534 default=20,
2540 default=20,
2535 )
2541 )
2536 coreconfigitem(
2542 coreconfigitem(
2537 b'web',
2543 b'web',
2538 b'server-header',
2544 b'server-header',
2539 default=None,
2545 default=None,
2540 )
2546 )
2541 coreconfigitem(
2547 coreconfigitem(
2542 b'web',
2548 b'web',
2543 b'static',
2549 b'static',
2544 default=None,
2550 default=None,
2545 )
2551 )
2546 coreconfigitem(
2552 coreconfigitem(
2547 b'web',
2553 b'web',
2548 b'staticurl',
2554 b'staticurl',
2549 default=None,
2555 default=None,
2550 )
2556 )
2551 coreconfigitem(
2557 coreconfigitem(
2552 b'web',
2558 b'web',
2553 b'stripes',
2559 b'stripes',
2554 default=1,
2560 default=1,
2555 )
2561 )
2556 coreconfigitem(
2562 coreconfigitem(
2557 b'web',
2563 b'web',
2558 b'style',
2564 b'style',
2559 default=b'paper',
2565 default=b'paper',
2560 )
2566 )
2561 coreconfigitem(
2567 coreconfigitem(
2562 b'web',
2568 b'web',
2563 b'templates',
2569 b'templates',
2564 default=None,
2570 default=None,
2565 )
2571 )
2566 coreconfigitem(
2572 coreconfigitem(
2567 b'web',
2573 b'web',
2568 b'view',
2574 b'view',
2569 default=b'served',
2575 default=b'served',
2570 experimental=True,
2576 experimental=True,
2571 )
2577 )
2572 coreconfigitem(
2578 coreconfigitem(
2573 b'worker',
2579 b'worker',
2574 b'backgroundclose',
2580 b'backgroundclose',
2575 default=dynamicdefault,
2581 default=dynamicdefault,
2576 )
2582 )
2577 # Windows defaults to a limit of 512 open files. A buffer of 128
2583 # Windows defaults to a limit of 512 open files. A buffer of 128
2578 # should give us enough headway.
2584 # should give us enough headway.
2579 coreconfigitem(
2585 coreconfigitem(
2580 b'worker',
2586 b'worker',
2581 b'backgroundclosemaxqueue',
2587 b'backgroundclosemaxqueue',
2582 default=384,
2588 default=384,
2583 )
2589 )
2584 coreconfigitem(
2590 coreconfigitem(
2585 b'worker',
2591 b'worker',
2586 b'backgroundcloseminfilecount',
2592 b'backgroundcloseminfilecount',
2587 default=2048,
2593 default=2048,
2588 )
2594 )
2589 coreconfigitem(
2595 coreconfigitem(
2590 b'worker',
2596 b'worker',
2591 b'backgroundclosethreadcount',
2597 b'backgroundclosethreadcount',
2592 default=4,
2598 default=4,
2593 )
2599 )
2594 coreconfigitem(
2600 coreconfigitem(
2595 b'worker',
2601 b'worker',
2596 b'enabled',
2602 b'enabled',
2597 default=True,
2603 default=True,
2598 )
2604 )
2599 coreconfigitem(
2605 coreconfigitem(
2600 b'worker',
2606 b'worker',
2601 b'numcpus',
2607 b'numcpus',
2602 default=None,
2608 default=None,
2603 )
2609 )
2604
2610
2605 # Rebase related configuration moved to core because other extension are doing
2611 # Rebase related configuration moved to core because other extension are doing
2606 # strange things. For example, shelve import the extensions to reuse some bit
2612 # strange things. For example, shelve import the extensions to reuse some bit
2607 # without formally loading it.
2613 # without formally loading it.
2608 coreconfigitem(
2614 coreconfigitem(
2609 b'commands',
2615 b'commands',
2610 b'rebase.requiredest',
2616 b'rebase.requiredest',
2611 default=False,
2617 default=False,
2612 )
2618 )
2613 coreconfigitem(
2619 coreconfigitem(
2614 b'experimental',
2620 b'experimental',
2615 b'rebaseskipobsolete',
2621 b'rebaseskipobsolete',
2616 default=True,
2622 default=True,
2617 )
2623 )
2618 coreconfigitem(
2624 coreconfigitem(
2619 b'rebase',
2625 b'rebase',
2620 b'singletransaction',
2626 b'singletransaction',
2621 default=False,
2627 default=False,
2622 )
2628 )
2623 coreconfigitem(
2629 coreconfigitem(
2624 b'rebase',
2630 b'rebase',
2625 b'experimental.inmemory',
2631 b'experimental.inmemory',
2626 default=False,
2632 default=False,
2627 )
2633 )
@@ -1,3698 +1,3702 b''
1 # localrepo.py - read/write repository class for mercurial
1 # localrepo.py - read/write repository class for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import functools
11 import functools
12 import os
12 import os
13 import random
13 import random
14 import sys
14 import sys
15 import time
15 import time
16 import weakref
16 import weakref
17
17
18 from .i18n import _
18 from .i18n import _
19 from .node import (
19 from .node import (
20 bin,
20 bin,
21 hex,
21 hex,
22 nullid,
22 nullid,
23 nullrev,
23 nullrev,
24 short,
24 short,
25 )
25 )
26 from .pycompat import (
26 from .pycompat import (
27 delattr,
27 delattr,
28 getattr,
28 getattr,
29 )
29 )
30 from . import (
30 from . import (
31 bookmarks,
31 bookmarks,
32 branchmap,
32 branchmap,
33 bundle2,
33 bundle2,
34 bundlecaches,
34 bundlecaches,
35 changegroup,
35 changegroup,
36 color,
36 color,
37 commit,
37 commit,
38 context,
38 context,
39 dirstate,
39 dirstate,
40 dirstateguard,
40 dirstateguard,
41 discovery,
41 discovery,
42 encoding,
42 encoding,
43 error,
43 error,
44 exchange,
44 exchange,
45 extensions,
45 extensions,
46 filelog,
46 filelog,
47 hook,
47 hook,
48 lock as lockmod,
48 lock as lockmod,
49 match as matchmod,
49 match as matchmod,
50 mergestate as mergestatemod,
50 mergestate as mergestatemod,
51 mergeutil,
51 mergeutil,
52 namespaces,
52 namespaces,
53 narrowspec,
53 narrowspec,
54 obsolete,
54 obsolete,
55 pathutil,
55 pathutil,
56 phases,
56 phases,
57 pushkey,
57 pushkey,
58 pycompat,
58 pycompat,
59 rcutil,
59 rcutil,
60 repoview,
60 repoview,
61 requirements as requirementsmod,
61 requirements as requirementsmod,
62 revlog,
62 revlog,
63 revset,
63 revset,
64 revsetlang,
64 revsetlang,
65 scmutil,
65 scmutil,
66 sparse,
66 sparse,
67 store as storemod,
67 store as storemod,
68 subrepoutil,
68 subrepoutil,
69 tags as tagsmod,
69 tags as tagsmod,
70 transaction,
70 transaction,
71 txnutil,
71 txnutil,
72 util,
72 util,
73 vfs as vfsmod,
73 vfs as vfsmod,
74 )
74 )
75
75
76 from .interfaces import (
76 from .interfaces import (
77 repository,
77 repository,
78 util as interfaceutil,
78 util as interfaceutil,
79 )
79 )
80
80
81 from .utils import (
81 from .utils import (
82 hashutil,
82 hashutil,
83 procutil,
83 procutil,
84 stringutil,
84 stringutil,
85 )
85 )
86
86
87 from .revlogutils import (
87 from .revlogutils import (
88 concurrency_checker as revlogchecker,
88 concurrency_checker as revlogchecker,
89 constants as revlogconst,
89 constants as revlogconst,
90 )
90 )
91
91
92 release = lockmod.release
92 release = lockmod.release
93 urlerr = util.urlerr
93 urlerr = util.urlerr
94 urlreq = util.urlreq
94 urlreq = util.urlreq
95
95
96 # set of (path, vfs-location) tuples. vfs-location is:
96 # set of (path, vfs-location) tuples. vfs-location is:
97 # - 'plain for vfs relative paths
97 # - 'plain for vfs relative paths
98 # - '' for svfs relative paths
98 # - '' for svfs relative paths
99 _cachedfiles = set()
99 _cachedfiles = set()
100
100
101
101
102 class _basefilecache(scmutil.filecache):
102 class _basefilecache(scmutil.filecache):
103 """All filecache usage on repo are done for logic that should be unfiltered"""
103 """All filecache usage on repo are done for logic that should be unfiltered"""
104
104
105 def __get__(self, repo, type=None):
105 def __get__(self, repo, type=None):
106 if repo is None:
106 if repo is None:
107 return self
107 return self
108 # proxy to unfiltered __dict__ since filtered repo has no entry
108 # proxy to unfiltered __dict__ since filtered repo has no entry
109 unfi = repo.unfiltered()
109 unfi = repo.unfiltered()
110 try:
110 try:
111 return unfi.__dict__[self.sname]
111 return unfi.__dict__[self.sname]
112 except KeyError:
112 except KeyError:
113 pass
113 pass
114 return super(_basefilecache, self).__get__(unfi, type)
114 return super(_basefilecache, self).__get__(unfi, type)
115
115
116 def set(self, repo, value):
116 def set(self, repo, value):
117 return super(_basefilecache, self).set(repo.unfiltered(), value)
117 return super(_basefilecache, self).set(repo.unfiltered(), value)
118
118
119
119
120 class repofilecache(_basefilecache):
120 class repofilecache(_basefilecache):
121 """filecache for files in .hg but outside of .hg/store"""
121 """filecache for files in .hg but outside of .hg/store"""
122
122
123 def __init__(self, *paths):
123 def __init__(self, *paths):
124 super(repofilecache, self).__init__(*paths)
124 super(repofilecache, self).__init__(*paths)
125 for path in paths:
125 for path in paths:
126 _cachedfiles.add((path, b'plain'))
126 _cachedfiles.add((path, b'plain'))
127
127
128 def join(self, obj, fname):
128 def join(self, obj, fname):
129 return obj.vfs.join(fname)
129 return obj.vfs.join(fname)
130
130
131
131
132 class storecache(_basefilecache):
132 class storecache(_basefilecache):
133 """filecache for files in the store"""
133 """filecache for files in the store"""
134
134
135 def __init__(self, *paths):
135 def __init__(self, *paths):
136 super(storecache, self).__init__(*paths)
136 super(storecache, self).__init__(*paths)
137 for path in paths:
137 for path in paths:
138 _cachedfiles.add((path, b''))
138 _cachedfiles.add((path, b''))
139
139
140 def join(self, obj, fname):
140 def join(self, obj, fname):
141 return obj.sjoin(fname)
141 return obj.sjoin(fname)
142
142
143
143
144 class mixedrepostorecache(_basefilecache):
144 class mixedrepostorecache(_basefilecache):
145 """filecache for a mix files in .hg/store and outside"""
145 """filecache for a mix files in .hg/store and outside"""
146
146
147 def __init__(self, *pathsandlocations):
147 def __init__(self, *pathsandlocations):
148 # scmutil.filecache only uses the path for passing back into our
148 # scmutil.filecache only uses the path for passing back into our
149 # join(), so we can safely pass a list of paths and locations
149 # join(), so we can safely pass a list of paths and locations
150 super(mixedrepostorecache, self).__init__(*pathsandlocations)
150 super(mixedrepostorecache, self).__init__(*pathsandlocations)
151 _cachedfiles.update(pathsandlocations)
151 _cachedfiles.update(pathsandlocations)
152
152
153 def join(self, obj, fnameandlocation):
153 def join(self, obj, fnameandlocation):
154 fname, location = fnameandlocation
154 fname, location = fnameandlocation
155 if location == b'plain':
155 if location == b'plain':
156 return obj.vfs.join(fname)
156 return obj.vfs.join(fname)
157 else:
157 else:
158 if location != b'':
158 if location != b'':
159 raise error.ProgrammingError(
159 raise error.ProgrammingError(
160 b'unexpected location: %s' % location
160 b'unexpected location: %s' % location
161 )
161 )
162 return obj.sjoin(fname)
162 return obj.sjoin(fname)
163
163
164
164
165 def isfilecached(repo, name):
165 def isfilecached(repo, name):
166 """check if a repo has already cached "name" filecache-ed property
166 """check if a repo has already cached "name" filecache-ed property
167
167
168 This returns (cachedobj-or-None, iscached) tuple.
168 This returns (cachedobj-or-None, iscached) tuple.
169 """
169 """
170 cacheentry = repo.unfiltered()._filecache.get(name, None)
170 cacheentry = repo.unfiltered()._filecache.get(name, None)
171 if not cacheentry:
171 if not cacheentry:
172 return None, False
172 return None, False
173 return cacheentry.obj, True
173 return cacheentry.obj, True
174
174
175
175
176 class unfilteredpropertycache(util.propertycache):
176 class unfilteredpropertycache(util.propertycache):
177 """propertycache that apply to unfiltered repo only"""
177 """propertycache that apply to unfiltered repo only"""
178
178
179 def __get__(self, repo, type=None):
179 def __get__(self, repo, type=None):
180 unfi = repo.unfiltered()
180 unfi = repo.unfiltered()
181 if unfi is repo:
181 if unfi is repo:
182 return super(unfilteredpropertycache, self).__get__(unfi)
182 return super(unfilteredpropertycache, self).__get__(unfi)
183 return getattr(unfi, self.name)
183 return getattr(unfi, self.name)
184
184
185
185
186 class filteredpropertycache(util.propertycache):
186 class filteredpropertycache(util.propertycache):
187 """propertycache that must take filtering in account"""
187 """propertycache that must take filtering in account"""
188
188
189 def cachevalue(self, obj, value):
189 def cachevalue(self, obj, value):
190 object.__setattr__(obj, self.name, value)
190 object.__setattr__(obj, self.name, value)
191
191
192
192
193 def hasunfilteredcache(repo, name):
193 def hasunfilteredcache(repo, name):
194 """check if a repo has an unfilteredpropertycache value for <name>"""
194 """check if a repo has an unfilteredpropertycache value for <name>"""
195 return name in vars(repo.unfiltered())
195 return name in vars(repo.unfiltered())
196
196
197
197
198 def unfilteredmethod(orig):
198 def unfilteredmethod(orig):
199 """decorate method that always need to be run on unfiltered version"""
199 """decorate method that always need to be run on unfiltered version"""
200
200
201 @functools.wraps(orig)
201 @functools.wraps(orig)
202 def wrapper(repo, *args, **kwargs):
202 def wrapper(repo, *args, **kwargs):
203 return orig(repo.unfiltered(), *args, **kwargs)
203 return orig(repo.unfiltered(), *args, **kwargs)
204
204
205 return wrapper
205 return wrapper
206
206
207
207
208 moderncaps = {
208 moderncaps = {
209 b'lookup',
209 b'lookup',
210 b'branchmap',
210 b'branchmap',
211 b'pushkey',
211 b'pushkey',
212 b'known',
212 b'known',
213 b'getbundle',
213 b'getbundle',
214 b'unbundle',
214 b'unbundle',
215 }
215 }
216 legacycaps = moderncaps.union({b'changegroupsubset'})
216 legacycaps = moderncaps.union({b'changegroupsubset'})
217
217
218
218
219 @interfaceutil.implementer(repository.ipeercommandexecutor)
219 @interfaceutil.implementer(repository.ipeercommandexecutor)
220 class localcommandexecutor(object):
220 class localcommandexecutor(object):
221 def __init__(self, peer):
221 def __init__(self, peer):
222 self._peer = peer
222 self._peer = peer
223 self._sent = False
223 self._sent = False
224 self._closed = False
224 self._closed = False
225
225
226 def __enter__(self):
226 def __enter__(self):
227 return self
227 return self
228
228
229 def __exit__(self, exctype, excvalue, exctb):
229 def __exit__(self, exctype, excvalue, exctb):
230 self.close()
230 self.close()
231
231
232 def callcommand(self, command, args):
232 def callcommand(self, command, args):
233 if self._sent:
233 if self._sent:
234 raise error.ProgrammingError(
234 raise error.ProgrammingError(
235 b'callcommand() cannot be used after sendcommands()'
235 b'callcommand() cannot be used after sendcommands()'
236 )
236 )
237
237
238 if self._closed:
238 if self._closed:
239 raise error.ProgrammingError(
239 raise error.ProgrammingError(
240 b'callcommand() cannot be used after close()'
240 b'callcommand() cannot be used after close()'
241 )
241 )
242
242
243 # We don't need to support anything fancy. Just call the named
243 # We don't need to support anything fancy. Just call the named
244 # method on the peer and return a resolved future.
244 # method on the peer and return a resolved future.
245 fn = getattr(self._peer, pycompat.sysstr(command))
245 fn = getattr(self._peer, pycompat.sysstr(command))
246
246
247 f = pycompat.futures.Future()
247 f = pycompat.futures.Future()
248
248
249 try:
249 try:
250 result = fn(**pycompat.strkwargs(args))
250 result = fn(**pycompat.strkwargs(args))
251 except Exception:
251 except Exception:
252 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
252 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
253 else:
253 else:
254 f.set_result(result)
254 f.set_result(result)
255
255
256 return f
256 return f
257
257
258 def sendcommands(self):
258 def sendcommands(self):
259 self._sent = True
259 self._sent = True
260
260
261 def close(self):
261 def close(self):
262 self._closed = True
262 self._closed = True
263
263
264
264
265 @interfaceutil.implementer(repository.ipeercommands)
265 @interfaceutil.implementer(repository.ipeercommands)
266 class localpeer(repository.peer):
266 class localpeer(repository.peer):
267 '''peer for a local repo; reflects only the most recent API'''
267 '''peer for a local repo; reflects only the most recent API'''
268
268
269 def __init__(self, repo, caps=None):
269 def __init__(self, repo, caps=None):
270 super(localpeer, self).__init__()
270 super(localpeer, self).__init__()
271
271
272 if caps is None:
272 if caps is None:
273 caps = moderncaps.copy()
273 caps = moderncaps.copy()
274 self._repo = repo.filtered(b'served')
274 self._repo = repo.filtered(b'served')
275 self.ui = repo.ui
275 self.ui = repo.ui
276 self._caps = repo._restrictcapabilities(caps)
276 self._caps = repo._restrictcapabilities(caps)
277
277
278 # Begin of _basepeer interface.
278 # Begin of _basepeer interface.
279
279
280 def url(self):
280 def url(self):
281 return self._repo.url()
281 return self._repo.url()
282
282
283 def local(self):
283 def local(self):
284 return self._repo
284 return self._repo
285
285
286 def peer(self):
286 def peer(self):
287 return self
287 return self
288
288
289 def canpush(self):
289 def canpush(self):
290 return True
290 return True
291
291
292 def close(self):
292 def close(self):
293 self._repo.close()
293 self._repo.close()
294
294
295 # End of _basepeer interface.
295 # End of _basepeer interface.
296
296
297 # Begin of _basewirecommands interface.
297 # Begin of _basewirecommands interface.
298
298
299 def branchmap(self):
299 def branchmap(self):
300 return self._repo.branchmap()
300 return self._repo.branchmap()
301
301
302 def capabilities(self):
302 def capabilities(self):
303 return self._caps
303 return self._caps
304
304
305 def clonebundles(self):
305 def clonebundles(self):
306 return self._repo.tryread(bundlecaches.CB_MANIFEST_FILE)
306 return self._repo.tryread(bundlecaches.CB_MANIFEST_FILE)
307
307
308 def debugwireargs(self, one, two, three=None, four=None, five=None):
308 def debugwireargs(self, one, two, three=None, four=None, five=None):
309 """Used to test argument passing over the wire"""
309 """Used to test argument passing over the wire"""
310 return b"%s %s %s %s %s" % (
310 return b"%s %s %s %s %s" % (
311 one,
311 one,
312 two,
312 two,
313 pycompat.bytestr(three),
313 pycompat.bytestr(three),
314 pycompat.bytestr(four),
314 pycompat.bytestr(four),
315 pycompat.bytestr(five),
315 pycompat.bytestr(five),
316 )
316 )
317
317
318 def getbundle(
318 def getbundle(
319 self, source, heads=None, common=None, bundlecaps=None, **kwargs
319 self, source, heads=None, common=None, bundlecaps=None, **kwargs
320 ):
320 ):
321 chunks = exchange.getbundlechunks(
321 chunks = exchange.getbundlechunks(
322 self._repo,
322 self._repo,
323 source,
323 source,
324 heads=heads,
324 heads=heads,
325 common=common,
325 common=common,
326 bundlecaps=bundlecaps,
326 bundlecaps=bundlecaps,
327 **kwargs
327 **kwargs
328 )[1]
328 )[1]
329 cb = util.chunkbuffer(chunks)
329 cb = util.chunkbuffer(chunks)
330
330
331 if exchange.bundle2requested(bundlecaps):
331 if exchange.bundle2requested(bundlecaps):
332 # When requesting a bundle2, getbundle returns a stream to make the
332 # When requesting a bundle2, getbundle returns a stream to make the
333 # wire level function happier. We need to build a proper object
333 # wire level function happier. We need to build a proper object
334 # from it in local peer.
334 # from it in local peer.
335 return bundle2.getunbundler(self.ui, cb)
335 return bundle2.getunbundler(self.ui, cb)
336 else:
336 else:
337 return changegroup.getunbundler(b'01', cb, None)
337 return changegroup.getunbundler(b'01', cb, None)
338
338
339 def heads(self):
339 def heads(self):
340 return self._repo.heads()
340 return self._repo.heads()
341
341
342 def known(self, nodes):
342 def known(self, nodes):
343 return self._repo.known(nodes)
343 return self._repo.known(nodes)
344
344
345 def listkeys(self, namespace):
345 def listkeys(self, namespace):
346 return self._repo.listkeys(namespace)
346 return self._repo.listkeys(namespace)
347
347
348 def lookup(self, key):
348 def lookup(self, key):
349 return self._repo.lookup(key)
349 return self._repo.lookup(key)
350
350
351 def pushkey(self, namespace, key, old, new):
351 def pushkey(self, namespace, key, old, new):
352 return self._repo.pushkey(namespace, key, old, new)
352 return self._repo.pushkey(namespace, key, old, new)
353
353
354 def stream_out(self):
354 def stream_out(self):
355 raise error.Abort(_(b'cannot perform stream clone against local peer'))
355 raise error.Abort(_(b'cannot perform stream clone against local peer'))
356
356
357 def unbundle(self, bundle, heads, url):
357 def unbundle(self, bundle, heads, url):
358 """apply a bundle on a repo
358 """apply a bundle on a repo
359
359
360 This function handles the repo locking itself."""
360 This function handles the repo locking itself."""
361 try:
361 try:
362 try:
362 try:
363 bundle = exchange.readbundle(self.ui, bundle, None)
363 bundle = exchange.readbundle(self.ui, bundle, None)
364 ret = exchange.unbundle(self._repo, bundle, heads, b'push', url)
364 ret = exchange.unbundle(self._repo, bundle, heads, b'push', url)
365 if util.safehasattr(ret, b'getchunks'):
365 if util.safehasattr(ret, b'getchunks'):
366 # This is a bundle20 object, turn it into an unbundler.
366 # This is a bundle20 object, turn it into an unbundler.
367 # This little dance should be dropped eventually when the
367 # This little dance should be dropped eventually when the
368 # API is finally improved.
368 # API is finally improved.
369 stream = util.chunkbuffer(ret.getchunks())
369 stream = util.chunkbuffer(ret.getchunks())
370 ret = bundle2.getunbundler(self.ui, stream)
370 ret = bundle2.getunbundler(self.ui, stream)
371 return ret
371 return ret
372 except Exception as exc:
372 except Exception as exc:
373 # If the exception contains output salvaged from a bundle2
373 # If the exception contains output salvaged from a bundle2
374 # reply, we need to make sure it is printed before continuing
374 # reply, we need to make sure it is printed before continuing
375 # to fail. So we build a bundle2 with such output and consume
375 # to fail. So we build a bundle2 with such output and consume
376 # it directly.
376 # it directly.
377 #
377 #
378 # This is not very elegant but allows a "simple" solution for
378 # This is not very elegant but allows a "simple" solution for
379 # issue4594
379 # issue4594
380 output = getattr(exc, '_bundle2salvagedoutput', ())
380 output = getattr(exc, '_bundle2salvagedoutput', ())
381 if output:
381 if output:
382 bundler = bundle2.bundle20(self._repo.ui)
382 bundler = bundle2.bundle20(self._repo.ui)
383 for out in output:
383 for out in output:
384 bundler.addpart(out)
384 bundler.addpart(out)
385 stream = util.chunkbuffer(bundler.getchunks())
385 stream = util.chunkbuffer(bundler.getchunks())
386 b = bundle2.getunbundler(self.ui, stream)
386 b = bundle2.getunbundler(self.ui, stream)
387 bundle2.processbundle(self._repo, b)
387 bundle2.processbundle(self._repo, b)
388 raise
388 raise
389 except error.PushRaced as exc:
389 except error.PushRaced as exc:
390 raise error.ResponseError(
390 raise error.ResponseError(
391 _(b'push failed:'), stringutil.forcebytestr(exc)
391 _(b'push failed:'), stringutil.forcebytestr(exc)
392 )
392 )
393
393
394 # End of _basewirecommands interface.
394 # End of _basewirecommands interface.
395
395
396 # Begin of peer interface.
396 # Begin of peer interface.
397
397
398 def commandexecutor(self):
398 def commandexecutor(self):
399 return localcommandexecutor(self)
399 return localcommandexecutor(self)
400
400
401 # End of peer interface.
401 # End of peer interface.
402
402
403
403
404 @interfaceutil.implementer(repository.ipeerlegacycommands)
404 @interfaceutil.implementer(repository.ipeerlegacycommands)
405 class locallegacypeer(localpeer):
405 class locallegacypeer(localpeer):
406 """peer extension which implements legacy methods too; used for tests with
406 """peer extension which implements legacy methods too; used for tests with
407 restricted capabilities"""
407 restricted capabilities"""
408
408
409 def __init__(self, repo):
409 def __init__(self, repo):
410 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
410 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
411
411
412 # Begin of baselegacywirecommands interface.
412 # Begin of baselegacywirecommands interface.
413
413
414 def between(self, pairs):
414 def between(self, pairs):
415 return self._repo.between(pairs)
415 return self._repo.between(pairs)
416
416
417 def branches(self, nodes):
417 def branches(self, nodes):
418 return self._repo.branches(nodes)
418 return self._repo.branches(nodes)
419
419
420 def changegroup(self, nodes, source):
420 def changegroup(self, nodes, source):
421 outgoing = discovery.outgoing(
421 outgoing = discovery.outgoing(
422 self._repo, missingroots=nodes, ancestorsof=self._repo.heads()
422 self._repo, missingroots=nodes, ancestorsof=self._repo.heads()
423 )
423 )
424 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
424 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
425
425
426 def changegroupsubset(self, bases, heads, source):
426 def changegroupsubset(self, bases, heads, source):
427 outgoing = discovery.outgoing(
427 outgoing = discovery.outgoing(
428 self._repo, missingroots=bases, ancestorsof=heads
428 self._repo, missingroots=bases, ancestorsof=heads
429 )
429 )
430 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
430 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
431
431
432 # End of baselegacywirecommands interface.
432 # End of baselegacywirecommands interface.
433
433
434
434
435 # Functions receiving (ui, features) that extensions can register to impact
435 # Functions receiving (ui, features) that extensions can register to impact
436 # the ability to load repositories with custom requirements. Only
436 # the ability to load repositories with custom requirements. Only
437 # functions defined in loaded extensions are called.
437 # functions defined in loaded extensions are called.
438 #
438 #
439 # The function receives a set of requirement strings that the repository
439 # The function receives a set of requirement strings that the repository
440 # is capable of opening. Functions will typically add elements to the
440 # is capable of opening. Functions will typically add elements to the
441 # set to reflect that the extension knows how to handle that requirements.
441 # set to reflect that the extension knows how to handle that requirements.
442 featuresetupfuncs = set()
442 featuresetupfuncs = set()
443
443
444
444
445 def _getsharedvfs(hgvfs, requirements):
445 def _getsharedvfs(hgvfs, requirements):
446 """returns the vfs object pointing to root of shared source
446 """returns the vfs object pointing to root of shared source
447 repo for a shared repository
447 repo for a shared repository
448
448
449 hgvfs is vfs pointing at .hg/ of current repo (shared one)
449 hgvfs is vfs pointing at .hg/ of current repo (shared one)
450 requirements is a set of requirements of current repo (shared one)
450 requirements is a set of requirements of current repo (shared one)
451 """
451 """
452 # The ``shared`` or ``relshared`` requirements indicate the
452 # The ``shared`` or ``relshared`` requirements indicate the
453 # store lives in the path contained in the ``.hg/sharedpath`` file.
453 # store lives in the path contained in the ``.hg/sharedpath`` file.
454 # This is an absolute path for ``shared`` and relative to
454 # This is an absolute path for ``shared`` and relative to
455 # ``.hg/`` for ``relshared``.
455 # ``.hg/`` for ``relshared``.
456 sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
456 sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
457 if requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements:
457 if requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements:
458 sharedpath = hgvfs.join(sharedpath)
458 sharedpath = hgvfs.join(sharedpath)
459
459
460 sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
460 sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
461
461
462 if not sharedvfs.exists():
462 if not sharedvfs.exists():
463 raise error.RepoError(
463 raise error.RepoError(
464 _(b'.hg/sharedpath points to nonexistent directory %s')
464 _(b'.hg/sharedpath points to nonexistent directory %s')
465 % sharedvfs.base
465 % sharedvfs.base
466 )
466 )
467 return sharedvfs
467 return sharedvfs
468
468
469
469
470 def _readrequires(vfs, allowmissing):
470 def _readrequires(vfs, allowmissing):
471 """reads the require file present at root of this vfs
471 """reads the require file present at root of this vfs
472 and return a set of requirements
472 and return a set of requirements
473
473
474 If allowmissing is True, we suppress ENOENT if raised"""
474 If allowmissing is True, we suppress ENOENT if raised"""
475 # requires file contains a newline-delimited list of
475 # requires file contains a newline-delimited list of
476 # features/capabilities the opener (us) must have in order to use
476 # features/capabilities the opener (us) must have in order to use
477 # the repository. This file was introduced in Mercurial 0.9.2,
477 # the repository. This file was introduced in Mercurial 0.9.2,
478 # which means very old repositories may not have one. We assume
478 # which means very old repositories may not have one. We assume
479 # a missing file translates to no requirements.
479 # a missing file translates to no requirements.
480 try:
480 try:
481 requirements = set(vfs.read(b'requires').splitlines())
481 requirements = set(vfs.read(b'requires').splitlines())
482 except IOError as e:
482 except IOError as e:
483 if not (allowmissing and e.errno == errno.ENOENT):
483 if not (allowmissing and e.errno == errno.ENOENT):
484 raise
484 raise
485 requirements = set()
485 requirements = set()
486 return requirements
486 return requirements
487
487
488
488
489 def makelocalrepository(baseui, path, intents=None):
489 def makelocalrepository(baseui, path, intents=None):
490 """Create a local repository object.
490 """Create a local repository object.
491
491
492 Given arguments needed to construct a local repository, this function
492 Given arguments needed to construct a local repository, this function
493 performs various early repository loading functionality (such as
493 performs various early repository loading functionality (such as
494 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
494 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
495 the repository can be opened, derives a type suitable for representing
495 the repository can be opened, derives a type suitable for representing
496 that repository, and returns an instance of it.
496 that repository, and returns an instance of it.
497
497
498 The returned object conforms to the ``repository.completelocalrepository``
498 The returned object conforms to the ``repository.completelocalrepository``
499 interface.
499 interface.
500
500
501 The repository type is derived by calling a series of factory functions
501 The repository type is derived by calling a series of factory functions
502 for each aspect/interface of the final repository. These are defined by
502 for each aspect/interface of the final repository. These are defined by
503 ``REPO_INTERFACES``.
503 ``REPO_INTERFACES``.
504
504
505 Each factory function is called to produce a type implementing a specific
505 Each factory function is called to produce a type implementing a specific
506 interface. The cumulative list of returned types will be combined into a
506 interface. The cumulative list of returned types will be combined into a
507 new type and that type will be instantiated to represent the local
507 new type and that type will be instantiated to represent the local
508 repository.
508 repository.
509
509
510 The factory functions each receive various state that may be consulted
510 The factory functions each receive various state that may be consulted
511 as part of deriving a type.
511 as part of deriving a type.
512
512
513 Extensions should wrap these factory functions to customize repository type
513 Extensions should wrap these factory functions to customize repository type
514 creation. Note that an extension's wrapped function may be called even if
514 creation. Note that an extension's wrapped function may be called even if
515 that extension is not loaded for the repo being constructed. Extensions
515 that extension is not loaded for the repo being constructed. Extensions
516 should check if their ``__name__`` appears in the
516 should check if their ``__name__`` appears in the
517 ``extensionmodulenames`` set passed to the factory function and no-op if
517 ``extensionmodulenames`` set passed to the factory function and no-op if
518 not.
518 not.
519 """
519 """
520 ui = baseui.copy()
520 ui = baseui.copy()
521 # Prevent copying repo configuration.
521 # Prevent copying repo configuration.
522 ui.copy = baseui.copy
522 ui.copy = baseui.copy
523
523
524 # Working directory VFS rooted at repository root.
524 # Working directory VFS rooted at repository root.
525 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
525 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
526
526
527 # Main VFS for .hg/ directory.
527 # Main VFS for .hg/ directory.
528 hgpath = wdirvfs.join(b'.hg')
528 hgpath = wdirvfs.join(b'.hg')
529 hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
529 hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
530 # Whether this repository is shared one or not
530 # Whether this repository is shared one or not
531 shared = False
531 shared = False
532 # If this repository is shared, vfs pointing to shared repo
532 # If this repository is shared, vfs pointing to shared repo
533 sharedvfs = None
533 sharedvfs = None
534
534
535 # The .hg/ path should exist and should be a directory. All other
535 # The .hg/ path should exist and should be a directory. All other
536 # cases are errors.
536 # cases are errors.
537 if not hgvfs.isdir():
537 if not hgvfs.isdir():
538 try:
538 try:
539 hgvfs.stat()
539 hgvfs.stat()
540 except OSError as e:
540 except OSError as e:
541 if e.errno != errno.ENOENT:
541 if e.errno != errno.ENOENT:
542 raise
542 raise
543 except ValueError as e:
543 except ValueError as e:
544 # Can be raised on Python 3.8 when path is invalid.
544 # Can be raised on Python 3.8 when path is invalid.
545 raise error.Abort(
545 raise error.Abort(
546 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
546 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
547 )
547 )
548
548
549 raise error.RepoError(_(b'repository %s not found') % path)
549 raise error.RepoError(_(b'repository %s not found') % path)
550
550
551 requirements = _readrequires(hgvfs, True)
551 requirements = _readrequires(hgvfs, True)
552 shared = (
552 shared = (
553 requirementsmod.SHARED_REQUIREMENT in requirements
553 requirementsmod.SHARED_REQUIREMENT in requirements
554 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
554 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
555 )
555 )
556 storevfs = None
556 storevfs = None
557 if shared:
557 if shared:
558 # This is a shared repo
558 # This is a shared repo
559 sharedvfs = _getsharedvfs(hgvfs, requirements)
559 sharedvfs = _getsharedvfs(hgvfs, requirements)
560 storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
560 storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
561 else:
561 else:
562 storevfs = vfsmod.vfs(hgvfs.join(b'store'))
562 storevfs = vfsmod.vfs(hgvfs.join(b'store'))
563
563
564 # if .hg/requires contains the sharesafe requirement, it means
564 # if .hg/requires contains the sharesafe requirement, it means
565 # there exists a `.hg/store/requires` too and we should read it
565 # there exists a `.hg/store/requires` too and we should read it
566 # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
566 # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
567 # is present. We never write SHARESAFE_REQUIREMENT for a repo if store
567 # is present. We never write SHARESAFE_REQUIREMENT for a repo if store
568 # is not present, refer checkrequirementscompat() for that
568 # is not present, refer checkrequirementscompat() for that
569 #
569 #
570 # However, if SHARESAFE_REQUIREMENT is not present, it means that the
570 # However, if SHARESAFE_REQUIREMENT is not present, it means that the
571 # repository was shared the old way. We check the share source .hg/requires
571 # repository was shared the old way. We check the share source .hg/requires
572 # for SHARESAFE_REQUIREMENT to detect whether the current repository needs
572 # for SHARESAFE_REQUIREMENT to detect whether the current repository needs
573 # to be reshared
573 # to be reshared
574 hint = _(b"see `hg help config.format.use-share-safe` for more information")
574 hint = _(b"see `hg help config.format.use-share-safe` for more information")
575 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
575 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
576
576
577 if (
577 if (
578 shared
578 shared
579 and requirementsmod.SHARESAFE_REQUIREMENT
579 and requirementsmod.SHARESAFE_REQUIREMENT
580 not in _readrequires(sharedvfs, True)
580 not in _readrequires(sharedvfs, True)
581 ):
581 ):
582 mismatch_warn = ui.configbool(
582 mismatch_warn = ui.configbool(
583 b'share', b'safe-mismatch.source-not-safe.warn'
583 b'share', b'safe-mismatch.source-not-safe.warn'
584 )
584 )
585 mismatch_config = ui.config(
585 mismatch_config = ui.config(
586 b'share', b'safe-mismatch.source-not-safe'
586 b'share', b'safe-mismatch.source-not-safe'
587 )
587 )
588 if mismatch_config in (
588 if mismatch_config in (
589 b'downgrade-allow',
589 b'downgrade-allow',
590 b'allow',
590 b'allow',
591 b'downgrade-abort',
591 b'downgrade-abort',
592 ):
592 ):
593 # prevent cyclic import localrepo -> upgrade -> localrepo
593 # prevent cyclic import localrepo -> upgrade -> localrepo
594 from . import upgrade
594 from . import upgrade
595
595
596 upgrade.downgrade_share_to_non_safe(
596 upgrade.downgrade_share_to_non_safe(
597 ui,
597 ui,
598 hgvfs,
598 hgvfs,
599 sharedvfs,
599 sharedvfs,
600 requirements,
600 requirements,
601 mismatch_config,
601 mismatch_config,
602 mismatch_warn,
602 mismatch_warn,
603 )
603 )
604 elif mismatch_config == b'abort':
604 elif mismatch_config == b'abort':
605 raise error.Abort(
605 raise error.Abort(
606 _(b"share source does not support share-safe requirement"),
606 _(b"share source does not support share-safe requirement"),
607 hint=hint,
607 hint=hint,
608 )
608 )
609 else:
609 else:
610 raise error.Abort(
610 raise error.Abort(
611 _(
611 _(
612 b"share-safe mismatch with source.\nUnrecognized"
612 b"share-safe mismatch with source.\nUnrecognized"
613 b" value '%s' of `share.safe-mismatch.source-not-safe`"
613 b" value '%s' of `share.safe-mismatch.source-not-safe`"
614 b" set."
614 b" set."
615 )
615 )
616 % mismatch_config,
616 % mismatch_config,
617 hint=hint,
617 hint=hint,
618 )
618 )
619 else:
619 else:
620 requirements |= _readrequires(storevfs, False)
620 requirements |= _readrequires(storevfs, False)
621 elif shared:
621 elif shared:
622 sourcerequires = _readrequires(sharedvfs, False)
622 sourcerequires = _readrequires(sharedvfs, False)
623 if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires:
623 if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires:
624 mismatch_config = ui.config(b'share', b'safe-mismatch.source-safe')
624 mismatch_config = ui.config(b'share', b'safe-mismatch.source-safe')
625 mismatch_warn = ui.configbool(
625 mismatch_warn = ui.configbool(
626 b'share', b'safe-mismatch.source-safe.warn'
626 b'share', b'safe-mismatch.source-safe.warn'
627 )
627 )
628 if mismatch_config in (
628 if mismatch_config in (
629 b'upgrade-allow',
629 b'upgrade-allow',
630 b'allow',
630 b'allow',
631 b'upgrade-abort',
631 b'upgrade-abort',
632 ):
632 ):
633 # prevent cyclic import localrepo -> upgrade -> localrepo
633 # prevent cyclic import localrepo -> upgrade -> localrepo
634 from . import upgrade
634 from . import upgrade
635
635
636 upgrade.upgrade_share_to_safe(
636 upgrade.upgrade_share_to_safe(
637 ui,
637 ui,
638 hgvfs,
638 hgvfs,
639 storevfs,
639 storevfs,
640 requirements,
640 requirements,
641 mismatch_config,
641 mismatch_config,
642 mismatch_warn,
642 mismatch_warn,
643 )
643 )
644 elif mismatch_config == b'abort':
644 elif mismatch_config == b'abort':
645 raise error.Abort(
645 raise error.Abort(
646 _(
646 _(
647 b'version mismatch: source uses share-safe'
647 b'version mismatch: source uses share-safe'
648 b' functionality while the current share does not'
648 b' functionality while the current share does not'
649 ),
649 ),
650 hint=hint,
650 hint=hint,
651 )
651 )
652 else:
652 else:
653 raise error.Abort(
653 raise error.Abort(
654 _(
654 _(
655 b"share-safe mismatch with source.\nUnrecognized"
655 b"share-safe mismatch with source.\nUnrecognized"
656 b" value '%s' of `share.safe-mismatch.source-safe` set."
656 b" value '%s' of `share.safe-mismatch.source-safe` set."
657 )
657 )
658 % mismatch_config,
658 % mismatch_config,
659 hint=hint,
659 hint=hint,
660 )
660 )
661
661
662 # The .hg/hgrc file may load extensions or contain config options
662 # The .hg/hgrc file may load extensions or contain config options
663 # that influence repository construction. Attempt to load it and
663 # that influence repository construction. Attempt to load it and
664 # process any new extensions that it may have pulled in.
664 # process any new extensions that it may have pulled in.
665 if loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs):
665 if loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs):
666 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
666 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
667 extensions.loadall(ui)
667 extensions.loadall(ui)
668 extensions.populateui(ui)
668 extensions.populateui(ui)
669
669
670 # Set of module names of extensions loaded for this repository.
670 # Set of module names of extensions loaded for this repository.
671 extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
671 extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
672
672
673 supportedrequirements = gathersupportedrequirements(ui)
673 supportedrequirements = gathersupportedrequirements(ui)
674
674
675 # We first validate the requirements are known.
675 # We first validate the requirements are known.
676 ensurerequirementsrecognized(requirements, supportedrequirements)
676 ensurerequirementsrecognized(requirements, supportedrequirements)
677
677
678 # Then we validate that the known set is reasonable to use together.
678 # Then we validate that the known set is reasonable to use together.
679 ensurerequirementscompatible(ui, requirements)
679 ensurerequirementscompatible(ui, requirements)
680
680
681 # TODO there are unhandled edge cases related to opening repositories with
681 # TODO there are unhandled edge cases related to opening repositories with
682 # shared storage. If storage is shared, we should also test for requirements
682 # shared storage. If storage is shared, we should also test for requirements
683 # compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
683 # compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
684 # that repo, as that repo may load extensions needed to open it. This is a
684 # that repo, as that repo may load extensions needed to open it. This is a
685 # bit complicated because we don't want the other hgrc to overwrite settings
685 # bit complicated because we don't want the other hgrc to overwrite settings
686 # in this hgrc.
686 # in this hgrc.
687 #
687 #
688 # This bug is somewhat mitigated by the fact that we copy the .hg/requires
688 # This bug is somewhat mitigated by the fact that we copy the .hg/requires
689 # file when sharing repos. But if a requirement is added after the share is
689 # file when sharing repos. But if a requirement is added after the share is
690 # performed, thereby introducing a new requirement for the opener, we may
690 # performed, thereby introducing a new requirement for the opener, we may
691 # will not see that and could encounter a run-time error interacting with
691 # will not see that and could encounter a run-time error interacting with
692 # that shared store since it has an unknown-to-us requirement.
692 # that shared store since it has an unknown-to-us requirement.
693
693
694 # At this point, we know we should be capable of opening the repository.
694 # At this point, we know we should be capable of opening the repository.
695 # Now get on with doing that.
695 # Now get on with doing that.
696
696
697 features = set()
697 features = set()
698
698
699 # The "store" part of the repository holds versioned data. How it is
699 # The "store" part of the repository holds versioned data. How it is
700 # accessed is determined by various requirements. If `shared` or
700 # accessed is determined by various requirements. If `shared` or
701 # `relshared` requirements are present, this indicates current repository
701 # `relshared` requirements are present, this indicates current repository
702 # is a share and store exists in path mentioned in `.hg/sharedpath`
702 # is a share and store exists in path mentioned in `.hg/sharedpath`
703 if shared:
703 if shared:
704 storebasepath = sharedvfs.base
704 storebasepath = sharedvfs.base
705 cachepath = sharedvfs.join(b'cache')
705 cachepath = sharedvfs.join(b'cache')
706 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
706 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
707 else:
707 else:
708 storebasepath = hgvfs.base
708 storebasepath = hgvfs.base
709 cachepath = hgvfs.join(b'cache')
709 cachepath = hgvfs.join(b'cache')
710 wcachepath = hgvfs.join(b'wcache')
710 wcachepath = hgvfs.join(b'wcache')
711
711
712 # The store has changed over time and the exact layout is dictated by
712 # The store has changed over time and the exact layout is dictated by
713 # requirements. The store interface abstracts differences across all
713 # requirements. The store interface abstracts differences across all
714 # of them.
714 # of them.
715 store = makestore(
715 store = makestore(
716 requirements,
716 requirements,
717 storebasepath,
717 storebasepath,
718 lambda base: vfsmod.vfs(base, cacheaudited=True),
718 lambda base: vfsmod.vfs(base, cacheaudited=True),
719 )
719 )
720 hgvfs.createmode = store.createmode
720 hgvfs.createmode = store.createmode
721
721
722 storevfs = store.vfs
722 storevfs = store.vfs
723 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
723 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
724
724
725 # The cache vfs is used to manage cache files.
725 # The cache vfs is used to manage cache files.
726 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
726 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
727 cachevfs.createmode = store.createmode
727 cachevfs.createmode = store.createmode
728 # The cache vfs is used to manage cache files related to the working copy
728 # The cache vfs is used to manage cache files related to the working copy
729 wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
729 wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
730 wcachevfs.createmode = store.createmode
730 wcachevfs.createmode = store.createmode
731
731
732 # Now resolve the type for the repository object. We do this by repeatedly
732 # Now resolve the type for the repository object. We do this by repeatedly
733 # calling a factory function to produces types for specific aspects of the
733 # calling a factory function to produces types for specific aspects of the
734 # repo's operation. The aggregate returned types are used as base classes
734 # repo's operation. The aggregate returned types are used as base classes
735 # for a dynamically-derived type, which will represent our new repository.
735 # for a dynamically-derived type, which will represent our new repository.
736
736
737 bases = []
737 bases = []
738 extrastate = {}
738 extrastate = {}
739
739
740 for iface, fn in REPO_INTERFACES:
740 for iface, fn in REPO_INTERFACES:
741 # We pass all potentially useful state to give extensions tons of
741 # We pass all potentially useful state to give extensions tons of
742 # flexibility.
742 # flexibility.
743 typ = fn()(
743 typ = fn()(
744 ui=ui,
744 ui=ui,
745 intents=intents,
745 intents=intents,
746 requirements=requirements,
746 requirements=requirements,
747 features=features,
747 features=features,
748 wdirvfs=wdirvfs,
748 wdirvfs=wdirvfs,
749 hgvfs=hgvfs,
749 hgvfs=hgvfs,
750 store=store,
750 store=store,
751 storevfs=storevfs,
751 storevfs=storevfs,
752 storeoptions=storevfs.options,
752 storeoptions=storevfs.options,
753 cachevfs=cachevfs,
753 cachevfs=cachevfs,
754 wcachevfs=wcachevfs,
754 wcachevfs=wcachevfs,
755 extensionmodulenames=extensionmodulenames,
755 extensionmodulenames=extensionmodulenames,
756 extrastate=extrastate,
756 extrastate=extrastate,
757 baseclasses=bases,
757 baseclasses=bases,
758 )
758 )
759
759
760 if not isinstance(typ, type):
760 if not isinstance(typ, type):
761 raise error.ProgrammingError(
761 raise error.ProgrammingError(
762 b'unable to construct type for %s' % iface
762 b'unable to construct type for %s' % iface
763 )
763 )
764
764
765 bases.append(typ)
765 bases.append(typ)
766
766
767 # type() allows you to use characters in type names that wouldn't be
767 # type() allows you to use characters in type names that wouldn't be
768 # recognized as Python symbols in source code. We abuse that to add
768 # recognized as Python symbols in source code. We abuse that to add
769 # rich information about our constructed repo.
769 # rich information about our constructed repo.
770 name = pycompat.sysstr(
770 name = pycompat.sysstr(
771 b'derivedrepo:%s<%s>' % (wdirvfs.base, b','.join(sorted(requirements)))
771 b'derivedrepo:%s<%s>' % (wdirvfs.base, b','.join(sorted(requirements)))
772 )
772 )
773
773
774 cls = type(name, tuple(bases), {})
774 cls = type(name, tuple(bases), {})
775
775
776 return cls(
776 return cls(
777 baseui=baseui,
777 baseui=baseui,
778 ui=ui,
778 ui=ui,
779 origroot=path,
779 origroot=path,
780 wdirvfs=wdirvfs,
780 wdirvfs=wdirvfs,
781 hgvfs=hgvfs,
781 hgvfs=hgvfs,
782 requirements=requirements,
782 requirements=requirements,
783 supportedrequirements=supportedrequirements,
783 supportedrequirements=supportedrequirements,
784 sharedpath=storebasepath,
784 sharedpath=storebasepath,
785 store=store,
785 store=store,
786 cachevfs=cachevfs,
786 cachevfs=cachevfs,
787 wcachevfs=wcachevfs,
787 wcachevfs=wcachevfs,
788 features=features,
788 features=features,
789 intents=intents,
789 intents=intents,
790 )
790 )
791
791
792
792
793 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None):
793 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None):
794 """Load hgrc files/content into a ui instance.
794 """Load hgrc files/content into a ui instance.
795
795
796 This is called during repository opening to load any additional
796 This is called during repository opening to load any additional
797 config files or settings relevant to the current repository.
797 config files or settings relevant to the current repository.
798
798
799 Returns a bool indicating whether any additional configs were loaded.
799 Returns a bool indicating whether any additional configs were loaded.
800
800
801 Extensions should monkeypatch this function to modify how per-repo
801 Extensions should monkeypatch this function to modify how per-repo
802 configs are loaded. For example, an extension may wish to pull in
802 configs are loaded. For example, an extension may wish to pull in
803 configs from alternate files or sources.
803 configs from alternate files or sources.
804
804
805 sharedvfs is vfs object pointing to source repo if the current one is a
805 sharedvfs is vfs object pointing to source repo if the current one is a
806 shared one
806 shared one
807 """
807 """
808 if not rcutil.use_repo_hgrc():
808 if not rcutil.use_repo_hgrc():
809 return False
809 return False
810
810
811 ret = False
811 ret = False
812 # first load config from shared source if we has to
812 # first load config from shared source if we has to
813 if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs:
813 if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs:
814 try:
814 try:
815 ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base)
815 ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base)
816 ret = True
816 ret = True
817 except IOError:
817 except IOError:
818 pass
818 pass
819
819
820 try:
820 try:
821 ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
821 ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
822 ret = True
822 ret = True
823 except IOError:
823 except IOError:
824 pass
824 pass
825
825
826 try:
826 try:
827 ui.readconfig(hgvfs.join(b'hgrc-not-shared'), root=wdirvfs.base)
827 ui.readconfig(hgvfs.join(b'hgrc-not-shared'), root=wdirvfs.base)
828 ret = True
828 ret = True
829 except IOError:
829 except IOError:
830 pass
830 pass
831
831
832 return ret
832 return ret
833
833
834
834
835 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
835 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
836 """Perform additional actions after .hg/hgrc is loaded.
836 """Perform additional actions after .hg/hgrc is loaded.
837
837
838 This function is called during repository loading immediately after
838 This function is called during repository loading immediately after
839 the .hg/hgrc file is loaded and before per-repo extensions are loaded.
839 the .hg/hgrc file is loaded and before per-repo extensions are loaded.
840
840
841 The function can be used to validate configs, automatically add
841 The function can be used to validate configs, automatically add
842 options (including extensions) based on requirements, etc.
842 options (including extensions) based on requirements, etc.
843 """
843 """
844
844
845 # Map of requirements to list of extensions to load automatically when
845 # Map of requirements to list of extensions to load automatically when
846 # requirement is present.
846 # requirement is present.
847 autoextensions = {
847 autoextensions = {
848 b'git': [b'git'],
848 b'git': [b'git'],
849 b'largefiles': [b'largefiles'],
849 b'largefiles': [b'largefiles'],
850 b'lfs': [b'lfs'],
850 b'lfs': [b'lfs'],
851 }
851 }
852
852
853 for requirement, names in sorted(autoextensions.items()):
853 for requirement, names in sorted(autoextensions.items()):
854 if requirement not in requirements:
854 if requirement not in requirements:
855 continue
855 continue
856
856
857 for name in names:
857 for name in names:
858 if not ui.hasconfig(b'extensions', name):
858 if not ui.hasconfig(b'extensions', name):
859 ui.setconfig(b'extensions', name, b'', source=b'autoload')
859 ui.setconfig(b'extensions', name, b'', source=b'autoload')
860
860
861
861
862 def gathersupportedrequirements(ui):
862 def gathersupportedrequirements(ui):
863 """Determine the complete set of recognized requirements."""
863 """Determine the complete set of recognized requirements."""
864 # Start with all requirements supported by this file.
864 # Start with all requirements supported by this file.
865 supported = set(localrepository._basesupported)
865 supported = set(localrepository._basesupported)
866
866
867 # Execute ``featuresetupfuncs`` entries if they belong to an extension
867 # Execute ``featuresetupfuncs`` entries if they belong to an extension
868 # relevant to this ui instance.
868 # relevant to this ui instance.
869 modules = {m.__name__ for n, m in extensions.extensions(ui)}
869 modules = {m.__name__ for n, m in extensions.extensions(ui)}
870
870
871 for fn in featuresetupfuncs:
871 for fn in featuresetupfuncs:
872 if fn.__module__ in modules:
872 if fn.__module__ in modules:
873 fn(ui, supported)
873 fn(ui, supported)
874
874
875 # Add derived requirements from registered compression engines.
875 # Add derived requirements from registered compression engines.
876 for name in util.compengines:
876 for name in util.compengines:
877 engine = util.compengines[name]
877 engine = util.compengines[name]
878 if engine.available() and engine.revlogheader():
878 if engine.available() and engine.revlogheader():
879 supported.add(b'exp-compression-%s' % name)
879 supported.add(b'exp-compression-%s' % name)
880 if engine.name() == b'zstd':
880 if engine.name() == b'zstd':
881 supported.add(b'revlog-compression-zstd')
881 supported.add(b'revlog-compression-zstd')
882
882
883 return supported
883 return supported
884
884
885
885
886 def ensurerequirementsrecognized(requirements, supported):
886 def ensurerequirementsrecognized(requirements, supported):
887 """Validate that a set of local requirements is recognized.
887 """Validate that a set of local requirements is recognized.
888
888
889 Receives a set of requirements. Raises an ``error.RepoError`` if there
889 Receives a set of requirements. Raises an ``error.RepoError`` if there
890 exists any requirement in that set that currently loaded code doesn't
890 exists any requirement in that set that currently loaded code doesn't
891 recognize.
891 recognize.
892
892
893 Returns a set of supported requirements.
893 Returns a set of supported requirements.
894 """
894 """
895 missing = set()
895 missing = set()
896
896
897 for requirement in requirements:
897 for requirement in requirements:
898 if requirement in supported:
898 if requirement in supported:
899 continue
899 continue
900
900
901 if not requirement or not requirement[0:1].isalnum():
901 if not requirement or not requirement[0:1].isalnum():
902 raise error.RequirementError(_(b'.hg/requires file is corrupt'))
902 raise error.RequirementError(_(b'.hg/requires file is corrupt'))
903
903
904 missing.add(requirement)
904 missing.add(requirement)
905
905
906 if missing:
906 if missing:
907 raise error.RequirementError(
907 raise error.RequirementError(
908 _(b'repository requires features unknown to this Mercurial: %s')
908 _(b'repository requires features unknown to this Mercurial: %s')
909 % b' '.join(sorted(missing)),
909 % b' '.join(sorted(missing)),
910 hint=_(
910 hint=_(
911 b'see https://mercurial-scm.org/wiki/MissingRequirement '
911 b'see https://mercurial-scm.org/wiki/MissingRequirement '
912 b'for more information'
912 b'for more information'
913 ),
913 ),
914 )
914 )
915
915
916
916
917 def ensurerequirementscompatible(ui, requirements):
917 def ensurerequirementscompatible(ui, requirements):
918 """Validates that a set of recognized requirements is mutually compatible.
918 """Validates that a set of recognized requirements is mutually compatible.
919
919
920 Some requirements may not be compatible with others or require
920 Some requirements may not be compatible with others or require
921 config options that aren't enabled. This function is called during
921 config options that aren't enabled. This function is called during
922 repository opening to ensure that the set of requirements needed
922 repository opening to ensure that the set of requirements needed
923 to open a repository is sane and compatible with config options.
923 to open a repository is sane and compatible with config options.
924
924
925 Extensions can monkeypatch this function to perform additional
925 Extensions can monkeypatch this function to perform additional
926 checking.
926 checking.
927
927
928 ``error.RepoError`` should be raised on failure.
928 ``error.RepoError`` should be raised on failure.
929 """
929 """
930 if (
930 if (
931 requirementsmod.SPARSE_REQUIREMENT in requirements
931 requirementsmod.SPARSE_REQUIREMENT in requirements
932 and not sparse.enabled
932 and not sparse.enabled
933 ):
933 ):
934 raise error.RepoError(
934 raise error.RepoError(
935 _(
935 _(
936 b'repository is using sparse feature but '
936 b'repository is using sparse feature but '
937 b'sparse is not enabled; enable the '
937 b'sparse is not enabled; enable the '
938 b'"sparse" extensions to access'
938 b'"sparse" extensions to access'
939 )
939 )
940 )
940 )
941
941
942
942
943 def makestore(requirements, path, vfstype):
943 def makestore(requirements, path, vfstype):
944 """Construct a storage object for a repository."""
944 """Construct a storage object for a repository."""
945 if requirementsmod.STORE_REQUIREMENT in requirements:
945 if requirementsmod.STORE_REQUIREMENT in requirements:
946 if requirementsmod.FNCACHE_REQUIREMENT in requirements:
946 if requirementsmod.FNCACHE_REQUIREMENT in requirements:
947 dotencode = requirementsmod.DOTENCODE_REQUIREMENT in requirements
947 dotencode = requirementsmod.DOTENCODE_REQUIREMENT in requirements
948 return storemod.fncachestore(path, vfstype, dotencode)
948 return storemod.fncachestore(path, vfstype, dotencode)
949
949
950 return storemod.encodedstore(path, vfstype)
950 return storemod.encodedstore(path, vfstype)
951
951
952 return storemod.basicstore(path, vfstype)
952 return storemod.basicstore(path, vfstype)
953
953
954
954
955 def resolvestorevfsoptions(ui, requirements, features):
955 def resolvestorevfsoptions(ui, requirements, features):
956 """Resolve the options to pass to the store vfs opener.
956 """Resolve the options to pass to the store vfs opener.
957
957
958 The returned dict is used to influence behavior of the storage layer.
958 The returned dict is used to influence behavior of the storage layer.
959 """
959 """
960 options = {}
960 options = {}
961
961
962 if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
962 if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
963 options[b'treemanifest'] = True
963 options[b'treemanifest'] = True
964
964
965 # experimental config: format.manifestcachesize
965 # experimental config: format.manifestcachesize
966 manifestcachesize = ui.configint(b'format', b'manifestcachesize')
966 manifestcachesize = ui.configint(b'format', b'manifestcachesize')
967 if manifestcachesize is not None:
967 if manifestcachesize is not None:
968 options[b'manifestcachesize'] = manifestcachesize
968 options[b'manifestcachesize'] = manifestcachesize
969
969
970 # In the absence of another requirement superseding a revlog-related
970 # In the absence of another requirement superseding a revlog-related
971 # requirement, we have to assume the repo is using revlog version 0.
971 # requirement, we have to assume the repo is using revlog version 0.
972 # This revlog format is super old and we don't bother trying to parse
972 # This revlog format is super old and we don't bother trying to parse
973 # opener options for it because those options wouldn't do anything
973 # opener options for it because those options wouldn't do anything
974 # meaningful on such old repos.
974 # meaningful on such old repos.
975 if (
975 if (
976 requirementsmod.REVLOGV1_REQUIREMENT in requirements
976 requirementsmod.REVLOGV1_REQUIREMENT in requirements
977 or requirementsmod.REVLOGV2_REQUIREMENT in requirements
977 or requirementsmod.REVLOGV2_REQUIREMENT in requirements
978 ):
978 ):
979 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
979 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
980 else: # explicitly mark repo as using revlogv0
980 else: # explicitly mark repo as using revlogv0
981 options[b'revlogv0'] = True
981 options[b'revlogv0'] = True
982
982
983 if requirementsmod.COPIESSDC_REQUIREMENT in requirements:
983 if requirementsmod.COPIESSDC_REQUIREMENT in requirements:
984 options[b'copies-storage'] = b'changeset-sidedata'
984 options[b'copies-storage'] = b'changeset-sidedata'
985 else:
985 else:
986 writecopiesto = ui.config(b'experimental', b'copies.write-to')
986 writecopiesto = ui.config(b'experimental', b'copies.write-to')
987 copiesextramode = (b'changeset-only', b'compatibility')
987 copiesextramode = (b'changeset-only', b'compatibility')
988 if writecopiesto in copiesextramode:
988 if writecopiesto in copiesextramode:
989 options[b'copies-storage'] = b'extra'
989 options[b'copies-storage'] = b'extra'
990
990
991 return options
991 return options
992
992
993
993
994 def resolverevlogstorevfsoptions(ui, requirements, features):
994 def resolverevlogstorevfsoptions(ui, requirements, features):
995 """Resolve opener options specific to revlogs."""
995 """Resolve opener options specific to revlogs."""
996
996
997 options = {}
997 options = {}
998 options[b'flagprocessors'] = {}
998 options[b'flagprocessors'] = {}
999
999
1000 if requirementsmod.REVLOGV1_REQUIREMENT in requirements:
1000 if requirementsmod.REVLOGV1_REQUIREMENT in requirements:
1001 options[b'revlogv1'] = True
1001 options[b'revlogv1'] = True
1002 if requirementsmod.REVLOGV2_REQUIREMENT in requirements:
1002 if requirementsmod.REVLOGV2_REQUIREMENT in requirements:
1003 options[b'revlogv2'] = True
1003 options[b'revlogv2'] = True
1004
1004
1005 if requirementsmod.GENERALDELTA_REQUIREMENT in requirements:
1005 if requirementsmod.GENERALDELTA_REQUIREMENT in requirements:
1006 options[b'generaldelta'] = True
1006 options[b'generaldelta'] = True
1007
1007
1008 # experimental config: format.chunkcachesize
1008 # experimental config: format.chunkcachesize
1009 chunkcachesize = ui.configint(b'format', b'chunkcachesize')
1009 chunkcachesize = ui.configint(b'format', b'chunkcachesize')
1010 if chunkcachesize is not None:
1010 if chunkcachesize is not None:
1011 options[b'chunkcachesize'] = chunkcachesize
1011 options[b'chunkcachesize'] = chunkcachesize
1012
1012
1013 deltabothparents = ui.configbool(
1013 deltabothparents = ui.configbool(
1014 b'storage', b'revlog.optimize-delta-parent-choice'
1014 b'storage', b'revlog.optimize-delta-parent-choice'
1015 )
1015 )
1016 options[b'deltabothparents'] = deltabothparents
1016 options[b'deltabothparents'] = deltabothparents
1017
1017
1018 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
1018 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
1019 lazydeltabase = False
1019 lazydeltabase = False
1020 if lazydelta:
1020 if lazydelta:
1021 lazydeltabase = ui.configbool(
1021 lazydeltabase = ui.configbool(
1022 b'storage', b'revlog.reuse-external-delta-parent'
1022 b'storage', b'revlog.reuse-external-delta-parent'
1023 )
1023 )
1024 if lazydeltabase is None:
1024 if lazydeltabase is None:
1025 lazydeltabase = not scmutil.gddeltaconfig(ui)
1025 lazydeltabase = not scmutil.gddeltaconfig(ui)
1026 options[b'lazydelta'] = lazydelta
1026 options[b'lazydelta'] = lazydelta
1027 options[b'lazydeltabase'] = lazydeltabase
1027 options[b'lazydeltabase'] = lazydeltabase
1028
1028
1029 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
1029 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
1030 if 0 <= chainspan:
1030 if 0 <= chainspan:
1031 options[b'maxdeltachainspan'] = chainspan
1031 options[b'maxdeltachainspan'] = chainspan
1032
1032
1033 mmapindexthreshold = ui.configbytes(b'experimental', b'mmapindexthreshold')
1033 mmapindexthreshold = ui.configbytes(b'experimental', b'mmapindexthreshold')
1034 if mmapindexthreshold is not None:
1034 if mmapindexthreshold is not None:
1035 options[b'mmapindexthreshold'] = mmapindexthreshold
1035 options[b'mmapindexthreshold'] = mmapindexthreshold
1036
1036
1037 withsparseread = ui.configbool(b'experimental', b'sparse-read')
1037 withsparseread = ui.configbool(b'experimental', b'sparse-read')
1038 srdensitythres = float(
1038 srdensitythres = float(
1039 ui.config(b'experimental', b'sparse-read.density-threshold')
1039 ui.config(b'experimental', b'sparse-read.density-threshold')
1040 )
1040 )
1041 srmingapsize = ui.configbytes(b'experimental', b'sparse-read.min-gap-size')
1041 srmingapsize = ui.configbytes(b'experimental', b'sparse-read.min-gap-size')
1042 options[b'with-sparse-read'] = withsparseread
1042 options[b'with-sparse-read'] = withsparseread
1043 options[b'sparse-read-density-threshold'] = srdensitythres
1043 options[b'sparse-read-density-threshold'] = srdensitythres
1044 options[b'sparse-read-min-gap-size'] = srmingapsize
1044 options[b'sparse-read-min-gap-size'] = srmingapsize
1045
1045
1046 sparserevlog = requirementsmod.SPARSEREVLOG_REQUIREMENT in requirements
1046 sparserevlog = requirementsmod.SPARSEREVLOG_REQUIREMENT in requirements
1047 options[b'sparse-revlog'] = sparserevlog
1047 options[b'sparse-revlog'] = sparserevlog
1048 if sparserevlog:
1048 if sparserevlog:
1049 options[b'generaldelta'] = True
1049 options[b'generaldelta'] = True
1050
1050
1051 sidedata = requirementsmod.SIDEDATA_REQUIREMENT in requirements
1051 sidedata = requirementsmod.SIDEDATA_REQUIREMENT in requirements
1052 options[b'side-data'] = sidedata
1052 options[b'side-data'] = sidedata
1053
1053
1054 maxchainlen = None
1054 maxchainlen = None
1055 if sparserevlog:
1055 if sparserevlog:
1056 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
1056 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
1057 # experimental config: format.maxchainlen
1057 # experimental config: format.maxchainlen
1058 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
1058 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
1059 if maxchainlen is not None:
1059 if maxchainlen is not None:
1060 options[b'maxchainlen'] = maxchainlen
1060 options[b'maxchainlen'] = maxchainlen
1061
1061
1062 for r in requirements:
1062 for r in requirements:
1063 # we allow multiple compression engine requirement to co-exist because
1063 # we allow multiple compression engine requirement to co-exist because
1064 # strickly speaking, revlog seems to support mixed compression style.
1064 # strickly speaking, revlog seems to support mixed compression style.
1065 #
1065 #
1066 # The compression used for new entries will be "the last one"
1066 # The compression used for new entries will be "the last one"
1067 prefix = r.startswith
1067 prefix = r.startswith
1068 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
1068 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
1069 options[b'compengine'] = r.split(b'-', 2)[2]
1069 options[b'compengine'] = r.split(b'-', 2)[2]
1070
1070
1071 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
1071 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
1072 if options[b'zlib.level'] is not None:
1072 if options[b'zlib.level'] is not None:
1073 if not (0 <= options[b'zlib.level'] <= 9):
1073 if not (0 <= options[b'zlib.level'] <= 9):
1074 msg = _(b'invalid value for `storage.revlog.zlib.level` config: %d')
1074 msg = _(b'invalid value for `storage.revlog.zlib.level` config: %d')
1075 raise error.Abort(msg % options[b'zlib.level'])
1075 raise error.Abort(msg % options[b'zlib.level'])
1076 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
1076 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
1077 if options[b'zstd.level'] is not None:
1077 if options[b'zstd.level'] is not None:
1078 if not (0 <= options[b'zstd.level'] <= 22):
1078 if not (0 <= options[b'zstd.level'] <= 22):
1079 msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
1079 msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
1080 raise error.Abort(msg % options[b'zstd.level'])
1080 raise error.Abort(msg % options[b'zstd.level'])
1081
1081
1082 if requirementsmod.NARROW_REQUIREMENT in requirements:
1082 if requirementsmod.NARROW_REQUIREMENT in requirements:
1083 options[b'enableellipsis'] = True
1083 options[b'enableellipsis'] = True
1084
1084
1085 if ui.configbool(b'experimental', b'rust.index'):
1085 if ui.configbool(b'experimental', b'rust.index'):
1086 options[b'rust.index'] = True
1086 options[b'rust.index'] = True
1087 if requirementsmod.NODEMAP_REQUIREMENT in requirements:
1087 if requirementsmod.NODEMAP_REQUIREMENT in requirements:
1088 slow_path = ui.config(
1088 slow_path = ui.config(
1089 b'storage', b'revlog.persistent-nodemap.slow-path'
1089 b'storage', b'revlog.persistent-nodemap.slow-path'
1090 )
1090 )
1091 if slow_path not in (b'allow', b'warn', b'abort'):
1091 if slow_path not in (b'allow', b'warn', b'abort'):
1092 default = ui.config_default(
1092 default = ui.config_default(
1093 b'storage', b'revlog.persistent-nodemap.slow-path'
1093 b'storage', b'revlog.persistent-nodemap.slow-path'
1094 )
1094 )
1095 msg = _(
1095 msg = _(
1096 b'unknown value for config '
1096 b'unknown value for config '
1097 b'"storage.revlog.persistent-nodemap.slow-path": "%s"\n'
1097 b'"storage.revlog.persistent-nodemap.slow-path": "%s"\n'
1098 )
1098 )
1099 ui.warn(msg % slow_path)
1099 ui.warn(msg % slow_path)
1100 if not ui.quiet:
1100 if not ui.quiet:
1101 ui.warn(_(b'falling back to default value: %s\n') % default)
1101 ui.warn(_(b'falling back to default value: %s\n') % default)
1102 slow_path = default
1102 slow_path = default
1103
1103
1104 msg = _(
1104 msg = _(
1105 b"accessing `persistent-nodemap` repository without associated "
1105 b"accessing `persistent-nodemap` repository without associated "
1106 b"fast implementation."
1106 b"fast implementation."
1107 )
1107 )
1108 hint = _(
1108 hint = _(
1109 b"check `hg help config.format.use-persistent-nodemap` "
1109 b"check `hg help config.format.use-persistent-nodemap` "
1110 b"for details"
1110 b"for details"
1111 )
1111 )
1112 if not revlog.HAS_FAST_PERSISTENT_NODEMAP:
1112 if not revlog.HAS_FAST_PERSISTENT_NODEMAP:
1113 if slow_path == b'warn':
1113 if slow_path == b'warn':
1114 msg = b"warning: " + msg + b'\n'
1114 msg = b"warning: " + msg + b'\n'
1115 ui.warn(msg)
1115 ui.warn(msg)
1116 if not ui.quiet:
1116 if not ui.quiet:
1117 hint = b'(' + hint + b')\n'
1117 hint = b'(' + hint + b')\n'
1118 ui.warn(hint)
1118 ui.warn(hint)
1119 if slow_path == b'abort':
1119 if slow_path == b'abort':
1120 raise error.Abort(msg, hint=hint)
1120 raise error.Abort(msg, hint=hint)
1121 options[b'persistent-nodemap'] = True
1121 options[b'persistent-nodemap'] = True
1122 if ui.configbool(b'storage', b'revlog.persistent-nodemap.mmap'):
1122 if ui.configbool(b'storage', b'revlog.persistent-nodemap.mmap'):
1123 options[b'persistent-nodemap.mmap'] = True
1123 options[b'persistent-nodemap.mmap'] = True
1124 if ui.configbool(b'devel', b'persistent-nodemap'):
1124 if ui.configbool(b'devel', b'persistent-nodemap'):
1125 options[b'devel-force-nodemap'] = True
1125 options[b'devel-force-nodemap'] = True
1126
1126
1127 return options
1127 return options
1128
1128
1129
1129
1130 def makemain(**kwargs):
1130 def makemain(**kwargs):
1131 """Produce a type conforming to ``ilocalrepositorymain``."""
1131 """Produce a type conforming to ``ilocalrepositorymain``."""
1132 return localrepository
1132 return localrepository
1133
1133
1134
1134
1135 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1135 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1136 class revlogfilestorage(object):
1136 class revlogfilestorage(object):
1137 """File storage when using revlogs."""
1137 """File storage when using revlogs."""
1138
1138
1139 def file(self, path):
1139 def file(self, path):
1140 if path.startswith(b'/'):
1140 if path.startswith(b'/'):
1141 path = path[1:]
1141 path = path[1:]
1142
1142
1143 return filelog.filelog(self.svfs, path)
1143 return filelog.filelog(self.svfs, path)
1144
1144
1145
1145
1146 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1146 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1147 class revlognarrowfilestorage(object):
1147 class revlognarrowfilestorage(object):
1148 """File storage when using revlogs and narrow files."""
1148 """File storage when using revlogs and narrow files."""
1149
1149
1150 def file(self, path):
1150 def file(self, path):
1151 if path.startswith(b'/'):
1151 if path.startswith(b'/'):
1152 path = path[1:]
1152 path = path[1:]
1153
1153
1154 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
1154 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
1155
1155
1156
1156
1157 def makefilestorage(requirements, features, **kwargs):
1157 def makefilestorage(requirements, features, **kwargs):
1158 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
1158 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
1159 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
1159 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
1160 features.add(repository.REPO_FEATURE_STREAM_CLONE)
1160 features.add(repository.REPO_FEATURE_STREAM_CLONE)
1161
1161
1162 if requirementsmod.NARROW_REQUIREMENT in requirements:
1162 if requirementsmod.NARROW_REQUIREMENT in requirements:
1163 return revlognarrowfilestorage
1163 return revlognarrowfilestorage
1164 else:
1164 else:
1165 return revlogfilestorage
1165 return revlogfilestorage
1166
1166
1167
1167
1168 # List of repository interfaces and factory functions for them. Each
1168 # List of repository interfaces and factory functions for them. Each
1169 # will be called in order during ``makelocalrepository()`` to iteratively
1169 # will be called in order during ``makelocalrepository()`` to iteratively
1170 # derive the final type for a local repository instance. We capture the
1170 # derive the final type for a local repository instance. We capture the
1171 # function as a lambda so we don't hold a reference and the module-level
1171 # function as a lambda so we don't hold a reference and the module-level
1172 # functions can be wrapped.
1172 # functions can be wrapped.
1173 REPO_INTERFACES = [
1173 REPO_INTERFACES = [
1174 (repository.ilocalrepositorymain, lambda: makemain),
1174 (repository.ilocalrepositorymain, lambda: makemain),
1175 (repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
1175 (repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
1176 ]
1176 ]
1177
1177
1178
1178
1179 @interfaceutil.implementer(repository.ilocalrepositorymain)
1179 @interfaceutil.implementer(repository.ilocalrepositorymain)
1180 class localrepository(object):
1180 class localrepository(object):
1181 """Main class for representing local repositories.
1181 """Main class for representing local repositories.
1182
1182
1183 All local repositories are instances of this class.
1183 All local repositories are instances of this class.
1184
1184
1185 Constructed on its own, instances of this class are not usable as
1185 Constructed on its own, instances of this class are not usable as
1186 repository objects. To obtain a usable repository object, call
1186 repository objects. To obtain a usable repository object, call
1187 ``hg.repository()``, ``localrepo.instance()``, or
1187 ``hg.repository()``, ``localrepo.instance()``, or
1188 ``localrepo.makelocalrepository()``. The latter is the lowest-level.
1188 ``localrepo.makelocalrepository()``. The latter is the lowest-level.
1189 ``instance()`` adds support for creating new repositories.
1189 ``instance()`` adds support for creating new repositories.
1190 ``hg.repository()`` adds more extension integration, including calling
1190 ``hg.repository()`` adds more extension integration, including calling
1191 ``reposetup()``. Generally speaking, ``hg.repository()`` should be
1191 ``reposetup()``. Generally speaking, ``hg.repository()`` should be
1192 used.
1192 used.
1193 """
1193 """
1194
1194
1195 # obsolete experimental requirements:
1195 # obsolete experimental requirements:
1196 # - manifestv2: An experimental new manifest format that allowed
1196 # - manifestv2: An experimental new manifest format that allowed
1197 # for stem compression of long paths. Experiment ended up not
1197 # for stem compression of long paths. Experiment ended up not
1198 # being successful (repository sizes went up due to worse delta
1198 # being successful (repository sizes went up due to worse delta
1199 # chains), and the code was deleted in 4.6.
1199 # chains), and the code was deleted in 4.6.
1200 supportedformats = {
1200 supportedformats = {
1201 requirementsmod.REVLOGV1_REQUIREMENT,
1201 requirementsmod.REVLOGV1_REQUIREMENT,
1202 requirementsmod.GENERALDELTA_REQUIREMENT,
1202 requirementsmod.GENERALDELTA_REQUIREMENT,
1203 requirementsmod.TREEMANIFEST_REQUIREMENT,
1203 requirementsmod.TREEMANIFEST_REQUIREMENT,
1204 requirementsmod.COPIESSDC_REQUIREMENT,
1204 requirementsmod.COPIESSDC_REQUIREMENT,
1205 requirementsmod.REVLOGV2_REQUIREMENT,
1205 requirementsmod.REVLOGV2_REQUIREMENT,
1206 requirementsmod.SIDEDATA_REQUIREMENT,
1206 requirementsmod.SIDEDATA_REQUIREMENT,
1207 requirementsmod.SPARSEREVLOG_REQUIREMENT,
1207 requirementsmod.SPARSEREVLOG_REQUIREMENT,
1208 requirementsmod.NODEMAP_REQUIREMENT,
1208 requirementsmod.NODEMAP_REQUIREMENT,
1209 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
1209 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
1210 requirementsmod.SHARESAFE_REQUIREMENT,
1210 requirementsmod.SHARESAFE_REQUIREMENT,
1211 }
1211 }
1212 _basesupported = supportedformats | {
1212 _basesupported = supportedformats | {
1213 requirementsmod.STORE_REQUIREMENT,
1213 requirementsmod.STORE_REQUIREMENT,
1214 requirementsmod.FNCACHE_REQUIREMENT,
1214 requirementsmod.FNCACHE_REQUIREMENT,
1215 requirementsmod.SHARED_REQUIREMENT,
1215 requirementsmod.SHARED_REQUIREMENT,
1216 requirementsmod.RELATIVE_SHARED_REQUIREMENT,
1216 requirementsmod.RELATIVE_SHARED_REQUIREMENT,
1217 requirementsmod.DOTENCODE_REQUIREMENT,
1217 requirementsmod.DOTENCODE_REQUIREMENT,
1218 requirementsmod.SPARSE_REQUIREMENT,
1218 requirementsmod.SPARSE_REQUIREMENT,
1219 requirementsmod.INTERNAL_PHASE_REQUIREMENT,
1219 requirementsmod.INTERNAL_PHASE_REQUIREMENT,
1220 }
1220 }
1221
1221
1222 # list of prefix for file which can be written without 'wlock'
1222 # list of prefix for file which can be written without 'wlock'
1223 # Extensions should extend this list when needed
1223 # Extensions should extend this list when needed
1224 _wlockfreeprefix = {
1224 _wlockfreeprefix = {
1225 # We migh consider requiring 'wlock' for the next
1225 # We migh consider requiring 'wlock' for the next
1226 # two, but pretty much all the existing code assume
1226 # two, but pretty much all the existing code assume
1227 # wlock is not needed so we keep them excluded for
1227 # wlock is not needed so we keep them excluded for
1228 # now.
1228 # now.
1229 b'hgrc',
1229 b'hgrc',
1230 b'requires',
1230 b'requires',
1231 # XXX cache is a complicatged business someone
1231 # XXX cache is a complicatged business someone
1232 # should investigate this in depth at some point
1232 # should investigate this in depth at some point
1233 b'cache/',
1233 b'cache/',
1234 # XXX shouldn't be dirstate covered by the wlock?
1234 # XXX shouldn't be dirstate covered by the wlock?
1235 b'dirstate',
1235 b'dirstate',
1236 # XXX bisect was still a bit too messy at the time
1236 # XXX bisect was still a bit too messy at the time
1237 # this changeset was introduced. Someone should fix
1237 # this changeset was introduced. Someone should fix
1238 # the remainig bit and drop this line
1238 # the remainig bit and drop this line
1239 b'bisect.state',
1239 b'bisect.state',
1240 }
1240 }
1241
1241
1242 def __init__(
1242 def __init__(
1243 self,
1243 self,
1244 baseui,
1244 baseui,
1245 ui,
1245 ui,
1246 origroot,
1246 origroot,
1247 wdirvfs,
1247 wdirvfs,
1248 hgvfs,
1248 hgvfs,
1249 requirements,
1249 requirements,
1250 supportedrequirements,
1250 supportedrequirements,
1251 sharedpath,
1251 sharedpath,
1252 store,
1252 store,
1253 cachevfs,
1253 cachevfs,
1254 wcachevfs,
1254 wcachevfs,
1255 features,
1255 features,
1256 intents=None,
1256 intents=None,
1257 ):
1257 ):
1258 """Create a new local repository instance.
1258 """Create a new local repository instance.
1259
1259
1260 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
1260 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
1261 or ``localrepo.makelocalrepository()`` for obtaining a new repository
1261 or ``localrepo.makelocalrepository()`` for obtaining a new repository
1262 object.
1262 object.
1263
1263
1264 Arguments:
1264 Arguments:
1265
1265
1266 baseui
1266 baseui
1267 ``ui.ui`` instance that ``ui`` argument was based off of.
1267 ``ui.ui`` instance that ``ui`` argument was based off of.
1268
1268
1269 ui
1269 ui
1270 ``ui.ui`` instance for use by the repository.
1270 ``ui.ui`` instance for use by the repository.
1271
1271
1272 origroot
1272 origroot
1273 ``bytes`` path to working directory root of this repository.
1273 ``bytes`` path to working directory root of this repository.
1274
1274
1275 wdirvfs
1275 wdirvfs
1276 ``vfs.vfs`` rooted at the working directory.
1276 ``vfs.vfs`` rooted at the working directory.
1277
1277
1278 hgvfs
1278 hgvfs
1279 ``vfs.vfs`` rooted at .hg/
1279 ``vfs.vfs`` rooted at .hg/
1280
1280
1281 requirements
1281 requirements
1282 ``set`` of bytestrings representing repository opening requirements.
1282 ``set`` of bytestrings representing repository opening requirements.
1283
1283
1284 supportedrequirements
1284 supportedrequirements
1285 ``set`` of bytestrings representing repository requirements that we
1285 ``set`` of bytestrings representing repository requirements that we
1286 know how to open. May be a supetset of ``requirements``.
1286 know how to open. May be a supetset of ``requirements``.
1287
1287
1288 sharedpath
1288 sharedpath
1289 ``bytes`` Defining path to storage base directory. Points to a
1289 ``bytes`` Defining path to storage base directory. Points to a
1290 ``.hg/`` directory somewhere.
1290 ``.hg/`` directory somewhere.
1291
1291
1292 store
1292 store
1293 ``store.basicstore`` (or derived) instance providing access to
1293 ``store.basicstore`` (or derived) instance providing access to
1294 versioned storage.
1294 versioned storage.
1295
1295
1296 cachevfs
1296 cachevfs
1297 ``vfs.vfs`` used for cache files.
1297 ``vfs.vfs`` used for cache files.
1298
1298
1299 wcachevfs
1299 wcachevfs
1300 ``vfs.vfs`` used for cache files related to the working copy.
1300 ``vfs.vfs`` used for cache files related to the working copy.
1301
1301
1302 features
1302 features
1303 ``set`` of bytestrings defining features/capabilities of this
1303 ``set`` of bytestrings defining features/capabilities of this
1304 instance.
1304 instance.
1305
1305
1306 intents
1306 intents
1307 ``set`` of system strings indicating what this repo will be used
1307 ``set`` of system strings indicating what this repo will be used
1308 for.
1308 for.
1309 """
1309 """
1310 self.baseui = baseui
1310 self.baseui = baseui
1311 self.ui = ui
1311 self.ui = ui
1312 self.origroot = origroot
1312 self.origroot = origroot
1313 # vfs rooted at working directory.
1313 # vfs rooted at working directory.
1314 self.wvfs = wdirvfs
1314 self.wvfs = wdirvfs
1315 self.root = wdirvfs.base
1315 self.root = wdirvfs.base
1316 # vfs rooted at .hg/. Used to access most non-store paths.
1316 # vfs rooted at .hg/. Used to access most non-store paths.
1317 self.vfs = hgvfs
1317 self.vfs = hgvfs
1318 self.path = hgvfs.base
1318 self.path = hgvfs.base
1319 self.requirements = requirements
1319 self.requirements = requirements
1320 self.supported = supportedrequirements
1320 self.supported = supportedrequirements
1321 self.sharedpath = sharedpath
1321 self.sharedpath = sharedpath
1322 self.store = store
1322 self.store = store
1323 self.cachevfs = cachevfs
1323 self.cachevfs = cachevfs
1324 self.wcachevfs = wcachevfs
1324 self.wcachevfs = wcachevfs
1325 self.features = features
1325 self.features = features
1326
1326
1327 self.filtername = None
1327 self.filtername = None
1328
1328
1329 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1329 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1330 b'devel', b'check-locks'
1330 b'devel', b'check-locks'
1331 ):
1331 ):
1332 self.vfs.audit = self._getvfsward(self.vfs.audit)
1332 self.vfs.audit = self._getvfsward(self.vfs.audit)
1333 # A list of callback to shape the phase if no data were found.
1333 # A list of callback to shape the phase if no data were found.
1334 # Callback are in the form: func(repo, roots) --> processed root.
1334 # Callback are in the form: func(repo, roots) --> processed root.
1335 # This list it to be filled by extension during repo setup
1335 # This list it to be filled by extension during repo setup
1336 self._phasedefaults = []
1336 self._phasedefaults = []
1337
1337
1338 color.setup(self.ui)
1338 color.setup(self.ui)
1339
1339
1340 self.spath = self.store.path
1340 self.spath = self.store.path
1341 self.svfs = self.store.vfs
1341 self.svfs = self.store.vfs
1342 self.sjoin = self.store.join
1342 self.sjoin = self.store.join
1343 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1343 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1344 b'devel', b'check-locks'
1344 b'devel', b'check-locks'
1345 ):
1345 ):
1346 if util.safehasattr(self.svfs, b'vfs'): # this is filtervfs
1346 if util.safehasattr(self.svfs, b'vfs'): # this is filtervfs
1347 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
1347 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
1348 else: # standard vfs
1348 else: # standard vfs
1349 self.svfs.audit = self._getsvfsward(self.svfs.audit)
1349 self.svfs.audit = self._getsvfsward(self.svfs.audit)
1350
1350
1351 self._dirstatevalidatewarned = False
1351 self._dirstatevalidatewarned = False
1352
1352
1353 self._branchcaches = branchmap.BranchMapCache()
1353 self._branchcaches = branchmap.BranchMapCache()
1354 self._revbranchcache = None
1354 self._revbranchcache = None
1355 self._filterpats = {}
1355 self._filterpats = {}
1356 self._datafilters = {}
1356 self._datafilters = {}
1357 self._transref = self._lockref = self._wlockref = None
1357 self._transref = self._lockref = self._wlockref = None
1358
1358
1359 # A cache for various files under .hg/ that tracks file changes,
1359 # A cache for various files under .hg/ that tracks file changes,
1360 # (used by the filecache decorator)
1360 # (used by the filecache decorator)
1361 #
1361 #
1362 # Maps a property name to its util.filecacheentry
1362 # Maps a property name to its util.filecacheentry
1363 self._filecache = {}
1363 self._filecache = {}
1364
1364
1365 # hold sets of revision to be filtered
1365 # hold sets of revision to be filtered
1366 # should be cleared when something might have changed the filter value:
1366 # should be cleared when something might have changed the filter value:
1367 # - new changesets,
1367 # - new changesets,
1368 # - phase change,
1368 # - phase change,
1369 # - new obsolescence marker,
1369 # - new obsolescence marker,
1370 # - working directory parent change,
1370 # - working directory parent change,
1371 # - bookmark changes
1371 # - bookmark changes
1372 self.filteredrevcache = {}
1372 self.filteredrevcache = {}
1373
1373
1374 # post-dirstate-status hooks
1374 # post-dirstate-status hooks
1375 self._postdsstatus = []
1375 self._postdsstatus = []
1376
1376
1377 # generic mapping between names and nodes
1377 # generic mapping between names and nodes
1378 self.names = namespaces.namespaces()
1378 self.names = namespaces.namespaces()
1379
1379
1380 # Key to signature value.
1380 # Key to signature value.
1381 self._sparsesignaturecache = {}
1381 self._sparsesignaturecache = {}
1382 # Signature to cached matcher instance.
1382 # Signature to cached matcher instance.
1383 self._sparsematchercache = {}
1383 self._sparsematchercache = {}
1384
1384
1385 self._extrafilterid = repoview.extrafilter(ui)
1385 self._extrafilterid = repoview.extrafilter(ui)
1386
1386
1387 self.filecopiesmode = None
1387 self.filecopiesmode = None
1388 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
1388 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
1389 self.filecopiesmode = b'changeset-sidedata'
1389 self.filecopiesmode = b'changeset-sidedata'
1390
1390
1391 def _getvfsward(self, origfunc):
1391 def _getvfsward(self, origfunc):
1392 """build a ward for self.vfs"""
1392 """build a ward for self.vfs"""
1393 rref = weakref.ref(self)
1393 rref = weakref.ref(self)
1394
1394
1395 def checkvfs(path, mode=None):
1395 def checkvfs(path, mode=None):
1396 ret = origfunc(path, mode=mode)
1396 ret = origfunc(path, mode=mode)
1397 repo = rref()
1397 repo = rref()
1398 if (
1398 if (
1399 repo is None
1399 repo is None
1400 or not util.safehasattr(repo, b'_wlockref')
1400 or not util.safehasattr(repo, b'_wlockref')
1401 or not util.safehasattr(repo, b'_lockref')
1401 or not util.safehasattr(repo, b'_lockref')
1402 ):
1402 ):
1403 return
1403 return
1404 if mode in (None, b'r', b'rb'):
1404 if mode in (None, b'r', b'rb'):
1405 return
1405 return
1406 if path.startswith(repo.path):
1406 if path.startswith(repo.path):
1407 # truncate name relative to the repository (.hg)
1407 # truncate name relative to the repository (.hg)
1408 path = path[len(repo.path) + 1 :]
1408 path = path[len(repo.path) + 1 :]
1409 if path.startswith(b'cache/'):
1409 if path.startswith(b'cache/'):
1410 msg = b'accessing cache with vfs instead of cachevfs: "%s"'
1410 msg = b'accessing cache with vfs instead of cachevfs: "%s"'
1411 repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs")
1411 repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs")
1412 # path prefixes covered by 'lock'
1412 # path prefixes covered by 'lock'
1413 vfs_path_prefixes = (
1413 vfs_path_prefixes = (
1414 b'journal.',
1414 b'journal.',
1415 b'undo.',
1415 b'undo.',
1416 b'strip-backup/',
1416 b'strip-backup/',
1417 b'cache/',
1417 b'cache/',
1418 )
1418 )
1419 if any(path.startswith(prefix) for prefix in vfs_path_prefixes):
1419 if any(path.startswith(prefix) for prefix in vfs_path_prefixes):
1420 if repo._currentlock(repo._lockref) is None:
1420 if repo._currentlock(repo._lockref) is None:
1421 repo.ui.develwarn(
1421 repo.ui.develwarn(
1422 b'write with no lock: "%s"' % path,
1422 b'write with no lock: "%s"' % path,
1423 stacklevel=3,
1423 stacklevel=3,
1424 config=b'check-locks',
1424 config=b'check-locks',
1425 )
1425 )
1426 elif repo._currentlock(repo._wlockref) is None:
1426 elif repo._currentlock(repo._wlockref) is None:
1427 # rest of vfs files are covered by 'wlock'
1427 # rest of vfs files are covered by 'wlock'
1428 #
1428 #
1429 # exclude special files
1429 # exclude special files
1430 for prefix in self._wlockfreeprefix:
1430 for prefix in self._wlockfreeprefix:
1431 if path.startswith(prefix):
1431 if path.startswith(prefix):
1432 return
1432 return
1433 repo.ui.develwarn(
1433 repo.ui.develwarn(
1434 b'write with no wlock: "%s"' % path,
1434 b'write with no wlock: "%s"' % path,
1435 stacklevel=3,
1435 stacklevel=3,
1436 config=b'check-locks',
1436 config=b'check-locks',
1437 )
1437 )
1438 return ret
1438 return ret
1439
1439
1440 return checkvfs
1440 return checkvfs
1441
1441
1442 def _getsvfsward(self, origfunc):
1442 def _getsvfsward(self, origfunc):
1443 """build a ward for self.svfs"""
1443 """build a ward for self.svfs"""
1444 rref = weakref.ref(self)
1444 rref = weakref.ref(self)
1445
1445
1446 def checksvfs(path, mode=None):
1446 def checksvfs(path, mode=None):
1447 ret = origfunc(path, mode=mode)
1447 ret = origfunc(path, mode=mode)
1448 repo = rref()
1448 repo = rref()
1449 if repo is None or not util.safehasattr(repo, b'_lockref'):
1449 if repo is None or not util.safehasattr(repo, b'_lockref'):
1450 return
1450 return
1451 if mode in (None, b'r', b'rb'):
1451 if mode in (None, b'r', b'rb'):
1452 return
1452 return
1453 if path.startswith(repo.sharedpath):
1453 if path.startswith(repo.sharedpath):
1454 # truncate name relative to the repository (.hg)
1454 # truncate name relative to the repository (.hg)
1455 path = path[len(repo.sharedpath) + 1 :]
1455 path = path[len(repo.sharedpath) + 1 :]
1456 if repo._currentlock(repo._lockref) is None:
1456 if repo._currentlock(repo._lockref) is None:
1457 repo.ui.develwarn(
1457 repo.ui.develwarn(
1458 b'write with no lock: "%s"' % path, stacklevel=4
1458 b'write with no lock: "%s"' % path, stacklevel=4
1459 )
1459 )
1460 return ret
1460 return ret
1461
1461
1462 return checksvfs
1462 return checksvfs
1463
1463
1464 def close(self):
1464 def close(self):
1465 self._writecaches()
1465 self._writecaches()
1466
1466
1467 def _writecaches(self):
1467 def _writecaches(self):
1468 if self._revbranchcache:
1468 if self._revbranchcache:
1469 self._revbranchcache.write()
1469 self._revbranchcache.write()
1470
1470
1471 def _restrictcapabilities(self, caps):
1471 def _restrictcapabilities(self, caps):
1472 if self.ui.configbool(b'experimental', b'bundle2-advertise'):
1472 if self.ui.configbool(b'experimental', b'bundle2-advertise'):
1473 caps = set(caps)
1473 caps = set(caps)
1474 capsblob = bundle2.encodecaps(
1474 capsblob = bundle2.encodecaps(
1475 bundle2.getrepocaps(self, role=b'client')
1475 bundle2.getrepocaps(self, role=b'client')
1476 )
1476 )
1477 caps.add(b'bundle2=' + urlreq.quote(capsblob))
1477 caps.add(b'bundle2=' + urlreq.quote(capsblob))
1478 return caps
1478 return caps
1479
1479
1480 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
1480 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
1481 # self -> auditor -> self._checknested -> self
1481 # self -> auditor -> self._checknested -> self
1482
1482
1483 @property
1483 @property
1484 def auditor(self):
1484 def auditor(self):
1485 # This is only used by context.workingctx.match in order to
1485 # This is only used by context.workingctx.match in order to
1486 # detect files in subrepos.
1486 # detect files in subrepos.
1487 return pathutil.pathauditor(self.root, callback=self._checknested)
1487 return pathutil.pathauditor(self.root, callback=self._checknested)
1488
1488
1489 @property
1489 @property
1490 def nofsauditor(self):
1490 def nofsauditor(self):
1491 # This is only used by context.basectx.match in order to detect
1491 # This is only used by context.basectx.match in order to detect
1492 # files in subrepos.
1492 # files in subrepos.
1493 return pathutil.pathauditor(
1493 return pathutil.pathauditor(
1494 self.root, callback=self._checknested, realfs=False, cached=True
1494 self.root, callback=self._checknested, realfs=False, cached=True
1495 )
1495 )
1496
1496
1497 def _checknested(self, path):
1497 def _checknested(self, path):
1498 """Determine if path is a legal nested repository."""
1498 """Determine if path is a legal nested repository."""
1499 if not path.startswith(self.root):
1499 if not path.startswith(self.root):
1500 return False
1500 return False
1501 subpath = path[len(self.root) + 1 :]
1501 subpath = path[len(self.root) + 1 :]
1502 normsubpath = util.pconvert(subpath)
1502 normsubpath = util.pconvert(subpath)
1503
1503
1504 # XXX: Checking against the current working copy is wrong in
1504 # XXX: Checking against the current working copy is wrong in
1505 # the sense that it can reject things like
1505 # the sense that it can reject things like
1506 #
1506 #
1507 # $ hg cat -r 10 sub/x.txt
1507 # $ hg cat -r 10 sub/x.txt
1508 #
1508 #
1509 # if sub/ is no longer a subrepository in the working copy
1509 # if sub/ is no longer a subrepository in the working copy
1510 # parent revision.
1510 # parent revision.
1511 #
1511 #
1512 # However, it can of course also allow things that would have
1512 # However, it can of course also allow things that would have
1513 # been rejected before, such as the above cat command if sub/
1513 # been rejected before, such as the above cat command if sub/
1514 # is a subrepository now, but was a normal directory before.
1514 # is a subrepository now, but was a normal directory before.
1515 # The old path auditor would have rejected by mistake since it
1515 # The old path auditor would have rejected by mistake since it
1516 # panics when it sees sub/.hg/.
1516 # panics when it sees sub/.hg/.
1517 #
1517 #
1518 # All in all, checking against the working copy seems sensible
1518 # All in all, checking against the working copy seems sensible
1519 # since we want to prevent access to nested repositories on
1519 # since we want to prevent access to nested repositories on
1520 # the filesystem *now*.
1520 # the filesystem *now*.
1521 ctx = self[None]
1521 ctx = self[None]
1522 parts = util.splitpath(subpath)
1522 parts = util.splitpath(subpath)
1523 while parts:
1523 while parts:
1524 prefix = b'/'.join(parts)
1524 prefix = b'/'.join(parts)
1525 if prefix in ctx.substate:
1525 if prefix in ctx.substate:
1526 if prefix == normsubpath:
1526 if prefix == normsubpath:
1527 return True
1527 return True
1528 else:
1528 else:
1529 sub = ctx.sub(prefix)
1529 sub = ctx.sub(prefix)
1530 return sub.checknested(subpath[len(prefix) + 1 :])
1530 return sub.checknested(subpath[len(prefix) + 1 :])
1531 else:
1531 else:
1532 parts.pop()
1532 parts.pop()
1533 return False
1533 return False
1534
1534
1535 def peer(self):
1535 def peer(self):
1536 return localpeer(self) # not cached to avoid reference cycle
1536 return localpeer(self) # not cached to avoid reference cycle
1537
1537
1538 def unfiltered(self):
1538 def unfiltered(self):
1539 """Return unfiltered version of the repository
1539 """Return unfiltered version of the repository
1540
1540
1541 Intended to be overwritten by filtered repo."""
1541 Intended to be overwritten by filtered repo."""
1542 return self
1542 return self
1543
1543
1544 def filtered(self, name, visibilityexceptions=None):
1544 def filtered(self, name, visibilityexceptions=None):
1545 """Return a filtered version of a repository
1545 """Return a filtered version of a repository
1546
1546
1547 The `name` parameter is the identifier of the requested view. This
1547 The `name` parameter is the identifier of the requested view. This
1548 will return a repoview object set "exactly" to the specified view.
1548 will return a repoview object set "exactly" to the specified view.
1549
1549
1550 This function does not apply recursive filtering to a repository. For
1550 This function does not apply recursive filtering to a repository. For
1551 example calling `repo.filtered("served")` will return a repoview using
1551 example calling `repo.filtered("served")` will return a repoview using
1552 the "served" view, regardless of the initial view used by `repo`.
1552 the "served" view, regardless of the initial view used by `repo`.
1553
1553
1554 In other word, there is always only one level of `repoview` "filtering".
1554 In other word, there is always only one level of `repoview` "filtering".
1555 """
1555 """
1556 if self._extrafilterid is not None and b'%' not in name:
1556 if self._extrafilterid is not None and b'%' not in name:
1557 name = name + b'%' + self._extrafilterid
1557 name = name + b'%' + self._extrafilterid
1558
1558
1559 cls = repoview.newtype(self.unfiltered().__class__)
1559 cls = repoview.newtype(self.unfiltered().__class__)
1560 return cls(self, name, visibilityexceptions)
1560 return cls(self, name, visibilityexceptions)
1561
1561
1562 @mixedrepostorecache(
1562 @mixedrepostorecache(
1563 (b'bookmarks', b'plain'),
1563 (b'bookmarks', b'plain'),
1564 (b'bookmarks.current', b'plain'),
1564 (b'bookmarks.current', b'plain'),
1565 (b'bookmarks', b''),
1565 (b'bookmarks', b''),
1566 (b'00changelog.i', b''),
1566 (b'00changelog.i', b''),
1567 )
1567 )
1568 def _bookmarks(self):
1568 def _bookmarks(self):
1569 # Since the multiple files involved in the transaction cannot be
1569 # Since the multiple files involved in the transaction cannot be
1570 # written atomically (with current repository format), there is a race
1570 # written atomically (with current repository format), there is a race
1571 # condition here.
1571 # condition here.
1572 #
1572 #
1573 # 1) changelog content A is read
1573 # 1) changelog content A is read
1574 # 2) outside transaction update changelog to content B
1574 # 2) outside transaction update changelog to content B
1575 # 3) outside transaction update bookmark file referring to content B
1575 # 3) outside transaction update bookmark file referring to content B
1576 # 4) bookmarks file content is read and filtered against changelog-A
1576 # 4) bookmarks file content is read and filtered against changelog-A
1577 #
1577 #
1578 # When this happens, bookmarks against nodes missing from A are dropped.
1578 # When this happens, bookmarks against nodes missing from A are dropped.
1579 #
1579 #
1580 # Having this happening during read is not great, but it become worse
1580 # Having this happening during read is not great, but it become worse
1581 # when this happen during write because the bookmarks to the "unknown"
1581 # when this happen during write because the bookmarks to the "unknown"
1582 # nodes will be dropped for good. However, writes happen within locks.
1582 # nodes will be dropped for good. However, writes happen within locks.
1583 # This locking makes it possible to have a race free consistent read.
1583 # This locking makes it possible to have a race free consistent read.
1584 # For this purpose data read from disc before locking are
1584 # For this purpose data read from disc before locking are
1585 # "invalidated" right after the locks are taken. This invalidations are
1585 # "invalidated" right after the locks are taken. This invalidations are
1586 # "light", the `filecache` mechanism keep the data in memory and will
1586 # "light", the `filecache` mechanism keep the data in memory and will
1587 # reuse them if the underlying files did not changed. Not parsing the
1587 # reuse them if the underlying files did not changed. Not parsing the
1588 # same data multiple times helps performances.
1588 # same data multiple times helps performances.
1589 #
1589 #
1590 # Unfortunately in the case describe above, the files tracked by the
1590 # Unfortunately in the case describe above, the files tracked by the
1591 # bookmarks file cache might not have changed, but the in-memory
1591 # bookmarks file cache might not have changed, but the in-memory
1592 # content is still "wrong" because we used an older changelog content
1592 # content is still "wrong" because we used an older changelog content
1593 # to process the on-disk data. So after locking, the changelog would be
1593 # to process the on-disk data. So after locking, the changelog would be
1594 # refreshed but `_bookmarks` would be preserved.
1594 # refreshed but `_bookmarks` would be preserved.
1595 # Adding `00changelog.i` to the list of tracked file is not
1595 # Adding `00changelog.i` to the list of tracked file is not
1596 # enough, because at the time we build the content for `_bookmarks` in
1596 # enough, because at the time we build the content for `_bookmarks` in
1597 # (4), the changelog file has already diverged from the content used
1597 # (4), the changelog file has already diverged from the content used
1598 # for loading `changelog` in (1)
1598 # for loading `changelog` in (1)
1599 #
1599 #
1600 # To prevent the issue, we force the changelog to be explicitly
1600 # To prevent the issue, we force the changelog to be explicitly
1601 # reloaded while computing `_bookmarks`. The data race can still happen
1601 # reloaded while computing `_bookmarks`. The data race can still happen
1602 # without the lock (with a narrower window), but it would no longer go
1602 # without the lock (with a narrower window), but it would no longer go
1603 # undetected during the lock time refresh.
1603 # undetected during the lock time refresh.
1604 #
1604 #
1605 # The new schedule is as follow
1605 # The new schedule is as follow
1606 #
1606 #
1607 # 1) filecache logic detect that `_bookmarks` needs to be computed
1607 # 1) filecache logic detect that `_bookmarks` needs to be computed
1608 # 2) cachestat for `bookmarks` and `changelog` are captured (for book)
1608 # 2) cachestat for `bookmarks` and `changelog` are captured (for book)
1609 # 3) We force `changelog` filecache to be tested
1609 # 3) We force `changelog` filecache to be tested
1610 # 4) cachestat for `changelog` are captured (for changelog)
1610 # 4) cachestat for `changelog` are captured (for changelog)
1611 # 5) `_bookmarks` is computed and cached
1611 # 5) `_bookmarks` is computed and cached
1612 #
1612 #
1613 # The step in (3) ensure we have a changelog at least as recent as the
1613 # The step in (3) ensure we have a changelog at least as recent as the
1614 # cache stat computed in (1). As a result at locking time:
1614 # cache stat computed in (1). As a result at locking time:
1615 # * if the changelog did not changed since (1) -> we can reuse the data
1615 # * if the changelog did not changed since (1) -> we can reuse the data
1616 # * otherwise -> the bookmarks get refreshed.
1616 # * otherwise -> the bookmarks get refreshed.
1617 self._refreshchangelog()
1617 self._refreshchangelog()
1618 return bookmarks.bmstore(self)
1618 return bookmarks.bmstore(self)
1619
1619
1620 def _refreshchangelog(self):
1620 def _refreshchangelog(self):
1621 """make sure the in memory changelog match the on-disk one"""
1621 """make sure the in memory changelog match the on-disk one"""
1622 if 'changelog' in vars(self) and self.currenttransaction() is None:
1622 if 'changelog' in vars(self) and self.currenttransaction() is None:
1623 del self.changelog
1623 del self.changelog
1624
1624
1625 @property
1625 @property
1626 def _activebookmark(self):
1626 def _activebookmark(self):
1627 return self._bookmarks.active
1627 return self._bookmarks.active
1628
1628
1629 # _phasesets depend on changelog. what we need is to call
1629 # _phasesets depend on changelog. what we need is to call
1630 # _phasecache.invalidate() if '00changelog.i' was changed, but it
1630 # _phasecache.invalidate() if '00changelog.i' was changed, but it
1631 # can't be easily expressed in filecache mechanism.
1631 # can't be easily expressed in filecache mechanism.
1632 @storecache(b'phaseroots', b'00changelog.i')
1632 @storecache(b'phaseroots', b'00changelog.i')
1633 def _phasecache(self):
1633 def _phasecache(self):
1634 return phases.phasecache(self, self._phasedefaults)
1634 return phases.phasecache(self, self._phasedefaults)
1635
1635
1636 @storecache(b'obsstore')
1636 @storecache(b'obsstore')
1637 def obsstore(self):
1637 def obsstore(self):
1638 return obsolete.makestore(self.ui, self)
1638 return obsolete.makestore(self.ui, self)
1639
1639
1640 @storecache(b'00changelog.i')
1640 @storecache(b'00changelog.i')
1641 def changelog(self):
1641 def changelog(self):
1642 # load dirstate before changelog to avoid race see issue6303
1642 # load dirstate before changelog to avoid race see issue6303
1643 self.dirstate.prefetch_parents()
1643 self.dirstate.prefetch_parents()
1644 return self.store.changelog(
1644 return self.store.changelog(
1645 txnutil.mayhavepending(self.root),
1645 txnutil.mayhavepending(self.root),
1646 concurrencychecker=revlogchecker.get_checker(self.ui, b'changelog'),
1646 concurrencychecker=revlogchecker.get_checker(self.ui, b'changelog'),
1647 )
1647 )
1648
1648
1649 @storecache(b'00manifest.i')
1649 @storecache(b'00manifest.i')
1650 def manifestlog(self):
1650 def manifestlog(self):
1651 return self.store.manifestlog(self, self._storenarrowmatch)
1651 return self.store.manifestlog(self, self._storenarrowmatch)
1652
1652
1653 @repofilecache(b'dirstate')
1653 @repofilecache(b'dirstate')
1654 def dirstate(self):
1654 def dirstate(self):
1655 return self._makedirstate()
1655 return self._makedirstate()
1656
1656
1657 def _makedirstate(self):
1657 def _makedirstate(self):
1658 """Extension point for wrapping the dirstate per-repo."""
1658 """Extension point for wrapping the dirstate per-repo."""
1659 sparsematchfn = lambda: sparse.matcher(self)
1659 sparsematchfn = lambda: sparse.matcher(self)
1660
1660
1661 return dirstate.dirstate(
1661 return dirstate.dirstate(
1662 self.vfs, self.ui, self.root, self._dirstatevalidate, sparsematchfn
1662 self.vfs, self.ui, self.root, self._dirstatevalidate, sparsematchfn
1663 )
1663 )
1664
1664
1665 def _dirstatevalidate(self, node):
1665 def _dirstatevalidate(self, node):
1666 try:
1666 try:
1667 self.changelog.rev(node)
1667 self.changelog.rev(node)
1668 return node
1668 return node
1669 except error.LookupError:
1669 except error.LookupError:
1670 if not self._dirstatevalidatewarned:
1670 if not self._dirstatevalidatewarned:
1671 self._dirstatevalidatewarned = True
1671 self._dirstatevalidatewarned = True
1672 self.ui.warn(
1672 self.ui.warn(
1673 _(b"warning: ignoring unknown working parent %s!\n")
1673 _(b"warning: ignoring unknown working parent %s!\n")
1674 % short(node)
1674 % short(node)
1675 )
1675 )
1676 return nullid
1676 return nullid
1677
1677
1678 @storecache(narrowspec.FILENAME)
1678 @storecache(narrowspec.FILENAME)
1679 def narrowpats(self):
1679 def narrowpats(self):
1680 """matcher patterns for this repository's narrowspec
1680 """matcher patterns for this repository's narrowspec
1681
1681
1682 A tuple of (includes, excludes).
1682 A tuple of (includes, excludes).
1683 """
1683 """
1684 return narrowspec.load(self)
1684 return narrowspec.load(self)
1685
1685
1686 @storecache(narrowspec.FILENAME)
1686 @storecache(narrowspec.FILENAME)
1687 def _storenarrowmatch(self):
1687 def _storenarrowmatch(self):
1688 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1688 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1689 return matchmod.always()
1689 return matchmod.always()
1690 include, exclude = self.narrowpats
1690 include, exclude = self.narrowpats
1691 return narrowspec.match(self.root, include=include, exclude=exclude)
1691 return narrowspec.match(self.root, include=include, exclude=exclude)
1692
1692
1693 @storecache(narrowspec.FILENAME)
1693 @storecache(narrowspec.FILENAME)
1694 def _narrowmatch(self):
1694 def _narrowmatch(self):
1695 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1695 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1696 return matchmod.always()
1696 return matchmod.always()
1697 narrowspec.checkworkingcopynarrowspec(self)
1697 narrowspec.checkworkingcopynarrowspec(self)
1698 include, exclude = self.narrowpats
1698 include, exclude = self.narrowpats
1699 return narrowspec.match(self.root, include=include, exclude=exclude)
1699 return narrowspec.match(self.root, include=include, exclude=exclude)
1700
1700
1701 def narrowmatch(self, match=None, includeexact=False):
1701 def narrowmatch(self, match=None, includeexact=False):
1702 """matcher corresponding the the repo's narrowspec
1702 """matcher corresponding the the repo's narrowspec
1703
1703
1704 If `match` is given, then that will be intersected with the narrow
1704 If `match` is given, then that will be intersected with the narrow
1705 matcher.
1705 matcher.
1706
1706
1707 If `includeexact` is True, then any exact matches from `match` will
1707 If `includeexact` is True, then any exact matches from `match` will
1708 be included even if they're outside the narrowspec.
1708 be included even if they're outside the narrowspec.
1709 """
1709 """
1710 if match:
1710 if match:
1711 if includeexact and not self._narrowmatch.always():
1711 if includeexact and not self._narrowmatch.always():
1712 # do not exclude explicitly-specified paths so that they can
1712 # do not exclude explicitly-specified paths so that they can
1713 # be warned later on
1713 # be warned later on
1714 em = matchmod.exact(match.files())
1714 em = matchmod.exact(match.files())
1715 nm = matchmod.unionmatcher([self._narrowmatch, em])
1715 nm = matchmod.unionmatcher([self._narrowmatch, em])
1716 return matchmod.intersectmatchers(match, nm)
1716 return matchmod.intersectmatchers(match, nm)
1717 return matchmod.intersectmatchers(match, self._narrowmatch)
1717 return matchmod.intersectmatchers(match, self._narrowmatch)
1718 return self._narrowmatch
1718 return self._narrowmatch
1719
1719
1720 def setnarrowpats(self, newincludes, newexcludes):
1720 def setnarrowpats(self, newincludes, newexcludes):
1721 narrowspec.save(self, newincludes, newexcludes)
1721 narrowspec.save(self, newincludes, newexcludes)
1722 self.invalidate(clearfilecache=True)
1722 self.invalidate(clearfilecache=True)
1723
1723
1724 @unfilteredpropertycache
1724 @unfilteredpropertycache
1725 def _quick_access_changeid_null(self):
1725 def _quick_access_changeid_null(self):
1726 return {
1726 return {
1727 b'null': (nullrev, nullid),
1727 b'null': (nullrev, nullid),
1728 nullrev: (nullrev, nullid),
1728 nullrev: (nullrev, nullid),
1729 nullid: (nullrev, nullid),
1729 nullid: (nullrev, nullid),
1730 }
1730 }
1731
1731
1732 @unfilteredpropertycache
1732 @unfilteredpropertycache
1733 def _quick_access_changeid_wc(self):
1733 def _quick_access_changeid_wc(self):
1734 # also fast path access to the working copy parents
1734 # also fast path access to the working copy parents
1735 # however, only do it for filter that ensure wc is visible.
1735 # however, only do it for filter that ensure wc is visible.
1736 quick = self._quick_access_changeid_null.copy()
1736 quick = self._quick_access_changeid_null.copy()
1737 cl = self.unfiltered().changelog
1737 cl = self.unfiltered().changelog
1738 for node in self.dirstate.parents():
1738 for node in self.dirstate.parents():
1739 if node == nullid:
1739 if node == nullid:
1740 continue
1740 continue
1741 rev = cl.index.get_rev(node)
1741 rev = cl.index.get_rev(node)
1742 if rev is None:
1742 if rev is None:
1743 # unknown working copy parent case:
1743 # unknown working copy parent case:
1744 #
1744 #
1745 # skip the fast path and let higher code deal with it
1745 # skip the fast path and let higher code deal with it
1746 continue
1746 continue
1747 pair = (rev, node)
1747 pair = (rev, node)
1748 quick[rev] = pair
1748 quick[rev] = pair
1749 quick[node] = pair
1749 quick[node] = pair
1750 # also add the parents of the parents
1750 # also add the parents of the parents
1751 for r in cl.parentrevs(rev):
1751 for r in cl.parentrevs(rev):
1752 if r == nullrev:
1752 if r == nullrev:
1753 continue
1753 continue
1754 n = cl.node(r)
1754 n = cl.node(r)
1755 pair = (r, n)
1755 pair = (r, n)
1756 quick[r] = pair
1756 quick[r] = pair
1757 quick[n] = pair
1757 quick[n] = pair
1758 p1node = self.dirstate.p1()
1758 p1node = self.dirstate.p1()
1759 if p1node != nullid:
1759 if p1node != nullid:
1760 quick[b'.'] = quick[p1node]
1760 quick[b'.'] = quick[p1node]
1761 return quick
1761 return quick
1762
1762
1763 @unfilteredmethod
1763 @unfilteredmethod
1764 def _quick_access_changeid_invalidate(self):
1764 def _quick_access_changeid_invalidate(self):
1765 if '_quick_access_changeid_wc' in vars(self):
1765 if '_quick_access_changeid_wc' in vars(self):
1766 del self.__dict__['_quick_access_changeid_wc']
1766 del self.__dict__['_quick_access_changeid_wc']
1767
1767
1768 @property
1768 @property
1769 def _quick_access_changeid(self):
1769 def _quick_access_changeid(self):
1770 """an helper dictionnary for __getitem__ calls
1770 """an helper dictionnary for __getitem__ calls
1771
1771
1772 This contains a list of symbol we can recognise right away without
1772 This contains a list of symbol we can recognise right away without
1773 further processing.
1773 further processing.
1774 """
1774 """
1775 if self.filtername in repoview.filter_has_wc:
1775 if self.filtername in repoview.filter_has_wc:
1776 return self._quick_access_changeid_wc
1776 return self._quick_access_changeid_wc
1777 return self._quick_access_changeid_null
1777 return self._quick_access_changeid_null
1778
1778
1779 def __getitem__(self, changeid):
1779 def __getitem__(self, changeid):
1780 # dealing with special cases
1780 # dealing with special cases
1781 if changeid is None:
1781 if changeid is None:
1782 return context.workingctx(self)
1782 return context.workingctx(self)
1783 if isinstance(changeid, context.basectx):
1783 if isinstance(changeid, context.basectx):
1784 return changeid
1784 return changeid
1785
1785
1786 # dealing with multiple revisions
1786 # dealing with multiple revisions
1787 if isinstance(changeid, slice):
1787 if isinstance(changeid, slice):
1788 # wdirrev isn't contiguous so the slice shouldn't include it
1788 # wdirrev isn't contiguous so the slice shouldn't include it
1789 return [
1789 return [
1790 self[i]
1790 self[i]
1791 for i in pycompat.xrange(*changeid.indices(len(self)))
1791 for i in pycompat.xrange(*changeid.indices(len(self)))
1792 if i not in self.changelog.filteredrevs
1792 if i not in self.changelog.filteredrevs
1793 ]
1793 ]
1794
1794
1795 # dealing with some special values
1795 # dealing with some special values
1796 quick_access = self._quick_access_changeid.get(changeid)
1796 quick_access = self._quick_access_changeid.get(changeid)
1797 if quick_access is not None:
1797 if quick_access is not None:
1798 rev, node = quick_access
1798 rev, node = quick_access
1799 return context.changectx(self, rev, node, maybe_filtered=False)
1799 return context.changectx(self, rev, node, maybe_filtered=False)
1800 if changeid == b'tip':
1800 if changeid == b'tip':
1801 node = self.changelog.tip()
1801 node = self.changelog.tip()
1802 rev = self.changelog.rev(node)
1802 rev = self.changelog.rev(node)
1803 return context.changectx(self, rev, node)
1803 return context.changectx(self, rev, node)
1804
1804
1805 # dealing with arbitrary values
1805 # dealing with arbitrary values
1806 try:
1806 try:
1807 if isinstance(changeid, int):
1807 if isinstance(changeid, int):
1808 node = self.changelog.node(changeid)
1808 node = self.changelog.node(changeid)
1809 rev = changeid
1809 rev = changeid
1810 elif changeid == b'.':
1810 elif changeid == b'.':
1811 # this is a hack to delay/avoid loading obsmarkers
1811 # this is a hack to delay/avoid loading obsmarkers
1812 # when we know that '.' won't be hidden
1812 # when we know that '.' won't be hidden
1813 node = self.dirstate.p1()
1813 node = self.dirstate.p1()
1814 rev = self.unfiltered().changelog.rev(node)
1814 rev = self.unfiltered().changelog.rev(node)
1815 elif len(changeid) == 20:
1815 elif len(changeid) == 20:
1816 try:
1816 try:
1817 node = changeid
1817 node = changeid
1818 rev = self.changelog.rev(changeid)
1818 rev = self.changelog.rev(changeid)
1819 except error.FilteredLookupError:
1819 except error.FilteredLookupError:
1820 changeid = hex(changeid) # for the error message
1820 changeid = hex(changeid) # for the error message
1821 raise
1821 raise
1822 except LookupError:
1822 except LookupError:
1823 # check if it might have come from damaged dirstate
1823 # check if it might have come from damaged dirstate
1824 #
1824 #
1825 # XXX we could avoid the unfiltered if we had a recognizable
1825 # XXX we could avoid the unfiltered if we had a recognizable
1826 # exception for filtered changeset access
1826 # exception for filtered changeset access
1827 if (
1827 if (
1828 self.local()
1828 self.local()
1829 and changeid in self.unfiltered().dirstate.parents()
1829 and changeid in self.unfiltered().dirstate.parents()
1830 ):
1830 ):
1831 msg = _(b"working directory has unknown parent '%s'!")
1831 msg = _(b"working directory has unknown parent '%s'!")
1832 raise error.Abort(msg % short(changeid))
1832 raise error.Abort(msg % short(changeid))
1833 changeid = hex(changeid) # for the error message
1833 changeid = hex(changeid) # for the error message
1834 raise
1834 raise
1835
1835
1836 elif len(changeid) == 40:
1836 elif len(changeid) == 40:
1837 node = bin(changeid)
1837 node = bin(changeid)
1838 rev = self.changelog.rev(node)
1838 rev = self.changelog.rev(node)
1839 else:
1839 else:
1840 raise error.ProgrammingError(
1840 raise error.ProgrammingError(
1841 b"unsupported changeid '%s' of type %s"
1841 b"unsupported changeid '%s' of type %s"
1842 % (changeid, pycompat.bytestr(type(changeid)))
1842 % (changeid, pycompat.bytestr(type(changeid)))
1843 )
1843 )
1844
1844
1845 return context.changectx(self, rev, node)
1845 return context.changectx(self, rev, node)
1846
1846
1847 except (error.FilteredIndexError, error.FilteredLookupError):
1847 except (error.FilteredIndexError, error.FilteredLookupError):
1848 raise error.FilteredRepoLookupError(
1848 raise error.FilteredRepoLookupError(
1849 _(b"filtered revision '%s'") % pycompat.bytestr(changeid)
1849 _(b"filtered revision '%s'") % pycompat.bytestr(changeid)
1850 )
1850 )
1851 except (IndexError, LookupError):
1851 except (IndexError, LookupError):
1852 raise error.RepoLookupError(
1852 raise error.RepoLookupError(
1853 _(b"unknown revision '%s'") % pycompat.bytestr(changeid)
1853 _(b"unknown revision '%s'") % pycompat.bytestr(changeid)
1854 )
1854 )
1855 except error.WdirUnsupported:
1855 except error.WdirUnsupported:
1856 return context.workingctx(self)
1856 return context.workingctx(self)
1857
1857
1858 def __contains__(self, changeid):
1858 def __contains__(self, changeid):
1859 """True if the given changeid exists"""
1859 """True if the given changeid exists"""
1860 try:
1860 try:
1861 self[changeid]
1861 self[changeid]
1862 return True
1862 return True
1863 except error.RepoLookupError:
1863 except error.RepoLookupError:
1864 return False
1864 return False
1865
1865
1866 def __nonzero__(self):
1866 def __nonzero__(self):
1867 return True
1867 return True
1868
1868
1869 __bool__ = __nonzero__
1869 __bool__ = __nonzero__
1870
1870
1871 def __len__(self):
1871 def __len__(self):
1872 # no need to pay the cost of repoview.changelog
1872 # no need to pay the cost of repoview.changelog
1873 unfi = self.unfiltered()
1873 unfi = self.unfiltered()
1874 return len(unfi.changelog)
1874 return len(unfi.changelog)
1875
1875
1876 def __iter__(self):
1876 def __iter__(self):
1877 return iter(self.changelog)
1877 return iter(self.changelog)
1878
1878
1879 def revs(self, expr, *args):
1879 def revs(self, expr, *args):
1880 """Find revisions matching a revset.
1880 """Find revisions matching a revset.
1881
1881
1882 The revset is specified as a string ``expr`` that may contain
1882 The revset is specified as a string ``expr`` that may contain
1883 %-formatting to escape certain types. See ``revsetlang.formatspec``.
1883 %-formatting to escape certain types. See ``revsetlang.formatspec``.
1884
1884
1885 Revset aliases from the configuration are not expanded. To expand
1885 Revset aliases from the configuration are not expanded. To expand
1886 user aliases, consider calling ``scmutil.revrange()`` or
1886 user aliases, consider calling ``scmutil.revrange()`` or
1887 ``repo.anyrevs([expr], user=True)``.
1887 ``repo.anyrevs([expr], user=True)``.
1888
1888
1889 Returns a smartset.abstractsmartset, which is a list-like interface
1889 Returns a smartset.abstractsmartset, which is a list-like interface
1890 that contains integer revisions.
1890 that contains integer revisions.
1891 """
1891 """
1892 tree = revsetlang.spectree(expr, *args)
1892 tree = revsetlang.spectree(expr, *args)
1893 return revset.makematcher(tree)(self)
1893 return revset.makematcher(tree)(self)
1894
1894
1895 def set(self, expr, *args):
1895 def set(self, expr, *args):
1896 """Find revisions matching a revset and emit changectx instances.
1896 """Find revisions matching a revset and emit changectx instances.
1897
1897
1898 This is a convenience wrapper around ``revs()`` that iterates the
1898 This is a convenience wrapper around ``revs()`` that iterates the
1899 result and is a generator of changectx instances.
1899 result and is a generator of changectx instances.
1900
1900
1901 Revset aliases from the configuration are not expanded. To expand
1901 Revset aliases from the configuration are not expanded. To expand
1902 user aliases, consider calling ``scmutil.revrange()``.
1902 user aliases, consider calling ``scmutil.revrange()``.
1903 """
1903 """
1904 for r in self.revs(expr, *args):
1904 for r in self.revs(expr, *args):
1905 yield self[r]
1905 yield self[r]
1906
1906
1907 def anyrevs(self, specs, user=False, localalias=None):
1907 def anyrevs(self, specs, user=False, localalias=None):
1908 """Find revisions matching one of the given revsets.
1908 """Find revisions matching one of the given revsets.
1909
1909
1910 Revset aliases from the configuration are not expanded by default. To
1910 Revset aliases from the configuration are not expanded by default. To
1911 expand user aliases, specify ``user=True``. To provide some local
1911 expand user aliases, specify ``user=True``. To provide some local
1912 definitions overriding user aliases, set ``localalias`` to
1912 definitions overriding user aliases, set ``localalias`` to
1913 ``{name: definitionstring}``.
1913 ``{name: definitionstring}``.
1914 """
1914 """
1915 if specs == [b'null']:
1915 if specs == [b'null']:
1916 return revset.baseset([nullrev])
1916 return revset.baseset([nullrev])
1917 if specs == [b'.']:
1917 if specs == [b'.']:
1918 quick_data = self._quick_access_changeid.get(b'.')
1918 quick_data = self._quick_access_changeid.get(b'.')
1919 if quick_data is not None:
1919 if quick_data is not None:
1920 return revset.baseset([quick_data[0]])
1920 return revset.baseset([quick_data[0]])
1921 if user:
1921 if user:
1922 m = revset.matchany(
1922 m = revset.matchany(
1923 self.ui,
1923 self.ui,
1924 specs,
1924 specs,
1925 lookup=revset.lookupfn(self),
1925 lookup=revset.lookupfn(self),
1926 localalias=localalias,
1926 localalias=localalias,
1927 )
1927 )
1928 else:
1928 else:
1929 m = revset.matchany(None, specs, localalias=localalias)
1929 m = revset.matchany(None, specs, localalias=localalias)
1930 return m(self)
1930 return m(self)
1931
1931
1932 def url(self):
1932 def url(self):
1933 return b'file:' + self.root
1933 return b'file:' + self.root
1934
1934
1935 def hook(self, name, throw=False, **args):
1935 def hook(self, name, throw=False, **args):
1936 """Call a hook, passing this repo instance.
1936 """Call a hook, passing this repo instance.
1937
1937
1938 This a convenience method to aid invoking hooks. Extensions likely
1938 This a convenience method to aid invoking hooks. Extensions likely
1939 won't call this unless they have registered a custom hook or are
1939 won't call this unless they have registered a custom hook or are
1940 replacing code that is expected to call a hook.
1940 replacing code that is expected to call a hook.
1941 """
1941 """
1942 return hook.hook(self.ui, self, name, throw, **args)
1942 return hook.hook(self.ui, self, name, throw, **args)
1943
1943
1944 @filteredpropertycache
1944 @filteredpropertycache
1945 def _tagscache(self):
1945 def _tagscache(self):
1946 """Returns a tagscache object that contains various tags related
1946 """Returns a tagscache object that contains various tags related
1947 caches."""
1947 caches."""
1948
1948
1949 # This simplifies its cache management by having one decorated
1949 # This simplifies its cache management by having one decorated
1950 # function (this one) and the rest simply fetch things from it.
1950 # function (this one) and the rest simply fetch things from it.
1951 class tagscache(object):
1951 class tagscache(object):
1952 def __init__(self):
1952 def __init__(self):
1953 # These two define the set of tags for this repository. tags
1953 # These two define the set of tags for this repository. tags
1954 # maps tag name to node; tagtypes maps tag name to 'global' or
1954 # maps tag name to node; tagtypes maps tag name to 'global' or
1955 # 'local'. (Global tags are defined by .hgtags across all
1955 # 'local'. (Global tags are defined by .hgtags across all
1956 # heads, and local tags are defined in .hg/localtags.)
1956 # heads, and local tags are defined in .hg/localtags.)
1957 # They constitute the in-memory cache of tags.
1957 # They constitute the in-memory cache of tags.
1958 self.tags = self.tagtypes = None
1958 self.tags = self.tagtypes = None
1959
1959
1960 self.nodetagscache = self.tagslist = None
1960 self.nodetagscache = self.tagslist = None
1961
1961
1962 cache = tagscache()
1962 cache = tagscache()
1963 cache.tags, cache.tagtypes = self._findtags()
1963 cache.tags, cache.tagtypes = self._findtags()
1964
1964
1965 return cache
1965 return cache
1966
1966
1967 def tags(self):
1967 def tags(self):
1968 '''return a mapping of tag to node'''
1968 '''return a mapping of tag to node'''
1969 t = {}
1969 t = {}
1970 if self.changelog.filteredrevs:
1970 if self.changelog.filteredrevs:
1971 tags, tt = self._findtags()
1971 tags, tt = self._findtags()
1972 else:
1972 else:
1973 tags = self._tagscache.tags
1973 tags = self._tagscache.tags
1974 rev = self.changelog.rev
1974 rev = self.changelog.rev
1975 for k, v in pycompat.iteritems(tags):
1975 for k, v in pycompat.iteritems(tags):
1976 try:
1976 try:
1977 # ignore tags to unknown nodes
1977 # ignore tags to unknown nodes
1978 rev(v)
1978 rev(v)
1979 t[k] = v
1979 t[k] = v
1980 except (error.LookupError, ValueError):
1980 except (error.LookupError, ValueError):
1981 pass
1981 pass
1982 return t
1982 return t
1983
1983
1984 def _findtags(self):
1984 def _findtags(self):
1985 """Do the hard work of finding tags. Return a pair of dicts
1985 """Do the hard work of finding tags. Return a pair of dicts
1986 (tags, tagtypes) where tags maps tag name to node, and tagtypes
1986 (tags, tagtypes) where tags maps tag name to node, and tagtypes
1987 maps tag name to a string like \'global\' or \'local\'.
1987 maps tag name to a string like \'global\' or \'local\'.
1988 Subclasses or extensions are free to add their own tags, but
1988 Subclasses or extensions are free to add their own tags, but
1989 should be aware that the returned dicts will be retained for the
1989 should be aware that the returned dicts will be retained for the
1990 duration of the localrepo object."""
1990 duration of the localrepo object."""
1991
1991
1992 # XXX what tagtype should subclasses/extensions use? Currently
1992 # XXX what tagtype should subclasses/extensions use? Currently
1993 # mq and bookmarks add tags, but do not set the tagtype at all.
1993 # mq and bookmarks add tags, but do not set the tagtype at all.
1994 # Should each extension invent its own tag type? Should there
1994 # Should each extension invent its own tag type? Should there
1995 # be one tagtype for all such "virtual" tags? Or is the status
1995 # be one tagtype for all such "virtual" tags? Or is the status
1996 # quo fine?
1996 # quo fine?
1997
1997
1998 # map tag name to (node, hist)
1998 # map tag name to (node, hist)
1999 alltags = tagsmod.findglobaltags(self.ui, self)
1999 alltags = tagsmod.findglobaltags(self.ui, self)
2000 # map tag name to tag type
2000 # map tag name to tag type
2001 tagtypes = {tag: b'global' for tag in alltags}
2001 tagtypes = {tag: b'global' for tag in alltags}
2002
2002
2003 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
2003 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
2004
2004
2005 # Build the return dicts. Have to re-encode tag names because
2005 # Build the return dicts. Have to re-encode tag names because
2006 # the tags module always uses UTF-8 (in order not to lose info
2006 # the tags module always uses UTF-8 (in order not to lose info
2007 # writing to the cache), but the rest of Mercurial wants them in
2007 # writing to the cache), but the rest of Mercurial wants them in
2008 # local encoding.
2008 # local encoding.
2009 tags = {}
2009 tags = {}
2010 for (name, (node, hist)) in pycompat.iteritems(alltags):
2010 for (name, (node, hist)) in pycompat.iteritems(alltags):
2011 if node != nullid:
2011 if node != nullid:
2012 tags[encoding.tolocal(name)] = node
2012 tags[encoding.tolocal(name)] = node
2013 tags[b'tip'] = self.changelog.tip()
2013 tags[b'tip'] = self.changelog.tip()
2014 tagtypes = {
2014 tagtypes = {
2015 encoding.tolocal(name): value
2015 encoding.tolocal(name): value
2016 for (name, value) in pycompat.iteritems(tagtypes)
2016 for (name, value) in pycompat.iteritems(tagtypes)
2017 }
2017 }
2018 return (tags, tagtypes)
2018 return (tags, tagtypes)
2019
2019
2020 def tagtype(self, tagname):
2020 def tagtype(self, tagname):
2021 """
2021 """
2022 return the type of the given tag. result can be:
2022 return the type of the given tag. result can be:
2023
2023
2024 'local' : a local tag
2024 'local' : a local tag
2025 'global' : a global tag
2025 'global' : a global tag
2026 None : tag does not exist
2026 None : tag does not exist
2027 """
2027 """
2028
2028
2029 return self._tagscache.tagtypes.get(tagname)
2029 return self._tagscache.tagtypes.get(tagname)
2030
2030
2031 def tagslist(self):
2031 def tagslist(self):
2032 '''return a list of tags ordered by revision'''
2032 '''return a list of tags ordered by revision'''
2033 if not self._tagscache.tagslist:
2033 if not self._tagscache.tagslist:
2034 l = []
2034 l = []
2035 for t, n in pycompat.iteritems(self.tags()):
2035 for t, n in pycompat.iteritems(self.tags()):
2036 l.append((self.changelog.rev(n), t, n))
2036 l.append((self.changelog.rev(n), t, n))
2037 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
2037 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
2038
2038
2039 return self._tagscache.tagslist
2039 return self._tagscache.tagslist
2040
2040
2041 def nodetags(self, node):
2041 def nodetags(self, node):
2042 '''return the tags associated with a node'''
2042 '''return the tags associated with a node'''
2043 if not self._tagscache.nodetagscache:
2043 if not self._tagscache.nodetagscache:
2044 nodetagscache = {}
2044 nodetagscache = {}
2045 for t, n in pycompat.iteritems(self._tagscache.tags):
2045 for t, n in pycompat.iteritems(self._tagscache.tags):
2046 nodetagscache.setdefault(n, []).append(t)
2046 nodetagscache.setdefault(n, []).append(t)
2047 for tags in pycompat.itervalues(nodetagscache):
2047 for tags in pycompat.itervalues(nodetagscache):
2048 tags.sort()
2048 tags.sort()
2049 self._tagscache.nodetagscache = nodetagscache
2049 self._tagscache.nodetagscache = nodetagscache
2050 return self._tagscache.nodetagscache.get(node, [])
2050 return self._tagscache.nodetagscache.get(node, [])
2051
2051
2052 def nodebookmarks(self, node):
2052 def nodebookmarks(self, node):
2053 """return the list of bookmarks pointing to the specified node"""
2053 """return the list of bookmarks pointing to the specified node"""
2054 return self._bookmarks.names(node)
2054 return self._bookmarks.names(node)
2055
2055
2056 def branchmap(self):
2056 def branchmap(self):
2057 """returns a dictionary {branch: [branchheads]} with branchheads
2057 """returns a dictionary {branch: [branchheads]} with branchheads
2058 ordered by increasing revision number"""
2058 ordered by increasing revision number"""
2059 return self._branchcaches[self]
2059 return self._branchcaches[self]
2060
2060
2061 @unfilteredmethod
2061 @unfilteredmethod
2062 def revbranchcache(self):
2062 def revbranchcache(self):
2063 if not self._revbranchcache:
2063 if not self._revbranchcache:
2064 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
2064 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
2065 return self._revbranchcache
2065 return self._revbranchcache
2066
2066
2067 def register_changeset(self, rev, changelogrevision):
2067 def register_changeset(self, rev, changelogrevision):
2068 self.revbranchcache().setdata(rev, changelogrevision)
2068 self.revbranchcache().setdata(rev, changelogrevision)
2069
2069
2070 def branchtip(self, branch, ignoremissing=False):
2070 def branchtip(self, branch, ignoremissing=False):
2071 """return the tip node for a given branch
2071 """return the tip node for a given branch
2072
2072
2073 If ignoremissing is True, then this method will not raise an error.
2073 If ignoremissing is True, then this method will not raise an error.
2074 This is helpful for callers that only expect None for a missing branch
2074 This is helpful for callers that only expect None for a missing branch
2075 (e.g. namespace).
2075 (e.g. namespace).
2076
2076
2077 """
2077 """
2078 try:
2078 try:
2079 return self.branchmap().branchtip(branch)
2079 return self.branchmap().branchtip(branch)
2080 except KeyError:
2080 except KeyError:
2081 if not ignoremissing:
2081 if not ignoremissing:
2082 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
2082 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
2083 else:
2083 else:
2084 pass
2084 pass
2085
2085
2086 def lookup(self, key):
2086 def lookup(self, key):
2087 node = scmutil.revsymbol(self, key).node()
2087 node = scmutil.revsymbol(self, key).node()
2088 if node is None:
2088 if node is None:
2089 raise error.RepoLookupError(_(b"unknown revision '%s'") % key)
2089 raise error.RepoLookupError(_(b"unknown revision '%s'") % key)
2090 return node
2090 return node
2091
2091
2092 def lookupbranch(self, key):
2092 def lookupbranch(self, key):
2093 if self.branchmap().hasbranch(key):
2093 if self.branchmap().hasbranch(key):
2094 return key
2094 return key
2095
2095
2096 return scmutil.revsymbol(self, key).branch()
2096 return scmutil.revsymbol(self, key).branch()
2097
2097
2098 def known(self, nodes):
2098 def known(self, nodes):
2099 cl = self.changelog
2099 cl = self.changelog
2100 get_rev = cl.index.get_rev
2100 get_rev = cl.index.get_rev
2101 filtered = cl.filteredrevs
2101 filtered = cl.filteredrevs
2102 result = []
2102 result = []
2103 for n in nodes:
2103 for n in nodes:
2104 r = get_rev(n)
2104 r = get_rev(n)
2105 resp = not (r is None or r in filtered)
2105 resp = not (r is None or r in filtered)
2106 result.append(resp)
2106 result.append(resp)
2107 return result
2107 return result
2108
2108
2109 def local(self):
2109 def local(self):
2110 return self
2110 return self
2111
2111
2112 def publishing(self):
2112 def publishing(self):
2113 # it's safe (and desirable) to trust the publish flag unconditionally
2113 # it's safe (and desirable) to trust the publish flag unconditionally
2114 # so that we don't finalize changes shared between users via ssh or nfs
2114 # so that we don't finalize changes shared between users via ssh or nfs
2115 return self.ui.configbool(b'phases', b'publish', untrusted=True)
2115 return self.ui.configbool(b'phases', b'publish', untrusted=True)
2116
2116
2117 def cancopy(self):
2117 def cancopy(self):
2118 # so statichttprepo's override of local() works
2118 # so statichttprepo's override of local() works
2119 if not self.local():
2119 if not self.local():
2120 return False
2120 return False
2121 if not self.publishing():
2121 if not self.publishing():
2122 return True
2122 return True
2123 # if publishing we can't copy if there is filtered content
2123 # if publishing we can't copy if there is filtered content
2124 return not self.filtered(b'visible').changelog.filteredrevs
2124 return not self.filtered(b'visible').changelog.filteredrevs
2125
2125
2126 def shared(self):
2126 def shared(self):
2127 '''the type of shared repository (None if not shared)'''
2127 '''the type of shared repository (None if not shared)'''
2128 if self.sharedpath != self.path:
2128 if self.sharedpath != self.path:
2129 return b'store'
2129 return b'store'
2130 return None
2130 return None
2131
2131
2132 def wjoin(self, f, *insidef):
2132 def wjoin(self, f, *insidef):
2133 return self.vfs.reljoin(self.root, f, *insidef)
2133 return self.vfs.reljoin(self.root, f, *insidef)
2134
2134
2135 def setparents(self, p1, p2=nullid):
2135 def setparents(self, p1, p2=nullid):
2136 self[None].setparents(p1, p2)
2136 self[None].setparents(p1, p2)
2137 self._quick_access_changeid_invalidate()
2137 self._quick_access_changeid_invalidate()
2138
2138
2139 def filectx(self, path, changeid=None, fileid=None, changectx=None):
2139 def filectx(self, path, changeid=None, fileid=None, changectx=None):
2140 """changeid must be a changeset revision, if specified.
2140 """changeid must be a changeset revision, if specified.
2141 fileid can be a file revision or node."""
2141 fileid can be a file revision or node."""
2142 return context.filectx(
2142 return context.filectx(
2143 self, path, changeid, fileid, changectx=changectx
2143 self, path, changeid, fileid, changectx=changectx
2144 )
2144 )
2145
2145
2146 def getcwd(self):
2146 def getcwd(self):
2147 return self.dirstate.getcwd()
2147 return self.dirstate.getcwd()
2148
2148
2149 def pathto(self, f, cwd=None):
2149 def pathto(self, f, cwd=None):
2150 return self.dirstate.pathto(f, cwd)
2150 return self.dirstate.pathto(f, cwd)
2151
2151
2152 def _loadfilter(self, filter):
2152 def _loadfilter(self, filter):
2153 if filter not in self._filterpats:
2153 if filter not in self._filterpats:
2154 l = []
2154 l = []
2155 for pat, cmd in self.ui.configitems(filter):
2155 for pat, cmd in self.ui.configitems(filter):
2156 if cmd == b'!':
2156 if cmd == b'!':
2157 continue
2157 continue
2158 mf = matchmod.match(self.root, b'', [pat])
2158 mf = matchmod.match(self.root, b'', [pat])
2159 fn = None
2159 fn = None
2160 params = cmd
2160 params = cmd
2161 for name, filterfn in pycompat.iteritems(self._datafilters):
2161 for name, filterfn in pycompat.iteritems(self._datafilters):
2162 if cmd.startswith(name):
2162 if cmd.startswith(name):
2163 fn = filterfn
2163 fn = filterfn
2164 params = cmd[len(name) :].lstrip()
2164 params = cmd[len(name) :].lstrip()
2165 break
2165 break
2166 if not fn:
2166 if not fn:
2167 fn = lambda s, c, **kwargs: procutil.filter(s, c)
2167 fn = lambda s, c, **kwargs: procutil.filter(s, c)
2168 fn.__name__ = 'commandfilter'
2168 fn.__name__ = 'commandfilter'
2169 # Wrap old filters not supporting keyword arguments
2169 # Wrap old filters not supporting keyword arguments
2170 if not pycompat.getargspec(fn)[2]:
2170 if not pycompat.getargspec(fn)[2]:
2171 oldfn = fn
2171 oldfn = fn
2172 fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c)
2172 fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c)
2173 fn.__name__ = 'compat-' + oldfn.__name__
2173 fn.__name__ = 'compat-' + oldfn.__name__
2174 l.append((mf, fn, params))
2174 l.append((mf, fn, params))
2175 self._filterpats[filter] = l
2175 self._filterpats[filter] = l
2176 return self._filterpats[filter]
2176 return self._filterpats[filter]
2177
2177
2178 def _filter(self, filterpats, filename, data):
2178 def _filter(self, filterpats, filename, data):
2179 for mf, fn, cmd in filterpats:
2179 for mf, fn, cmd in filterpats:
2180 if mf(filename):
2180 if mf(filename):
2181 self.ui.debug(
2181 self.ui.debug(
2182 b"filtering %s through %s\n"
2182 b"filtering %s through %s\n"
2183 % (filename, cmd or pycompat.sysbytes(fn.__name__))
2183 % (filename, cmd or pycompat.sysbytes(fn.__name__))
2184 )
2184 )
2185 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
2185 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
2186 break
2186 break
2187
2187
2188 return data
2188 return data
2189
2189
2190 @unfilteredpropertycache
2190 @unfilteredpropertycache
2191 def _encodefilterpats(self):
2191 def _encodefilterpats(self):
2192 return self._loadfilter(b'encode')
2192 return self._loadfilter(b'encode')
2193
2193
2194 @unfilteredpropertycache
2194 @unfilteredpropertycache
2195 def _decodefilterpats(self):
2195 def _decodefilterpats(self):
2196 return self._loadfilter(b'decode')
2196 return self._loadfilter(b'decode')
2197
2197
2198 def adddatafilter(self, name, filter):
2198 def adddatafilter(self, name, filter):
2199 self._datafilters[name] = filter
2199 self._datafilters[name] = filter
2200
2200
2201 def wread(self, filename):
2201 def wread(self, filename):
2202 if self.wvfs.islink(filename):
2202 if self.wvfs.islink(filename):
2203 data = self.wvfs.readlink(filename)
2203 data = self.wvfs.readlink(filename)
2204 else:
2204 else:
2205 data = self.wvfs.read(filename)
2205 data = self.wvfs.read(filename)
2206 return self._filter(self._encodefilterpats, filename, data)
2206 return self._filter(self._encodefilterpats, filename, data)
2207
2207
2208 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
2208 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
2209 """write ``data`` into ``filename`` in the working directory
2209 """write ``data`` into ``filename`` in the working directory
2210
2210
2211 This returns length of written (maybe decoded) data.
2211 This returns length of written (maybe decoded) data.
2212 """
2212 """
2213 data = self._filter(self._decodefilterpats, filename, data)
2213 data = self._filter(self._decodefilterpats, filename, data)
2214 if b'l' in flags:
2214 if b'l' in flags:
2215 self.wvfs.symlink(data, filename)
2215 self.wvfs.symlink(data, filename)
2216 else:
2216 else:
2217 self.wvfs.write(
2217 self.wvfs.write(
2218 filename, data, backgroundclose=backgroundclose, **kwargs
2218 filename, data, backgroundclose=backgroundclose, **kwargs
2219 )
2219 )
2220 if b'x' in flags:
2220 if b'x' in flags:
2221 self.wvfs.setflags(filename, False, True)
2221 self.wvfs.setflags(filename, False, True)
2222 else:
2222 else:
2223 self.wvfs.setflags(filename, False, False)
2223 self.wvfs.setflags(filename, False, False)
2224 return len(data)
2224 return len(data)
2225
2225
2226 def wwritedata(self, filename, data):
2226 def wwritedata(self, filename, data):
2227 return self._filter(self._decodefilterpats, filename, data)
2227 return self._filter(self._decodefilterpats, filename, data)
2228
2228
2229 def currenttransaction(self):
2229 def currenttransaction(self):
2230 """return the current transaction or None if non exists"""
2230 """return the current transaction or None if non exists"""
2231 if self._transref:
2231 if self._transref:
2232 tr = self._transref()
2232 tr = self._transref()
2233 else:
2233 else:
2234 tr = None
2234 tr = None
2235
2235
2236 if tr and tr.running():
2236 if tr and tr.running():
2237 return tr
2237 return tr
2238 return None
2238 return None
2239
2239
2240 def transaction(self, desc, report=None):
2240 def transaction(self, desc, report=None):
2241 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
2241 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
2242 b'devel', b'check-locks'
2242 b'devel', b'check-locks'
2243 ):
2243 ):
2244 if self._currentlock(self._lockref) is None:
2244 if self._currentlock(self._lockref) is None:
2245 raise error.ProgrammingError(b'transaction requires locking')
2245 raise error.ProgrammingError(b'transaction requires locking')
2246 tr = self.currenttransaction()
2246 tr = self.currenttransaction()
2247 if tr is not None:
2247 if tr is not None:
2248 return tr.nest(name=desc)
2248 return tr.nest(name=desc)
2249
2249
2250 # abort here if the journal already exists
2250 # abort here if the journal already exists
2251 if self.svfs.exists(b"journal"):
2251 if self.svfs.exists(b"journal"):
2252 raise error.RepoError(
2252 raise error.RepoError(
2253 _(b"abandoned transaction found"),
2253 _(b"abandoned transaction found"),
2254 hint=_(b"run 'hg recover' to clean up transaction"),
2254 hint=_(b"run 'hg recover' to clean up transaction"),
2255 )
2255 )
2256
2256
2257 idbase = b"%.40f#%f" % (random.random(), time.time())
2257 idbase = b"%.40f#%f" % (random.random(), time.time())
2258 ha = hex(hashutil.sha1(idbase).digest())
2258 ha = hex(hashutil.sha1(idbase).digest())
2259 txnid = b'TXN:' + ha
2259 txnid = b'TXN:' + ha
2260 self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
2260 self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
2261
2261
2262 self._writejournal(desc)
2262 self._writejournal(desc)
2263 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
2263 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
2264 if report:
2264 if report:
2265 rp = report
2265 rp = report
2266 else:
2266 else:
2267 rp = self.ui.warn
2267 rp = self.ui.warn
2268 vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
2268 vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
2269 # we must avoid cyclic reference between repo and transaction.
2269 # we must avoid cyclic reference between repo and transaction.
2270 reporef = weakref.ref(self)
2270 reporef = weakref.ref(self)
2271 # Code to track tag movement
2271 # Code to track tag movement
2272 #
2272 #
2273 # Since tags are all handled as file content, it is actually quite hard
2273 # Since tags are all handled as file content, it is actually quite hard
2274 # to track these movement from a code perspective. So we fallback to a
2274 # to track these movement from a code perspective. So we fallback to a
2275 # tracking at the repository level. One could envision to track changes
2275 # tracking at the repository level. One could envision to track changes
2276 # to the '.hgtags' file through changegroup apply but that fails to
2276 # to the '.hgtags' file through changegroup apply but that fails to
2277 # cope with case where transaction expose new heads without changegroup
2277 # cope with case where transaction expose new heads without changegroup
2278 # being involved (eg: phase movement).
2278 # being involved (eg: phase movement).
2279 #
2279 #
2280 # For now, We gate the feature behind a flag since this likely comes
2280 # For now, We gate the feature behind a flag since this likely comes
2281 # with performance impacts. The current code run more often than needed
2281 # with performance impacts. The current code run more often than needed
2282 # and do not use caches as much as it could. The current focus is on
2282 # and do not use caches as much as it could. The current focus is on
2283 # the behavior of the feature so we disable it by default. The flag
2283 # the behavior of the feature so we disable it by default. The flag
2284 # will be removed when we are happy with the performance impact.
2284 # will be removed when we are happy with the performance impact.
2285 #
2285 #
2286 # Once this feature is no longer experimental move the following
2286 # Once this feature is no longer experimental move the following
2287 # documentation to the appropriate help section:
2287 # documentation to the appropriate help section:
2288 #
2288 #
2289 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
2289 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
2290 # tags (new or changed or deleted tags). In addition the details of
2290 # tags (new or changed or deleted tags). In addition the details of
2291 # these changes are made available in a file at:
2291 # these changes are made available in a file at:
2292 # ``REPOROOT/.hg/changes/tags.changes``.
2292 # ``REPOROOT/.hg/changes/tags.changes``.
2293 # Make sure you check for HG_TAG_MOVED before reading that file as it
2293 # Make sure you check for HG_TAG_MOVED before reading that file as it
2294 # might exist from a previous transaction even if no tag were touched
2294 # might exist from a previous transaction even if no tag were touched
2295 # in this one. Changes are recorded in a line base format::
2295 # in this one. Changes are recorded in a line base format::
2296 #
2296 #
2297 # <action> <hex-node> <tag-name>\n
2297 # <action> <hex-node> <tag-name>\n
2298 #
2298 #
2299 # Actions are defined as follow:
2299 # Actions are defined as follow:
2300 # "-R": tag is removed,
2300 # "-R": tag is removed,
2301 # "+A": tag is added,
2301 # "+A": tag is added,
2302 # "-M": tag is moved (old value),
2302 # "-M": tag is moved (old value),
2303 # "+M": tag is moved (new value),
2303 # "+M": tag is moved (new value),
2304 tracktags = lambda x: None
2304 tracktags = lambda x: None
2305 # experimental config: experimental.hook-track-tags
2305 # experimental config: experimental.hook-track-tags
2306 shouldtracktags = self.ui.configbool(
2306 shouldtracktags = self.ui.configbool(
2307 b'experimental', b'hook-track-tags'
2307 b'experimental', b'hook-track-tags'
2308 )
2308 )
2309 if desc != b'strip' and shouldtracktags:
2309 if desc != b'strip' and shouldtracktags:
2310 oldheads = self.changelog.headrevs()
2310 oldheads = self.changelog.headrevs()
2311
2311
2312 def tracktags(tr2):
2312 def tracktags(tr2):
2313 repo = reporef()
2313 repo = reporef()
2314 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
2314 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
2315 newheads = repo.changelog.headrevs()
2315 newheads = repo.changelog.headrevs()
2316 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
2316 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
2317 # notes: we compare lists here.
2317 # notes: we compare lists here.
2318 # As we do it only once buiding set would not be cheaper
2318 # As we do it only once buiding set would not be cheaper
2319 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
2319 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
2320 if changes:
2320 if changes:
2321 tr2.hookargs[b'tag_moved'] = b'1'
2321 tr2.hookargs[b'tag_moved'] = b'1'
2322 with repo.vfs(
2322 with repo.vfs(
2323 b'changes/tags.changes', b'w', atomictemp=True
2323 b'changes/tags.changes', b'w', atomictemp=True
2324 ) as changesfile:
2324 ) as changesfile:
2325 # note: we do not register the file to the transaction
2325 # note: we do not register the file to the transaction
2326 # because we needs it to still exist on the transaction
2326 # because we needs it to still exist on the transaction
2327 # is close (for txnclose hooks)
2327 # is close (for txnclose hooks)
2328 tagsmod.writediff(changesfile, changes)
2328 tagsmod.writediff(changesfile, changes)
2329
2329
2330 def validate(tr2):
2330 def validate(tr2):
2331 """will run pre-closing hooks"""
2331 """will run pre-closing hooks"""
2332 # XXX the transaction API is a bit lacking here so we take a hacky
2332 # XXX the transaction API is a bit lacking here so we take a hacky
2333 # path for now
2333 # path for now
2334 #
2334 #
2335 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
2335 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
2336 # dict is copied before these run. In addition we needs the data
2336 # dict is copied before these run. In addition we needs the data
2337 # available to in memory hooks too.
2337 # available to in memory hooks too.
2338 #
2338 #
2339 # Moreover, we also need to make sure this runs before txnclose
2339 # Moreover, we also need to make sure this runs before txnclose
2340 # hooks and there is no "pending" mechanism that would execute
2340 # hooks and there is no "pending" mechanism that would execute
2341 # logic only if hooks are about to run.
2341 # logic only if hooks are about to run.
2342 #
2342 #
2343 # Fixing this limitation of the transaction is also needed to track
2343 # Fixing this limitation of the transaction is also needed to track
2344 # other families of changes (bookmarks, phases, obsolescence).
2344 # other families of changes (bookmarks, phases, obsolescence).
2345 #
2345 #
2346 # This will have to be fixed before we remove the experimental
2346 # This will have to be fixed before we remove the experimental
2347 # gating.
2347 # gating.
2348 tracktags(tr2)
2348 tracktags(tr2)
2349 repo = reporef()
2349 repo = reporef()
2350
2350
2351 singleheadopt = (b'experimental', b'single-head-per-branch')
2351 singleheadopt = (b'experimental', b'single-head-per-branch')
2352 singlehead = repo.ui.configbool(*singleheadopt)
2352 singlehead = repo.ui.configbool(*singleheadopt)
2353 if singlehead:
2353 if singlehead:
2354 singleheadsub = repo.ui.configsuboptions(*singleheadopt)[1]
2354 singleheadsub = repo.ui.configsuboptions(*singleheadopt)[1]
2355 accountclosed = singleheadsub.get(
2355 accountclosed = singleheadsub.get(
2356 b"account-closed-heads", False
2356 b"account-closed-heads", False
2357 )
2357 )
2358 if singleheadsub.get(b"public-changes-only", False):
2358 if singleheadsub.get(b"public-changes-only", False):
2359 filtername = b"immutable"
2359 filtername = b"immutable"
2360 else:
2360 else:
2361 filtername = b"visible"
2361 filtername = b"visible"
2362 scmutil.enforcesinglehead(
2362 scmutil.enforcesinglehead(
2363 repo, tr2, desc, accountclosed, filtername
2363 repo, tr2, desc, accountclosed, filtername
2364 )
2364 )
2365 if hook.hashook(repo.ui, b'pretxnclose-bookmark'):
2365 if hook.hashook(repo.ui, b'pretxnclose-bookmark'):
2366 for name, (old, new) in sorted(
2366 for name, (old, new) in sorted(
2367 tr.changes[b'bookmarks'].items()
2367 tr.changes[b'bookmarks'].items()
2368 ):
2368 ):
2369 args = tr.hookargs.copy()
2369 args = tr.hookargs.copy()
2370 args.update(bookmarks.preparehookargs(name, old, new))
2370 args.update(bookmarks.preparehookargs(name, old, new))
2371 repo.hook(
2371 repo.hook(
2372 b'pretxnclose-bookmark',
2372 b'pretxnclose-bookmark',
2373 throw=True,
2373 throw=True,
2374 **pycompat.strkwargs(args)
2374 **pycompat.strkwargs(args)
2375 )
2375 )
2376 if hook.hashook(repo.ui, b'pretxnclose-phase'):
2376 if hook.hashook(repo.ui, b'pretxnclose-phase'):
2377 cl = repo.unfiltered().changelog
2377 cl = repo.unfiltered().changelog
2378 for revs, (old, new) in tr.changes[b'phases']:
2378 for revs, (old, new) in tr.changes[b'phases']:
2379 for rev in revs:
2379 for rev in revs:
2380 args = tr.hookargs.copy()
2380 args = tr.hookargs.copy()
2381 node = hex(cl.node(rev))
2381 node = hex(cl.node(rev))
2382 args.update(phases.preparehookargs(node, old, new))
2382 args.update(phases.preparehookargs(node, old, new))
2383 repo.hook(
2383 repo.hook(
2384 b'pretxnclose-phase',
2384 b'pretxnclose-phase',
2385 throw=True,
2385 throw=True,
2386 **pycompat.strkwargs(args)
2386 **pycompat.strkwargs(args)
2387 )
2387 )
2388
2388
2389 repo.hook(
2389 repo.hook(
2390 b'pretxnclose', throw=True, **pycompat.strkwargs(tr.hookargs)
2390 b'pretxnclose', throw=True, **pycompat.strkwargs(tr.hookargs)
2391 )
2391 )
2392
2392
2393 def releasefn(tr, success):
2393 def releasefn(tr, success):
2394 repo = reporef()
2394 repo = reporef()
2395 if repo is None:
2395 if repo is None:
2396 # If the repo has been GC'd (and this release function is being
2396 # If the repo has been GC'd (and this release function is being
2397 # called from transaction.__del__), there's not much we can do,
2397 # called from transaction.__del__), there's not much we can do,
2398 # so just leave the unfinished transaction there and let the
2398 # so just leave the unfinished transaction there and let the
2399 # user run `hg recover`.
2399 # user run `hg recover`.
2400 return
2400 return
2401 if success:
2401 if success:
2402 # this should be explicitly invoked here, because
2402 # this should be explicitly invoked here, because
2403 # in-memory changes aren't written out at closing
2403 # in-memory changes aren't written out at closing
2404 # transaction, if tr.addfilegenerator (via
2404 # transaction, if tr.addfilegenerator (via
2405 # dirstate.write or so) isn't invoked while
2405 # dirstate.write or so) isn't invoked while
2406 # transaction running
2406 # transaction running
2407 repo.dirstate.write(None)
2407 repo.dirstate.write(None)
2408 else:
2408 else:
2409 # discard all changes (including ones already written
2409 # discard all changes (including ones already written
2410 # out) in this transaction
2410 # out) in this transaction
2411 narrowspec.restorebackup(self, b'journal.narrowspec')
2411 narrowspec.restorebackup(self, b'journal.narrowspec')
2412 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
2412 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
2413 repo.dirstate.restorebackup(None, b'journal.dirstate')
2413 repo.dirstate.restorebackup(None, b'journal.dirstate')
2414
2414
2415 repo.invalidate(clearfilecache=True)
2415 repo.invalidate(clearfilecache=True)
2416
2416
2417 tr = transaction.transaction(
2417 tr = transaction.transaction(
2418 rp,
2418 rp,
2419 self.svfs,
2419 self.svfs,
2420 vfsmap,
2420 vfsmap,
2421 b"journal",
2421 b"journal",
2422 b"undo",
2422 b"undo",
2423 aftertrans(renames),
2423 aftertrans(renames),
2424 self.store.createmode,
2424 self.store.createmode,
2425 validator=validate,
2425 validator=validate,
2426 releasefn=releasefn,
2426 releasefn=releasefn,
2427 checkambigfiles=_cachedfiles,
2427 checkambigfiles=_cachedfiles,
2428 name=desc,
2428 name=desc,
2429 )
2429 )
2430 tr.changes[b'origrepolen'] = len(self)
2430 tr.changes[b'origrepolen'] = len(self)
2431 tr.changes[b'obsmarkers'] = set()
2431 tr.changes[b'obsmarkers'] = set()
2432 tr.changes[b'phases'] = []
2432 tr.changes[b'phases'] = []
2433 tr.changes[b'bookmarks'] = {}
2433 tr.changes[b'bookmarks'] = {}
2434
2434
2435 tr.hookargs[b'txnid'] = txnid
2435 tr.hookargs[b'txnid'] = txnid
2436 tr.hookargs[b'txnname'] = desc
2436 tr.hookargs[b'txnname'] = desc
2437 tr.hookargs[b'changes'] = tr.changes
2437 tr.hookargs[b'changes'] = tr.changes
2438 # note: writing the fncache only during finalize mean that the file is
2438 # note: writing the fncache only during finalize mean that the file is
2439 # outdated when running hooks. As fncache is used for streaming clone,
2439 # outdated when running hooks. As fncache is used for streaming clone,
2440 # this is not expected to break anything that happen during the hooks.
2440 # this is not expected to break anything that happen during the hooks.
2441 tr.addfinalize(b'flush-fncache', self.store.write)
2441 tr.addfinalize(b'flush-fncache', self.store.write)
2442
2442
2443 def txnclosehook(tr2):
2443 def txnclosehook(tr2):
2444 """To be run if transaction is successful, will schedule a hook run"""
2444 """To be run if transaction is successful, will schedule a hook run"""
2445 # Don't reference tr2 in hook() so we don't hold a reference.
2445 # Don't reference tr2 in hook() so we don't hold a reference.
2446 # This reduces memory consumption when there are multiple
2446 # This reduces memory consumption when there are multiple
2447 # transactions per lock. This can likely go away if issue5045
2447 # transactions per lock. This can likely go away if issue5045
2448 # fixes the function accumulation.
2448 # fixes the function accumulation.
2449 hookargs = tr2.hookargs
2449 hookargs = tr2.hookargs
2450
2450
2451 def hookfunc(unused_success):
2451 def hookfunc(unused_success):
2452 repo = reporef()
2452 repo = reporef()
2453 if hook.hashook(repo.ui, b'txnclose-bookmark'):
2453 if hook.hashook(repo.ui, b'txnclose-bookmark'):
2454 bmchanges = sorted(tr.changes[b'bookmarks'].items())
2454 bmchanges = sorted(tr.changes[b'bookmarks'].items())
2455 for name, (old, new) in bmchanges:
2455 for name, (old, new) in bmchanges:
2456 args = tr.hookargs.copy()
2456 args = tr.hookargs.copy()
2457 args.update(bookmarks.preparehookargs(name, old, new))
2457 args.update(bookmarks.preparehookargs(name, old, new))
2458 repo.hook(
2458 repo.hook(
2459 b'txnclose-bookmark',
2459 b'txnclose-bookmark',
2460 throw=False,
2460 throw=False,
2461 **pycompat.strkwargs(args)
2461 **pycompat.strkwargs(args)
2462 )
2462 )
2463
2463
2464 if hook.hashook(repo.ui, b'txnclose-phase'):
2464 if hook.hashook(repo.ui, b'txnclose-phase'):
2465 cl = repo.unfiltered().changelog
2465 cl = repo.unfiltered().changelog
2466 phasemv = sorted(
2466 phasemv = sorted(
2467 tr.changes[b'phases'], key=lambda r: r[0][0]
2467 tr.changes[b'phases'], key=lambda r: r[0][0]
2468 )
2468 )
2469 for revs, (old, new) in phasemv:
2469 for revs, (old, new) in phasemv:
2470 for rev in revs:
2470 for rev in revs:
2471 args = tr.hookargs.copy()
2471 args = tr.hookargs.copy()
2472 node = hex(cl.node(rev))
2472 node = hex(cl.node(rev))
2473 args.update(phases.preparehookargs(node, old, new))
2473 args.update(phases.preparehookargs(node, old, new))
2474 repo.hook(
2474 repo.hook(
2475 b'txnclose-phase',
2475 b'txnclose-phase',
2476 throw=False,
2476 throw=False,
2477 **pycompat.strkwargs(args)
2477 **pycompat.strkwargs(args)
2478 )
2478 )
2479
2479
2480 repo.hook(
2480 repo.hook(
2481 b'txnclose', throw=False, **pycompat.strkwargs(hookargs)
2481 b'txnclose', throw=False, **pycompat.strkwargs(hookargs)
2482 )
2482 )
2483
2483
2484 reporef()._afterlock(hookfunc)
2484 reporef()._afterlock(hookfunc)
2485
2485
2486 tr.addfinalize(b'txnclose-hook', txnclosehook)
2486 tr.addfinalize(b'txnclose-hook', txnclosehook)
2487 # Include a leading "-" to make it happen before the transaction summary
2487 # Include a leading "-" to make it happen before the transaction summary
2488 # reports registered via scmutil.registersummarycallback() whose names
2488 # reports registered via scmutil.registersummarycallback() whose names
2489 # are 00-txnreport etc. That way, the caches will be warm when the
2489 # are 00-txnreport etc. That way, the caches will be warm when the
2490 # callbacks run.
2490 # callbacks run.
2491 tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr))
2491 tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr))
2492
2492
2493 def txnaborthook(tr2):
2493 def txnaborthook(tr2):
2494 """To be run if transaction is aborted"""
2494 """To be run if transaction is aborted"""
2495 reporef().hook(
2495 reporef().hook(
2496 b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs)
2496 b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs)
2497 )
2497 )
2498
2498
2499 tr.addabort(b'txnabort-hook', txnaborthook)
2499 tr.addabort(b'txnabort-hook', txnaborthook)
2500 # avoid eager cache invalidation. in-memory data should be identical
2500 # avoid eager cache invalidation. in-memory data should be identical
2501 # to stored data if transaction has no error.
2501 # to stored data if transaction has no error.
2502 tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats)
2502 tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats)
2503 self._transref = weakref.ref(tr)
2503 self._transref = weakref.ref(tr)
2504 scmutil.registersummarycallback(self, tr, desc)
2504 scmutil.registersummarycallback(self, tr, desc)
2505 return tr
2505 return tr
2506
2506
2507 def _journalfiles(self):
2507 def _journalfiles(self):
2508 return (
2508 return (
2509 (self.svfs, b'journal'),
2509 (self.svfs, b'journal'),
2510 (self.svfs, b'journal.narrowspec'),
2510 (self.svfs, b'journal.narrowspec'),
2511 (self.vfs, b'journal.narrowspec.dirstate'),
2511 (self.vfs, b'journal.narrowspec.dirstate'),
2512 (self.vfs, b'journal.dirstate'),
2512 (self.vfs, b'journal.dirstate'),
2513 (self.vfs, b'journal.branch'),
2513 (self.vfs, b'journal.branch'),
2514 (self.vfs, b'journal.desc'),
2514 (self.vfs, b'journal.desc'),
2515 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
2515 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
2516 (self.svfs, b'journal.phaseroots'),
2516 (self.svfs, b'journal.phaseroots'),
2517 )
2517 )
2518
2518
2519 def undofiles(self):
2519 def undofiles(self):
2520 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
2520 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
2521
2521
2522 @unfilteredmethod
2522 @unfilteredmethod
2523 def _writejournal(self, desc):
2523 def _writejournal(self, desc):
2524 self.dirstate.savebackup(None, b'journal.dirstate')
2524 self.dirstate.savebackup(None, b'journal.dirstate')
2525 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
2525 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
2526 narrowspec.savebackup(self, b'journal.narrowspec')
2526 narrowspec.savebackup(self, b'journal.narrowspec')
2527 self.vfs.write(
2527 self.vfs.write(
2528 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
2528 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
2529 )
2529 )
2530 self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
2530 self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
2531 bookmarksvfs = bookmarks.bookmarksvfs(self)
2531 bookmarksvfs = bookmarks.bookmarksvfs(self)
2532 bookmarksvfs.write(
2532 bookmarksvfs.write(
2533 b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks")
2533 b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks")
2534 )
2534 )
2535 self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots"))
2535 self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots"))
2536
2536
2537 def recover(self):
2537 def recover(self):
2538 with self.lock():
2538 with self.lock():
2539 if self.svfs.exists(b"journal"):
2539 if self.svfs.exists(b"journal"):
2540 self.ui.status(_(b"rolling back interrupted transaction\n"))
2540 self.ui.status(_(b"rolling back interrupted transaction\n"))
2541 vfsmap = {
2541 vfsmap = {
2542 b'': self.svfs,
2542 b'': self.svfs,
2543 b'plain': self.vfs,
2543 b'plain': self.vfs,
2544 }
2544 }
2545 transaction.rollback(
2545 transaction.rollback(
2546 self.svfs,
2546 self.svfs,
2547 vfsmap,
2547 vfsmap,
2548 b"journal",
2548 b"journal",
2549 self.ui.warn,
2549 self.ui.warn,
2550 checkambigfiles=_cachedfiles,
2550 checkambigfiles=_cachedfiles,
2551 )
2551 )
2552 self.invalidate()
2552 self.invalidate()
2553 return True
2553 return True
2554 else:
2554 else:
2555 self.ui.warn(_(b"no interrupted transaction available\n"))
2555 self.ui.warn(_(b"no interrupted transaction available\n"))
2556 return False
2556 return False
2557
2557
2558 def rollback(self, dryrun=False, force=False):
2558 def rollback(self, dryrun=False, force=False):
2559 wlock = lock = dsguard = None
2559 wlock = lock = dsguard = None
2560 try:
2560 try:
2561 wlock = self.wlock()
2561 wlock = self.wlock()
2562 lock = self.lock()
2562 lock = self.lock()
2563 if self.svfs.exists(b"undo"):
2563 if self.svfs.exists(b"undo"):
2564 dsguard = dirstateguard.dirstateguard(self, b'rollback')
2564 dsguard = dirstateguard.dirstateguard(self, b'rollback')
2565
2565
2566 return self._rollback(dryrun, force, dsguard)
2566 return self._rollback(dryrun, force, dsguard)
2567 else:
2567 else:
2568 self.ui.warn(_(b"no rollback information available\n"))
2568 self.ui.warn(_(b"no rollback information available\n"))
2569 return 1
2569 return 1
2570 finally:
2570 finally:
2571 release(dsguard, lock, wlock)
2571 release(dsguard, lock, wlock)
2572
2572
2573 @unfilteredmethod # Until we get smarter cache management
2573 @unfilteredmethod # Until we get smarter cache management
2574 def _rollback(self, dryrun, force, dsguard):
2574 def _rollback(self, dryrun, force, dsguard):
2575 ui = self.ui
2575 ui = self.ui
2576 try:
2576 try:
2577 args = self.vfs.read(b'undo.desc').splitlines()
2577 args = self.vfs.read(b'undo.desc').splitlines()
2578 (oldlen, desc, detail) = (int(args[0]), args[1], None)
2578 (oldlen, desc, detail) = (int(args[0]), args[1], None)
2579 if len(args) >= 3:
2579 if len(args) >= 3:
2580 detail = args[2]
2580 detail = args[2]
2581 oldtip = oldlen - 1
2581 oldtip = oldlen - 1
2582
2582
2583 if detail and ui.verbose:
2583 if detail and ui.verbose:
2584 msg = _(
2584 msg = _(
2585 b'repository tip rolled back to revision %d'
2585 b'repository tip rolled back to revision %d'
2586 b' (undo %s: %s)\n'
2586 b' (undo %s: %s)\n'
2587 ) % (oldtip, desc, detail)
2587 ) % (oldtip, desc, detail)
2588 else:
2588 else:
2589 msg = _(
2589 msg = _(
2590 b'repository tip rolled back to revision %d (undo %s)\n'
2590 b'repository tip rolled back to revision %d (undo %s)\n'
2591 ) % (oldtip, desc)
2591 ) % (oldtip, desc)
2592 except IOError:
2592 except IOError:
2593 msg = _(b'rolling back unknown transaction\n')
2593 msg = _(b'rolling back unknown transaction\n')
2594 desc = None
2594 desc = None
2595
2595
2596 if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
2596 if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
2597 raise error.Abort(
2597 raise error.Abort(
2598 _(
2598 _(
2599 b'rollback of last commit while not checked out '
2599 b'rollback of last commit while not checked out '
2600 b'may lose data'
2600 b'may lose data'
2601 ),
2601 ),
2602 hint=_(b'use -f to force'),
2602 hint=_(b'use -f to force'),
2603 )
2603 )
2604
2604
2605 ui.status(msg)
2605 ui.status(msg)
2606 if dryrun:
2606 if dryrun:
2607 return 0
2607 return 0
2608
2608
2609 parents = self.dirstate.parents()
2609 parents = self.dirstate.parents()
2610 self.destroying()
2610 self.destroying()
2611 vfsmap = {b'plain': self.vfs, b'': self.svfs}
2611 vfsmap = {b'plain': self.vfs, b'': self.svfs}
2612 transaction.rollback(
2612 transaction.rollback(
2613 self.svfs, vfsmap, b'undo', ui.warn, checkambigfiles=_cachedfiles
2613 self.svfs, vfsmap, b'undo', ui.warn, checkambigfiles=_cachedfiles
2614 )
2614 )
2615 bookmarksvfs = bookmarks.bookmarksvfs(self)
2615 bookmarksvfs = bookmarks.bookmarksvfs(self)
2616 if bookmarksvfs.exists(b'undo.bookmarks'):
2616 if bookmarksvfs.exists(b'undo.bookmarks'):
2617 bookmarksvfs.rename(
2617 bookmarksvfs.rename(
2618 b'undo.bookmarks', b'bookmarks', checkambig=True
2618 b'undo.bookmarks', b'bookmarks', checkambig=True
2619 )
2619 )
2620 if self.svfs.exists(b'undo.phaseroots'):
2620 if self.svfs.exists(b'undo.phaseroots'):
2621 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
2621 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
2622 self.invalidate()
2622 self.invalidate()
2623
2623
2624 has_node = self.changelog.index.has_node
2624 has_node = self.changelog.index.has_node
2625 parentgone = any(not has_node(p) for p in parents)
2625 parentgone = any(not has_node(p) for p in parents)
2626 if parentgone:
2626 if parentgone:
2627 # prevent dirstateguard from overwriting already restored one
2627 # prevent dirstateguard from overwriting already restored one
2628 dsguard.close()
2628 dsguard.close()
2629
2629
2630 narrowspec.restorebackup(self, b'undo.narrowspec')
2630 narrowspec.restorebackup(self, b'undo.narrowspec')
2631 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
2631 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
2632 self.dirstate.restorebackup(None, b'undo.dirstate')
2632 self.dirstate.restorebackup(None, b'undo.dirstate')
2633 try:
2633 try:
2634 branch = self.vfs.read(b'undo.branch')
2634 branch = self.vfs.read(b'undo.branch')
2635 self.dirstate.setbranch(encoding.tolocal(branch))
2635 self.dirstate.setbranch(encoding.tolocal(branch))
2636 except IOError:
2636 except IOError:
2637 ui.warn(
2637 ui.warn(
2638 _(
2638 _(
2639 b'named branch could not be reset: '
2639 b'named branch could not be reset: '
2640 b'current branch is still \'%s\'\n'
2640 b'current branch is still \'%s\'\n'
2641 )
2641 )
2642 % self.dirstate.branch()
2642 % self.dirstate.branch()
2643 )
2643 )
2644
2644
2645 parents = tuple([p.rev() for p in self[None].parents()])
2645 parents = tuple([p.rev() for p in self[None].parents()])
2646 if len(parents) > 1:
2646 if len(parents) > 1:
2647 ui.status(
2647 ui.status(
2648 _(
2648 _(
2649 b'working directory now based on '
2649 b'working directory now based on '
2650 b'revisions %d and %d\n'
2650 b'revisions %d and %d\n'
2651 )
2651 )
2652 % parents
2652 % parents
2653 )
2653 )
2654 else:
2654 else:
2655 ui.status(
2655 ui.status(
2656 _(b'working directory now based on revision %d\n') % parents
2656 _(b'working directory now based on revision %d\n') % parents
2657 )
2657 )
2658 mergestatemod.mergestate.clean(self)
2658 mergestatemod.mergestate.clean(self)
2659
2659
2660 # TODO: if we know which new heads may result from this rollback, pass
2660 # TODO: if we know which new heads may result from this rollback, pass
2661 # them to destroy(), which will prevent the branchhead cache from being
2661 # them to destroy(), which will prevent the branchhead cache from being
2662 # invalidated.
2662 # invalidated.
2663 self.destroyed()
2663 self.destroyed()
2664 return 0
2664 return 0
2665
2665
2666 def _buildcacheupdater(self, newtransaction):
2666 def _buildcacheupdater(self, newtransaction):
2667 """called during transaction to build the callback updating cache
2667 """called during transaction to build the callback updating cache
2668
2668
2669 Lives on the repository to help extension who might want to augment
2669 Lives on the repository to help extension who might want to augment
2670 this logic. For this purpose, the created transaction is passed to the
2670 this logic. For this purpose, the created transaction is passed to the
2671 method.
2671 method.
2672 """
2672 """
2673 # we must avoid cyclic reference between repo and transaction.
2673 # we must avoid cyclic reference between repo and transaction.
2674 reporef = weakref.ref(self)
2674 reporef = weakref.ref(self)
2675
2675
2676 def updater(tr):
2676 def updater(tr):
2677 repo = reporef()
2677 repo = reporef()
2678 repo.updatecaches(tr)
2678 repo.updatecaches(tr)
2679
2679
2680 return updater
2680 return updater
2681
2681
2682 @unfilteredmethod
2682 @unfilteredmethod
2683 def updatecaches(self, tr=None, full=False):
2683 def updatecaches(self, tr=None, full=False):
2684 """warm appropriate caches
2684 """warm appropriate caches
2685
2685
2686 If this function is called after a transaction closed. The transaction
2686 If this function is called after a transaction closed. The transaction
2687 will be available in the 'tr' argument. This can be used to selectively
2687 will be available in the 'tr' argument. This can be used to selectively
2688 update caches relevant to the changes in that transaction.
2688 update caches relevant to the changes in that transaction.
2689
2689
2690 If 'full' is set, make sure all caches the function knows about have
2690 If 'full' is set, make sure all caches the function knows about have
2691 up-to-date data. Even the ones usually loaded more lazily.
2691 up-to-date data. Even the ones usually loaded more lazily.
2692 """
2692 """
2693 if tr is not None and tr.hookargs.get(b'source') == b'strip':
2693 if tr is not None and tr.hookargs.get(b'source') == b'strip':
2694 # During strip, many caches are invalid but
2694 # During strip, many caches are invalid but
2695 # later call to `destroyed` will refresh them.
2695 # later call to `destroyed` will refresh them.
2696 return
2696 return
2697
2697
2698 if tr is None or tr.changes[b'origrepolen'] < len(self):
2698 if tr is None or tr.changes[b'origrepolen'] < len(self):
2699 # accessing the 'served' branchmap should refresh all the others,
2699 # accessing the 'served' branchmap should refresh all the others,
2700 self.ui.debug(b'updating the branch cache\n')
2700 self.ui.debug(b'updating the branch cache\n')
2701 self.filtered(b'served').branchmap()
2701 self.filtered(b'served').branchmap()
2702 self.filtered(b'served.hidden').branchmap()
2702 self.filtered(b'served.hidden').branchmap()
2703
2703
2704 if full:
2704 if full:
2705 unfi = self.unfiltered()
2705 unfi = self.unfiltered()
2706
2706
2707 self.changelog.update_caches(transaction=tr)
2707 self.changelog.update_caches(transaction=tr)
2708 self.manifestlog.update_caches(transaction=tr)
2708 self.manifestlog.update_caches(transaction=tr)
2709
2709
2710 rbc = unfi.revbranchcache()
2710 rbc = unfi.revbranchcache()
2711 for r in unfi.changelog:
2711 for r in unfi.changelog:
2712 rbc.branchinfo(r)
2712 rbc.branchinfo(r)
2713 rbc.write()
2713 rbc.write()
2714
2714
2715 # ensure the working copy parents are in the manifestfulltextcache
2715 # ensure the working copy parents are in the manifestfulltextcache
2716 for ctx in self[b'.'].parents():
2716 for ctx in self[b'.'].parents():
2717 ctx.manifest() # accessing the manifest is enough
2717 ctx.manifest() # accessing the manifest is enough
2718
2718
2719 # accessing fnode cache warms the cache
2719 # accessing fnode cache warms the cache
2720 tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
2720 tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
2721 # accessing tags warm the cache
2721 # accessing tags warm the cache
2722 self.tags()
2722 self.tags()
2723 self.filtered(b'served').tags()
2723 self.filtered(b'served').tags()
2724
2724
2725 # The `full` arg is documented as updating even the lazily-loaded
2725 # The `full` arg is documented as updating even the lazily-loaded
2726 # caches immediately, so we're forcing a write to cause these caches
2726 # caches immediately, so we're forcing a write to cause these caches
2727 # to be warmed up even if they haven't explicitly been requested
2727 # to be warmed up even if they haven't explicitly been requested
2728 # yet (if they've never been used by hg, they won't ever have been
2728 # yet (if they've never been used by hg, they won't ever have been
2729 # written, even if they're a subset of another kind of cache that
2729 # written, even if they're a subset of another kind of cache that
2730 # *has* been used).
2730 # *has* been used).
2731 for filt in repoview.filtertable.keys():
2731 for filt in repoview.filtertable.keys():
2732 filtered = self.filtered(filt)
2732 filtered = self.filtered(filt)
2733 filtered.branchmap().write(filtered)
2733 filtered.branchmap().write(filtered)
2734
2734
2735 def invalidatecaches(self):
2735 def invalidatecaches(self):
2736
2736
2737 if '_tagscache' in vars(self):
2737 if '_tagscache' in vars(self):
2738 # can't use delattr on proxy
2738 # can't use delattr on proxy
2739 del self.__dict__['_tagscache']
2739 del self.__dict__['_tagscache']
2740
2740
2741 self._branchcaches.clear()
2741 self._branchcaches.clear()
2742 self.invalidatevolatilesets()
2742 self.invalidatevolatilesets()
2743 self._sparsesignaturecache.clear()
2743 self._sparsesignaturecache.clear()
2744
2744
2745 def invalidatevolatilesets(self):
2745 def invalidatevolatilesets(self):
2746 self.filteredrevcache.clear()
2746 self.filteredrevcache.clear()
2747 obsolete.clearobscaches(self)
2747 obsolete.clearobscaches(self)
2748 self._quick_access_changeid_invalidate()
2748 self._quick_access_changeid_invalidate()
2749
2749
2750 def invalidatedirstate(self):
2750 def invalidatedirstate(self):
2751 """Invalidates the dirstate, causing the next call to dirstate
2751 """Invalidates the dirstate, causing the next call to dirstate
2752 to check if it was modified since the last time it was read,
2752 to check if it was modified since the last time it was read,
2753 rereading it if it has.
2753 rereading it if it has.
2754
2754
2755 This is different to dirstate.invalidate() that it doesn't always
2755 This is different to dirstate.invalidate() that it doesn't always
2756 rereads the dirstate. Use dirstate.invalidate() if you want to
2756 rereads the dirstate. Use dirstate.invalidate() if you want to
2757 explicitly read the dirstate again (i.e. restoring it to a previous
2757 explicitly read the dirstate again (i.e. restoring it to a previous
2758 known good state)."""
2758 known good state)."""
2759 if hasunfilteredcache(self, 'dirstate'):
2759 if hasunfilteredcache(self, 'dirstate'):
2760 for k in self.dirstate._filecache:
2760 for k in self.dirstate._filecache:
2761 try:
2761 try:
2762 delattr(self.dirstate, k)
2762 delattr(self.dirstate, k)
2763 except AttributeError:
2763 except AttributeError:
2764 pass
2764 pass
2765 delattr(self.unfiltered(), 'dirstate')
2765 delattr(self.unfiltered(), 'dirstate')
2766
2766
2767 def invalidate(self, clearfilecache=False):
2767 def invalidate(self, clearfilecache=False):
2768 """Invalidates both store and non-store parts other than dirstate
2768 """Invalidates both store and non-store parts other than dirstate
2769
2769
2770 If a transaction is running, invalidation of store is omitted,
2770 If a transaction is running, invalidation of store is omitted,
2771 because discarding in-memory changes might cause inconsistency
2771 because discarding in-memory changes might cause inconsistency
2772 (e.g. incomplete fncache causes unintentional failure, but
2772 (e.g. incomplete fncache causes unintentional failure, but
2773 redundant one doesn't).
2773 redundant one doesn't).
2774 """
2774 """
2775 unfiltered = self.unfiltered() # all file caches are stored unfiltered
2775 unfiltered = self.unfiltered() # all file caches are stored unfiltered
2776 for k in list(self._filecache.keys()):
2776 for k in list(self._filecache.keys()):
2777 # dirstate is invalidated separately in invalidatedirstate()
2777 # dirstate is invalidated separately in invalidatedirstate()
2778 if k == b'dirstate':
2778 if k == b'dirstate':
2779 continue
2779 continue
2780 if (
2780 if (
2781 k == b'changelog'
2781 k == b'changelog'
2782 and self.currenttransaction()
2782 and self.currenttransaction()
2783 and self.changelog._delayed
2783 and self.changelog._delayed
2784 ):
2784 ):
2785 # The changelog object may store unwritten revisions. We don't
2785 # The changelog object may store unwritten revisions. We don't
2786 # want to lose them.
2786 # want to lose them.
2787 # TODO: Solve the problem instead of working around it.
2787 # TODO: Solve the problem instead of working around it.
2788 continue
2788 continue
2789
2789
2790 if clearfilecache:
2790 if clearfilecache:
2791 del self._filecache[k]
2791 del self._filecache[k]
2792 try:
2792 try:
2793 delattr(unfiltered, k)
2793 delattr(unfiltered, k)
2794 except AttributeError:
2794 except AttributeError:
2795 pass
2795 pass
2796 self.invalidatecaches()
2796 self.invalidatecaches()
2797 if not self.currenttransaction():
2797 if not self.currenttransaction():
2798 # TODO: Changing contents of store outside transaction
2798 # TODO: Changing contents of store outside transaction
2799 # causes inconsistency. We should make in-memory store
2799 # causes inconsistency. We should make in-memory store
2800 # changes detectable, and abort if changed.
2800 # changes detectable, and abort if changed.
2801 self.store.invalidatecaches()
2801 self.store.invalidatecaches()
2802
2802
2803 def invalidateall(self):
2803 def invalidateall(self):
2804 """Fully invalidates both store and non-store parts, causing the
2804 """Fully invalidates both store and non-store parts, causing the
2805 subsequent operation to reread any outside changes."""
2805 subsequent operation to reread any outside changes."""
2806 # extension should hook this to invalidate its caches
2806 # extension should hook this to invalidate its caches
2807 self.invalidate()
2807 self.invalidate()
2808 self.invalidatedirstate()
2808 self.invalidatedirstate()
2809
2809
2810 @unfilteredmethod
2810 @unfilteredmethod
2811 def _refreshfilecachestats(self, tr):
2811 def _refreshfilecachestats(self, tr):
2812 """Reload stats of cached files so that they are flagged as valid"""
2812 """Reload stats of cached files so that they are flagged as valid"""
2813 for k, ce in self._filecache.items():
2813 for k, ce in self._filecache.items():
2814 k = pycompat.sysstr(k)
2814 k = pycompat.sysstr(k)
2815 if k == 'dirstate' or k not in self.__dict__:
2815 if k == 'dirstate' or k not in self.__dict__:
2816 continue
2816 continue
2817 ce.refresh()
2817 ce.refresh()
2818
2818
2819 def _lock(
2819 def _lock(
2820 self,
2820 self,
2821 vfs,
2821 vfs,
2822 lockname,
2822 lockname,
2823 wait,
2823 wait,
2824 releasefn,
2824 releasefn,
2825 acquirefn,
2825 acquirefn,
2826 desc,
2826 desc,
2827 ):
2827 ):
2828 timeout = 0
2828 timeout = 0
2829 warntimeout = 0
2829 warntimeout = 0
2830 if wait:
2830 if wait:
2831 timeout = self.ui.configint(b"ui", b"timeout")
2831 timeout = self.ui.configint(b"ui", b"timeout")
2832 warntimeout = self.ui.configint(b"ui", b"timeout.warn")
2832 warntimeout = self.ui.configint(b"ui", b"timeout.warn")
2833 # internal config: ui.signal-safe-lock
2833 # internal config: ui.signal-safe-lock
2834 signalsafe = self.ui.configbool(b'ui', b'signal-safe-lock')
2834 signalsafe = self.ui.configbool(b'ui', b'signal-safe-lock')
2835
2835
2836 l = lockmod.trylock(
2836 l = lockmod.trylock(
2837 self.ui,
2837 self.ui,
2838 vfs,
2838 vfs,
2839 lockname,
2839 lockname,
2840 timeout,
2840 timeout,
2841 warntimeout,
2841 warntimeout,
2842 releasefn=releasefn,
2842 releasefn=releasefn,
2843 acquirefn=acquirefn,
2843 acquirefn=acquirefn,
2844 desc=desc,
2844 desc=desc,
2845 signalsafe=signalsafe,
2845 signalsafe=signalsafe,
2846 )
2846 )
2847 return l
2847 return l
2848
2848
2849 def _afterlock(self, callback):
2849 def _afterlock(self, callback):
2850 """add a callback to be run when the repository is fully unlocked
2850 """add a callback to be run when the repository is fully unlocked
2851
2851
2852 The callback will be executed when the outermost lock is released
2852 The callback will be executed when the outermost lock is released
2853 (with wlock being higher level than 'lock')."""
2853 (with wlock being higher level than 'lock')."""
2854 for ref in (self._wlockref, self._lockref):
2854 for ref in (self._wlockref, self._lockref):
2855 l = ref and ref()
2855 l = ref and ref()
2856 if l and l.held:
2856 if l and l.held:
2857 l.postrelease.append(callback)
2857 l.postrelease.append(callback)
2858 break
2858 break
2859 else: # no lock have been found.
2859 else: # no lock have been found.
2860 callback(True)
2860 callback(True)
2861
2861
2862 def lock(self, wait=True):
2862 def lock(self, wait=True):
2863 """Lock the repository store (.hg/store) and return a weak reference
2863 """Lock the repository store (.hg/store) and return a weak reference
2864 to the lock. Use this before modifying the store (e.g. committing or
2864 to the lock. Use this before modifying the store (e.g. committing or
2865 stripping). If you are opening a transaction, get a lock as well.)
2865 stripping). If you are opening a transaction, get a lock as well.)
2866
2866
2867 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2867 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2868 'wlock' first to avoid a dead-lock hazard."""
2868 'wlock' first to avoid a dead-lock hazard."""
2869 l = self._currentlock(self._lockref)
2869 l = self._currentlock(self._lockref)
2870 if l is not None:
2870 if l is not None:
2871 l.lock()
2871 l.lock()
2872 return l
2872 return l
2873
2873
2874 l = self._lock(
2874 l = self._lock(
2875 vfs=self.svfs,
2875 vfs=self.svfs,
2876 lockname=b"lock",
2876 lockname=b"lock",
2877 wait=wait,
2877 wait=wait,
2878 releasefn=None,
2878 releasefn=None,
2879 acquirefn=self.invalidate,
2879 acquirefn=self.invalidate,
2880 desc=_(b'repository %s') % self.origroot,
2880 desc=_(b'repository %s') % self.origroot,
2881 )
2881 )
2882 self._lockref = weakref.ref(l)
2882 self._lockref = weakref.ref(l)
2883 return l
2883 return l
2884
2884
2885 def wlock(self, wait=True):
2885 def wlock(self, wait=True):
2886 """Lock the non-store parts of the repository (everything under
2886 """Lock the non-store parts of the repository (everything under
2887 .hg except .hg/store) and return a weak reference to the lock.
2887 .hg except .hg/store) and return a weak reference to the lock.
2888
2888
2889 Use this before modifying files in .hg.
2889 Use this before modifying files in .hg.
2890
2890
2891 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2891 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2892 'wlock' first to avoid a dead-lock hazard."""
2892 'wlock' first to avoid a dead-lock hazard."""
2893 l = self._wlockref and self._wlockref()
2893 l = self._wlockref and self._wlockref()
2894 if l is not None and l.held:
2894 if l is not None and l.held:
2895 l.lock()
2895 l.lock()
2896 return l
2896 return l
2897
2897
2898 # We do not need to check for non-waiting lock acquisition. Such
2898 # We do not need to check for non-waiting lock acquisition. Such
2899 # acquisition would not cause dead-lock as they would just fail.
2899 # acquisition would not cause dead-lock as they would just fail.
2900 if wait and (
2900 if wait and (
2901 self.ui.configbool(b'devel', b'all-warnings')
2901 self.ui.configbool(b'devel', b'all-warnings')
2902 or self.ui.configbool(b'devel', b'check-locks')
2902 or self.ui.configbool(b'devel', b'check-locks')
2903 ):
2903 ):
2904 if self._currentlock(self._lockref) is not None:
2904 if self._currentlock(self._lockref) is not None:
2905 self.ui.develwarn(b'"wlock" acquired after "lock"')
2905 self.ui.develwarn(b'"wlock" acquired after "lock"')
2906
2906
2907 def unlock():
2907 def unlock():
2908 if self.dirstate.pendingparentchange():
2908 if self.dirstate.pendingparentchange():
2909 self.dirstate.invalidate()
2909 self.dirstate.invalidate()
2910 else:
2910 else:
2911 self.dirstate.write(None)
2911 self.dirstate.write(None)
2912
2912
2913 self._filecache[b'dirstate'].refresh()
2913 self._filecache[b'dirstate'].refresh()
2914
2914
2915 l = self._lock(
2915 l = self._lock(
2916 self.vfs,
2916 self.vfs,
2917 b"wlock",
2917 b"wlock",
2918 wait,
2918 wait,
2919 unlock,
2919 unlock,
2920 self.invalidatedirstate,
2920 self.invalidatedirstate,
2921 _(b'working directory of %s') % self.origroot,
2921 _(b'working directory of %s') % self.origroot,
2922 )
2922 )
2923 self._wlockref = weakref.ref(l)
2923 self._wlockref = weakref.ref(l)
2924 return l
2924 return l
2925
2925
2926 def _currentlock(self, lockref):
2926 def _currentlock(self, lockref):
2927 """Returns the lock if it's held, or None if it's not."""
2927 """Returns the lock if it's held, or None if it's not."""
2928 if lockref is None:
2928 if lockref is None:
2929 return None
2929 return None
2930 l = lockref()
2930 l = lockref()
2931 if l is None or not l.held:
2931 if l is None or not l.held:
2932 return None
2932 return None
2933 return l
2933 return l
2934
2934
2935 def currentwlock(self):
2935 def currentwlock(self):
2936 """Returns the wlock if it's held, or None if it's not."""
2936 """Returns the wlock if it's held, or None if it's not."""
2937 return self._currentlock(self._wlockref)
2937 return self._currentlock(self._wlockref)
2938
2938
2939 def checkcommitpatterns(self, wctx, match, status, fail):
2939 def checkcommitpatterns(self, wctx, match, status, fail):
2940 """check for commit arguments that aren't committable"""
2940 """check for commit arguments that aren't committable"""
2941 if match.isexact() or match.prefix():
2941 if match.isexact() or match.prefix():
2942 matched = set(status.modified + status.added + status.removed)
2942 matched = set(status.modified + status.added + status.removed)
2943
2943
2944 for f in match.files():
2944 for f in match.files():
2945 f = self.dirstate.normalize(f)
2945 f = self.dirstate.normalize(f)
2946 if f == b'.' or f in matched or f in wctx.substate:
2946 if f == b'.' or f in matched or f in wctx.substate:
2947 continue
2947 continue
2948 if f in status.deleted:
2948 if f in status.deleted:
2949 fail(f, _(b'file not found!'))
2949 fail(f, _(b'file not found!'))
2950 # Is it a directory that exists or used to exist?
2950 # Is it a directory that exists or used to exist?
2951 if self.wvfs.isdir(f) or wctx.p1().hasdir(f):
2951 if self.wvfs.isdir(f) or wctx.p1().hasdir(f):
2952 d = f + b'/'
2952 d = f + b'/'
2953 for mf in matched:
2953 for mf in matched:
2954 if mf.startswith(d):
2954 if mf.startswith(d):
2955 break
2955 break
2956 else:
2956 else:
2957 fail(f, _(b"no match under directory!"))
2957 fail(f, _(b"no match under directory!"))
2958 elif f not in self.dirstate:
2958 elif f not in self.dirstate:
2959 fail(f, _(b"file not tracked!"))
2959 fail(f, _(b"file not tracked!"))
2960
2960
2961 @unfilteredmethod
2961 @unfilteredmethod
2962 def commit(
2962 def commit(
2963 self,
2963 self,
2964 text=b"",
2964 text=b"",
2965 user=None,
2965 user=None,
2966 date=None,
2966 date=None,
2967 match=None,
2967 match=None,
2968 force=False,
2968 force=False,
2969 editor=None,
2969 editor=None,
2970 extra=None,
2970 extra=None,
2971 ):
2971 ):
2972 """Add a new revision to current repository.
2972 """Add a new revision to current repository.
2973
2973
2974 Revision information is gathered from the working directory,
2974 Revision information is gathered from the working directory,
2975 match can be used to filter the committed files. If editor is
2975 match can be used to filter the committed files. If editor is
2976 supplied, it is called to get a commit message.
2976 supplied, it is called to get a commit message.
2977 """
2977 """
2978 if extra is None:
2978 if extra is None:
2979 extra = {}
2979 extra = {}
2980
2980
2981 def fail(f, msg):
2981 def fail(f, msg):
2982 raise error.InputError(b'%s: %s' % (f, msg))
2982 raise error.InputError(b'%s: %s' % (f, msg))
2983
2983
2984 if not match:
2984 if not match:
2985 match = matchmod.always()
2985 match = matchmod.always()
2986
2986
2987 if not force:
2987 if not force:
2988 match.bad = fail
2988 match.bad = fail
2989
2989
2990 # lock() for recent changelog (see issue4368)
2990 # lock() for recent changelog (see issue4368)
2991 with self.wlock(), self.lock():
2991 with self.wlock(), self.lock():
2992 wctx = self[None]
2992 wctx = self[None]
2993 merge = len(wctx.parents()) > 1
2993 merge = len(wctx.parents()) > 1
2994
2994
2995 if not force and merge and not match.always():
2995 if not force and merge and not match.always():
2996 raise error.Abort(
2996 raise error.Abort(
2997 _(
2997 _(
2998 b'cannot partially commit a merge '
2998 b'cannot partially commit a merge '
2999 b'(do not specify files or patterns)'
2999 b'(do not specify files or patterns)'
3000 )
3000 )
3001 )
3001 )
3002
3002
3003 status = self.status(match=match, clean=force)
3003 status = self.status(match=match, clean=force)
3004 if force:
3004 if force:
3005 status.modified.extend(
3005 status.modified.extend(
3006 status.clean
3006 status.clean
3007 ) # mq may commit clean files
3007 ) # mq may commit clean files
3008
3008
3009 # check subrepos
3009 # check subrepos
3010 subs, commitsubs, newstate = subrepoutil.precommit(
3010 subs, commitsubs, newstate = subrepoutil.precommit(
3011 self.ui, wctx, status, match, force=force
3011 self.ui, wctx, status, match, force=force
3012 )
3012 )
3013
3013
3014 # make sure all explicit patterns are matched
3014 # make sure all explicit patterns are matched
3015 if not force:
3015 if not force:
3016 self.checkcommitpatterns(wctx, match, status, fail)
3016 self.checkcommitpatterns(wctx, match, status, fail)
3017
3017
3018 cctx = context.workingcommitctx(
3018 cctx = context.workingcommitctx(
3019 self, status, text, user, date, extra
3019 self, status, text, user, date, extra
3020 )
3020 )
3021
3021
3022 ms = mergestatemod.mergestate.read(self)
3022 ms = mergestatemod.mergestate.read(self)
3023 mergeutil.checkunresolved(ms)
3023 mergeutil.checkunresolved(ms)
3024
3024
3025 # internal config: ui.allowemptycommit
3025 # internal config: ui.allowemptycommit
3026 if cctx.isempty() and not self.ui.configbool(
3026 if cctx.isempty() and not self.ui.configbool(
3027 b'ui', b'allowemptycommit'
3027 b'ui', b'allowemptycommit'
3028 ):
3028 ):
3029 self.ui.debug(b'nothing to commit, clearing merge state\n')
3029 self.ui.debug(b'nothing to commit, clearing merge state\n')
3030 ms.reset()
3030 ms.reset()
3031 return None
3031 return None
3032
3032
3033 if merge and cctx.deleted():
3033 if merge and cctx.deleted():
3034 raise error.Abort(_(b"cannot commit merge with missing files"))
3034 raise error.Abort(_(b"cannot commit merge with missing files"))
3035
3035
3036 if editor:
3036 if editor:
3037 cctx._text = editor(self, cctx, subs)
3037 cctx._text = editor(self, cctx, subs)
3038 edited = text != cctx._text
3038 edited = text != cctx._text
3039
3039
3040 # Save commit message in case this transaction gets rolled back
3040 # Save commit message in case this transaction gets rolled back
3041 # (e.g. by a pretxncommit hook). Leave the content alone on
3041 # (e.g. by a pretxncommit hook). Leave the content alone on
3042 # the assumption that the user will use the same editor again.
3042 # the assumption that the user will use the same editor again.
3043 msgfn = self.savecommitmessage(cctx._text)
3043 msgfn = self.savecommitmessage(cctx._text)
3044
3044
3045 # commit subs and write new state
3045 # commit subs and write new state
3046 if subs:
3046 if subs:
3047 uipathfn = scmutil.getuipathfn(self)
3047 uipathfn = scmutil.getuipathfn(self)
3048 for s in sorted(commitsubs):
3048 for s in sorted(commitsubs):
3049 sub = wctx.sub(s)
3049 sub = wctx.sub(s)
3050 self.ui.status(
3050 self.ui.status(
3051 _(b'committing subrepository %s\n')
3051 _(b'committing subrepository %s\n')
3052 % uipathfn(subrepoutil.subrelpath(sub))
3052 % uipathfn(subrepoutil.subrelpath(sub))
3053 )
3053 )
3054 sr = sub.commit(cctx._text, user, date)
3054 sr = sub.commit(cctx._text, user, date)
3055 newstate[s] = (newstate[s][0], sr)
3055 newstate[s] = (newstate[s][0], sr)
3056 subrepoutil.writestate(self, newstate)
3056 subrepoutil.writestate(self, newstate)
3057
3057
3058 p1, p2 = self.dirstate.parents()
3058 p1, p2 = self.dirstate.parents()
3059 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or b'')
3059 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or b'')
3060 try:
3060 try:
3061 self.hook(
3061 self.hook(
3062 b"precommit", throw=True, parent1=hookp1, parent2=hookp2
3062 b"precommit", throw=True, parent1=hookp1, parent2=hookp2
3063 )
3063 )
3064 with self.transaction(b'commit'):
3064 with self.transaction(b'commit'):
3065 ret = self.commitctx(cctx, True)
3065 ret = self.commitctx(cctx, True)
3066 # update bookmarks, dirstate and mergestate
3066 # update bookmarks, dirstate and mergestate
3067 bookmarks.update(self, [p1, p2], ret)
3067 bookmarks.update(self, [p1, p2], ret)
3068 cctx.markcommitted(ret)
3068 cctx.markcommitted(ret)
3069 ms.reset()
3069 ms.reset()
3070 except: # re-raises
3070 except: # re-raises
3071 if edited:
3071 if edited:
3072 self.ui.write(
3072 self.ui.write(
3073 _(b'note: commit message saved in %s\n') % msgfn
3073 _(b'note: commit message saved in %s\n') % msgfn
3074 )
3074 )
3075 self.ui.write(
3075 self.ui.write(
3076 _(
3076 _(
3077 b"note: use 'hg commit --logfile "
3077 b"note: use 'hg commit --logfile "
3078 b".hg/last-message.txt --edit' to reuse it\n"
3078 b".hg/last-message.txt --edit' to reuse it\n"
3079 )
3079 )
3080 )
3080 )
3081 raise
3081 raise
3082
3082
3083 def commithook(unused_success):
3083 def commithook(unused_success):
3084 # hack for command that use a temporary commit (eg: histedit)
3084 # hack for command that use a temporary commit (eg: histedit)
3085 # temporary commit got stripped before hook release
3085 # temporary commit got stripped before hook release
3086 if self.changelog.hasnode(ret):
3086 if self.changelog.hasnode(ret):
3087 self.hook(
3087 self.hook(
3088 b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2
3088 b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2
3089 )
3089 )
3090
3090
3091 self._afterlock(commithook)
3091 self._afterlock(commithook)
3092 return ret
3092 return ret
3093
3093
3094 @unfilteredmethod
3094 @unfilteredmethod
3095 def commitctx(self, ctx, error=False, origctx=None):
3095 def commitctx(self, ctx, error=False, origctx=None):
3096 return commit.commitctx(self, ctx, error=error, origctx=origctx)
3096 return commit.commitctx(self, ctx, error=error, origctx=origctx)
3097
3097
3098 @unfilteredmethod
3098 @unfilteredmethod
3099 def destroying(self):
3099 def destroying(self):
3100 """Inform the repository that nodes are about to be destroyed.
3100 """Inform the repository that nodes are about to be destroyed.
3101 Intended for use by strip and rollback, so there's a common
3101 Intended for use by strip and rollback, so there's a common
3102 place for anything that has to be done before destroying history.
3102 place for anything that has to be done before destroying history.
3103
3103
3104 This is mostly useful for saving state that is in memory and waiting
3104 This is mostly useful for saving state that is in memory and waiting
3105 to be flushed when the current lock is released. Because a call to
3105 to be flushed when the current lock is released. Because a call to
3106 destroyed is imminent, the repo will be invalidated causing those
3106 destroyed is imminent, the repo will be invalidated causing those
3107 changes to stay in memory (waiting for the next unlock), or vanish
3107 changes to stay in memory (waiting for the next unlock), or vanish
3108 completely.
3108 completely.
3109 """
3109 """
3110 # When using the same lock to commit and strip, the phasecache is left
3110 # When using the same lock to commit and strip, the phasecache is left
3111 # dirty after committing. Then when we strip, the repo is invalidated,
3111 # dirty after committing. Then when we strip, the repo is invalidated,
3112 # causing those changes to disappear.
3112 # causing those changes to disappear.
3113 if '_phasecache' in vars(self):
3113 if '_phasecache' in vars(self):
3114 self._phasecache.write()
3114 self._phasecache.write()
3115
3115
3116 @unfilteredmethod
3116 @unfilteredmethod
3117 def destroyed(self):
3117 def destroyed(self):
3118 """Inform the repository that nodes have been destroyed.
3118 """Inform the repository that nodes have been destroyed.
3119 Intended for use by strip and rollback, so there's a common
3119 Intended for use by strip and rollback, so there's a common
3120 place for anything that has to be done after destroying history.
3120 place for anything that has to be done after destroying history.
3121 """
3121 """
3122 # When one tries to:
3122 # When one tries to:
3123 # 1) destroy nodes thus calling this method (e.g. strip)
3123 # 1) destroy nodes thus calling this method (e.g. strip)
3124 # 2) use phasecache somewhere (e.g. commit)
3124 # 2) use phasecache somewhere (e.g. commit)
3125 #
3125 #
3126 # then 2) will fail because the phasecache contains nodes that were
3126 # then 2) will fail because the phasecache contains nodes that were
3127 # removed. We can either remove phasecache from the filecache,
3127 # removed. We can either remove phasecache from the filecache,
3128 # causing it to reload next time it is accessed, or simply filter
3128 # causing it to reload next time it is accessed, or simply filter
3129 # the removed nodes now and write the updated cache.
3129 # the removed nodes now and write the updated cache.
3130 self._phasecache.filterunknown(self)
3130 self._phasecache.filterunknown(self)
3131 self._phasecache.write()
3131 self._phasecache.write()
3132
3132
3133 # refresh all repository caches
3133 # refresh all repository caches
3134 self.updatecaches()
3134 self.updatecaches()
3135
3135
3136 # Ensure the persistent tag cache is updated. Doing it now
3136 # Ensure the persistent tag cache is updated. Doing it now
3137 # means that the tag cache only has to worry about destroyed
3137 # means that the tag cache only has to worry about destroyed
3138 # heads immediately after a strip/rollback. That in turn
3138 # heads immediately after a strip/rollback. That in turn
3139 # guarantees that "cachetip == currenttip" (comparing both rev
3139 # guarantees that "cachetip == currenttip" (comparing both rev
3140 # and node) always means no nodes have been added or destroyed.
3140 # and node) always means no nodes have been added or destroyed.
3141
3141
3142 # XXX this is suboptimal when qrefresh'ing: we strip the current
3142 # XXX this is suboptimal when qrefresh'ing: we strip the current
3143 # head, refresh the tag cache, then immediately add a new head.
3143 # head, refresh the tag cache, then immediately add a new head.
3144 # But I think doing it this way is necessary for the "instant
3144 # But I think doing it this way is necessary for the "instant
3145 # tag cache retrieval" case to work.
3145 # tag cache retrieval" case to work.
3146 self.invalidate()
3146 self.invalidate()
3147
3147
3148 def status(
3148 def status(
3149 self,
3149 self,
3150 node1=b'.',
3150 node1=b'.',
3151 node2=None,
3151 node2=None,
3152 match=None,
3152 match=None,
3153 ignored=False,
3153 ignored=False,
3154 clean=False,
3154 clean=False,
3155 unknown=False,
3155 unknown=False,
3156 listsubrepos=False,
3156 listsubrepos=False,
3157 ):
3157 ):
3158 '''a convenience method that calls node1.status(node2)'''
3158 '''a convenience method that calls node1.status(node2)'''
3159 return self[node1].status(
3159 return self[node1].status(
3160 node2, match, ignored, clean, unknown, listsubrepos
3160 node2, match, ignored, clean, unknown, listsubrepos
3161 )
3161 )
3162
3162
3163 def addpostdsstatus(self, ps):
3163 def addpostdsstatus(self, ps):
3164 """Add a callback to run within the wlock, at the point at which status
3164 """Add a callback to run within the wlock, at the point at which status
3165 fixups happen.
3165 fixups happen.
3166
3166
3167 On status completion, callback(wctx, status) will be called with the
3167 On status completion, callback(wctx, status) will be called with the
3168 wlock held, unless the dirstate has changed from underneath or the wlock
3168 wlock held, unless the dirstate has changed from underneath or the wlock
3169 couldn't be grabbed.
3169 couldn't be grabbed.
3170
3170
3171 Callbacks should not capture and use a cached copy of the dirstate --
3171 Callbacks should not capture and use a cached copy of the dirstate --
3172 it might change in the meanwhile. Instead, they should access the
3172 it might change in the meanwhile. Instead, they should access the
3173 dirstate via wctx.repo().dirstate.
3173 dirstate via wctx.repo().dirstate.
3174
3174
3175 This list is emptied out after each status run -- extensions should
3175 This list is emptied out after each status run -- extensions should
3176 make sure it adds to this list each time dirstate.status is called.
3176 make sure it adds to this list each time dirstate.status is called.
3177 Extensions should also make sure they don't call this for statuses
3177 Extensions should also make sure they don't call this for statuses
3178 that don't involve the dirstate.
3178 that don't involve the dirstate.
3179 """
3179 """
3180
3180
3181 # The list is located here for uniqueness reasons -- it is actually
3181 # The list is located here for uniqueness reasons -- it is actually
3182 # managed by the workingctx, but that isn't unique per-repo.
3182 # managed by the workingctx, but that isn't unique per-repo.
3183 self._postdsstatus.append(ps)
3183 self._postdsstatus.append(ps)
3184
3184
3185 def postdsstatus(self):
3185 def postdsstatus(self):
3186 """Used by workingctx to get the list of post-dirstate-status hooks."""
3186 """Used by workingctx to get the list of post-dirstate-status hooks."""
3187 return self._postdsstatus
3187 return self._postdsstatus
3188
3188
3189 def clearpostdsstatus(self):
3189 def clearpostdsstatus(self):
3190 """Used by workingctx to clear post-dirstate-status hooks."""
3190 """Used by workingctx to clear post-dirstate-status hooks."""
3191 del self._postdsstatus[:]
3191 del self._postdsstatus[:]
3192
3192
3193 def heads(self, start=None):
3193 def heads(self, start=None):
3194 if start is None:
3194 if start is None:
3195 cl = self.changelog
3195 cl = self.changelog
3196 headrevs = reversed(cl.headrevs())
3196 headrevs = reversed(cl.headrevs())
3197 return [cl.node(rev) for rev in headrevs]
3197 return [cl.node(rev) for rev in headrevs]
3198
3198
3199 heads = self.changelog.heads(start)
3199 heads = self.changelog.heads(start)
3200 # sort the output in rev descending order
3200 # sort the output in rev descending order
3201 return sorted(heads, key=self.changelog.rev, reverse=True)
3201 return sorted(heads, key=self.changelog.rev, reverse=True)
3202
3202
3203 def branchheads(self, branch=None, start=None, closed=False):
3203 def branchheads(self, branch=None, start=None, closed=False):
3204 """return a (possibly filtered) list of heads for the given branch
3204 """return a (possibly filtered) list of heads for the given branch
3205
3205
3206 Heads are returned in topological order, from newest to oldest.
3206 Heads are returned in topological order, from newest to oldest.
3207 If branch is None, use the dirstate branch.
3207 If branch is None, use the dirstate branch.
3208 If start is not None, return only heads reachable from start.
3208 If start is not None, return only heads reachable from start.
3209 If closed is True, return heads that are marked as closed as well.
3209 If closed is True, return heads that are marked as closed as well.
3210 """
3210 """
3211 if branch is None:
3211 if branch is None:
3212 branch = self[None].branch()
3212 branch = self[None].branch()
3213 branches = self.branchmap()
3213 branches = self.branchmap()
3214 if not branches.hasbranch(branch):
3214 if not branches.hasbranch(branch):
3215 return []
3215 return []
3216 # the cache returns heads ordered lowest to highest
3216 # the cache returns heads ordered lowest to highest
3217 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
3217 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
3218 if start is not None:
3218 if start is not None:
3219 # filter out the heads that cannot be reached from startrev
3219 # filter out the heads that cannot be reached from startrev
3220 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
3220 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
3221 bheads = [h for h in bheads if h in fbheads]
3221 bheads = [h for h in bheads if h in fbheads]
3222 return bheads
3222 return bheads
3223
3223
3224 def branches(self, nodes):
3224 def branches(self, nodes):
3225 if not nodes:
3225 if not nodes:
3226 nodes = [self.changelog.tip()]
3226 nodes = [self.changelog.tip()]
3227 b = []
3227 b = []
3228 for n in nodes:
3228 for n in nodes:
3229 t = n
3229 t = n
3230 while True:
3230 while True:
3231 p = self.changelog.parents(n)
3231 p = self.changelog.parents(n)
3232 if p[1] != nullid or p[0] == nullid:
3232 if p[1] != nullid or p[0] == nullid:
3233 b.append((t, n, p[0], p[1]))
3233 b.append((t, n, p[0], p[1]))
3234 break
3234 break
3235 n = p[0]
3235 n = p[0]
3236 return b
3236 return b
3237
3237
3238 def between(self, pairs):
3238 def between(self, pairs):
3239 r = []
3239 r = []
3240
3240
3241 for top, bottom in pairs:
3241 for top, bottom in pairs:
3242 n, l, i = top, [], 0
3242 n, l, i = top, [], 0
3243 f = 1
3243 f = 1
3244
3244
3245 while n != bottom and n != nullid:
3245 while n != bottom and n != nullid:
3246 p = self.changelog.parents(n)[0]
3246 p = self.changelog.parents(n)[0]
3247 if i == f:
3247 if i == f:
3248 l.append(n)
3248 l.append(n)
3249 f = f * 2
3249 f = f * 2
3250 n = p
3250 n = p
3251 i += 1
3251 i += 1
3252
3252
3253 r.append(l)
3253 r.append(l)
3254
3254
3255 return r
3255 return r
3256
3256
3257 def checkpush(self, pushop):
3257 def checkpush(self, pushop):
3258 """Extensions can override this function if additional checks have
3258 """Extensions can override this function if additional checks have
3259 to be performed before pushing, or call it if they override push
3259 to be performed before pushing, or call it if they override push
3260 command.
3260 command.
3261 """
3261 """
3262
3262
3263 @unfilteredpropertycache
3263 @unfilteredpropertycache
3264 def prepushoutgoinghooks(self):
3264 def prepushoutgoinghooks(self):
3265 """Return util.hooks consists of a pushop with repo, remote, outgoing
3265 """Return util.hooks consists of a pushop with repo, remote, outgoing
3266 methods, which are called before pushing changesets.
3266 methods, which are called before pushing changesets.
3267 """
3267 """
3268 return util.hooks()
3268 return util.hooks()
3269
3269
3270 def pushkey(self, namespace, key, old, new):
3270 def pushkey(self, namespace, key, old, new):
3271 try:
3271 try:
3272 tr = self.currenttransaction()
3272 tr = self.currenttransaction()
3273 hookargs = {}
3273 hookargs = {}
3274 if tr is not None:
3274 if tr is not None:
3275 hookargs.update(tr.hookargs)
3275 hookargs.update(tr.hookargs)
3276 hookargs = pycompat.strkwargs(hookargs)
3276 hookargs = pycompat.strkwargs(hookargs)
3277 hookargs['namespace'] = namespace
3277 hookargs['namespace'] = namespace
3278 hookargs['key'] = key
3278 hookargs['key'] = key
3279 hookargs['old'] = old
3279 hookargs['old'] = old
3280 hookargs['new'] = new
3280 hookargs['new'] = new
3281 self.hook(b'prepushkey', throw=True, **hookargs)
3281 self.hook(b'prepushkey', throw=True, **hookargs)
3282 except error.HookAbort as exc:
3282 except error.HookAbort as exc:
3283 self.ui.write_err(_(b"pushkey-abort: %s\n") % exc)
3283 self.ui.write_err(_(b"pushkey-abort: %s\n") % exc)
3284 if exc.hint:
3284 if exc.hint:
3285 self.ui.write_err(_(b"(%s)\n") % exc.hint)
3285 self.ui.write_err(_(b"(%s)\n") % exc.hint)
3286 return False
3286 return False
3287 self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key))
3287 self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key))
3288 ret = pushkey.push(self, namespace, key, old, new)
3288 ret = pushkey.push(self, namespace, key, old, new)
3289
3289
3290 def runhook(unused_success):
3290 def runhook(unused_success):
3291 self.hook(
3291 self.hook(
3292 b'pushkey',
3292 b'pushkey',
3293 namespace=namespace,
3293 namespace=namespace,
3294 key=key,
3294 key=key,
3295 old=old,
3295 old=old,
3296 new=new,
3296 new=new,
3297 ret=ret,
3297 ret=ret,
3298 )
3298 )
3299
3299
3300 self._afterlock(runhook)
3300 self._afterlock(runhook)
3301 return ret
3301 return ret
3302
3302
3303 def listkeys(self, namespace):
3303 def listkeys(self, namespace):
3304 self.hook(b'prelistkeys', throw=True, namespace=namespace)
3304 self.hook(b'prelistkeys', throw=True, namespace=namespace)
3305 self.ui.debug(b'listing keys for "%s"\n' % namespace)
3305 self.ui.debug(b'listing keys for "%s"\n' % namespace)
3306 values = pushkey.list(self, namespace)
3306 values = pushkey.list(self, namespace)
3307 self.hook(b'listkeys', namespace=namespace, values=values)
3307 self.hook(b'listkeys', namespace=namespace, values=values)
3308 return values
3308 return values
3309
3309
3310 def debugwireargs(self, one, two, three=None, four=None, five=None):
3310 def debugwireargs(self, one, two, three=None, four=None, five=None):
3311 '''used to test argument passing over the wire'''
3311 '''used to test argument passing over the wire'''
3312 return b"%s %s %s %s %s" % (
3312 return b"%s %s %s %s %s" % (
3313 one,
3313 one,
3314 two,
3314 two,
3315 pycompat.bytestr(three),
3315 pycompat.bytestr(three),
3316 pycompat.bytestr(four),
3316 pycompat.bytestr(four),
3317 pycompat.bytestr(five),
3317 pycompat.bytestr(five),
3318 )
3318 )
3319
3319
3320 def savecommitmessage(self, text):
3320 def savecommitmessage(self, text):
3321 fp = self.vfs(b'last-message.txt', b'wb')
3321 fp = self.vfs(b'last-message.txt', b'wb')
3322 try:
3322 try:
3323 fp.write(text)
3323 fp.write(text)
3324 finally:
3324 finally:
3325 fp.close()
3325 fp.close()
3326 return self.pathto(fp.name[len(self.root) + 1 :])
3326 return self.pathto(fp.name[len(self.root) + 1 :])
3327
3327
3328
3328
3329 # used to avoid circular references so destructors work
3329 # used to avoid circular references so destructors work
3330 def aftertrans(files):
3330 def aftertrans(files):
3331 renamefiles = [tuple(t) for t in files]
3331 renamefiles = [tuple(t) for t in files]
3332
3332
3333 def a():
3333 def a():
3334 for vfs, src, dest in renamefiles:
3334 for vfs, src, dest in renamefiles:
3335 # if src and dest refer to a same file, vfs.rename is a no-op,
3335 # if src and dest refer to a same file, vfs.rename is a no-op,
3336 # leaving both src and dest on disk. delete dest to make sure
3336 # leaving both src and dest on disk. delete dest to make sure
3337 # the rename couldn't be such a no-op.
3337 # the rename couldn't be such a no-op.
3338 vfs.tryunlink(dest)
3338 vfs.tryunlink(dest)
3339 try:
3339 try:
3340 vfs.rename(src, dest)
3340 vfs.rename(src, dest)
3341 except OSError: # journal file does not yet exist
3341 except OSError: # journal file does not yet exist
3342 pass
3342 pass
3343
3343
3344 return a
3344 return a
3345
3345
3346
3346
3347 def undoname(fn):
3347 def undoname(fn):
3348 base, name = os.path.split(fn)
3348 base, name = os.path.split(fn)
3349 assert name.startswith(b'journal')
3349 assert name.startswith(b'journal')
3350 return os.path.join(base, name.replace(b'journal', b'undo', 1))
3350 return os.path.join(base, name.replace(b'journal', b'undo', 1))
3351
3351
3352
3352
3353 def instance(ui, path, create, intents=None, createopts=None):
3353 def instance(ui, path, create, intents=None, createopts=None):
3354 localpath = util.urllocalpath(path)
3354 localpath = util.urllocalpath(path)
3355 if create:
3355 if create:
3356 createrepository(ui, localpath, createopts=createopts)
3356 createrepository(ui, localpath, createopts=createopts)
3357
3357
3358 return makelocalrepository(ui, localpath, intents=intents)
3358 return makelocalrepository(ui, localpath, intents=intents)
3359
3359
3360
3360
3361 def islocal(path):
3361 def islocal(path):
3362 return True
3362 return True
3363
3363
3364
3364
3365 def defaultcreateopts(ui, createopts=None):
3365 def defaultcreateopts(ui, createopts=None):
3366 """Populate the default creation options for a repository.
3366 """Populate the default creation options for a repository.
3367
3367
3368 A dictionary of explicitly requested creation options can be passed
3368 A dictionary of explicitly requested creation options can be passed
3369 in. Missing keys will be populated.
3369 in. Missing keys will be populated.
3370 """
3370 """
3371 createopts = dict(createopts or {})
3371 createopts = dict(createopts or {})
3372
3372
3373 if b'backend' not in createopts:
3373 if b'backend' not in createopts:
3374 # experimental config: storage.new-repo-backend
3374 # experimental config: storage.new-repo-backend
3375 createopts[b'backend'] = ui.config(b'storage', b'new-repo-backend')
3375 createopts[b'backend'] = ui.config(b'storage', b'new-repo-backend')
3376
3376
3377 return createopts
3377 return createopts
3378
3378
3379
3379
3380 def newreporequirements(ui, createopts):
3380 def newreporequirements(ui, createopts):
3381 """Determine the set of requirements for a new local repository.
3381 """Determine the set of requirements for a new local repository.
3382
3382
3383 Extensions can wrap this function to specify custom requirements for
3383 Extensions can wrap this function to specify custom requirements for
3384 new repositories.
3384 new repositories.
3385 """
3385 """
3386 # If the repo is being created from a shared repository, we copy
3386 # If the repo is being created from a shared repository, we copy
3387 # its requirements.
3387 # its requirements.
3388 if b'sharedrepo' in createopts:
3388 if b'sharedrepo' in createopts:
3389 requirements = set(createopts[b'sharedrepo'].requirements)
3389 requirements = set(createopts[b'sharedrepo'].requirements)
3390 if createopts.get(b'sharedrelative'):
3390 if createopts.get(b'sharedrelative'):
3391 requirements.add(requirementsmod.RELATIVE_SHARED_REQUIREMENT)
3391 requirements.add(requirementsmod.RELATIVE_SHARED_REQUIREMENT)
3392 else:
3392 else:
3393 requirements.add(requirementsmod.SHARED_REQUIREMENT)
3393 requirements.add(requirementsmod.SHARED_REQUIREMENT)
3394
3394
3395 return requirements
3395 return requirements
3396
3396
3397 if b'backend' not in createopts:
3397 if b'backend' not in createopts:
3398 raise error.ProgrammingError(
3398 raise error.ProgrammingError(
3399 b'backend key not present in createopts; '
3399 b'backend key not present in createopts; '
3400 b'was defaultcreateopts() called?'
3400 b'was defaultcreateopts() called?'
3401 )
3401 )
3402
3402
3403 if createopts[b'backend'] != b'revlogv1':
3403 if createopts[b'backend'] != b'revlogv1':
3404 raise error.Abort(
3404 raise error.Abort(
3405 _(
3405 _(
3406 b'unable to determine repository requirements for '
3406 b'unable to determine repository requirements for '
3407 b'storage backend: %s'
3407 b'storage backend: %s'
3408 )
3408 )
3409 % createopts[b'backend']
3409 % createopts[b'backend']
3410 )
3410 )
3411
3411
3412 requirements = {requirementsmod.REVLOGV1_REQUIREMENT}
3412 requirements = {requirementsmod.REVLOGV1_REQUIREMENT}
3413 if ui.configbool(b'format', b'usestore'):
3413 if ui.configbool(b'format', b'usestore'):
3414 requirements.add(requirementsmod.STORE_REQUIREMENT)
3414 requirements.add(requirementsmod.STORE_REQUIREMENT)
3415 if ui.configbool(b'format', b'usefncache'):
3415 if ui.configbool(b'format', b'usefncache'):
3416 requirements.add(requirementsmod.FNCACHE_REQUIREMENT)
3416 requirements.add(requirementsmod.FNCACHE_REQUIREMENT)
3417 if ui.configbool(b'format', b'dotencode'):
3417 if ui.configbool(b'format', b'dotencode'):
3418 requirements.add(requirementsmod.DOTENCODE_REQUIREMENT)
3418 requirements.add(requirementsmod.DOTENCODE_REQUIREMENT)
3419
3419
3420 compengines = ui.configlist(b'format', b'revlog-compression')
3420 compengines = ui.configlist(b'format', b'revlog-compression')
3421 for compengine in compengines:
3421 for compengine in compengines:
3422 if compengine in util.compengines:
3422 if compengine in util.compengines:
3423 break
3423 break
3424 else:
3424 else:
3425 raise error.Abort(
3425 raise error.Abort(
3426 _(
3426 _(
3427 b'compression engines %s defined by '
3427 b'compression engines %s defined by '
3428 b'format.revlog-compression not available'
3428 b'format.revlog-compression not available'
3429 )
3429 )
3430 % b', '.join(b'"%s"' % e for e in compengines),
3430 % b', '.join(b'"%s"' % e for e in compengines),
3431 hint=_(
3431 hint=_(
3432 b'run "hg debuginstall" to list available '
3432 b'run "hg debuginstall" to list available '
3433 b'compression engines'
3433 b'compression engines'
3434 ),
3434 ),
3435 )
3435 )
3436
3436
3437 # zlib is the historical default and doesn't need an explicit requirement.
3437 # zlib is the historical default and doesn't need an explicit requirement.
3438 if compengine == b'zstd':
3438 if compengine == b'zstd':
3439 requirements.add(b'revlog-compression-zstd')
3439 requirements.add(b'revlog-compression-zstd')
3440 elif compengine != b'zlib':
3440 elif compengine != b'zlib':
3441 requirements.add(b'exp-compression-%s' % compengine)
3441 requirements.add(b'exp-compression-%s' % compengine)
3442
3442
3443 if scmutil.gdinitconfig(ui):
3443 if scmutil.gdinitconfig(ui):
3444 requirements.add(requirementsmod.GENERALDELTA_REQUIREMENT)
3444 requirements.add(requirementsmod.GENERALDELTA_REQUIREMENT)
3445 if ui.configbool(b'format', b'sparse-revlog'):
3445 if ui.configbool(b'format', b'sparse-revlog'):
3446 requirements.add(requirementsmod.SPARSEREVLOG_REQUIREMENT)
3446 requirements.add(requirementsmod.SPARSEREVLOG_REQUIREMENT)
3447
3447
3448 # experimental config: format.exp-use-side-data
3448 # experimental config: format.exp-use-side-data
3449 if ui.configbool(b'format', b'exp-use-side-data'):
3449 if ui.configbool(b'format', b'exp-use-side-data'):
3450 requirements.discard(requirementsmod.REVLOGV1_REQUIREMENT)
3451 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3450 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
3452 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
3451 # experimental config: format.exp-use-copies-side-data-changeset
3453 # experimental config: format.exp-use-copies-side-data-changeset
3452 if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'):
3454 if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'):
3455 requirements.discard(requirementsmod.REVLOGV1_REQUIREMENT)
3456 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3453 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
3457 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
3454 requirements.add(requirementsmod.COPIESSDC_REQUIREMENT)
3458 requirements.add(requirementsmod.COPIESSDC_REQUIREMENT)
3455 if ui.configbool(b'experimental', b'treemanifest'):
3459 if ui.configbool(b'experimental', b'treemanifest'):
3456 requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
3460 requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
3457
3461
3458 revlogv2 = ui.config(b'experimental', b'revlogv2')
3462 revlogv2 = ui.config(b'experimental', b'revlogv2')
3459 if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
3463 if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
3460 requirements.remove(requirementsmod.REVLOGV1_REQUIREMENT)
3464 requirements.discard(requirementsmod.REVLOGV1_REQUIREMENT)
3461 # generaldelta is implied by revlogv2.
3465 # generaldelta is implied by revlogv2.
3462 requirements.discard(requirementsmod.GENERALDELTA_REQUIREMENT)
3466 requirements.discard(requirementsmod.GENERALDELTA_REQUIREMENT)
3463 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3467 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3464 # experimental config: format.internal-phase
3468 # experimental config: format.internal-phase
3465 if ui.configbool(b'format', b'internal-phase'):
3469 if ui.configbool(b'format', b'internal-phase'):
3466 requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
3470 requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
3467
3471
3468 if createopts.get(b'narrowfiles'):
3472 if createopts.get(b'narrowfiles'):
3469 requirements.add(requirementsmod.NARROW_REQUIREMENT)
3473 requirements.add(requirementsmod.NARROW_REQUIREMENT)
3470
3474
3471 if createopts.get(b'lfs'):
3475 if createopts.get(b'lfs'):
3472 requirements.add(b'lfs')
3476 requirements.add(b'lfs')
3473
3477
3474 if ui.configbool(b'format', b'bookmarks-in-store'):
3478 if ui.configbool(b'format', b'bookmarks-in-store'):
3475 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3479 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3476
3480
3477 if ui.configbool(b'format', b'use-persistent-nodemap'):
3481 if ui.configbool(b'format', b'use-persistent-nodemap'):
3478 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
3482 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
3479
3483
3480 # if share-safe is enabled, let's create the new repository with the new
3484 # if share-safe is enabled, let's create the new repository with the new
3481 # requirement
3485 # requirement
3482 if ui.configbool(b'format', b'use-share-safe'):
3486 if ui.configbool(b'format', b'use-share-safe'):
3483 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
3487 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
3484
3488
3485 return requirements
3489 return requirements
3486
3490
3487
3491
3488 def checkrequirementscompat(ui, requirements):
3492 def checkrequirementscompat(ui, requirements):
3489 """Checks compatibility of repository requirements enabled and disabled.
3493 """Checks compatibility of repository requirements enabled and disabled.
3490
3494
3491 Returns a set of requirements which needs to be dropped because dependend
3495 Returns a set of requirements which needs to be dropped because dependend
3492 requirements are not enabled. Also warns users about it"""
3496 requirements are not enabled. Also warns users about it"""
3493
3497
3494 dropped = set()
3498 dropped = set()
3495
3499
3496 if requirementsmod.STORE_REQUIREMENT not in requirements:
3500 if requirementsmod.STORE_REQUIREMENT not in requirements:
3497 if bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT in requirements:
3501 if bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT in requirements:
3498 ui.warn(
3502 ui.warn(
3499 _(
3503 _(
3500 b'ignoring enabled \'format.bookmarks-in-store\' config '
3504 b'ignoring enabled \'format.bookmarks-in-store\' config '
3501 b'beacuse it is incompatible with disabled '
3505 b'beacuse it is incompatible with disabled '
3502 b'\'format.usestore\' config\n'
3506 b'\'format.usestore\' config\n'
3503 )
3507 )
3504 )
3508 )
3505 dropped.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3509 dropped.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3506
3510
3507 if (
3511 if (
3508 requirementsmod.SHARED_REQUIREMENT in requirements
3512 requirementsmod.SHARED_REQUIREMENT in requirements
3509 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
3513 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
3510 ):
3514 ):
3511 raise error.Abort(
3515 raise error.Abort(
3512 _(
3516 _(
3513 b"cannot create shared repository as source was created"
3517 b"cannot create shared repository as source was created"
3514 b" with 'format.usestore' config disabled"
3518 b" with 'format.usestore' config disabled"
3515 )
3519 )
3516 )
3520 )
3517
3521
3518 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
3522 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
3519 ui.warn(
3523 ui.warn(
3520 _(
3524 _(
3521 b"ignoring enabled 'format.use-share-safe' config because "
3525 b"ignoring enabled 'format.use-share-safe' config because "
3522 b"it is incompatible with disabled 'format.usestore'"
3526 b"it is incompatible with disabled 'format.usestore'"
3523 b" config\n"
3527 b" config\n"
3524 )
3528 )
3525 )
3529 )
3526 dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
3530 dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
3527
3531
3528 return dropped
3532 return dropped
3529
3533
3530
3534
3531 def filterknowncreateopts(ui, createopts):
3535 def filterknowncreateopts(ui, createopts):
3532 """Filters a dict of repo creation options against options that are known.
3536 """Filters a dict of repo creation options against options that are known.
3533
3537
3534 Receives a dict of repo creation options and returns a dict of those
3538 Receives a dict of repo creation options and returns a dict of those
3535 options that we don't know how to handle.
3539 options that we don't know how to handle.
3536
3540
3537 This function is called as part of repository creation. If the
3541 This function is called as part of repository creation. If the
3538 returned dict contains any items, repository creation will not
3542 returned dict contains any items, repository creation will not
3539 be allowed, as it means there was a request to create a repository
3543 be allowed, as it means there was a request to create a repository
3540 with options not recognized by loaded code.
3544 with options not recognized by loaded code.
3541
3545
3542 Extensions can wrap this function to filter out creation options
3546 Extensions can wrap this function to filter out creation options
3543 they know how to handle.
3547 they know how to handle.
3544 """
3548 """
3545 known = {
3549 known = {
3546 b'backend',
3550 b'backend',
3547 b'lfs',
3551 b'lfs',
3548 b'narrowfiles',
3552 b'narrowfiles',
3549 b'sharedrepo',
3553 b'sharedrepo',
3550 b'sharedrelative',
3554 b'sharedrelative',
3551 b'shareditems',
3555 b'shareditems',
3552 b'shallowfilestore',
3556 b'shallowfilestore',
3553 }
3557 }
3554
3558
3555 return {k: v for k, v in createopts.items() if k not in known}
3559 return {k: v for k, v in createopts.items() if k not in known}
3556
3560
3557
3561
3558 def createrepository(ui, path, createopts=None):
3562 def createrepository(ui, path, createopts=None):
3559 """Create a new repository in a vfs.
3563 """Create a new repository in a vfs.
3560
3564
3561 ``path`` path to the new repo's working directory.
3565 ``path`` path to the new repo's working directory.
3562 ``createopts`` options for the new repository.
3566 ``createopts`` options for the new repository.
3563
3567
3564 The following keys for ``createopts`` are recognized:
3568 The following keys for ``createopts`` are recognized:
3565
3569
3566 backend
3570 backend
3567 The storage backend to use.
3571 The storage backend to use.
3568 lfs
3572 lfs
3569 Repository will be created with ``lfs`` requirement. The lfs extension
3573 Repository will be created with ``lfs`` requirement. The lfs extension
3570 will automatically be loaded when the repository is accessed.
3574 will automatically be loaded when the repository is accessed.
3571 narrowfiles
3575 narrowfiles
3572 Set up repository to support narrow file storage.
3576 Set up repository to support narrow file storage.
3573 sharedrepo
3577 sharedrepo
3574 Repository object from which storage should be shared.
3578 Repository object from which storage should be shared.
3575 sharedrelative
3579 sharedrelative
3576 Boolean indicating if the path to the shared repo should be
3580 Boolean indicating if the path to the shared repo should be
3577 stored as relative. By default, the pointer to the "parent" repo
3581 stored as relative. By default, the pointer to the "parent" repo
3578 is stored as an absolute path.
3582 is stored as an absolute path.
3579 shareditems
3583 shareditems
3580 Set of items to share to the new repository (in addition to storage).
3584 Set of items to share to the new repository (in addition to storage).
3581 shallowfilestore
3585 shallowfilestore
3582 Indicates that storage for files should be shallow (not all ancestor
3586 Indicates that storage for files should be shallow (not all ancestor
3583 revisions are known).
3587 revisions are known).
3584 """
3588 """
3585 createopts = defaultcreateopts(ui, createopts=createopts)
3589 createopts = defaultcreateopts(ui, createopts=createopts)
3586
3590
3587 unknownopts = filterknowncreateopts(ui, createopts)
3591 unknownopts = filterknowncreateopts(ui, createopts)
3588
3592
3589 if not isinstance(unknownopts, dict):
3593 if not isinstance(unknownopts, dict):
3590 raise error.ProgrammingError(
3594 raise error.ProgrammingError(
3591 b'filterknowncreateopts() did not return a dict'
3595 b'filterknowncreateopts() did not return a dict'
3592 )
3596 )
3593
3597
3594 if unknownopts:
3598 if unknownopts:
3595 raise error.Abort(
3599 raise error.Abort(
3596 _(
3600 _(
3597 b'unable to create repository because of unknown '
3601 b'unable to create repository because of unknown '
3598 b'creation option: %s'
3602 b'creation option: %s'
3599 )
3603 )
3600 % b', '.join(sorted(unknownopts)),
3604 % b', '.join(sorted(unknownopts)),
3601 hint=_(b'is a required extension not loaded?'),
3605 hint=_(b'is a required extension not loaded?'),
3602 )
3606 )
3603
3607
3604 requirements = newreporequirements(ui, createopts=createopts)
3608 requirements = newreporequirements(ui, createopts=createopts)
3605 requirements -= checkrequirementscompat(ui, requirements)
3609 requirements -= checkrequirementscompat(ui, requirements)
3606
3610
3607 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
3611 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
3608
3612
3609 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
3613 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
3610 if hgvfs.exists():
3614 if hgvfs.exists():
3611 raise error.RepoError(_(b'repository %s already exists') % path)
3615 raise error.RepoError(_(b'repository %s already exists') % path)
3612
3616
3613 if b'sharedrepo' in createopts:
3617 if b'sharedrepo' in createopts:
3614 sharedpath = createopts[b'sharedrepo'].sharedpath
3618 sharedpath = createopts[b'sharedrepo'].sharedpath
3615
3619
3616 if createopts.get(b'sharedrelative'):
3620 if createopts.get(b'sharedrelative'):
3617 try:
3621 try:
3618 sharedpath = os.path.relpath(sharedpath, hgvfs.base)
3622 sharedpath = os.path.relpath(sharedpath, hgvfs.base)
3619 except (IOError, ValueError) as e:
3623 except (IOError, ValueError) as e:
3620 # ValueError is raised on Windows if the drive letters differ
3624 # ValueError is raised on Windows if the drive letters differ
3621 # on each path.
3625 # on each path.
3622 raise error.Abort(
3626 raise error.Abort(
3623 _(b'cannot calculate relative path'),
3627 _(b'cannot calculate relative path'),
3624 hint=stringutil.forcebytestr(e),
3628 hint=stringutil.forcebytestr(e),
3625 )
3629 )
3626
3630
3627 if not wdirvfs.exists():
3631 if not wdirvfs.exists():
3628 wdirvfs.makedirs()
3632 wdirvfs.makedirs()
3629
3633
3630 hgvfs.makedir(notindexed=True)
3634 hgvfs.makedir(notindexed=True)
3631 if b'sharedrepo' not in createopts:
3635 if b'sharedrepo' not in createopts:
3632 hgvfs.mkdir(b'cache')
3636 hgvfs.mkdir(b'cache')
3633 hgvfs.mkdir(b'wcache')
3637 hgvfs.mkdir(b'wcache')
3634
3638
3635 has_store = requirementsmod.STORE_REQUIREMENT in requirements
3639 has_store = requirementsmod.STORE_REQUIREMENT in requirements
3636 if has_store and b'sharedrepo' not in createopts:
3640 if has_store and b'sharedrepo' not in createopts:
3637 hgvfs.mkdir(b'store')
3641 hgvfs.mkdir(b'store')
3638
3642
3639 # We create an invalid changelog outside the store so very old
3643 # We create an invalid changelog outside the store so very old
3640 # Mercurial versions (which didn't know about the requirements
3644 # Mercurial versions (which didn't know about the requirements
3641 # file) encounter an error on reading the changelog. This
3645 # file) encounter an error on reading the changelog. This
3642 # effectively locks out old clients and prevents them from
3646 # effectively locks out old clients and prevents them from
3643 # mucking with a repo in an unknown format.
3647 # mucking with a repo in an unknown format.
3644 #
3648 #
3645 # The revlog header has version 65535, which won't be recognized by
3649 # The revlog header has version 65535, which won't be recognized by
3646 # such old clients.
3650 # such old clients.
3647 hgvfs.append(
3651 hgvfs.append(
3648 b'00changelog.i',
3652 b'00changelog.i',
3649 b'\0\0\xFF\xFF dummy changelog to prevent using the old repo '
3653 b'\0\0\xFF\xFF dummy changelog to prevent using the old repo '
3650 b'layout',
3654 b'layout',
3651 )
3655 )
3652
3656
3653 # Filter the requirements into working copy and store ones
3657 # Filter the requirements into working copy and store ones
3654 wcreq, storereq = scmutil.filterrequirements(requirements)
3658 wcreq, storereq = scmutil.filterrequirements(requirements)
3655 # write working copy ones
3659 # write working copy ones
3656 scmutil.writerequires(hgvfs, wcreq)
3660 scmutil.writerequires(hgvfs, wcreq)
3657 # If there are store requirements and the current repository
3661 # If there are store requirements and the current repository
3658 # is not a shared one, write stored requirements
3662 # is not a shared one, write stored requirements
3659 # For new shared repository, we don't need to write the store
3663 # For new shared repository, we don't need to write the store
3660 # requirements as they are already present in store requires
3664 # requirements as they are already present in store requires
3661 if storereq and b'sharedrepo' not in createopts:
3665 if storereq and b'sharedrepo' not in createopts:
3662 storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
3666 storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
3663 scmutil.writerequires(storevfs, storereq)
3667 scmutil.writerequires(storevfs, storereq)
3664
3668
3665 # Write out file telling readers where to find the shared store.
3669 # Write out file telling readers where to find the shared store.
3666 if b'sharedrepo' in createopts:
3670 if b'sharedrepo' in createopts:
3667 hgvfs.write(b'sharedpath', sharedpath)
3671 hgvfs.write(b'sharedpath', sharedpath)
3668
3672
3669 if createopts.get(b'shareditems'):
3673 if createopts.get(b'shareditems'):
3670 shared = b'\n'.join(sorted(createopts[b'shareditems'])) + b'\n'
3674 shared = b'\n'.join(sorted(createopts[b'shareditems'])) + b'\n'
3671 hgvfs.write(b'shared', shared)
3675 hgvfs.write(b'shared', shared)
3672
3676
3673
3677
3674 def poisonrepository(repo):
3678 def poisonrepository(repo):
3675 """Poison a repository instance so it can no longer be used."""
3679 """Poison a repository instance so it can no longer be used."""
3676 # Perform any cleanup on the instance.
3680 # Perform any cleanup on the instance.
3677 repo.close()
3681 repo.close()
3678
3682
3679 # Our strategy is to replace the type of the object with one that
3683 # Our strategy is to replace the type of the object with one that
3680 # has all attribute lookups result in error.
3684 # has all attribute lookups result in error.
3681 #
3685 #
3682 # But we have to allow the close() method because some constructors
3686 # But we have to allow the close() method because some constructors
3683 # of repos call close() on repo references.
3687 # of repos call close() on repo references.
3684 class poisonedrepository(object):
3688 class poisonedrepository(object):
3685 def __getattribute__(self, item):
3689 def __getattribute__(self, item):
3686 if item == 'close':
3690 if item == 'close':
3687 return object.__getattribute__(self, item)
3691 return object.__getattribute__(self, item)
3688
3692
3689 raise error.ProgrammingError(
3693 raise error.ProgrammingError(
3690 b'repo instances should not be used after unshare'
3694 b'repo instances should not be used after unshare'
3691 )
3695 )
3692
3696
3693 def close(self):
3697 def close(self):
3694 pass
3698 pass
3695
3699
3696 # We may have a repoview, which intercepts __setattr__. So be sure
3700 # We may have a repoview, which intercepts __setattr__. So be sure
3697 # we operate at the lowest level possible.
3701 # we operate at the lowest level possible.
3698 object.__setattr__(repo, '__class__', poisonedrepository)
3702 object.__setattr__(repo, '__class__', poisonedrepository)
@@ -1,1011 +1,1040 b''
1 # upgrade.py - functions for in place upgrade of Mercurial repository
1 # upgrade.py - functions for in place upgrade of Mercurial repository
2 #
2 #
3 # Copyright (c) 2016-present, Gregory Szorc
3 # Copyright (c) 2016-present, Gregory Szorc
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from ..i18n import _
10 from ..i18n import _
11 from .. import (
11 from .. import (
12 error,
12 error,
13 localrepo,
13 localrepo,
14 requirements,
14 requirements,
15 revlog,
15 revlog,
16 util,
16 util,
17 )
17 )
18
18
19 from ..utils import compression
19 from ..utils import compression
20
20
21 # list of requirements that request a clone of all revlog if added/removed
21 # list of requirements that request a clone of all revlog if added/removed
22 RECLONES_REQUIREMENTS = {
22 RECLONES_REQUIREMENTS = {
23 requirements.GENERALDELTA_REQUIREMENT,
23 requirements.GENERALDELTA_REQUIREMENT,
24 requirements.SPARSEREVLOG_REQUIREMENT,
24 requirements.SPARSEREVLOG_REQUIREMENT,
25 }
25 }
26
26
27
27
28 def preservedrequirements(repo):
28 def preservedrequirements(repo):
29 return set()
29 return set()
30
30
31
31
32 FORMAT_VARIANT = b'deficiency'
32 FORMAT_VARIANT = b'deficiency'
33 OPTIMISATION = b'optimization'
33 OPTIMISATION = b'optimization'
34
34
35
35
36 class improvement(object):
36 class improvement(object):
37 """Represents an improvement that can be made as part of an upgrade.
37 """Represents an improvement that can be made as part of an upgrade.
38
38
39 The following attributes are defined on each instance:
39 The following attributes are defined on each instance:
40
40
41 name
41 name
42 Machine-readable string uniquely identifying this improvement. It
42 Machine-readable string uniquely identifying this improvement. It
43 will be mapped to an action later in the upgrade process.
43 will be mapped to an action later in the upgrade process.
44
44
45 type
45 type
46 Either ``FORMAT_VARIANT`` or ``OPTIMISATION``.
46 Either ``FORMAT_VARIANT`` or ``OPTIMISATION``.
47 A format variant is where we change the storage format. Not all format
47 A format variant is where we change the storage format. Not all format
48 variant changes are an obvious problem.
48 variant changes are an obvious problem.
49 An optimization is an action (sometimes optional) that
49 An optimization is an action (sometimes optional) that
50 can be taken to further improve the state of the repository.
50 can be taken to further improve the state of the repository.
51
51
52 description
52 description
53 Message intended for humans explaining the improvement in more detail,
53 Message intended for humans explaining the improvement in more detail,
54 including the implications of it. For ``FORMAT_VARIANT`` types, should be
54 including the implications of it. For ``FORMAT_VARIANT`` types, should be
55 worded in the present tense. For ``OPTIMISATION`` types, should be
55 worded in the present tense. For ``OPTIMISATION`` types, should be
56 worded in the future tense.
56 worded in the future tense.
57
57
58 upgrademessage
58 upgrademessage
59 Message intended for humans explaining what an upgrade addressing this
59 Message intended for humans explaining what an upgrade addressing this
60 issue will do. Should be worded in the future tense.
60 issue will do. Should be worded in the future tense.
61
61
62 postupgrademessage
62 postupgrademessage
63 Message intended for humans which will be shown post an upgrade
63 Message intended for humans which will be shown post an upgrade
64 operation when the improvement will be added
64 operation when the improvement will be added
65
65
66 postdowngrademessage
66 postdowngrademessage
67 Message intended for humans which will be shown post an upgrade
67 Message intended for humans which will be shown post an upgrade
68 operation in which this improvement was removed
68 operation in which this improvement was removed
69
69
70 touches_filelogs (bool)
70 touches_filelogs (bool)
71 Whether this improvement touches filelogs
71 Whether this improvement touches filelogs
72
72
73 touches_manifests (bool)
73 touches_manifests (bool)
74 Whether this improvement touches manifests
74 Whether this improvement touches manifests
75
75
76 touches_changelog (bool)
76 touches_changelog (bool)
77 Whether this improvement touches changelog
77 Whether this improvement touches changelog
78
78
79 touches_requirements (bool)
79 touches_requirements (bool)
80 Whether this improvement changes repository requirements
80 Whether this improvement changes repository requirements
81 """
81 """
82
82
83 def __init__(self, name, type, description, upgrademessage):
83 def __init__(self, name, type, description, upgrademessage):
84 self.name = name
84 self.name = name
85 self.type = type
85 self.type = type
86 self.description = description
86 self.description = description
87 self.upgrademessage = upgrademessage
87 self.upgrademessage = upgrademessage
88 self.postupgrademessage = None
88 self.postupgrademessage = None
89 self.postdowngrademessage = None
89 self.postdowngrademessage = None
90 # By default for now, we assume every improvement touches
90 # By default for now, we assume every improvement touches
91 # all the things
91 # all the things
92 self.touches_filelogs = True
92 self.touches_filelogs = True
93 self.touches_manifests = True
93 self.touches_manifests = True
94 self.touches_changelog = True
94 self.touches_changelog = True
95 self.touches_requirements = True
95 self.touches_requirements = True
96
96
97 def __eq__(self, other):
97 def __eq__(self, other):
98 if not isinstance(other, improvement):
98 if not isinstance(other, improvement):
99 # This is what python tell use to do
99 # This is what python tell use to do
100 return NotImplemented
100 return NotImplemented
101 return self.name == other.name
101 return self.name == other.name
102
102
103 def __ne__(self, other):
103 def __ne__(self, other):
104 return not (self == other)
104 return not (self == other)
105
105
106 def __hash__(self):
106 def __hash__(self):
107 return hash(self.name)
107 return hash(self.name)
108
108
109
109
110 allformatvariant = []
110 allformatvariant = []
111
111
112
112
113 def registerformatvariant(cls):
113 def registerformatvariant(cls):
114 allformatvariant.append(cls)
114 allformatvariant.append(cls)
115 return cls
115 return cls
116
116
117
117
118 class formatvariant(improvement):
118 class formatvariant(improvement):
119 """an improvement subclass dedicated to repository format"""
119 """an improvement subclass dedicated to repository format"""
120
120
121 type = FORMAT_VARIANT
121 type = FORMAT_VARIANT
122 ### The following attributes should be defined for each class:
122 ### The following attributes should be defined for each class:
123
123
124 # machine-readable string uniquely identifying this improvement. it will be
124 # machine-readable string uniquely identifying this improvement. it will be
125 # mapped to an action later in the upgrade process.
125 # mapped to an action later in the upgrade process.
126 name = None
126 name = None
127
127
128 # message intended for humans explaining the improvement in more detail,
128 # message intended for humans explaining the improvement in more detail,
129 # including the implications of it ``FORMAT_VARIANT`` types, should be
129 # including the implications of it ``FORMAT_VARIANT`` types, should be
130 # worded
130 # worded
131 # in the present tense.
131 # in the present tense.
132 description = None
132 description = None
133
133
134 # message intended for humans explaining what an upgrade addressing this
134 # message intended for humans explaining what an upgrade addressing this
135 # issue will do. should be worded in the future tense.
135 # issue will do. should be worded in the future tense.
136 upgrademessage = None
136 upgrademessage = None
137
137
138 # value of current Mercurial default for new repository
138 # value of current Mercurial default for new repository
139 default = None
139 default = None
140
140
141 # Message intended for humans which will be shown post an upgrade
141 # Message intended for humans which will be shown post an upgrade
142 # operation when the improvement will be added
142 # operation when the improvement will be added
143 postupgrademessage = None
143 postupgrademessage = None
144
144
145 # Message intended for humans which will be shown post an upgrade
145 # Message intended for humans which will be shown post an upgrade
146 # operation in which this improvement was removed
146 # operation in which this improvement was removed
147 postdowngrademessage = None
147 postdowngrademessage = None
148
148
149 # By default for now, we assume every improvement touches all the things
149 # By default for now, we assume every improvement touches all the things
150 touches_filelogs = True
150 touches_filelogs = True
151 touches_manifests = True
151 touches_manifests = True
152 touches_changelog = True
152 touches_changelog = True
153 touches_requirements = True
153 touches_requirements = True
154
154
155 def __init__(self):
155 def __init__(self):
156 raise NotImplementedError()
156 raise NotImplementedError()
157
157
158 @staticmethod
158 @staticmethod
159 def fromrepo(repo):
159 def fromrepo(repo):
160 """current value of the variant in the repository"""
160 """current value of the variant in the repository"""
161 raise NotImplementedError()
161 raise NotImplementedError()
162
162
163 @staticmethod
163 @staticmethod
164 def fromconfig(repo):
164 def fromconfig(repo):
165 """current value of the variant in the configuration"""
165 """current value of the variant in the configuration"""
166 raise NotImplementedError()
166 raise NotImplementedError()
167
167
168
168
169 class requirementformatvariant(formatvariant):
169 class requirementformatvariant(formatvariant):
170 """formatvariant based on a 'requirement' name.
170 """formatvariant based on a 'requirement' name.
171
171
172 Many format variant are controlled by a 'requirement'. We define a small
172 Many format variant are controlled by a 'requirement'. We define a small
173 subclass to factor the code.
173 subclass to factor the code.
174 """
174 """
175
175
176 # the requirement that control this format variant
176 # the requirement that control this format variant
177 _requirement = None
177 _requirement = None
178
178
179 @staticmethod
179 @staticmethod
180 def _newreporequirements(ui):
180 def _newreporequirements(ui):
181 return localrepo.newreporequirements(
181 return localrepo.newreporequirements(
182 ui, localrepo.defaultcreateopts(ui)
182 ui, localrepo.defaultcreateopts(ui)
183 )
183 )
184
184
185 @classmethod
185 @classmethod
186 def fromrepo(cls, repo):
186 def fromrepo(cls, repo):
187 assert cls._requirement is not None
187 assert cls._requirement is not None
188 return cls._requirement in repo.requirements
188 return cls._requirement in repo.requirements
189
189
190 @classmethod
190 @classmethod
191 def fromconfig(cls, repo):
191 def fromconfig(cls, repo):
192 assert cls._requirement is not None
192 assert cls._requirement is not None
193 return cls._requirement in cls._newreporequirements(repo.ui)
193 return cls._requirement in cls._newreporequirements(repo.ui)
194
194
195
195
196 @registerformatvariant
196 @registerformatvariant
197 class fncache(requirementformatvariant):
197 class fncache(requirementformatvariant):
198 name = b'fncache'
198 name = b'fncache'
199
199
200 _requirement = requirements.FNCACHE_REQUIREMENT
200 _requirement = requirements.FNCACHE_REQUIREMENT
201
201
202 default = True
202 default = True
203
203
204 description = _(
204 description = _(
205 b'long and reserved filenames may not work correctly; '
205 b'long and reserved filenames may not work correctly; '
206 b'repository performance is sub-optimal'
206 b'repository performance is sub-optimal'
207 )
207 )
208
208
209 upgrademessage = _(
209 upgrademessage = _(
210 b'repository will be more resilient to storing '
210 b'repository will be more resilient to storing '
211 b'certain paths and performance of certain '
211 b'certain paths and performance of certain '
212 b'operations should be improved'
212 b'operations should be improved'
213 )
213 )
214
214
215
215
216 @registerformatvariant
216 @registerformatvariant
217 class dotencode(requirementformatvariant):
217 class dotencode(requirementformatvariant):
218 name = b'dotencode'
218 name = b'dotencode'
219
219
220 _requirement = requirements.DOTENCODE_REQUIREMENT
220 _requirement = requirements.DOTENCODE_REQUIREMENT
221
221
222 default = True
222 default = True
223
223
224 description = _(
224 description = _(
225 b'storage of filenames beginning with a period or '
225 b'storage of filenames beginning with a period or '
226 b'space may not work correctly'
226 b'space may not work correctly'
227 )
227 )
228
228
229 upgrademessage = _(
229 upgrademessage = _(
230 b'repository will be better able to store files '
230 b'repository will be better able to store files '
231 b'beginning with a space or period'
231 b'beginning with a space or period'
232 )
232 )
233
233
234
234
235 @registerformatvariant
235 @registerformatvariant
236 class generaldelta(requirementformatvariant):
236 class generaldelta(requirementformatvariant):
237 name = b'generaldelta'
237 name = b'generaldelta'
238
238
239 _requirement = requirements.GENERALDELTA_REQUIREMENT
239 _requirement = requirements.GENERALDELTA_REQUIREMENT
240
240
241 default = True
241 default = True
242
242
243 description = _(
243 description = _(
244 b'deltas within internal storage are unable to '
244 b'deltas within internal storage are unable to '
245 b'choose optimal revisions; repository is larger and '
245 b'choose optimal revisions; repository is larger and '
246 b'slower than it could be; interaction with other '
246 b'slower than it could be; interaction with other '
247 b'repositories may require extra network and CPU '
247 b'repositories may require extra network and CPU '
248 b'resources, making "hg push" and "hg pull" slower'
248 b'resources, making "hg push" and "hg pull" slower'
249 )
249 )
250
250
251 upgrademessage = _(
251 upgrademessage = _(
252 b'repository storage will be able to create '
252 b'repository storage will be able to create '
253 b'optimal deltas; new repository data will be '
253 b'optimal deltas; new repository data will be '
254 b'smaller and read times should decrease; '
254 b'smaller and read times should decrease; '
255 b'interacting with other repositories using this '
255 b'interacting with other repositories using this '
256 b'storage model should require less network and '
256 b'storage model should require less network and '
257 b'CPU resources, making "hg push" and "hg pull" '
257 b'CPU resources, making "hg push" and "hg pull" '
258 b'faster'
258 b'faster'
259 )
259 )
260
260
261
261
262 @registerformatvariant
262 @registerformatvariant
263 class sharesafe(requirementformatvariant):
263 class sharesafe(requirementformatvariant):
264 name = b'share-safe'
264 name = b'share-safe'
265 _requirement = requirements.SHARESAFE_REQUIREMENT
265 _requirement = requirements.SHARESAFE_REQUIREMENT
266
266
267 default = False
267 default = False
268
268
269 description = _(
269 description = _(
270 b'old shared repositories do not share source repository '
270 b'old shared repositories do not share source repository '
271 b'requirements and config. This leads to various problems '
271 b'requirements and config. This leads to various problems '
272 b'when the source repository format is upgraded or some new '
272 b'when the source repository format is upgraded or some new '
273 b'extensions are enabled.'
273 b'extensions are enabled.'
274 )
274 )
275
275
276 upgrademessage = _(
276 upgrademessage = _(
277 b'Upgrades a repository to share-safe format so that future '
277 b'Upgrades a repository to share-safe format so that future '
278 b'shares of this repository share its requirements and configs.'
278 b'shares of this repository share its requirements and configs.'
279 )
279 )
280
280
281 postdowngrademessage = _(
281 postdowngrademessage = _(
282 b'repository downgraded to not use share safe mode, '
282 b'repository downgraded to not use share safe mode, '
283 b'existing shares will not work and needs to'
283 b'existing shares will not work and needs to'
284 b' be reshared.'
284 b' be reshared.'
285 )
285 )
286
286
287 postupgrademessage = _(
287 postupgrademessage = _(
288 b'repository upgraded to share safe mode, existing'
288 b'repository upgraded to share safe mode, existing'
289 b' shares will still work in old non-safe mode. '
289 b' shares will still work in old non-safe mode. '
290 b'Re-share existing shares to use them in safe mode'
290 b'Re-share existing shares to use them in safe mode'
291 b' New shares will be created in safe mode.'
291 b' New shares will be created in safe mode.'
292 )
292 )
293
293
294 # upgrade only needs to change the requirements
294 # upgrade only needs to change the requirements
295 touches_filelogs = False
295 touches_filelogs = False
296 touches_manifests = False
296 touches_manifests = False
297 touches_changelog = False
297 touches_changelog = False
298 touches_requirements = True
298 touches_requirements = True
299
299
300
300
301 @registerformatvariant
301 @registerformatvariant
302 class sparserevlog(requirementformatvariant):
302 class sparserevlog(requirementformatvariant):
303 name = b'sparserevlog'
303 name = b'sparserevlog'
304
304
305 _requirement = requirements.SPARSEREVLOG_REQUIREMENT
305 _requirement = requirements.SPARSEREVLOG_REQUIREMENT
306
306
307 default = True
307 default = True
308
308
309 description = _(
309 description = _(
310 b'in order to limit disk reading and memory usage on older '
310 b'in order to limit disk reading and memory usage on older '
311 b'version, the span of a delta chain from its root to its '
311 b'version, the span of a delta chain from its root to its '
312 b'end is limited, whatever the relevant data in this span. '
312 b'end is limited, whatever the relevant data in this span. '
313 b'This can severly limit Mercurial ability to build good '
313 b'This can severly limit Mercurial ability to build good '
314 b'chain of delta resulting is much more storage space being '
314 b'chain of delta resulting is much more storage space being '
315 b'taken and limit reusability of on disk delta during '
315 b'taken and limit reusability of on disk delta during '
316 b'exchange.'
316 b'exchange.'
317 )
317 )
318
318
319 upgrademessage = _(
319 upgrademessage = _(
320 b'Revlog supports delta chain with more unused data '
320 b'Revlog supports delta chain with more unused data '
321 b'between payload. These gaps will be skipped at read '
321 b'between payload. These gaps will be skipped at read '
322 b'time. This allows for better delta chains, making a '
322 b'time. This allows for better delta chains, making a '
323 b'better compression and faster exchange with server.'
323 b'better compression and faster exchange with server.'
324 )
324 )
325
325
326
326
327 @registerformatvariant
327 @registerformatvariant
328 class sidedata(requirementformatvariant):
328 class sidedata(requirementformatvariant):
329 name = b'sidedata'
329 name = b'sidedata'
330
330
331 _requirement = requirements.SIDEDATA_REQUIREMENT
331 _requirement = requirements.REVLOGV2_REQUIREMENT
332
332
333 default = False
333 default = False
334
334
335 description = _(
335 description = _(
336 b'Allows storage of extra data alongside a revision, '
336 b'Allows storage of extra data alongside a revision, '
337 b'unlocking various caching options.'
337 b'unlocking various caching options.'
338 )
338 )
339
339
340 upgrademessage = _(b'Allows storage of extra data alongside a revision.')
340 upgrademessage = _(b'Allows storage of extra data alongside a revision.')
341
341
342 @classmethod
343 def fromrepo(cls, repo):
344 assert cls._requirement is not None
345 return cls._requirement in repo.requirements
346
342
347
343 @registerformatvariant
348 @registerformatvariant
344 class persistentnodemap(requirementformatvariant):
349 class persistentnodemap(requirementformatvariant):
345 name = b'persistent-nodemap'
350 name = b'persistent-nodemap'
346
351
347 _requirement = requirements.NODEMAP_REQUIREMENT
352 _requirement = requirements.NODEMAP_REQUIREMENT
348
353
349 default = False
354 default = False
350
355
351 description = _(
356 description = _(
352 b'persist the node -> rev mapping on disk to speedup lookup'
357 b'persist the node -> rev mapping on disk to speedup lookup'
353 )
358 )
354
359
355 upgrademessage = _(b'Speedup revision lookup by node id.')
360 upgrademessage = _(b'Speedup revision lookup by node id.')
356
361
357
362
358 @registerformatvariant
363 @registerformatvariant
359 class copiessdc(requirementformatvariant):
364 class copiessdc(requirementformatvariant):
360 name = b'copies-sdc'
365 name = b'copies-sdc'
361
366
362 _requirement = requirements.COPIESSDC_REQUIREMENT
367 _requirement = requirements.COPIESSDC_REQUIREMENT
363
368
364 default = False
369 default = False
365
370
366 description = _(b'Stores copies information alongside changesets.')
371 description = _(b'Stores copies information alongside changesets.')
367
372
368 upgrademessage = _(
373 upgrademessage = _(
369 b'Allows to use more efficient algorithm to deal with ' b'copy tracing.'
374 b'Allows to use more efficient algorithm to deal with ' b'copy tracing.'
370 )
375 )
371
376
372
377
373 @registerformatvariant
378 @registerformatvariant
379 class revlogv2(requirementformatvariant):
380 name = b'revlog-v2'
381 _requirement = requirements.REVLOGV2_REQUIREMENT
382 default = False
383 description = _(b'Version 2 of the revlog.')
384 upgrademessage = _(b'very experimental')
385
386
387 @registerformatvariant
374 class removecldeltachain(formatvariant):
388 class removecldeltachain(formatvariant):
375 name = b'plain-cl-delta'
389 name = b'plain-cl-delta'
376
390
377 default = True
391 default = True
378
392
379 description = _(
393 description = _(
380 b'changelog storage is using deltas instead of '
394 b'changelog storage is using deltas instead of '
381 b'raw entries; changelog reading and any '
395 b'raw entries; changelog reading and any '
382 b'operation relying on changelog data are slower '
396 b'operation relying on changelog data are slower '
383 b'than they could be'
397 b'than they could be'
384 )
398 )
385
399
386 upgrademessage = _(
400 upgrademessage = _(
387 b'changelog storage will be reformated to '
401 b'changelog storage will be reformated to '
388 b'store raw entries; changelog reading will be '
402 b'store raw entries; changelog reading will be '
389 b'faster; changelog size may be reduced'
403 b'faster; changelog size may be reduced'
390 )
404 )
391
405
392 @staticmethod
406 @staticmethod
393 def fromrepo(repo):
407 def fromrepo(repo):
394 # Mercurial 4.0 changed changelogs to not use delta chains. Search for
408 # Mercurial 4.0 changed changelogs to not use delta chains. Search for
395 # changelogs with deltas.
409 # changelogs with deltas.
396 cl = repo.changelog
410 cl = repo.changelog
397 chainbase = cl.chainbase
411 chainbase = cl.chainbase
398 return all(rev == chainbase(rev) for rev in cl)
412 return all(rev == chainbase(rev) for rev in cl)
399
413
400 @staticmethod
414 @staticmethod
401 def fromconfig(repo):
415 def fromconfig(repo):
402 return True
416 return True
403
417
404
418
405 @registerformatvariant
419 @registerformatvariant
406 class compressionengine(formatvariant):
420 class compressionengine(formatvariant):
407 name = b'compression'
421 name = b'compression'
408 default = b'zlib'
422 default = b'zlib'
409
423
410 description = _(
424 description = _(
411 b'Compresion algorithm used to compress data. '
425 b'Compresion algorithm used to compress data. '
412 b'Some engine are faster than other'
426 b'Some engine are faster than other'
413 )
427 )
414
428
415 upgrademessage = _(
429 upgrademessage = _(
416 b'revlog content will be recompressed with the new algorithm.'
430 b'revlog content will be recompressed with the new algorithm.'
417 )
431 )
418
432
419 @classmethod
433 @classmethod
420 def fromrepo(cls, repo):
434 def fromrepo(cls, repo):
421 # we allow multiple compression engine requirement to co-exist because
435 # we allow multiple compression engine requirement to co-exist because
422 # strickly speaking, revlog seems to support mixed compression style.
436 # strickly speaking, revlog seems to support mixed compression style.
423 #
437 #
424 # The compression used for new entries will be "the last one"
438 # The compression used for new entries will be "the last one"
425 compression = b'zlib'
439 compression = b'zlib'
426 for req in repo.requirements:
440 for req in repo.requirements:
427 prefix = req.startswith
441 prefix = req.startswith
428 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
442 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
429 compression = req.split(b'-', 2)[2]
443 compression = req.split(b'-', 2)[2]
430 return compression
444 return compression
431
445
432 @classmethod
446 @classmethod
433 def fromconfig(cls, repo):
447 def fromconfig(cls, repo):
434 compengines = repo.ui.configlist(b'format', b'revlog-compression')
448 compengines = repo.ui.configlist(b'format', b'revlog-compression')
435 # return the first valid value as the selection code would do
449 # return the first valid value as the selection code would do
436 for comp in compengines:
450 for comp in compengines:
437 if comp in util.compengines:
451 if comp in util.compengines:
438 return comp
452 return comp
439
453
440 # no valide compression found lets display it all for clarity
454 # no valide compression found lets display it all for clarity
441 return b','.join(compengines)
455 return b','.join(compengines)
442
456
443
457
444 @registerformatvariant
458 @registerformatvariant
445 class compressionlevel(formatvariant):
459 class compressionlevel(formatvariant):
446 name = b'compression-level'
460 name = b'compression-level'
447 default = b'default'
461 default = b'default'
448
462
449 description = _(b'compression level')
463 description = _(b'compression level')
450
464
451 upgrademessage = _(b'revlog content will be recompressed')
465 upgrademessage = _(b'revlog content will be recompressed')
452
466
453 @classmethod
467 @classmethod
454 def fromrepo(cls, repo):
468 def fromrepo(cls, repo):
455 comp = compressionengine.fromrepo(repo)
469 comp = compressionengine.fromrepo(repo)
456 level = None
470 level = None
457 if comp == b'zlib':
471 if comp == b'zlib':
458 level = repo.ui.configint(b'storage', b'revlog.zlib.level')
472 level = repo.ui.configint(b'storage', b'revlog.zlib.level')
459 elif comp == b'zstd':
473 elif comp == b'zstd':
460 level = repo.ui.configint(b'storage', b'revlog.zstd.level')
474 level = repo.ui.configint(b'storage', b'revlog.zstd.level')
461 if level is None:
475 if level is None:
462 return b'default'
476 return b'default'
463 return bytes(level)
477 return bytes(level)
464
478
465 @classmethod
479 @classmethod
466 def fromconfig(cls, repo):
480 def fromconfig(cls, repo):
467 comp = compressionengine.fromconfig(repo)
481 comp = compressionengine.fromconfig(repo)
468 level = None
482 level = None
469 if comp == b'zlib':
483 if comp == b'zlib':
470 level = repo.ui.configint(b'storage', b'revlog.zlib.level')
484 level = repo.ui.configint(b'storage', b'revlog.zlib.level')
471 elif comp == b'zstd':
485 elif comp == b'zstd':
472 level = repo.ui.configint(b'storage', b'revlog.zstd.level')
486 level = repo.ui.configint(b'storage', b'revlog.zstd.level')
473 if level is None:
487 if level is None:
474 return b'default'
488 return b'default'
475 return bytes(level)
489 return bytes(level)
476
490
477
491
478 def find_format_upgrades(repo):
492 def find_format_upgrades(repo):
479 """returns a list of format upgrades which can be perform on the repo"""
493 """returns a list of format upgrades which can be perform on the repo"""
480 upgrades = []
494 upgrades = []
481
495
482 # We could detect lack of revlogv1 and store here, but they were added
496 # We could detect lack of revlogv1 and store here, but they were added
483 # in 0.9.2 and we don't support upgrading repos without these
497 # in 0.9.2 and we don't support upgrading repos without these
484 # requirements, so let's not bother.
498 # requirements, so let's not bother.
485
499
486 for fv in allformatvariant:
500 for fv in allformatvariant:
487 if not fv.fromrepo(repo):
501 if not fv.fromrepo(repo):
488 upgrades.append(fv)
502 upgrades.append(fv)
489
503
490 return upgrades
504 return upgrades
491
505
492
506
493 def find_format_downgrades(repo):
507 def find_format_downgrades(repo):
494 """returns a list of format downgrades which will be performed on the repo
508 """returns a list of format downgrades which will be performed on the repo
495 because of disabled config option for them"""
509 because of disabled config option for them"""
496
510
497 downgrades = []
511 downgrades = []
498
512
499 for fv in allformatvariant:
513 for fv in allformatvariant:
500 if fv.name == b'compression':
514 if fv.name == b'compression':
501 # If there is a compression change between repository
515 # If there is a compression change between repository
502 # and config, destination repository compression will change
516 # and config, destination repository compression will change
503 # and current compression will be removed.
517 # and current compression will be removed.
504 if fv.fromrepo(repo) != fv.fromconfig(repo):
518 if fv.fromrepo(repo) != fv.fromconfig(repo):
505 downgrades.append(fv)
519 downgrades.append(fv)
506 continue
520 continue
507 # format variant exist in repo but does not exist in new repository
521 # format variant exist in repo but does not exist in new repository
508 # config
522 # config
509 if fv.fromrepo(repo) and not fv.fromconfig(repo):
523 if fv.fromrepo(repo) and not fv.fromconfig(repo):
510 downgrades.append(fv)
524 downgrades.append(fv)
511
525
512 return downgrades
526 return downgrades
513
527
514
528
515 ALL_OPTIMISATIONS = []
529 ALL_OPTIMISATIONS = []
516
530
517
531
518 def register_optimization(obj):
532 def register_optimization(obj):
519 ALL_OPTIMISATIONS.append(obj)
533 ALL_OPTIMISATIONS.append(obj)
520 return obj
534 return obj
521
535
522
536
523 register_optimization(
537 register_optimization(
524 improvement(
538 improvement(
525 name=b're-delta-parent',
539 name=b're-delta-parent',
526 type=OPTIMISATION,
540 type=OPTIMISATION,
527 description=_(
541 description=_(
528 b'deltas within internal storage will be recalculated to '
542 b'deltas within internal storage will be recalculated to '
529 b'choose an optimal base revision where this was not '
543 b'choose an optimal base revision where this was not '
530 b'already done; the size of the repository may shrink and '
544 b'already done; the size of the repository may shrink and '
531 b'various operations may become faster; the first time '
545 b'various operations may become faster; the first time '
532 b'this optimization is performed could slow down upgrade '
546 b'this optimization is performed could slow down upgrade '
533 b'execution considerably; subsequent invocations should '
547 b'execution considerably; subsequent invocations should '
534 b'not run noticeably slower'
548 b'not run noticeably slower'
535 ),
549 ),
536 upgrademessage=_(
550 upgrademessage=_(
537 b'deltas within internal storage will choose a new '
551 b'deltas within internal storage will choose a new '
538 b'base revision if needed'
552 b'base revision if needed'
539 ),
553 ),
540 )
554 )
541 )
555 )
542
556
543 register_optimization(
557 register_optimization(
544 improvement(
558 improvement(
545 name=b're-delta-multibase',
559 name=b're-delta-multibase',
546 type=OPTIMISATION,
560 type=OPTIMISATION,
547 description=_(
561 description=_(
548 b'deltas within internal storage will be recalculated '
562 b'deltas within internal storage will be recalculated '
549 b'against multiple base revision and the smallest '
563 b'against multiple base revision and the smallest '
550 b'difference will be used; the size of the repository may '
564 b'difference will be used; the size of the repository may '
551 b'shrink significantly when there are many merges; this '
565 b'shrink significantly when there are many merges; this '
552 b'optimization will slow down execution in proportion to '
566 b'optimization will slow down execution in proportion to '
553 b'the number of merges in the repository and the amount '
567 b'the number of merges in the repository and the amount '
554 b'of files in the repository; this slow down should not '
568 b'of files in the repository; this slow down should not '
555 b'be significant unless there are tens of thousands of '
569 b'be significant unless there are tens of thousands of '
556 b'files and thousands of merges'
570 b'files and thousands of merges'
557 ),
571 ),
558 upgrademessage=_(
572 upgrademessage=_(
559 b'deltas within internal storage will choose an '
573 b'deltas within internal storage will choose an '
560 b'optimal delta by computing deltas against multiple '
574 b'optimal delta by computing deltas against multiple '
561 b'parents; may slow down execution time '
575 b'parents; may slow down execution time '
562 b'significantly'
576 b'significantly'
563 ),
577 ),
564 )
578 )
565 )
579 )
566
580
567 register_optimization(
581 register_optimization(
568 improvement(
582 improvement(
569 name=b're-delta-all',
583 name=b're-delta-all',
570 type=OPTIMISATION,
584 type=OPTIMISATION,
571 description=_(
585 description=_(
572 b'deltas within internal storage will always be '
586 b'deltas within internal storage will always be '
573 b'recalculated without reusing prior deltas; this will '
587 b'recalculated without reusing prior deltas; this will '
574 b'likely make execution run several times slower; this '
588 b'likely make execution run several times slower; this '
575 b'optimization is typically not needed'
589 b'optimization is typically not needed'
576 ),
590 ),
577 upgrademessage=_(
591 upgrademessage=_(
578 b'deltas within internal storage will be fully '
592 b'deltas within internal storage will be fully '
579 b'recomputed; this will likely drastically slow down '
593 b'recomputed; this will likely drastically slow down '
580 b'execution time'
594 b'execution time'
581 ),
595 ),
582 )
596 )
583 )
597 )
584
598
585 register_optimization(
599 register_optimization(
586 improvement(
600 improvement(
587 name=b're-delta-fulladd',
601 name=b're-delta-fulladd',
588 type=OPTIMISATION,
602 type=OPTIMISATION,
589 description=_(
603 description=_(
590 b'every revision will be re-added as if it was new '
604 b'every revision will be re-added as if it was new '
591 b'content. It will go through the full storage '
605 b'content. It will go through the full storage '
592 b'mechanism giving extensions a chance to process it '
606 b'mechanism giving extensions a chance to process it '
593 b'(eg. lfs). This is similar to "re-delta-all" but even '
607 b'(eg. lfs). This is similar to "re-delta-all" but even '
594 b'slower since more logic is involved.'
608 b'slower since more logic is involved.'
595 ),
609 ),
596 upgrademessage=_(
610 upgrademessage=_(
597 b'each revision will be added as new content to the '
611 b'each revision will be added as new content to the '
598 b'internal storage; this will likely drastically slow '
612 b'internal storage; this will likely drastically slow '
599 b'down execution time, but some extensions might need '
613 b'down execution time, but some extensions might need '
600 b'it'
614 b'it'
601 ),
615 ),
602 )
616 )
603 )
617 )
604
618
605
619
606 def findoptimizations(repo):
620 def findoptimizations(repo):
607 """Determine optimisation that could be used during upgrade"""
621 """Determine optimisation that could be used during upgrade"""
608 # These are unconditionally added. There is logic later that figures out
622 # These are unconditionally added. There is logic later that figures out
609 # which ones to apply.
623 # which ones to apply.
610 return list(ALL_OPTIMISATIONS)
624 return list(ALL_OPTIMISATIONS)
611
625
612
626
613 def determine_upgrade_actions(
627 def determine_upgrade_actions(
614 repo, format_upgrades, optimizations, sourcereqs, destreqs
628 repo, format_upgrades, optimizations, sourcereqs, destreqs
615 ):
629 ):
616 """Determine upgrade actions that will be performed.
630 """Determine upgrade actions that will be performed.
617
631
618 Given a list of improvements as returned by ``find_format_upgrades`` and
632 Given a list of improvements as returned by ``find_format_upgrades`` and
619 ``findoptimizations``, determine the list of upgrade actions that
633 ``findoptimizations``, determine the list of upgrade actions that
620 will be performed.
634 will be performed.
621
635
622 The role of this function is to filter improvements if needed, apply
636 The role of this function is to filter improvements if needed, apply
623 recommended optimizations from the improvements list that make sense,
637 recommended optimizations from the improvements list that make sense,
624 etc.
638 etc.
625
639
626 Returns a list of action names.
640 Returns a list of action names.
627 """
641 """
628 newactions = []
642 newactions = []
629
643
630 for d in format_upgrades:
644 for d in format_upgrades:
631 name = d._requirement
645 name = d._requirement
632
646
633 # If the action is a requirement that doesn't show up in the
647 # If the action is a requirement that doesn't show up in the
634 # destination requirements, prune the action.
648 # destination requirements, prune the action.
635 if name is not None and name not in destreqs:
649 if name is not None and name not in destreqs:
636 continue
650 continue
637
651
638 newactions.append(d)
652 newactions.append(d)
639
653
640 newactions.extend(o for o in sorted(optimizations) if o not in newactions)
654 newactions.extend(o for o in sorted(optimizations) if o not in newactions)
641
655
642 # FUTURE consider adding some optimizations here for certain transitions.
656 # FUTURE consider adding some optimizations here for certain transitions.
643 # e.g. adding generaldelta could schedule parent redeltas.
657 # e.g. adding generaldelta could schedule parent redeltas.
644
658
645 return newactions
659 return newactions
646
660
647
661
648 class UpgradeOperation(object):
662 class UpgradeOperation(object):
649 """represent the work to be done during an upgrade"""
663 """represent the work to be done during an upgrade"""
650
664
651 def __init__(
665 def __init__(
652 self,
666 self,
653 ui,
667 ui,
654 new_requirements,
668 new_requirements,
655 current_requirements,
669 current_requirements,
656 upgrade_actions,
670 upgrade_actions,
657 removed_actions,
671 removed_actions,
658 revlogs_to_process,
672 revlogs_to_process,
659 backup_store,
673 backup_store,
660 ):
674 ):
661 self.ui = ui
675 self.ui = ui
662 self.new_requirements = new_requirements
676 self.new_requirements = new_requirements
663 self.current_requirements = current_requirements
677 self.current_requirements = current_requirements
664 # list of upgrade actions the operation will perform
678 # list of upgrade actions the operation will perform
665 self.upgrade_actions = upgrade_actions
679 self.upgrade_actions = upgrade_actions
666 self._upgrade_actions_names = set([a.name for a in upgrade_actions])
680 self._upgrade_actions_names = set([a.name for a in upgrade_actions])
667 self.removed_actions = removed_actions
681 self.removed_actions = removed_actions
668 self.revlogs_to_process = revlogs_to_process
682 self.revlogs_to_process = revlogs_to_process
669 # requirements which will be added by the operation
683 # requirements which will be added by the operation
670 self._added_requirements = (
684 self._added_requirements = (
671 self.new_requirements - self.current_requirements
685 self.new_requirements - self.current_requirements
672 )
686 )
673 # requirements which will be removed by the operation
687 # requirements which will be removed by the operation
674 self._removed_requirements = (
688 self._removed_requirements = (
675 self.current_requirements - self.new_requirements
689 self.current_requirements - self.new_requirements
676 )
690 )
677 # requirements which will be preserved by the operation
691 # requirements which will be preserved by the operation
678 self._preserved_requirements = (
692 self._preserved_requirements = (
679 self.current_requirements & self.new_requirements
693 self.current_requirements & self.new_requirements
680 )
694 )
681 # optimizations which are not used and it's recommended that they
695 # optimizations which are not used and it's recommended that they
682 # should use them
696 # should use them
683 all_optimizations = findoptimizations(None)
697 all_optimizations = findoptimizations(None)
684 self.unused_optimizations = [
698 self.unused_optimizations = [
685 i for i in all_optimizations if i not in self.upgrade_actions
699 i for i in all_optimizations if i not in self.upgrade_actions
686 ]
700 ]
687
701
688 # delta reuse mode of this upgrade operation
702 # delta reuse mode of this upgrade operation
689 self.delta_reuse_mode = revlog.revlog.DELTAREUSEALWAYS
703 self.delta_reuse_mode = revlog.revlog.DELTAREUSEALWAYS
690 if b're-delta-all' in self._upgrade_actions_names:
704 if b're-delta-all' in self._upgrade_actions_names:
691 self.delta_reuse_mode = revlog.revlog.DELTAREUSENEVER
705 self.delta_reuse_mode = revlog.revlog.DELTAREUSENEVER
692 elif b're-delta-parent' in self._upgrade_actions_names:
706 elif b're-delta-parent' in self._upgrade_actions_names:
693 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS
707 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS
694 elif b're-delta-multibase' in self._upgrade_actions_names:
708 elif b're-delta-multibase' in self._upgrade_actions_names:
695 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS
709 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS
696 elif b're-delta-fulladd' in self._upgrade_actions_names:
710 elif b're-delta-fulladd' in self._upgrade_actions_names:
697 self.delta_reuse_mode = revlog.revlog.DELTAREUSEFULLADD
711 self.delta_reuse_mode = revlog.revlog.DELTAREUSEFULLADD
698
712
699 # should this operation force re-delta of both parents
713 # should this operation force re-delta of both parents
700 self.force_re_delta_both_parents = (
714 self.force_re_delta_both_parents = (
701 b're-delta-multibase' in self._upgrade_actions_names
715 b're-delta-multibase' in self._upgrade_actions_names
702 )
716 )
703
717
704 # should this operation create a backup of the store
718 # should this operation create a backup of the store
705 self.backup_store = backup_store
719 self.backup_store = backup_store
706
720
707 # whether the operation touches different revlogs at all or not
721 # whether the operation touches different revlogs at all or not
708 self.touches_filelogs = self._touches_filelogs()
722 self.touches_filelogs = self._touches_filelogs()
709 self.touches_manifests = self._touches_manifests()
723 self.touches_manifests = self._touches_manifests()
710 self.touches_changelog = self._touches_changelog()
724 self.touches_changelog = self._touches_changelog()
711 # whether the operation touches requirements file or not
725 # whether the operation touches requirements file or not
712 self.touches_requirements = self._touches_requirements()
726 self.touches_requirements = self._touches_requirements()
713 self.touches_store = (
727 self.touches_store = (
714 self.touches_filelogs
728 self.touches_filelogs
715 or self.touches_manifests
729 or self.touches_manifests
716 or self.touches_changelog
730 or self.touches_changelog
717 )
731 )
718 # does the operation only touches repository requirement
732 # does the operation only touches repository requirement
719 self.requirements_only = (
733 self.requirements_only = (
720 self.touches_requirements and not self.touches_store
734 self.touches_requirements and not self.touches_store
721 )
735 )
722
736
723 def _touches_filelogs(self):
737 def _touches_filelogs(self):
724 for a in self.upgrade_actions:
738 for a in self.upgrade_actions:
725 # in optimisations, we re-process the revlogs again
739 # in optimisations, we re-process the revlogs again
726 if a.type == OPTIMISATION:
740 if a.type == OPTIMISATION:
727 return True
741 return True
728 elif a.touches_filelogs:
742 elif a.touches_filelogs:
729 return True
743 return True
730 for a in self.removed_actions:
744 for a in self.removed_actions:
731 if a.touches_filelogs:
745 if a.touches_filelogs:
732 return True
746 return True
733 return False
747 return False
734
748
735 def _touches_manifests(self):
749 def _touches_manifests(self):
736 for a in self.upgrade_actions:
750 for a in self.upgrade_actions:
737 # in optimisations, we re-process the revlogs again
751 # in optimisations, we re-process the revlogs again
738 if a.type == OPTIMISATION:
752 if a.type == OPTIMISATION:
739 return True
753 return True
740 elif a.touches_manifests:
754 elif a.touches_manifests:
741 return True
755 return True
742 for a in self.removed_actions:
756 for a in self.removed_actions:
743 if a.touches_manifests:
757 if a.touches_manifests:
744 return True
758 return True
745 return False
759 return False
746
760
747 def _touches_changelog(self):
761 def _touches_changelog(self):
748 for a in self.upgrade_actions:
762 for a in self.upgrade_actions:
749 # in optimisations, we re-process the revlogs again
763 # in optimisations, we re-process the revlogs again
750 if a.type == OPTIMISATION:
764 if a.type == OPTIMISATION:
751 return True
765 return True
752 elif a.touches_changelog:
766 elif a.touches_changelog:
753 return True
767 return True
754 for a in self.removed_actions:
768 for a in self.removed_actions:
755 if a.touches_changelog:
769 if a.touches_changelog:
756 return True
770 return True
757 return False
771 return False
758
772
759 def _touches_requirements(self):
773 def _touches_requirements(self):
760 for a in self.upgrade_actions:
774 for a in self.upgrade_actions:
761 # optimisations are used to re-process revlogs and does not result
775 # optimisations are used to re-process revlogs and does not result
762 # in a requirement being added or removed
776 # in a requirement being added or removed
763 if a.type == OPTIMISATION:
777 if a.type == OPTIMISATION:
764 pass
778 pass
765 elif a.touches_requirements:
779 elif a.touches_requirements:
766 return True
780 return True
767 for a in self.removed_actions:
781 for a in self.removed_actions:
768 if a.touches_requirements:
782 if a.touches_requirements:
769 return True
783 return True
770
784
771 return False
785 return False
772
786
773 def _write_labeled(self, l, label):
787 def _write_labeled(self, l, label):
774 """
788 """
775 Utility function to aid writing of a list under one label
789 Utility function to aid writing of a list under one label
776 """
790 """
777 first = True
791 first = True
778 for r in sorted(l):
792 for r in sorted(l):
779 if not first:
793 if not first:
780 self.ui.write(b', ')
794 self.ui.write(b', ')
781 self.ui.write(r, label=label)
795 self.ui.write(r, label=label)
782 first = False
796 first = False
783
797
784 def print_requirements(self):
798 def print_requirements(self):
785 self.ui.write(_(b'requirements\n'))
799 self.ui.write(_(b'requirements\n'))
786 self.ui.write(_(b' preserved: '))
800 self.ui.write(_(b' preserved: '))
787 self._write_labeled(
801 self._write_labeled(
788 self._preserved_requirements, "upgrade-repo.requirement.preserved"
802 self._preserved_requirements, "upgrade-repo.requirement.preserved"
789 )
803 )
790 self.ui.write((b'\n'))
804 self.ui.write((b'\n'))
791 if self._removed_requirements:
805 if self._removed_requirements:
792 self.ui.write(_(b' removed: '))
806 self.ui.write(_(b' removed: '))
793 self._write_labeled(
807 self._write_labeled(
794 self._removed_requirements, "upgrade-repo.requirement.removed"
808 self._removed_requirements, "upgrade-repo.requirement.removed"
795 )
809 )
796 self.ui.write((b'\n'))
810 self.ui.write((b'\n'))
797 if self._added_requirements:
811 if self._added_requirements:
798 self.ui.write(_(b' added: '))
812 self.ui.write(_(b' added: '))
799 self._write_labeled(
813 self._write_labeled(
800 self._added_requirements, "upgrade-repo.requirement.added"
814 self._added_requirements, "upgrade-repo.requirement.added"
801 )
815 )
802 self.ui.write((b'\n'))
816 self.ui.write((b'\n'))
803 self.ui.write(b'\n')
817 self.ui.write(b'\n')
804
818
805 def print_optimisations(self):
819 def print_optimisations(self):
806 optimisations = [
820 optimisations = [
807 a for a in self.upgrade_actions if a.type == OPTIMISATION
821 a for a in self.upgrade_actions if a.type == OPTIMISATION
808 ]
822 ]
809 optimisations.sort(key=lambda a: a.name)
823 optimisations.sort(key=lambda a: a.name)
810 if optimisations:
824 if optimisations:
811 self.ui.write(_(b'optimisations: '))
825 self.ui.write(_(b'optimisations: '))
812 self._write_labeled(
826 self._write_labeled(
813 [a.name for a in optimisations],
827 [a.name for a in optimisations],
814 "upgrade-repo.optimisation.performed",
828 "upgrade-repo.optimisation.performed",
815 )
829 )
816 self.ui.write(b'\n\n')
830 self.ui.write(b'\n\n')
817
831
818 def print_upgrade_actions(self):
832 def print_upgrade_actions(self):
819 for a in self.upgrade_actions:
833 for a in self.upgrade_actions:
820 self.ui.status(b'%s\n %s\n\n' % (a.name, a.upgrademessage))
834 self.ui.status(b'%s\n %s\n\n' % (a.name, a.upgrademessage))
821
835
822 def print_affected_revlogs(self):
836 def print_affected_revlogs(self):
823 if not self.revlogs_to_process:
837 if not self.revlogs_to_process:
824 self.ui.write((b'no revlogs to process\n'))
838 self.ui.write((b'no revlogs to process\n'))
825 else:
839 else:
826 self.ui.write((b'processed revlogs:\n'))
840 self.ui.write((b'processed revlogs:\n'))
827 for r in sorted(self.revlogs_to_process):
841 for r in sorted(self.revlogs_to_process):
828 self.ui.write((b' - %s\n' % r))
842 self.ui.write((b' - %s\n' % r))
829 self.ui.write((b'\n'))
843 self.ui.write((b'\n'))
830
844
831 def print_unused_optimizations(self):
845 def print_unused_optimizations(self):
832 for i in self.unused_optimizations:
846 for i in self.unused_optimizations:
833 self.ui.status(_(b'%s\n %s\n\n') % (i.name, i.description))
847 self.ui.status(_(b'%s\n %s\n\n') % (i.name, i.description))
834
848
835 def has_upgrade_action(self, name):
849 def has_upgrade_action(self, name):
836 """ Check whether the upgrade operation will perform this action """
850 """ Check whether the upgrade operation will perform this action """
837 return name in self._upgrade_actions_names
851 return name in self._upgrade_actions_names
838
852
839 def print_post_op_messages(self):
853 def print_post_op_messages(self):
840 """ print post upgrade operation warning messages """
854 """ print post upgrade operation warning messages """
841 for a in self.upgrade_actions:
855 for a in self.upgrade_actions:
842 if a.postupgrademessage is not None:
856 if a.postupgrademessage is not None:
843 self.ui.warn(b'%s\n' % a.postupgrademessage)
857 self.ui.warn(b'%s\n' % a.postupgrademessage)
844 for a in self.removed_actions:
858 for a in self.removed_actions:
845 if a.postdowngrademessage is not None:
859 if a.postdowngrademessage is not None:
846 self.ui.warn(b'%s\n' % a.postdowngrademessage)
860 self.ui.warn(b'%s\n' % a.postdowngrademessage)
847
861
848
862
849 ### Code checking if a repository can got through the upgrade process at all. #
863 ### Code checking if a repository can got through the upgrade process at all. #
850
864
851
865
852 def requiredsourcerequirements(repo):
866 def requiredsourcerequirements(repo):
853 """Obtain requirements required to be present to upgrade a repo.
867 """Obtain requirements required to be present to upgrade a repo.
854
868
855 An upgrade will not be allowed if the repository doesn't have the
869 An upgrade will not be allowed if the repository doesn't have the
856 requirements returned by this function.
870 requirements returned by this function.
857 """
871 """
858 return {
872 return {
859 # Introduced in Mercurial 0.9.2.
873 # Introduced in Mercurial 0.9.2.
860 requirements.REVLOGV1_REQUIREMENT,
861 # Introduced in Mercurial 0.9.2.
862 requirements.STORE_REQUIREMENT,
874 requirements.STORE_REQUIREMENT,
863 }
875 }
864
876
865
877
866 def blocksourcerequirements(repo):
878 def blocksourcerequirements(repo):
867 """Obtain requirements that will prevent an upgrade from occurring.
879 """Obtain requirements that will prevent an upgrade from occurring.
868
880
869 An upgrade cannot be performed if the source repository contains a
881 An upgrade cannot be performed if the source repository contains a
870 requirements in the returned set.
882 requirements in the returned set.
871 """
883 """
872 return {
884 return {
873 # The upgrade code does not yet support these experimental features.
885 # The upgrade code does not yet support these experimental features.
874 # This is an artificial limitation.
886 # This is an artificial limitation.
875 requirements.TREEMANIFEST_REQUIREMENT,
887 requirements.TREEMANIFEST_REQUIREMENT,
876 # This was a precursor to generaldelta and was never enabled by default.
888 # This was a precursor to generaldelta and was never enabled by default.
877 # It should (hopefully) not exist in the wild.
889 # It should (hopefully) not exist in the wild.
878 b'parentdelta',
890 b'parentdelta',
879 # Upgrade should operate on the actual store, not the shared link.
891 # Upgrade should operate on the actual store, not the shared link.
880 requirements.SHARED_REQUIREMENT,
892 requirements.SHARED_REQUIREMENT,
881 }
893 }
882
894
883
895
896 def check_revlog_version(reqs):
897 """Check that the requirements contain at least one Revlog version"""
898 all_revlogs = {
899 requirements.REVLOGV1_REQUIREMENT,
900 requirements.REVLOGV2_REQUIREMENT,
901 }
902 if not all_revlogs.intersection(reqs):
903 msg = _(b'cannot upgrade repository; missing a revlog version')
904 raise error.Abort(msg)
905
906
884 def check_source_requirements(repo):
907 def check_source_requirements(repo):
885 """Ensure that no existing requirements prevent the repository upgrade"""
908 """Ensure that no existing requirements prevent the repository upgrade"""
886
909
910 check_revlog_version(repo.requirements)
887 required = requiredsourcerequirements(repo)
911 required = requiredsourcerequirements(repo)
888 missingreqs = required - repo.requirements
912 missingreqs = required - repo.requirements
889 if missingreqs:
913 if missingreqs:
890 msg = _(b'cannot upgrade repository; requirement missing: %s')
914 msg = _(b'cannot upgrade repository; requirement missing: %s')
891 missingreqs = b', '.join(sorted(missingreqs))
915 missingreqs = b', '.join(sorted(missingreqs))
892 raise error.Abort(msg % missingreqs)
916 raise error.Abort(msg % missingreqs)
893
917
894 blocking = blocksourcerequirements(repo)
918 blocking = blocksourcerequirements(repo)
895 blockingreqs = blocking & repo.requirements
919 blockingreqs = blocking & repo.requirements
896 if blockingreqs:
920 if blockingreqs:
897 m = _(b'cannot upgrade repository; unsupported source requirement: %s')
921 m = _(b'cannot upgrade repository; unsupported source requirement: %s')
898 blockingreqs = b', '.join(sorted(blockingreqs))
922 blockingreqs = b', '.join(sorted(blockingreqs))
899 raise error.Abort(m % blockingreqs)
923 raise error.Abort(m % blockingreqs)
900
924
901
925
902 ### Verify the validity of the planned requirement changes ####################
926 ### Verify the validity of the planned requirement changes ####################
903
927
904
928
905 def supportremovedrequirements(repo):
929 def supportremovedrequirements(repo):
906 """Obtain requirements that can be removed during an upgrade.
930 """Obtain requirements that can be removed during an upgrade.
907
931
908 If an upgrade were to create a repository that dropped a requirement,
932 If an upgrade were to create a repository that dropped a requirement,
909 the dropped requirement must appear in the returned set for the upgrade
933 the dropped requirement must appear in the returned set for the upgrade
910 to be allowed.
934 to be allowed.
911 """
935 """
912 supported = {
936 supported = {
913 requirements.SPARSEREVLOG_REQUIREMENT,
937 requirements.SPARSEREVLOG_REQUIREMENT,
914 requirements.SIDEDATA_REQUIREMENT,
938 requirements.SIDEDATA_REQUIREMENT,
915 requirements.COPIESSDC_REQUIREMENT,
939 requirements.COPIESSDC_REQUIREMENT,
916 requirements.NODEMAP_REQUIREMENT,
940 requirements.NODEMAP_REQUIREMENT,
917 requirements.SHARESAFE_REQUIREMENT,
941 requirements.SHARESAFE_REQUIREMENT,
942 requirements.REVLOGV2_REQUIREMENT,
943 requirements.REVLOGV1_REQUIREMENT,
918 }
944 }
919 for name in compression.compengines:
945 for name in compression.compengines:
920 engine = compression.compengines[name]
946 engine = compression.compengines[name]
921 if engine.available() and engine.revlogheader():
947 if engine.available() and engine.revlogheader():
922 supported.add(b'exp-compression-%s' % name)
948 supported.add(b'exp-compression-%s' % name)
923 if engine.name() == b'zstd':
949 if engine.name() == b'zstd':
924 supported.add(b'revlog-compression-zstd')
950 supported.add(b'revlog-compression-zstd')
925 return supported
951 return supported
926
952
927
953
928 def supporteddestrequirements(repo):
954 def supporteddestrequirements(repo):
929 """Obtain requirements that upgrade supports in the destination.
955 """Obtain requirements that upgrade supports in the destination.
930
956
931 If the result of the upgrade would create requirements not in this set,
957 If the result of the upgrade would create requirements not in this set,
932 the upgrade is disallowed.
958 the upgrade is disallowed.
933
959
934 Extensions should monkeypatch this to add their custom requirements.
960 Extensions should monkeypatch this to add their custom requirements.
935 """
961 """
936 supported = {
962 supported = {
937 requirements.DOTENCODE_REQUIREMENT,
963 requirements.DOTENCODE_REQUIREMENT,
938 requirements.FNCACHE_REQUIREMENT,
964 requirements.FNCACHE_REQUIREMENT,
939 requirements.GENERALDELTA_REQUIREMENT,
965 requirements.GENERALDELTA_REQUIREMENT,
940 requirements.REVLOGV1_REQUIREMENT,
966 requirements.REVLOGV1_REQUIREMENT, # allowed in case of downgrade
941 requirements.STORE_REQUIREMENT,
967 requirements.STORE_REQUIREMENT,
942 requirements.SPARSEREVLOG_REQUIREMENT,
968 requirements.SPARSEREVLOG_REQUIREMENT,
943 requirements.SIDEDATA_REQUIREMENT,
969 requirements.SIDEDATA_REQUIREMENT,
944 requirements.COPIESSDC_REQUIREMENT,
970 requirements.COPIESSDC_REQUIREMENT,
945 requirements.NODEMAP_REQUIREMENT,
971 requirements.NODEMAP_REQUIREMENT,
946 requirements.SHARESAFE_REQUIREMENT,
972 requirements.SHARESAFE_REQUIREMENT,
973 requirements.REVLOGV2_REQUIREMENT,
947 }
974 }
948 for name in compression.compengines:
975 for name in compression.compengines:
949 engine = compression.compengines[name]
976 engine = compression.compengines[name]
950 if engine.available() and engine.revlogheader():
977 if engine.available() and engine.revlogheader():
951 supported.add(b'exp-compression-%s' % name)
978 supported.add(b'exp-compression-%s' % name)
952 if engine.name() == b'zstd':
979 if engine.name() == b'zstd':
953 supported.add(b'revlog-compression-zstd')
980 supported.add(b'revlog-compression-zstd')
954 return supported
981 return supported
955
982
956
983
957 def allowednewrequirements(repo):
984 def allowednewrequirements(repo):
958 """Obtain requirements that can be added to a repository during upgrade.
985 """Obtain requirements that can be added to a repository during upgrade.
959
986
960 This is used to disallow proposed requirements from being added when
987 This is used to disallow proposed requirements from being added when
961 they weren't present before.
988 they weren't present before.
962
989
963 We use a list of allowed requirement additions instead of a list of known
990 We use a list of allowed requirement additions instead of a list of known
964 bad additions because the whitelist approach is safer and will prevent
991 bad additions because the whitelist approach is safer and will prevent
965 future, unknown requirements from accidentally being added.
992 future, unknown requirements from accidentally being added.
966 """
993 """
967 supported = {
994 supported = {
968 requirements.DOTENCODE_REQUIREMENT,
995 requirements.DOTENCODE_REQUIREMENT,
969 requirements.FNCACHE_REQUIREMENT,
996 requirements.FNCACHE_REQUIREMENT,
970 requirements.GENERALDELTA_REQUIREMENT,
997 requirements.GENERALDELTA_REQUIREMENT,
971 requirements.SPARSEREVLOG_REQUIREMENT,
998 requirements.SPARSEREVLOG_REQUIREMENT,
972 requirements.SIDEDATA_REQUIREMENT,
999 requirements.SIDEDATA_REQUIREMENT,
973 requirements.COPIESSDC_REQUIREMENT,
1000 requirements.COPIESSDC_REQUIREMENT,
974 requirements.NODEMAP_REQUIREMENT,
1001 requirements.NODEMAP_REQUIREMENT,
975 requirements.SHARESAFE_REQUIREMENT,
1002 requirements.SHARESAFE_REQUIREMENT,
1003 requirements.REVLOGV1_REQUIREMENT,
1004 requirements.REVLOGV2_REQUIREMENT,
976 }
1005 }
977 for name in compression.compengines:
1006 for name in compression.compengines:
978 engine = compression.compengines[name]
1007 engine = compression.compengines[name]
979 if engine.available() and engine.revlogheader():
1008 if engine.available() and engine.revlogheader():
980 supported.add(b'exp-compression-%s' % name)
1009 supported.add(b'exp-compression-%s' % name)
981 if engine.name() == b'zstd':
1010 if engine.name() == b'zstd':
982 supported.add(b'revlog-compression-zstd')
1011 supported.add(b'revlog-compression-zstd')
983 return supported
1012 return supported
984
1013
985
1014
986 def check_requirements_changes(repo, new_reqs):
1015 def check_requirements_changes(repo, new_reqs):
987 old_reqs = repo.requirements
1016 old_reqs = repo.requirements
988
1017 check_revlog_version(repo.requirements)
989 support_removal = supportremovedrequirements(repo)
1018 support_removal = supportremovedrequirements(repo)
990 no_remove_reqs = old_reqs - new_reqs - support_removal
1019 no_remove_reqs = old_reqs - new_reqs - support_removal
991 if no_remove_reqs:
1020 if no_remove_reqs:
992 msg = _(b'cannot upgrade repository; requirement would be removed: %s')
1021 msg = _(b'cannot upgrade repository; requirement would be removed: %s')
993 no_remove_reqs = b', '.join(sorted(no_remove_reqs))
1022 no_remove_reqs = b', '.join(sorted(no_remove_reqs))
994 raise error.Abort(msg % no_remove_reqs)
1023 raise error.Abort(msg % no_remove_reqs)
995
1024
996 support_addition = allowednewrequirements(repo)
1025 support_addition = allowednewrequirements(repo)
997 no_add_reqs = new_reqs - old_reqs - support_addition
1026 no_add_reqs = new_reqs - old_reqs - support_addition
998 if no_add_reqs:
1027 if no_add_reqs:
999 m = _(b'cannot upgrade repository; do not support adding requirement: ')
1028 m = _(b'cannot upgrade repository; do not support adding requirement: ')
1000 no_add_reqs = b', '.join(sorted(no_add_reqs))
1029 no_add_reqs = b', '.join(sorted(no_add_reqs))
1001 raise error.Abort(m + no_add_reqs)
1030 raise error.Abort(m + no_add_reqs)
1002
1031
1003 supported = supporteddestrequirements(repo)
1032 supported = supporteddestrequirements(repo)
1004 unsupported_reqs = new_reqs - supported
1033 unsupported_reqs = new_reqs - supported
1005 if unsupported_reqs:
1034 if unsupported_reqs:
1006 msg = _(
1035 msg = _(
1007 b'cannot upgrade repository; do not support destination '
1036 b'cannot upgrade repository; do not support destination '
1008 b'requirement: %s'
1037 b'requirement: %s'
1009 )
1038 )
1010 unsupported_reqs = b', '.join(sorted(unsupported_reqs))
1039 unsupported_reqs = b', '.join(sorted(unsupported_reqs))
1011 raise error.Abort(msg % unsupported_reqs)
1040 raise error.Abort(msg % unsupported_reqs)
@@ -1,3463 +1,3467 b''
1 #testcases filelog compatibility changeset sidedata upgraded upgraded-parallel
1 #testcases filelog compatibility changeset sidedata upgraded upgraded-parallel
2
2
3 =====================================================
3 =====================================================
4 Test Copy tracing for chain of copies involving merge
4 Test Copy tracing for chain of copies involving merge
5 =====================================================
5 =====================================================
6
6
7 This test files covers copies/rename case for a chains of commit where merges
7 This test files covers copies/rename case for a chains of commit where merges
8 are involved. It cheks we do not have unwanted update of behavior and that the
8 are involved. It cheks we do not have unwanted update of behavior and that the
9 different options to retrieve copies behave correctly.
9 different options to retrieve copies behave correctly.
10
10
11
11
12 Setup
12 Setup
13 =====
13 =====
14
14
15 use git diff to see rename
15 use git diff to see rename
16
16
17 $ cat << EOF >> ./no-linkrev
17 $ cat << EOF >> ./no-linkrev
18 > #!$PYTHON
18 > #!$PYTHON
19 > # filter out linkrev part of the debugindex command
19 > # filter out linkrev part of the debugindex command
20 > import sys
20 > import sys
21 > for line in sys.stdin:
21 > for line in sys.stdin:
22 > if " linkrev " in line:
22 > if " linkrev " in line:
23 > print(line.rstrip())
23 > print(line.rstrip())
24 > else:
24 > else:
25 > l = "%s *%s" % (line[:6], line[14:].rstrip())
25 > l = "%s *%s" % (line[:6], line[14:].rstrip())
26 > print(l)
26 > print(l)
27 > EOF
27 > EOF
28 $ chmod +x no-linkrev
28 $ chmod +x no-linkrev
29
29
30 $ cat << EOF >> $HGRCPATH
30 $ cat << EOF >> $HGRCPATH
31 > [diff]
31 > [diff]
32 > git=yes
32 > git=yes
33 > [command-templates]
33 > [command-templates]
34 > log={desc}\n
34 > log={desc}\n
35 > EOF
35 > EOF
36
36
37 #if compatibility
37 #if compatibility
38 $ cat >> $HGRCPATH << EOF
38 $ cat >> $HGRCPATH << EOF
39 > [experimental]
39 > [experimental]
40 > copies.read-from = compatibility
40 > copies.read-from = compatibility
41 > EOF
41 > EOF
42 #endif
42 #endif
43
43
44 #if changeset
44 #if changeset
45 $ cat >> $HGRCPATH << EOF
45 $ cat >> $HGRCPATH << EOF
46 > [experimental]
46 > [experimental]
47 > copies.read-from = changeset-only
47 > copies.read-from = changeset-only
48 > copies.write-to = changeset-only
48 > copies.write-to = changeset-only
49 > EOF
49 > EOF
50 #endif
50 #endif
51
51
52 #if sidedata
52 #if sidedata
53 $ cat >> $HGRCPATH << EOF
53 $ cat >> $HGRCPATH << EOF
54 > [format]
54 > [format]
55 > exp-use-side-data = yes
55 > exp-use-side-data = yes
56 > exp-use-copies-side-data-changeset = yes
56 > exp-use-copies-side-data-changeset = yes
57 > EOF
57 > EOF
58 #endif
58 #endif
59
59
60
60
61 $ cat > same-content.txt << EOF
61 $ cat > same-content.txt << EOF
62 > Here is some content that will be the same accros multiple file.
62 > Here is some content that will be the same accros multiple file.
63 >
63 >
64 > This is done on purpose so that we end up in some merge situation, were the
64 > This is done on purpose so that we end up in some merge situation, were the
65 > resulting content is the same as in the parent(s), but a new filenodes still
65 > resulting content is the same as in the parent(s), but a new filenodes still
66 > need to be created to record some file history information (especially
66 > need to be created to record some file history information (especially
67 > about copies).
67 > about copies).
68 > EOF
68 > EOF
69
69
70 $ hg init repo-chain
70 $ hg init repo-chain
71 $ cd repo-chain
71 $ cd repo-chain
72
72
73 Add some linear rename initialy
73 Add some linear rename initialy
74
74
75 $ cp ../same-content.txt a
75 $ cp ../same-content.txt a
76 $ cp ../same-content.txt b
76 $ cp ../same-content.txt b
77 $ cp ../same-content.txt h
77 $ cp ../same-content.txt h
78 $ echo "original content for P" > p
78 $ echo "original content for P" > p
79 $ echo "original content for Q" > q
79 $ echo "original content for Q" > q
80 $ echo "original content for R" > r
80 $ echo "original content for R" > r
81 $ hg ci -Am 'i-0 initial commit: a b h p q r'
81 $ hg ci -Am 'i-0 initial commit: a b h p q r'
82 adding a
82 adding a
83 adding b
83 adding b
84 adding h
84 adding h
85 adding p
85 adding p
86 adding q
86 adding q
87 adding r
87 adding r
88 $ hg mv a c
88 $ hg mv a c
89 $ hg mv p s
89 $ hg mv p s
90 $ hg ci -Am 'i-1: a -move-> c, p -move-> s'
90 $ hg ci -Am 'i-1: a -move-> c, p -move-> s'
91 $ hg mv c d
91 $ hg mv c d
92 $ hg mv s t
92 $ hg mv s t
93 $ hg ci -Am 'i-2: c -move-> d, s -move-> t'
93 $ hg ci -Am 'i-2: c -move-> d, s -move-> t'
94 $ hg log -G
94 $ hg log -G
95 @ i-2: c -move-> d, s -move-> t
95 @ i-2: c -move-> d, s -move-> t
96 |
96 |
97 o i-1: a -move-> c, p -move-> s
97 o i-1: a -move-> c, p -move-> s
98 |
98 |
99 o i-0 initial commit: a b h p q r
99 o i-0 initial commit: a b h p q r
100
100
101
101
102 And having another branch with renames on the other side
102 And having another branch with renames on the other side
103
103
104 $ hg mv d e
104 $ hg mv d e
105 $ hg ci -Am 'a-1: d -move-> e'
105 $ hg ci -Am 'a-1: d -move-> e'
106 $ hg mv e f
106 $ hg mv e f
107 $ hg ci -Am 'a-2: e -move-> f'
107 $ hg ci -Am 'a-2: e -move-> f'
108 $ hg log -G --rev '::.'
108 $ hg log -G --rev '::.'
109 @ a-2: e -move-> f
109 @ a-2: e -move-> f
110 |
110 |
111 o a-1: d -move-> e
111 o a-1: d -move-> e
112 |
112 |
113 o i-2: c -move-> d, s -move-> t
113 o i-2: c -move-> d, s -move-> t
114 |
114 |
115 o i-1: a -move-> c, p -move-> s
115 o i-1: a -move-> c, p -move-> s
116 |
116 |
117 o i-0 initial commit: a b h p q r
117 o i-0 initial commit: a b h p q r
118
118
119
119
120 Have a branching with nothing on one side
120 Have a branching with nothing on one side
121
121
122 $ hg up 'desc("i-2")'
122 $ hg up 'desc("i-2")'
123 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
123 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
124 $ echo foo > b
124 $ echo foo > b
125 $ hg ci -m 'b-1: b update'
125 $ hg ci -m 'b-1: b update'
126 created new head
126 created new head
127 $ hg log -G --rev '::.'
127 $ hg log -G --rev '::.'
128 @ b-1: b update
128 @ b-1: b update
129 |
129 |
130 o i-2: c -move-> d, s -move-> t
130 o i-2: c -move-> d, s -move-> t
131 |
131 |
132 o i-1: a -move-> c, p -move-> s
132 o i-1: a -move-> c, p -move-> s
133 |
133 |
134 o i-0 initial commit: a b h p q r
134 o i-0 initial commit: a b h p q r
135
135
136
136
137 Create a branch that delete a file previous renamed
137 Create a branch that delete a file previous renamed
138
138
139 $ hg up 'desc("i-2")'
139 $ hg up 'desc("i-2")'
140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 $ hg rm d
141 $ hg rm d
142 $ hg ci -m 'c-1 delete d'
142 $ hg ci -m 'c-1 delete d'
143 created new head
143 created new head
144 $ hg log -G --rev '::.'
144 $ hg log -G --rev '::.'
145 @ c-1 delete d
145 @ c-1 delete d
146 |
146 |
147 o i-2: c -move-> d, s -move-> t
147 o i-2: c -move-> d, s -move-> t
148 |
148 |
149 o i-1: a -move-> c, p -move-> s
149 o i-1: a -move-> c, p -move-> s
150 |
150 |
151 o i-0 initial commit: a b h p q r
151 o i-0 initial commit: a b h p q r
152
152
153
153
154 Create a branch that delete a file previous renamed and recreate it
154 Create a branch that delete a file previous renamed and recreate it
155
155
156 $ hg up 'desc("i-2")'
156 $ hg up 'desc("i-2")'
157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 $ hg rm d
158 $ hg rm d
159 $ hg ci -m 'd-1 delete d'
159 $ hg ci -m 'd-1 delete d'
160 created new head
160 created new head
161 $ echo bar > d
161 $ echo bar > d
162 $ hg add d
162 $ hg add d
163 $ hg ci -m 'd-2 re-add d'
163 $ hg ci -m 'd-2 re-add d'
164 $ hg log -G --rev '::.'
164 $ hg log -G --rev '::.'
165 @ d-2 re-add d
165 @ d-2 re-add d
166 |
166 |
167 o d-1 delete d
167 o d-1 delete d
168 |
168 |
169 o i-2: c -move-> d, s -move-> t
169 o i-2: c -move-> d, s -move-> t
170 |
170 |
171 o i-1: a -move-> c, p -move-> s
171 o i-1: a -move-> c, p -move-> s
172 |
172 |
173 o i-0 initial commit: a b h p q r
173 o i-0 initial commit: a b h p q r
174
174
175
175
176 Having another branch renaming a different file to the same filename as another
176 Having another branch renaming a different file to the same filename as another
177
177
178 $ hg up 'desc("i-2")'
178 $ hg up 'desc("i-2")'
179 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
180 $ hg mv b g
180 $ hg mv b g
181 $ hg ci -m 'e-1 b -move-> g'
181 $ hg ci -m 'e-1 b -move-> g'
182 created new head
182 created new head
183 $ hg mv g f
183 $ hg mv g f
184 $ hg ci -m 'e-2 g -move-> f'
184 $ hg ci -m 'e-2 g -move-> f'
185 $ hg log -G --rev '::.'
185 $ hg log -G --rev '::.'
186 @ e-2 g -move-> f
186 @ e-2 g -move-> f
187 |
187 |
188 o e-1 b -move-> g
188 o e-1 b -move-> g
189 |
189 |
190 o i-2: c -move-> d, s -move-> t
190 o i-2: c -move-> d, s -move-> t
191 |
191 |
192 o i-1: a -move-> c, p -move-> s
192 o i-1: a -move-> c, p -move-> s
193 |
193 |
194 o i-0 initial commit: a b h p q r
194 o i-0 initial commit: a b h p q r
195
195
196 $ hg up -q null
196 $ hg up -q null
197
197
198 Having a branch similar to the 'a' one, but moving the 'p' file around.
198 Having a branch similar to the 'a' one, but moving the 'p' file around.
199
199
200 $ hg up 'desc("i-2")'
200 $ hg up 'desc("i-2")'
201 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
201 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
202 $ hg mv t u
202 $ hg mv t u
203 $ hg ci -Am 'p-1: t -move-> u'
203 $ hg ci -Am 'p-1: t -move-> u'
204 created new head
204 created new head
205 $ hg mv u v
205 $ hg mv u v
206 $ hg ci -Am 'p-2: u -move-> v'
206 $ hg ci -Am 'p-2: u -move-> v'
207 $ hg log -G --rev '::.'
207 $ hg log -G --rev '::.'
208 @ p-2: u -move-> v
208 @ p-2: u -move-> v
209 |
209 |
210 o p-1: t -move-> u
210 o p-1: t -move-> u
211 |
211 |
212 o i-2: c -move-> d, s -move-> t
212 o i-2: c -move-> d, s -move-> t
213 |
213 |
214 o i-1: a -move-> c, p -move-> s
214 o i-1: a -move-> c, p -move-> s
215 |
215 |
216 o i-0 initial commit: a b h p q r
216 o i-0 initial commit: a b h p q r
217
217
218 $ hg up -q null
218 $ hg up -q null
219
219
220 Having another branch renaming a different file to the same filename as another
220 Having another branch renaming a different file to the same filename as another
221
221
222 $ hg up 'desc("i-2")'
222 $ hg up 'desc("i-2")'
223 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 $ hg mv r w
224 $ hg mv r w
225 $ hg ci -m 'q-1 r -move-> w'
225 $ hg ci -m 'q-1 r -move-> w'
226 created new head
226 created new head
227 $ hg mv w v
227 $ hg mv w v
228 $ hg ci -m 'q-2 w -move-> v'
228 $ hg ci -m 'q-2 w -move-> v'
229 $ hg log -G --rev '::.'
229 $ hg log -G --rev '::.'
230 @ q-2 w -move-> v
230 @ q-2 w -move-> v
231 |
231 |
232 o q-1 r -move-> w
232 o q-1 r -move-> w
233 |
233 |
234 o i-2: c -move-> d, s -move-> t
234 o i-2: c -move-> d, s -move-> t
235 |
235 |
236 o i-1: a -move-> c, p -move-> s
236 o i-1: a -move-> c, p -move-> s
237 |
237 |
238 o i-0 initial commit: a b h p q r
238 o i-0 initial commit: a b h p q r
239
239
240 $ hg up -q null
240 $ hg up -q null
241
241
242 Setup all merge
242 Setup all merge
243 ===============
243 ===============
244
244
245 This is done beforehand to validate that the upgrade process creates valid copy
245 This is done beforehand to validate that the upgrade process creates valid copy
246 information.
246 information.
247
247
248 merging with unrelated change does not interfere with the renames
248 merging with unrelated change does not interfere with the renames
249 ---------------------------------------------------------------
249 ---------------------------------------------------------------
250
250
251 - rename on one side
251 - rename on one side
252 - unrelated change on the other side
252 - unrelated change on the other side
253
253
254 $ case_desc="simple merge - A side: multiple renames, B side: unrelated update"
254 $ case_desc="simple merge - A side: multiple renames, B side: unrelated update"
255
255
256 $ hg up 'desc("b-1")'
256 $ hg up 'desc("b-1")'
257 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 $ hg merge 'desc("a-2")'
258 $ hg merge 'desc("a-2")'
259 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
259 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
260 (branch merge, don't forget to commit)
260 (branch merge, don't forget to commit)
261 $ hg ci -m "mBAm-0 $case_desc - one way"
261 $ hg ci -m "mBAm-0 $case_desc - one way"
262 $ hg up 'desc("a-2")'
262 $ hg up 'desc("a-2")'
263 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 $ hg merge 'desc("b-1")'
264 $ hg merge 'desc("b-1")'
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 (branch merge, don't forget to commit)
266 (branch merge, don't forget to commit)
267 $ hg ci -m "mABm-0 $case_desc - the other way"
267 $ hg ci -m "mABm-0 $case_desc - the other way"
268 created new head
268 created new head
269 $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))'
269 $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))'
270 @ mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
270 @ mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
271 |\
271 |\
272 +---o mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
272 +---o mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
273 | |/
273 | |/
274 | o b-1: b update
274 | o b-1: b update
275 | |
275 | |
276 o | a-2: e -move-> f
276 o | a-2: e -move-> f
277 | |
277 | |
278 o | a-1: d -move-> e
278 o | a-1: d -move-> e
279 |/
279 |/
280 o i-2: c -move-> d, s -move-> t
280 o i-2: c -move-> d, s -move-> t
281 |
281 |
282 o i-1: a -move-> c, p -move-> s
282 o i-1: a -move-> c, p -move-> s
283 |
283 |
284 o i-0 initial commit: a b h p q r
284 o i-0 initial commit: a b h p q r
285
285
286
286
287
287
288 merging with the side having a delete
288 merging with the side having a delete
289 -------------------------------------
289 -------------------------------------
290
290
291 case summary:
291 case summary:
292 - one with change to an unrelated file
292 - one with change to an unrelated file
293 - one deleting the change
293 - one deleting the change
294 and recreate an unrelated file after the merge
294 and recreate an unrelated file after the merge
295
295
296 $ case_desc="simple merge - C side: delete a file with copies history , B side: unrelated update"
296 $ case_desc="simple merge - C side: delete a file with copies history , B side: unrelated update"
297
297
298 $ hg up 'desc("b-1")'
298 $ hg up 'desc("b-1")'
299 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
299 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
300 $ hg merge 'desc("c-1")'
300 $ hg merge 'desc("c-1")'
301 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
301 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
302 (branch merge, don't forget to commit)
302 (branch merge, don't forget to commit)
303 $ hg ci -m "mBCm-0 $case_desc - one way"
303 $ hg ci -m "mBCm-0 $case_desc - one way"
304 $ echo bar > d
304 $ echo bar > d
305 $ hg add d
305 $ hg add d
306 $ hg ci -m 'mBCm-1 re-add d'
306 $ hg ci -m 'mBCm-1 re-add d'
307 $ hg up 'desc("c-1")'
307 $ hg up 'desc("c-1")'
308 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
308 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
309 $ hg merge 'desc("b-1")'
309 $ hg merge 'desc("b-1")'
310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 (branch merge, don't forget to commit)
311 (branch merge, don't forget to commit)
312 $ hg ci -m "mCBm-0 $case_desc - the other way"
312 $ hg ci -m "mCBm-0 $case_desc - the other way"
313 created new head
313 created new head
314 $ echo bar > d
314 $ echo bar > d
315 $ hg add d
315 $ hg add d
316 $ hg ci -m 'mCBm-1 re-add d'
316 $ hg ci -m 'mCBm-1 re-add d'
317 $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))'
317 $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))'
318 @ mCBm-1 re-add d
318 @ mCBm-1 re-add d
319 |
319 |
320 o mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
320 o mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
321 |\
321 |\
322 | | o mBCm-1 re-add d
322 | | o mBCm-1 re-add d
323 | | |
323 | | |
324 +---o mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
324 +---o mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
325 | |/
325 | |/
326 | o c-1 delete d
326 | o c-1 delete d
327 | |
327 | |
328 o | b-1: b update
328 o | b-1: b update
329 |/
329 |/
330 o i-2: c -move-> d, s -move-> t
330 o i-2: c -move-> d, s -move-> t
331 |
331 |
332 o i-1: a -move-> c, p -move-> s
332 o i-1: a -move-> c, p -move-> s
333 |
333 |
334 o i-0 initial commit: a b h p q r
334 o i-0 initial commit: a b h p q r
335
335
336
336
337 Comparing with a merge re-adding the file afterward
337 Comparing with a merge re-adding the file afterward
338 ---------------------------------------------------
338 ---------------------------------------------------
339
339
340 Merge:
340 Merge:
341 - one with change to an unrelated file
341 - one with change to an unrelated file
342 - one deleting and recreating the change
342 - one deleting and recreating the change
343
343
344 $ case_desc="simple merge - B side: unrelated update, D side: delete and recreate a file (with different content)"
344 $ case_desc="simple merge - B side: unrelated update, D side: delete and recreate a file (with different content)"
345
345
346 $ hg up 'desc("b-1")'
346 $ hg up 'desc("b-1")'
347 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 $ hg merge 'desc("d-2")'
348 $ hg merge 'desc("d-2")'
349 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 (branch merge, don't forget to commit)
350 (branch merge, don't forget to commit)
351 $ hg ci -m "mBDm-0 $case_desc - one way"
351 $ hg ci -m "mBDm-0 $case_desc - one way"
352 $ hg up 'desc("d-2")'
352 $ hg up 'desc("d-2")'
353 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
353 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
354 $ hg merge 'desc("b-1")'
354 $ hg merge 'desc("b-1")'
355 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
355 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
356 (branch merge, don't forget to commit)
356 (branch merge, don't forget to commit)
357 $ hg ci -m "mDBm-0 $case_desc - the other way"
357 $ hg ci -m "mDBm-0 $case_desc - the other way"
358 created new head
358 created new head
359 $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))'
359 $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))'
360 @ mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
360 @ mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
361 |\
361 |\
362 +---o mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
362 +---o mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
363 | |/
363 | |/
364 | o d-2 re-add d
364 | o d-2 re-add d
365 | |
365 | |
366 | o d-1 delete d
366 | o d-1 delete d
367 | |
367 | |
368 o | b-1: b update
368 o | b-1: b update
369 |/
369 |/
370 o i-2: c -move-> d, s -move-> t
370 o i-2: c -move-> d, s -move-> t
371 |
371 |
372 o i-1: a -move-> c, p -move-> s
372 o i-1: a -move-> c, p -move-> s
373 |
373 |
374 o i-0 initial commit: a b h p q r
374 o i-0 initial commit: a b h p q r
375
375
376
376
377
377
378 Comparing with a merge with colliding rename
378 Comparing with a merge with colliding rename
379 --------------------------------------------
379 --------------------------------------------
380
380
381 Subcase: new copy information on both side
381 Subcase: new copy information on both side
382 ``````````````````````````````````````````
382 ``````````````````````````````````````````
383
383
384 - the "e-" branch renaming b to f (through 'g')
384 - the "e-" branch renaming b to f (through 'g')
385 - the "a-" branch renaming d to f (through e)
385 - the "a-" branch renaming d to f (through e)
386
386
387 $ case_desc="merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f)"
387 $ case_desc="merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f)"
388
388
389 $ hg up 'desc("a-2")'
389 $ hg up 'desc("a-2")'
390 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
390 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
391 $ hg merge 'desc("e-2")'
391 $ hg merge 'desc("e-2")'
392 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
392 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
393 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
393 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
394 (branch merge, don't forget to commit)
394 (branch merge, don't forget to commit)
395 $ hg ci -m "mAEm-0 $case_desc - one way"
395 $ hg ci -m "mAEm-0 $case_desc - one way"
396 $ hg up 'desc("e-2")'
396 $ hg up 'desc("e-2")'
397 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
397 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
399 $ hg merge 'desc("a-2")'
399 $ hg merge 'desc("a-2")'
400 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
400 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
402 (branch merge, don't forget to commit)
402 (branch merge, don't forget to commit)
403 $ hg ci -m "mEAm-0 $case_desc - the other way"
403 $ hg ci -m "mEAm-0 $case_desc - the other way"
404 created new head
404 created new head
405 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
405 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
406 @ mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
406 @ mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
407 |\
407 |\
408 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
408 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
409 | |/
409 | |/
410 | o e-2 g -move-> f
410 | o e-2 g -move-> f
411 | |
411 | |
412 | o e-1 b -move-> g
412 | o e-1 b -move-> g
413 | |
413 | |
414 o | a-2: e -move-> f
414 o | a-2: e -move-> f
415 | |
415 | |
416 o | a-1: d -move-> e
416 o | a-1: d -move-> e
417 |/
417 |/
418 o i-2: c -move-> d, s -move-> t
418 o i-2: c -move-> d, s -move-> t
419 |
419 |
420 o i-1: a -move-> c, p -move-> s
420 o i-1: a -move-> c, p -move-> s
421 |
421 |
422 o i-0 initial commit: a b h p q r
422 o i-0 initial commit: a b h p q r
423
423
424
424
425 Subcase: new copy information on both side with an actual merge happening
425 Subcase: new copy information on both side with an actual merge happening
426 `````````````````````````````````````````````````````````````````````````
426 `````````````````````````````````````````````````````````````````````````
427
427
428 - the "p-" branch renaming 't' to 'v' (through 'u')
428 - the "p-" branch renaming 't' to 'v' (through 'u')
429 - the "q-" branch renaming 'r' to 'v' (through 'w')
429 - the "q-" branch renaming 'r' to 'v' (through 'w')
430
430
431 $ case_desc="merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content)"
431 $ case_desc="merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content)"
432
432
433 $ hg up 'desc("p-2")'
433 $ hg up 'desc("p-2")'
434 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
434 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
435 $ hg merge 'desc("q-2")' --tool ':union'
435 $ hg merge 'desc("q-2")' --tool ':union'
436 merging v
436 merging v
437 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
437 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
438 (branch merge, don't forget to commit)
438 (branch merge, don't forget to commit)
439 $ hg ci -m "mPQm-0 $case_desc - one way"
439 $ hg ci -m "mPQm-0 $case_desc - one way"
440 $ hg up 'desc("q-2")'
440 $ hg up 'desc("q-2")'
441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 $ hg merge 'desc("p-2")' --tool ':union'
442 $ hg merge 'desc("p-2")' --tool ':union'
443 merging v
443 merging v
444 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
444 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
445 (branch merge, don't forget to commit)
445 (branch merge, don't forget to commit)
446 $ hg ci -m "mQPm-0 $case_desc - the other way"
446 $ hg ci -m "mQPm-0 $case_desc - the other way"
447 created new head
447 created new head
448 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
448 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
449 o mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
449 o mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
450 |\
450 |\
451 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
451 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
452 | |/
452 | |/
453 | o e-2 g -move-> f
453 | o e-2 g -move-> f
454 | |
454 | |
455 | o e-1 b -move-> g
455 | o e-1 b -move-> g
456 | |
456 | |
457 o | a-2: e -move-> f
457 o | a-2: e -move-> f
458 | |
458 | |
459 o | a-1: d -move-> e
459 o | a-1: d -move-> e
460 |/
460 |/
461 o i-2: c -move-> d, s -move-> t
461 o i-2: c -move-> d, s -move-> t
462 |
462 |
463 o i-1: a -move-> c, p -move-> s
463 o i-1: a -move-> c, p -move-> s
464 |
464 |
465 o i-0 initial commit: a b h p q r
465 o i-0 initial commit: a b h p q r
466
466
467
467
468 Subcase: existing copy information overwritten on one branch
468 Subcase: existing copy information overwritten on one branch
469 ````````````````````````````````````````````````````````````
469 ````````````````````````````````````````````````````````````
470
470
471 Merge:
471 Merge:
472 - one with change to an unrelated file (b)
472 - one with change to an unrelated file (b)
473 - one overwriting a file (d) with a rename (from h to i to d)
473 - one overwriting a file (d) with a rename (from h to i to d)
474
474
475 $ case_desc="simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d)"
475 $ case_desc="simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d)"
476
476
477 $ hg up 'desc("i-2")'
477 $ hg up 'desc("i-2")'
478 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
478 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
479 $ hg mv h i
479 $ hg mv h i
480 $ hg commit -m "f-1: rename h -> i"
480 $ hg commit -m "f-1: rename h -> i"
481 created new head
481 created new head
482 $ hg mv --force i d
482 $ hg mv --force i d
483 $ hg commit -m "f-2: rename i -> d"
483 $ hg commit -m "f-2: rename i -> d"
484 $ hg debugindex d | ../no-linkrev
484 $ hg debugindex d | ../no-linkrev
485 rev linkrev nodeid p1 p2
485 rev linkrev nodeid p1 p2
486 0 * d8252ab2e760 000000000000 000000000000 (no-changeset !)
486 0 * d8252ab2e760 000000000000 000000000000 (no-changeset !)
487 0 * ae258f702dfe 000000000000 000000000000 (changeset !)
487 0 * ae258f702dfe 000000000000 000000000000 (changeset !)
488 1 * b004912a8510 000000000000 000000000000
488 1 * b004912a8510 000000000000 000000000000
489 2 * 7b79e2fe0c89 000000000000 000000000000 (no-changeset !)
489 2 * 7b79e2fe0c89 000000000000 000000000000 (no-changeset !)
490 $ hg up 'desc("b-1")'
490 $ hg up 'desc("b-1")'
491 3 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
491 3 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
492 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
492 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
493 $ hg merge 'desc("f-2")'
493 $ hg merge 'desc("f-2")'
494 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
494 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
495 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
495 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
496 (branch merge, don't forget to commit)
496 (branch merge, don't forget to commit)
497 $ hg ci -m "mBFm-0 $case_desc - one way"
497 $ hg ci -m "mBFm-0 $case_desc - one way"
498 $ hg up 'desc("f-2")'
498 $ hg up 'desc("f-2")'
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 $ hg merge 'desc("b-1")'
500 $ hg merge 'desc("b-1")'
501 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
501 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
502 (branch merge, don't forget to commit)
502 (branch merge, don't forget to commit)
503 $ hg ci -m "mFBm-0 $case_desc - the other way"
503 $ hg ci -m "mFBm-0 $case_desc - the other way"
504 created new head
504 created new head
505 $ hg up null --quiet
505 $ hg up null --quiet
506 $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))'
506 $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))'
507 o mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
507 o mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
508 |\
508 |\
509 +---o mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
509 +---o mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
510 | |/
510 | |/
511 | o f-2: rename i -> d
511 | o f-2: rename i -> d
512 | |
512 | |
513 | o f-1: rename h -> i
513 | o f-1: rename h -> i
514 | |
514 | |
515 o | b-1: b update
515 o | b-1: b update
516 |/
516 |/
517 o i-2: c -move-> d, s -move-> t
517 o i-2: c -move-> d, s -move-> t
518 |
518 |
519 o i-1: a -move-> c, p -move-> s
519 o i-1: a -move-> c, p -move-> s
520 |
520 |
521 o i-0 initial commit: a b h p q r
521 o i-0 initial commit: a b h p q r
522
522
523
523
524 Subcase: existing copy information overwritten on one branch, with different content)
524 Subcase: existing copy information overwritten on one branch, with different content)
525 `````````````````````````````````````````````````````````````````````````````````````
525 `````````````````````````````````````````````````````````````````````````````````````
526
526
527 Merge:
527 Merge:
528 - one with change to an unrelated file (b)
528 - one with change to an unrelated file (b)
529 - one overwriting a file (t) with a rename (from r to x to t), v content is not the same as on the other branch
529 - one overwriting a file (t) with a rename (from r to x to t), v content is not the same as on the other branch
530
530
531 $ case_desc="simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content"
531 $ case_desc="simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content"
532
532
533 $ hg up 'desc("i-2")'
533 $ hg up 'desc("i-2")'
534 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
534 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
535 $ hg mv r x
535 $ hg mv r x
536 $ hg commit -m "r-1: rename r -> x"
536 $ hg commit -m "r-1: rename r -> x"
537 created new head
537 created new head
538 $ hg mv --force x t
538 $ hg mv --force x t
539 $ hg commit -m "r-2: rename t -> x"
539 $ hg commit -m "r-2: rename t -> x"
540 $ hg debugindex t | ../no-linkrev
540 $ hg debugindex t | ../no-linkrev
541 rev linkrev nodeid p1 p2
541 rev linkrev nodeid p1 p2
542 0 * d74efbf65309 000000000000 000000000000 (no-changeset !)
542 0 * d74efbf65309 000000000000 000000000000 (no-changeset !)
543 1 * 02a930b9d7ad 000000000000 000000000000 (no-changeset !)
543 1 * 02a930b9d7ad 000000000000 000000000000 (no-changeset !)
544 0 * 5aed6a8dbff0 000000000000 000000000000 (changeset !)
544 0 * 5aed6a8dbff0 000000000000 000000000000 (changeset !)
545 1 * a38b2fa17021 000000000000 000000000000 (changeset !)
545 1 * a38b2fa17021 000000000000 000000000000 (changeset !)
546 $ hg up 'desc("b-1")'
546 $ hg up 'desc("b-1")'
547 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
547 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 $ hg merge 'desc("r-2")'
548 $ hg merge 'desc("r-2")'
549 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
549 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
550 (branch merge, don't forget to commit)
550 (branch merge, don't forget to commit)
551 $ hg ci -m "mBRm-0 $case_desc - one way"
551 $ hg ci -m "mBRm-0 $case_desc - one way"
552 $ hg up 'desc("r-2")'
552 $ hg up 'desc("r-2")'
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 $ hg merge 'desc("b-1")'
554 $ hg merge 'desc("b-1")'
555 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
555 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 (branch merge, don't forget to commit)
556 (branch merge, don't forget to commit)
557 $ hg ci -m "mRBm-0 $case_desc - the other way"
557 $ hg ci -m "mRBm-0 $case_desc - the other way"
558 created new head
558 created new head
559 $ hg up null --quiet
559 $ hg up null --quiet
560 $ hg log -G --rev '::(desc("mBRm")+desc("mRBm"))'
560 $ hg log -G --rev '::(desc("mBRm")+desc("mRBm"))'
561 o mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
561 o mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
562 |\
562 |\
563 +---o mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
563 +---o mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
564 | |/
564 | |/
565 | o r-2: rename t -> x
565 | o r-2: rename t -> x
566 | |
566 | |
567 | o r-1: rename r -> x
567 | o r-1: rename r -> x
568 | |
568 | |
569 o | b-1: b update
569 o | b-1: b update
570 |/
570 |/
571 o i-2: c -move-> d, s -move-> t
571 o i-2: c -move-> d, s -move-> t
572 |
572 |
573 o i-1: a -move-> c, p -move-> s
573 o i-1: a -move-> c, p -move-> s
574 |
574 |
575 o i-0 initial commit: a b h p q r
575 o i-0 initial commit: a b h p q r
576
576
577
577
578
578
579 Subcase: reset of the copy history on one side
579 Subcase: reset of the copy history on one side
580 ``````````````````````````````````````````````
580 ``````````````````````````````````````````````
581
581
582 Merge:
582 Merge:
583 - one with change to a file
583 - one with change to a file
584 - one deleting and recreating the file
584 - one deleting and recreating the file
585
585
586 Unlike in the 'BD/DB' cases, an actual merge happened here. So we should
586 Unlike in the 'BD/DB' cases, an actual merge happened here. So we should
587 consider history and rename on both branch of the merge.
587 consider history and rename on both branch of the merge.
588
588
589 $ case_desc="actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content"
589 $ case_desc="actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content"
590
590
591 $ hg up 'desc("i-2")'
591 $ hg up 'desc("i-2")'
592 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
592 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
593 $ echo "some update" >> d
593 $ echo "some update" >> d
594 $ hg commit -m "g-1: update d"
594 $ hg commit -m "g-1: update d"
595 created new head
595 created new head
596 $ hg up 'desc("d-2")'
596 $ hg up 'desc("d-2")'
597 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
598 $ hg merge 'desc("g-1")' --tool :union
598 $ hg merge 'desc("g-1")' --tool :union
599 merging d
599 merging d
600 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
600 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 (branch merge, don't forget to commit)
601 (branch merge, don't forget to commit)
602 $ hg ci -m "mDGm-0 $case_desc - one way"
602 $ hg ci -m "mDGm-0 $case_desc - one way"
603 $ hg up 'desc("g-1")'
603 $ hg up 'desc("g-1")'
604 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
604 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
605 $ hg merge 'desc("d-2")' --tool :union
605 $ hg merge 'desc("d-2")' --tool :union
606 merging d
606 merging d
607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 (branch merge, don't forget to commit)
608 (branch merge, don't forget to commit)
609 $ hg ci -m "mGDm-0 $case_desc - the other way"
609 $ hg ci -m "mGDm-0 $case_desc - the other way"
610 created new head
610 created new head
611 $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))'
611 $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))'
612 @ mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
612 @ mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
613 |\
613 |\
614 +---o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
614 +---o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
615 | |/
615 | |/
616 | o g-1: update d
616 | o g-1: update d
617 | |
617 | |
618 o | d-2 re-add d
618 o | d-2 re-add d
619 | |
619 | |
620 o | d-1 delete d
620 o | d-1 delete d
621 |/
621 |/
622 o i-2: c -move-> d, s -move-> t
622 o i-2: c -move-> d, s -move-> t
623 |
623 |
624 o i-1: a -move-> c, p -move-> s
624 o i-1: a -move-> c, p -move-> s
625 |
625 |
626 o i-0 initial commit: a b h p q r
626 o i-0 initial commit: a b h p q r
627
627
628
628
629 Subcase: merging a change to a file with a "copy overwrite" to that file from another branch
629 Subcase: merging a change to a file with a "copy overwrite" to that file from another branch
630 ````````````````````````````````````````````````````````````````````````````````````````````
630 ````````````````````````````````````````````````````````````````````````````````````````````
631
631
632 Merge:
632 Merge:
633 - one with change to a file (d)
633 - one with change to a file (d)
634 - one overwriting that file with a rename (from h to i, to d)
634 - one overwriting that file with a rename (from h to i, to d)
635
635
636 This case is similar to BF/FB, but an actual merge happens, so both side of the
636 This case is similar to BF/FB, but an actual merge happens, so both side of the
637 history are relevant.
637 history are relevant.
638
638
639 Note:
639 Note:
640 | In this case, the merge get conflicting information since on one side we have
640 | In this case, the merge get conflicting information since on one side we have
641 | "a -> c -> d". and one the other one we have "h -> i -> d".
641 | "a -> c -> d". and one the other one we have "h -> i -> d".
642 |
642 |
643 | The current code arbitrarily pick one side
643 | The current code arbitrarily pick one side
644
644
645 $ case_desc="merge - G side: content change, F side: copy overwrite, no content change"
645 $ case_desc="merge - G side: content change, F side: copy overwrite, no content change"
646
646
647 $ hg up 'desc("f-2")'
647 $ hg up 'desc("f-2")'
648 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
648 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
649 $ hg merge 'desc("g-1")' --tool :union
649 $ hg merge 'desc("g-1")' --tool :union
650 merging d (no-changeset !)
650 merging d (no-changeset !)
651 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (no-changeset !)
651 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (no-changeset !)
652 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
652 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
653 (branch merge, don't forget to commit)
653 (branch merge, don't forget to commit)
654 $ hg ci -m "mFGm-0 $case_desc - one way"
654 $ hg ci -m "mFGm-0 $case_desc - one way"
655 created new head
655 created new head
656 $ hg up 'desc("g-1")'
656 $ hg up 'desc("g-1")'
657 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
657 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
658 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
658 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
659 $ hg merge 'desc("f-2")' --tool :union
659 $ hg merge 'desc("f-2")' --tool :union
660 merging d (no-changeset !)
660 merging d (no-changeset !)
661 0 files updated, 1 files merged, 1 files removed, 0 files unresolved (no-changeset !)
661 0 files updated, 1 files merged, 1 files removed, 0 files unresolved (no-changeset !)
662 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
662 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
663 (branch merge, don't forget to commit)
663 (branch merge, don't forget to commit)
664 $ hg ci -m "mGFm-0 $case_desc - the other way"
664 $ hg ci -m "mGFm-0 $case_desc - the other way"
665 created new head
665 created new head
666 $ hg log -G --rev '::(desc("mGFm")+desc("mFGm"))'
666 $ hg log -G --rev '::(desc("mGFm")+desc("mFGm"))'
667 @ mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
667 @ mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
668 |\
668 |\
669 +---o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
669 +---o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
670 | |/
670 | |/
671 | o g-1: update d
671 | o g-1: update d
672 | |
672 | |
673 o | f-2: rename i -> d
673 o | f-2: rename i -> d
674 | |
674 | |
675 o | f-1: rename h -> i
675 o | f-1: rename h -> i
676 |/
676 |/
677 o i-2: c -move-> d, s -move-> t
677 o i-2: c -move-> d, s -move-> t
678 |
678 |
679 o i-1: a -move-> c, p -move-> s
679 o i-1: a -move-> c, p -move-> s
680 |
680 |
681 o i-0 initial commit: a b h p q r
681 o i-0 initial commit: a b h p q r
682
682
683
683
684
684
685 Comparing with merging with a deletion (and keeping the file)
685 Comparing with merging with a deletion (and keeping the file)
686 -------------------------------------------------------------
686 -------------------------------------------------------------
687
687
688 Merge:
688 Merge:
689 - one removing a file (d)
689 - one removing a file (d)
690 - one updating that file
690 - one updating that file
691 - the merge keep the modified version of the file (canceling the delete)
691 - the merge keep the modified version of the file (canceling the delete)
692
692
693 In this case, the file keep on living after the merge. So we should not drop its
693 In this case, the file keep on living after the merge. So we should not drop its
694 copy tracing chain.
694 copy tracing chain.
695
695
696 $ case_desc="merge updated/deleted - revive the file (updated content)"
696 $ case_desc="merge updated/deleted - revive the file (updated content)"
697
697
698 $ hg up 'desc("c-1")'
698 $ hg up 'desc("c-1")'
699 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
699 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
700 $ hg merge 'desc("g-1")'
700 $ hg merge 'desc("g-1")'
701 file 'd' was deleted in local [working copy] but was modified in other [merge rev].
701 file 'd' was deleted in local [working copy] but was modified in other [merge rev].
702 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
702 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
703 What do you want to do? u
703 What do you want to do? u
704 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
704 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
705 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
705 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
706 [1]
706 [1]
707 $ hg resolve -t :other d
707 $ hg resolve -t :other d
708 (no more unresolved files)
708 (no more unresolved files)
709 $ hg ci -m "mCGm-0 $case_desc - one way"
709 $ hg ci -m "mCGm-0 $case_desc - one way"
710 created new head
710 created new head
711
711
712 $ hg up 'desc("g-1")'
712 $ hg up 'desc("g-1")'
713 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
713 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
714 $ hg merge 'desc("c-1")'
714 $ hg merge 'desc("c-1")'
715 file 'd' was deleted in other [merge rev] but was modified in local [working copy].
715 file 'd' was deleted in other [merge rev] but was modified in local [working copy].
716 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
716 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
717 What do you want to do? u
717 What do you want to do? u
718 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
718 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
719 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
719 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
720 [1]
720 [1]
721 $ hg resolve -t :local d
721 $ hg resolve -t :local d
722 (no more unresolved files)
722 (no more unresolved files)
723 $ hg ci -m "mGCm-0 $case_desc - the other way"
723 $ hg ci -m "mGCm-0 $case_desc - the other way"
724 created new head
724 created new head
725
725
726 $ hg log -G --rev '::(desc("mCGm")+desc("mGCm"))'
726 $ hg log -G --rev '::(desc("mCGm")+desc("mGCm"))'
727 @ mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
727 @ mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
728 |\
728 |\
729 +---o mCGm-0 merge updated/deleted - revive the file (updated content) - one way
729 +---o mCGm-0 merge updated/deleted - revive the file (updated content) - one way
730 | |/
730 | |/
731 | o g-1: update d
731 | o g-1: update d
732 | |
732 | |
733 o | c-1 delete d
733 o | c-1 delete d
734 |/
734 |/
735 o i-2: c -move-> d, s -move-> t
735 o i-2: c -move-> d, s -move-> t
736 |
736 |
737 o i-1: a -move-> c, p -move-> s
737 o i-1: a -move-> c, p -move-> s
738 |
738 |
739 o i-0 initial commit: a b h p q r
739 o i-0 initial commit: a b h p q r
740
740
741
741
742
742
743
743
744 Comparing with merge restoring an untouched deleted file
744 Comparing with merge restoring an untouched deleted file
745 --------------------------------------------------------
745 --------------------------------------------------------
746
746
747 Merge:
747 Merge:
748 - one removing a file (d)
748 - one removing a file (d)
749 - one leaving the file untouched
749 - one leaving the file untouched
750 - the merge actively restore the file to the same content.
750 - the merge actively restore the file to the same content.
751
751
752 In this case, the file keep on living after the merge. So we should not drop its
752 In this case, the file keep on living after the merge. So we should not drop its
753 copy tracing chain.
753 copy tracing chain.
754
754
755 $ case_desc="merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge)"
755 $ case_desc="merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge)"
756
756
757 $ hg up 'desc("c-1")'
757 $ hg up 'desc("c-1")'
758 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
758 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
759 $ hg merge 'desc("b-1")'
759 $ hg merge 'desc("b-1")'
760 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
760 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
761 (branch merge, don't forget to commit)
761 (branch merge, don't forget to commit)
762 $ hg revert --rev 'desc("b-1")' d
762 $ hg revert --rev 'desc("b-1")' d
763 $ hg ci -m "mCB-revert-m-0 $case_desc - one way"
763 $ hg ci -m "mCB-revert-m-0 $case_desc - one way"
764 created new head
764 created new head
765
765
766 $ hg up 'desc("b-1")'
766 $ hg up 'desc("b-1")'
767 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
767 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
768 $ hg merge 'desc("c-1")'
768 $ hg merge 'desc("c-1")'
769 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
769 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
770 (branch merge, don't forget to commit)
770 (branch merge, don't forget to commit)
771 $ hg revert --rev 'desc("b-1")' d
771 $ hg revert --rev 'desc("b-1")' d
772 $ hg ci -m "mBC-revert-m-0 $case_desc - the other way"
772 $ hg ci -m "mBC-revert-m-0 $case_desc - the other way"
773 created new head
773 created new head
774
774
775 $ hg log -G --rev '::(desc("mCB-revert-m")+desc("mBC-revert-m"))'
775 $ hg log -G --rev '::(desc("mCB-revert-m")+desc("mBC-revert-m"))'
776 @ mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
776 @ mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
777 |\
777 |\
778 +---o mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
778 +---o mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
779 | |/
779 | |/
780 | o c-1 delete d
780 | o c-1 delete d
781 | |
781 | |
782 o | b-1: b update
782 o | b-1: b update
783 |/
783 |/
784 o i-2: c -move-> d, s -move-> t
784 o i-2: c -move-> d, s -move-> t
785 |
785 |
786 o i-1: a -move-> c, p -move-> s
786 o i-1: a -move-> c, p -move-> s
787 |
787 |
788 o i-0 initial commit: a b h p q r
788 o i-0 initial commit: a b h p q r
789
789
790
790
791
791
792 $ hg up null --quiet
792 $ hg up null --quiet
793
793
794 Merging a branch where a rename was deleted with a branch where the same file was renamed
794 Merging a branch where a rename was deleted with a branch where the same file was renamed
795 ------------------------------------------------------------------------------------------
795 ------------------------------------------------------------------------------------------
796
796
797 Create a "conflicting" merge where `d` get removed on one branch before its
797 Create a "conflicting" merge where `d` get removed on one branch before its
798 rename information actually conflict with the other branch.
798 rename information actually conflict with the other branch.
799
799
800 (the copy information from the branch that was not deleted should win).
800 (the copy information from the branch that was not deleted should win).
801
801
802 $ case_desc="simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch)"
802 $ case_desc="simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch)"
803
803
804 $ hg up 'desc("i-0")'
804 $ hg up 'desc("i-0")'
805 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
805 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
806 $ hg mv b d
806 $ hg mv b d
807 $ hg ci -m "h-1: b -(move)-> d"
807 $ hg ci -m "h-1: b -(move)-> d"
808 created new head
808 created new head
809
809
810 $ hg up 'desc("c-1")'
810 $ hg up 'desc("c-1")'
811 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
811 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
812 $ hg merge 'desc("h-1")'
812 $ hg merge 'desc("h-1")'
813 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
813 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
814 (branch merge, don't forget to commit)
814 (branch merge, don't forget to commit)
815 $ hg ci -m "mCH-delete-before-conflict-m-0 $case_desc - one way"
815 $ hg ci -m "mCH-delete-before-conflict-m-0 $case_desc - one way"
816
816
817 $ hg up 'desc("h-1")'
817 $ hg up 'desc("h-1")'
818 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
818 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
819 $ hg merge 'desc("c-1")'
819 $ hg merge 'desc("c-1")'
820 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
820 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
821 (branch merge, don't forget to commit)
821 (branch merge, don't forget to commit)
822 $ hg ci -m "mHC-delete-before-conflict-m-0 $case_desc - the other way"
822 $ hg ci -m "mHC-delete-before-conflict-m-0 $case_desc - the other way"
823 created new head
823 created new head
824 $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))'
824 $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))'
825 @ mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
825 @ mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
826 |\
826 |\
827 +---o mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
827 +---o mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
828 | |/
828 | |/
829 | o h-1: b -(move)-> d
829 | o h-1: b -(move)-> d
830 | |
830 | |
831 o | c-1 delete d
831 o | c-1 delete d
832 | |
832 | |
833 o | i-2: c -move-> d, s -move-> t
833 o | i-2: c -move-> d, s -move-> t
834 | |
834 | |
835 o | i-1: a -move-> c, p -move-> s
835 o | i-1: a -move-> c, p -move-> s
836 |/
836 |/
837 o i-0 initial commit: a b h p q r
837 o i-0 initial commit: a b h p q r
838
838
839
839
840 Variant of previous with extra changes introduced by the merge
840 Variant of previous with extra changes introduced by the merge
841 --------------------------------------------------------------
841 --------------------------------------------------------------
842
842
843 Multiple cases above explicitely test cases where content are the same on both side during merge. In this section we will introduce variants for theses cases where new change are introduced to these file content during the merges.
843 Multiple cases above explicitely test cases where content are the same on both side during merge. In this section we will introduce variants for theses cases where new change are introduced to these file content during the merges.
844
844
845
845
846 Subcase: merge has same initial content on both side, but merge introduced a change
846 Subcase: merge has same initial content on both side, but merge introduced a change
847 ```````````````````````````````````````````````````````````````````````````````````
847 ```````````````````````````````````````````````````````````````````````````````````
848
848
849 Same as `mAEm` and `mEAm` but with extra change to the file before commiting
849 Same as `mAEm` and `mEAm` but with extra change to the file before commiting
850
850
851 - the "e-" branch renaming b to f (through 'g')
851 - the "e-" branch renaming b to f (through 'g')
852 - the "a-" branch renaming d to f (through e)
852 - the "a-" branch renaming d to f (through e)
853
853
854 $ case_desc="merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent)"
854 $ case_desc="merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent)"
855
855
856 $ hg up 'desc("a-2")'
856 $ hg up 'desc("a-2")'
857 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
857 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
858 $ hg merge 'desc("e-2")'
858 $ hg merge 'desc("e-2")'
859 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
859 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
860 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
860 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
861 (branch merge, don't forget to commit)
861 (branch merge, don't forget to commit)
862 $ echo "content change for mAE-change-m" > f
862 $ echo "content change for mAE-change-m" > f
863 $ hg ci -m "mAE-change-m-0 $case_desc - one way"
863 $ hg ci -m "mAE-change-m-0 $case_desc - one way"
864 created new head
864 created new head
865 $ hg up 'desc("e-2")'
865 $ hg up 'desc("e-2")'
866 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
866 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
867 $ hg merge 'desc("a-2")'
867 $ hg merge 'desc("a-2")'
868 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
868 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
869 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
869 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
870 (branch merge, don't forget to commit)
870 (branch merge, don't forget to commit)
871 $ echo "content change for mEA-change-m" > f
871 $ echo "content change for mEA-change-m" > f
872 $ hg ci -m "mEA-change-m-0 $case_desc - the other way"
872 $ hg ci -m "mEA-change-m-0 $case_desc - the other way"
873 created new head
873 created new head
874 $ hg log -G --rev '::(desc("mAE-change-m")+desc("mEA-change-m"))'
874 $ hg log -G --rev '::(desc("mAE-change-m")+desc("mEA-change-m"))'
875 @ mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
875 @ mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
876 |\
876 |\
877 +---o mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
877 +---o mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
878 | |/
878 | |/
879 | o e-2 g -move-> f
879 | o e-2 g -move-> f
880 | |
880 | |
881 | o e-1 b -move-> g
881 | o e-1 b -move-> g
882 | |
882 | |
883 o | a-2: e -move-> f
883 o | a-2: e -move-> f
884 | |
884 | |
885 o | a-1: d -move-> e
885 o | a-1: d -move-> e
886 |/
886 |/
887 o i-2: c -move-> d, s -move-> t
887 o i-2: c -move-> d, s -move-> t
888 |
888 |
889 o i-1: a -move-> c, p -move-> s
889 o i-1: a -move-> c, p -move-> s
890 |
890 |
891 o i-0 initial commit: a b h p q r
891 o i-0 initial commit: a b h p q r
892
892
893
893
894 Decision from previous merge are properly chained with later merge
894 Decision from previous merge are properly chained with later merge
895 ------------------------------------------------------------------
895 ------------------------------------------------------------------
896
896
897 Subcase: chaining conflicting rename resolution
897 Subcase: chaining conflicting rename resolution
898 ```````````````````````````````````````````````
898 ```````````````````````````````````````````````
899
899
900 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
900 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
901 add more change on the respective branch and merge again. These second merge
901 add more change on the respective branch and merge again. These second merge
902 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
902 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
903 about that file should stay unchanged.
903 about that file should stay unchanged.
904
904
905 $ case_desc="chained merges (conflict -> simple) - same content everywhere"
905 $ case_desc="chained merges (conflict -> simple) - same content everywhere"
906
906
907 (extra unrelated changes)
907 (extra unrelated changes)
908
908
909 $ hg up 'desc("a-2")'
909 $ hg up 'desc("a-2")'
910 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
910 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
911 $ echo j > unrelated-j
911 $ echo j > unrelated-j
912 $ hg add unrelated-j
912 $ hg add unrelated-j
913 $ hg ci -m 'j-1: unrelated changes (based on the "a" series of changes)'
913 $ hg ci -m 'j-1: unrelated changes (based on the "a" series of changes)'
914 created new head
914 created new head
915
915
916 $ hg up 'desc("e-2")'
916 $ hg up 'desc("e-2")'
917 2 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
917 2 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
918 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
918 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
919 $ echo k > unrelated-k
919 $ echo k > unrelated-k
920 $ hg add unrelated-k
920 $ hg add unrelated-k
921 $ hg ci -m 'k-1: unrelated changes (based on "e" changes)'
921 $ hg ci -m 'k-1: unrelated changes (based on "e" changes)'
922 created new head
922 created new head
923
923
924 (merge variant 1)
924 (merge variant 1)
925
925
926 $ hg up 'desc("mAEm")'
926 $ hg up 'desc("mAEm")'
927 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
927 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
928 0 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
928 0 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
929 $ hg merge 'desc("k-1")'
929 $ hg merge 'desc("k-1")'
930 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
930 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
931 (branch merge, don't forget to commit)
931 (branch merge, don't forget to commit)
932 $ hg ci -m "mAE,Km: $case_desc"
932 $ hg ci -m "mAE,Km: $case_desc"
933
933
934 (merge variant 2)
934 (merge variant 2)
935
935
936 $ hg up 'desc("k-1")'
936 $ hg up 'desc("k-1")'
937 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
937 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
938 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
938 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
939
939
940 $ hg merge 'desc("mAEm")'
940 $ hg merge 'desc("mAEm")'
941 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
941 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
942 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
942 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
943 (branch merge, don't forget to commit)
943 (branch merge, don't forget to commit)
944 $ hg ci -m "mK,AEm: $case_desc"
944 $ hg ci -m "mK,AEm: $case_desc"
945 created new head
945 created new head
946
946
947 (merge variant 3)
947 (merge variant 3)
948
948
949 $ hg up 'desc("mEAm")'
949 $ hg up 'desc("mEAm")'
950 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
950 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
951 $ hg merge 'desc("j-1")'
951 $ hg merge 'desc("j-1")'
952 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
952 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
953 (branch merge, don't forget to commit)
953 (branch merge, don't forget to commit)
954 $ hg ci -m "mEA,Jm: $case_desc"
954 $ hg ci -m "mEA,Jm: $case_desc"
955
955
956 (merge variant 4)
956 (merge variant 4)
957
957
958 $ hg up 'desc("j-1")'
958 $ hg up 'desc("j-1")'
959 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
959 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
960 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
960 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
961 $ hg merge 'desc("mEAm")'
961 $ hg merge 'desc("mEAm")'
962 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
962 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
963 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
963 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
964 (branch merge, don't forget to commit)
964 (branch merge, don't forget to commit)
965 $ hg ci -m "mJ,EAm: $case_desc"
965 $ hg ci -m "mJ,EAm: $case_desc"
966 created new head
966 created new head
967
967
968
968
969 $ hg log -G --rev '::(desc("mAE,Km") + desc("mK,AEm") + desc("mEA,Jm") + desc("mJ,EAm"))'
969 $ hg log -G --rev '::(desc("mAE,Km") + desc("mK,AEm") + desc("mEA,Jm") + desc("mJ,EAm"))'
970 @ mJ,EAm: chained merges (conflict -> simple) - same content everywhere
970 @ mJ,EAm: chained merges (conflict -> simple) - same content everywhere
971 |\
971 |\
972 +---o mEA,Jm: chained merges (conflict -> simple) - same content everywhere
972 +---o mEA,Jm: chained merges (conflict -> simple) - same content everywhere
973 | |/
973 | |/
974 | | o mK,AEm: chained merges (conflict -> simple) - same content everywhere
974 | | o mK,AEm: chained merges (conflict -> simple) - same content everywhere
975 | | |\
975 | | |\
976 | | +---o mAE,Km: chained merges (conflict -> simple) - same content everywhere
976 | | +---o mAE,Km: chained merges (conflict -> simple) - same content everywhere
977 | | | |/
977 | | | |/
978 | | | o k-1: unrelated changes (based on "e" changes)
978 | | | o k-1: unrelated changes (based on "e" changes)
979 | | | |
979 | | | |
980 | o | | j-1: unrelated changes (based on the "a" series of changes)
980 | o | | j-1: unrelated changes (based on the "a" series of changes)
981 | | | |
981 | | | |
982 o-----+ mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
982 o-----+ mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
983 |/ / /
983 |/ / /
984 | o / mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
984 | o / mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
985 |/|/
985 |/|/
986 | o e-2 g -move-> f
986 | o e-2 g -move-> f
987 | |
987 | |
988 | o e-1 b -move-> g
988 | o e-1 b -move-> g
989 | |
989 | |
990 o | a-2: e -move-> f
990 o | a-2: e -move-> f
991 | |
991 | |
992 o | a-1: d -move-> e
992 o | a-1: d -move-> e
993 |/
993 |/
994 o i-2: c -move-> d, s -move-> t
994 o i-2: c -move-> d, s -move-> t
995 |
995 |
996 o i-1: a -move-> c, p -move-> s
996 o i-1: a -move-> c, p -move-> s
997 |
997 |
998 o i-0 initial commit: a b h p q r
998 o i-0 initial commit: a b h p q r
999
999
1000
1000
1001 Subcase: chaining conflicting rename resolution, with actual merging happening
1001 Subcase: chaining conflicting rename resolution, with actual merging happening
1002 ``````````````````````````````````````````````````````````````````````````````
1002 ``````````````````````````````````````````````````````````````````````````````
1003
1003
1004 The "mPQm" and "mQPm" case create a rename tracking conflict on file 't'. We
1004 The "mPQm" and "mQPm" case create a rename tracking conflict on file 't'. We
1005 add more change on the respective branch and merge again. These second merge
1005 add more change on the respective branch and merge again. These second merge
1006 does not involve the file 't' and the arbitration done within "mPQm" and "mQP"
1006 does not involve the file 't' and the arbitration done within "mPQm" and "mQP"
1007 about that file should stay unchanged.
1007 about that file should stay unchanged.
1008
1008
1009 $ case_desc="chained merges (conflict -> simple) - different content"
1009 $ case_desc="chained merges (conflict -> simple) - different content"
1010
1010
1011 (extra unrelated changes)
1011 (extra unrelated changes)
1012
1012
1013 $ hg up 'desc("p-2")'
1013 $ hg up 'desc("p-2")'
1014 3 files updated, 0 files merged, 3 files removed, 0 files unresolved
1014 3 files updated, 0 files merged, 3 files removed, 0 files unresolved
1015 $ echo s > unrelated-s
1015 $ echo s > unrelated-s
1016 $ hg add unrelated-s
1016 $ hg add unrelated-s
1017 $ hg ci -m 's-1: unrelated changes (based on the "p" series of changes)'
1017 $ hg ci -m 's-1: unrelated changes (based on the "p" series of changes)'
1018 created new head
1018 created new head
1019
1019
1020 $ hg up 'desc("q-2")'
1020 $ hg up 'desc("q-2")'
1021 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
1021 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
1022 $ echo t > unrelated-t
1022 $ echo t > unrelated-t
1023 $ hg add unrelated-t
1023 $ hg add unrelated-t
1024 $ hg ci -m 't-1: unrelated changes (based on "q" changes)'
1024 $ hg ci -m 't-1: unrelated changes (based on "q" changes)'
1025 created new head
1025 created new head
1026
1026
1027 (merge variant 1)
1027 (merge variant 1)
1028
1028
1029 $ hg up 'desc("mPQm")'
1029 $ hg up 'desc("mPQm")'
1030 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1030 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1031 $ hg merge 'desc("t-1")'
1031 $ hg merge 'desc("t-1")'
1032 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1032 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1033 (branch merge, don't forget to commit)
1033 (branch merge, don't forget to commit)
1034 $ hg ci -m "mPQ,Tm: $case_desc"
1034 $ hg ci -m "mPQ,Tm: $case_desc"
1035
1035
1036 (merge variant 2)
1036 (merge variant 2)
1037
1037
1038 $ hg up 'desc("t-1")'
1038 $ hg up 'desc("t-1")'
1039 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1039 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1040
1040
1041 $ hg merge 'desc("mPQm")'
1041 $ hg merge 'desc("mPQm")'
1042 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1042 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1043 (branch merge, don't forget to commit)
1043 (branch merge, don't forget to commit)
1044 $ hg ci -m "mT,PQm: $case_desc"
1044 $ hg ci -m "mT,PQm: $case_desc"
1045 created new head
1045 created new head
1046
1046
1047 (merge variant 3)
1047 (merge variant 3)
1048
1048
1049 $ hg up 'desc("mQPm")'
1049 $ hg up 'desc("mQPm")'
1050 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1050 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1051 $ hg merge 'desc("s-1")'
1051 $ hg merge 'desc("s-1")'
1052 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1052 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1053 (branch merge, don't forget to commit)
1053 (branch merge, don't forget to commit)
1054 $ hg ci -m "mQP,Sm: $case_desc"
1054 $ hg ci -m "mQP,Sm: $case_desc"
1055
1055
1056 (merge variant 4)
1056 (merge variant 4)
1057
1057
1058 $ hg up 'desc("s-1")'
1058 $ hg up 'desc("s-1")'
1059 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1059 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1060 $ hg merge 'desc("mQPm")'
1060 $ hg merge 'desc("mQPm")'
1061 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1061 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1062 (branch merge, don't forget to commit)
1062 (branch merge, don't forget to commit)
1063 $ hg ci -m "mS,QPm: $case_desc"
1063 $ hg ci -m "mS,QPm: $case_desc"
1064 created new head
1064 created new head
1065 $ hg up null --quiet
1065 $ hg up null --quiet
1066
1066
1067
1067
1068 $ hg log -G --rev '::(desc("mPQ,Tm") + desc("mT,PQm") + desc("mQP,Sm") + desc("mS,QPm"))'
1068 $ hg log -G --rev '::(desc("mPQ,Tm") + desc("mT,PQm") + desc("mQP,Sm") + desc("mS,QPm"))'
1069 o mS,QPm: chained merges (conflict -> simple) - different content
1069 o mS,QPm: chained merges (conflict -> simple) - different content
1070 |\
1070 |\
1071 +---o mQP,Sm: chained merges (conflict -> simple) - different content
1071 +---o mQP,Sm: chained merges (conflict -> simple) - different content
1072 | |/
1072 | |/
1073 | | o mT,PQm: chained merges (conflict -> simple) - different content
1073 | | o mT,PQm: chained merges (conflict -> simple) - different content
1074 | | |\
1074 | | |\
1075 | | +---o mPQ,Tm: chained merges (conflict -> simple) - different content
1075 | | +---o mPQ,Tm: chained merges (conflict -> simple) - different content
1076 | | | |/
1076 | | | |/
1077 | | | o t-1: unrelated changes (based on "q" changes)
1077 | | | o t-1: unrelated changes (based on "q" changes)
1078 | | | |
1078 | | | |
1079 | o | | s-1: unrelated changes (based on the "p" series of changes)
1079 | o | | s-1: unrelated changes (based on the "p" series of changes)
1080 | | | |
1080 | | | |
1081 o-----+ mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
1081 o-----+ mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
1082 |/ / /
1082 |/ / /
1083 | o / mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
1083 | o / mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
1084 |/|/
1084 |/|/
1085 | o q-2 w -move-> v
1085 | o q-2 w -move-> v
1086 | |
1086 | |
1087 | o q-1 r -move-> w
1087 | o q-1 r -move-> w
1088 | |
1088 | |
1089 o | p-2: u -move-> v
1089 o | p-2: u -move-> v
1090 | |
1090 | |
1091 o | p-1: t -move-> u
1091 o | p-1: t -move-> u
1092 |/
1092 |/
1093 o i-2: c -move-> d, s -move-> t
1093 o i-2: c -move-> d, s -move-> t
1094 |
1094 |
1095 o i-1: a -move-> c, p -move-> s
1095 o i-1: a -move-> c, p -move-> s
1096 |
1096 |
1097 o i-0 initial commit: a b h p q r
1097 o i-0 initial commit: a b h p q r
1098
1098
1099
1099
1100 Subcase: chaining salvage information during a merge
1100 Subcase: chaining salvage information during a merge
1101 ````````````````````````````````````````````````````
1101 ````````````````````````````````````````````````````
1102
1102
1103 We add more change on the branch were the file was deleted. merging again
1103 We add more change on the branch were the file was deleted. merging again
1104 should preserve the fact eh file was salvaged.
1104 should preserve the fact eh file was salvaged.
1105
1105
1106 $ case_desc="chained merges (salvaged -> simple) - same content (when the file exists)"
1106 $ case_desc="chained merges (salvaged -> simple) - same content (when the file exists)"
1107
1107
1108 (creating the change)
1108 (creating the change)
1109
1109
1110 $ hg up 'desc("c-1")'
1110 $ hg up 'desc("c-1")'
1111 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1111 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1112 $ echo l > unrelated-l
1112 $ echo l > unrelated-l
1113 $ hg add unrelated-l
1113 $ hg add unrelated-l
1114 $ hg ci -m 'l-1: unrelated changes (based on "c" changes)'
1114 $ hg ci -m 'l-1: unrelated changes (based on "c" changes)'
1115 created new head
1115 created new head
1116
1116
1117 (Merge variant 1)
1117 (Merge variant 1)
1118
1118
1119 $ hg up 'desc("mBC-revert-m")'
1119 $ hg up 'desc("mBC-revert-m")'
1120 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1120 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1121 $ hg merge 'desc("l-1")'
1121 $ hg merge 'desc("l-1")'
1122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1123 (branch merge, don't forget to commit)
1123 (branch merge, don't forget to commit)
1124 $ hg ci -m "mBC+revert,Lm: $case_desc"
1124 $ hg ci -m "mBC+revert,Lm: $case_desc"
1125
1125
1126 (Merge variant 2)
1126 (Merge variant 2)
1127
1127
1128 $ hg up 'desc("mCB-revert-m")'
1128 $ hg up 'desc("mCB-revert-m")'
1129 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1129 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1130 $ hg merge 'desc("l-1")'
1130 $ hg merge 'desc("l-1")'
1131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1132 (branch merge, don't forget to commit)
1132 (branch merge, don't forget to commit)
1133 $ hg ci -m "mCB+revert,Lm: $case_desc"
1133 $ hg ci -m "mCB+revert,Lm: $case_desc"
1134
1134
1135 (Merge variant 3)
1135 (Merge variant 3)
1136
1136
1137 $ hg up 'desc("l-1")'
1137 $ hg up 'desc("l-1")'
1138 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1138 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1139
1139
1140 $ hg merge 'desc("mBC-revert-m")'
1140 $ hg merge 'desc("mBC-revert-m")'
1141 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1141 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1142 (branch merge, don't forget to commit)
1142 (branch merge, don't forget to commit)
1143 $ hg ci -m "mL,BC+revertm: $case_desc"
1143 $ hg ci -m "mL,BC+revertm: $case_desc"
1144 created new head
1144 created new head
1145
1145
1146 (Merge variant 4)
1146 (Merge variant 4)
1147
1147
1148 $ hg up 'desc("l-1")'
1148 $ hg up 'desc("l-1")'
1149 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1149 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1150
1150
1151 $ hg merge 'desc("mCB-revert-m")'
1151 $ hg merge 'desc("mCB-revert-m")'
1152 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1152 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1153 (branch merge, don't forget to commit)
1153 (branch merge, don't forget to commit)
1154 $ hg ci -m "mL,CB+revertm: $case_desc"
1154 $ hg ci -m "mL,CB+revertm: $case_desc"
1155 created new head
1155 created new head
1156
1156
1157 $ hg log -G --rev '::(desc("mBC+revert,Lm") + desc("mCB+revert,Lm") + desc("mL,BC+revertm") + desc("mL,CB+revertm"))'
1157 $ hg log -G --rev '::(desc("mBC+revert,Lm") + desc("mCB+revert,Lm") + desc("mL,BC+revertm") + desc("mL,CB+revertm"))'
1158 @ mL,CB+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1158 @ mL,CB+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1159 |\
1159 |\
1160 | | o mL,BC+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1160 | | o mL,BC+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1161 | |/|
1161 | |/|
1162 +-+---o mCB+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1162 +-+---o mCB+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1163 | | |
1163 | | |
1164 | +---o mBC+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1164 | +---o mBC+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1165 | | |/
1165 | | |/
1166 | o | l-1: unrelated changes (based on "c" changes)
1166 | o | l-1: unrelated changes (based on "c" changes)
1167 | | |
1167 | | |
1168 | | o mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1168 | | o mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1169 | |/|
1169 | |/|
1170 o---+ mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1170 o---+ mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1171 |/ /
1171 |/ /
1172 o | c-1 delete d
1172 o | c-1 delete d
1173 | |
1173 | |
1174 | o b-1: b update
1174 | o b-1: b update
1175 |/
1175 |/
1176 o i-2: c -move-> d, s -move-> t
1176 o i-2: c -move-> d, s -move-> t
1177 |
1177 |
1178 o i-1: a -move-> c, p -move-> s
1178 o i-1: a -move-> c, p -move-> s
1179 |
1179 |
1180 o i-0 initial commit: a b h p q r
1180 o i-0 initial commit: a b h p q r
1181
1181
1182
1182
1183
1183
1184 Subcase: chaining "merged" information during a merge
1184 Subcase: chaining "merged" information during a merge
1185 ``````````````````````````````````````````````````````
1185 ``````````````````````````````````````````````````````
1186
1186
1187 When a non-rename change are merged with a copy overwrite, the merge pick the copy source from (p1) as the reference. We should preserve this information in subsequent merges.
1187 When a non-rename change are merged with a copy overwrite, the merge pick the copy source from (p1) as the reference. We should preserve this information in subsequent merges.
1188
1188
1189 $ case_desc="chained merges (copy-overwrite -> simple) - same content"
1189 $ case_desc="chained merges (copy-overwrite -> simple) - same content"
1190
1190
1191 (extra unrelated changes)
1191 (extra unrelated changes)
1192
1192
1193 $ hg up 'desc("f-2")'
1193 $ hg up 'desc("f-2")'
1194 2 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1194 2 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1195 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1195 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1196 $ echo n > unrelated-n
1196 $ echo n > unrelated-n
1197 $ hg add unrelated-n
1197 $ hg add unrelated-n
1198 $ hg ci -m 'n-1: unrelated changes (based on the "f" series of changes)'
1198 $ hg ci -m 'n-1: unrelated changes (based on the "f" series of changes)'
1199 created new head
1199 created new head
1200
1200
1201 $ hg up 'desc("g-1")'
1201 $ hg up 'desc("g-1")'
1202 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1202 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1203 $ echo o > unrelated-o
1203 $ echo o > unrelated-o
1204 $ hg add unrelated-o
1204 $ hg add unrelated-o
1205 $ hg ci -m 'o-1: unrelated changes (based on "g" changes)'
1205 $ hg ci -m 'o-1: unrelated changes (based on "g" changes)'
1206 created new head
1206 created new head
1207
1207
1208 (merge variant 1)
1208 (merge variant 1)
1209
1209
1210 $ hg up 'desc("mFGm")'
1210 $ hg up 'desc("mFGm")'
1211 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1211 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1212 0 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1212 0 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1213 $ hg merge 'desc("o-1")'
1213 $ hg merge 'desc("o-1")'
1214 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1214 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1215 (branch merge, don't forget to commit)
1215 (branch merge, don't forget to commit)
1216 $ hg ci -m "mFG,Om: $case_desc"
1216 $ hg ci -m "mFG,Om: $case_desc"
1217
1217
1218 (merge variant 2)
1218 (merge variant 2)
1219
1219
1220 $ hg up 'desc("o-1")'
1220 $ hg up 'desc("o-1")'
1221 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
1221 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
1222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
1222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
1223 $ hg merge 'desc("FGm")'
1223 $ hg merge 'desc("FGm")'
1224 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
1224 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
1225 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
1225 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
1226 (branch merge, don't forget to commit)
1226 (branch merge, don't forget to commit)
1227 $ hg ci -m "mO,FGm: $case_desc"
1227 $ hg ci -m "mO,FGm: $case_desc"
1228 created new head
1228 created new head
1229
1229
1230 (merge variant 3)
1230 (merge variant 3)
1231
1231
1232 $ hg up 'desc("mGFm")'
1232 $ hg up 'desc("mGFm")'
1233 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1233 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1234 $ hg merge 'desc("n-1")'
1234 $ hg merge 'desc("n-1")'
1235 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1235 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1236 (branch merge, don't forget to commit)
1236 (branch merge, don't forget to commit)
1237 $ hg ci -m "mGF,Nm: $case_desc"
1237 $ hg ci -m "mGF,Nm: $case_desc"
1238
1238
1239 (merge variant 4)
1239 (merge variant 4)
1240
1240
1241 $ hg up 'desc("n-1")'
1241 $ hg up 'desc("n-1")'
1242 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1242 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1243 $ hg merge 'desc("mGFm")'
1243 $ hg merge 'desc("mGFm")'
1244 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1244 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1245 (branch merge, don't forget to commit)
1245 (branch merge, don't forget to commit)
1246 $ hg ci -m "mN,GFm: $case_desc"
1246 $ hg ci -m "mN,GFm: $case_desc"
1247 created new head
1247 created new head
1248
1248
1249 $ hg log -G --rev '::(desc("mFG,Om") + desc("mO,FGm") + desc("mGF,Nm") + desc("mN,GFm"))'
1249 $ hg log -G --rev '::(desc("mFG,Om") + desc("mO,FGm") + desc("mGF,Nm") + desc("mN,GFm"))'
1250 @ mN,GFm: chained merges (copy-overwrite -> simple) - same content
1250 @ mN,GFm: chained merges (copy-overwrite -> simple) - same content
1251 |\
1251 |\
1252 +---o mGF,Nm: chained merges (copy-overwrite -> simple) - same content
1252 +---o mGF,Nm: chained merges (copy-overwrite -> simple) - same content
1253 | |/
1253 | |/
1254 | | o mO,FGm: chained merges (copy-overwrite -> simple) - same content
1254 | | o mO,FGm: chained merges (copy-overwrite -> simple) - same content
1255 | | |\
1255 | | |\
1256 | | +---o mFG,Om: chained merges (copy-overwrite -> simple) - same content
1256 | | +---o mFG,Om: chained merges (copy-overwrite -> simple) - same content
1257 | | | |/
1257 | | | |/
1258 | | | o o-1: unrelated changes (based on "g" changes)
1258 | | | o o-1: unrelated changes (based on "g" changes)
1259 | | | |
1259 | | | |
1260 | o | | n-1: unrelated changes (based on the "f" series of changes)
1260 | o | | n-1: unrelated changes (based on the "f" series of changes)
1261 | | | |
1261 | | | |
1262 o-----+ mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
1262 o-----+ mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
1263 |/ / /
1263 |/ / /
1264 | o / mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
1264 | o / mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
1265 |/|/
1265 |/|/
1266 | o g-1: update d
1266 | o g-1: update d
1267 | |
1267 | |
1268 o | f-2: rename i -> d
1268 o | f-2: rename i -> d
1269 | |
1269 | |
1270 o | f-1: rename h -> i
1270 o | f-1: rename h -> i
1271 |/
1271 |/
1272 o i-2: c -move-> d, s -move-> t
1272 o i-2: c -move-> d, s -move-> t
1273 |
1273 |
1274 o i-1: a -move-> c, p -move-> s
1274 o i-1: a -move-> c, p -move-> s
1275 |
1275 |
1276 o i-0 initial commit: a b h p q r
1276 o i-0 initial commit: a b h p q r
1277
1277
1278
1278
1279 Subcase: chaining conflicting rename resolution, with extra change during the merge
1279 Subcase: chaining conflicting rename resolution, with extra change during the merge
1280 ```````````````````````````````````````````````````````````````````````````````````
1280 ```````````````````````````````````````````````````````````````````````````````````
1281
1281
1282 The "mEA-change-m-0" and "mAE-change-m-0" case create a rename tracking conflict on file 'f'. We
1282 The "mEA-change-m-0" and "mAE-change-m-0" case create a rename tracking conflict on file 'f'. We
1283 add more change on the respective branch and merge again. These second merge
1283 add more change on the respective branch and merge again. These second merge
1284 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
1284 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
1285 about that file should stay unchanged.
1285 about that file should stay unchanged.
1286
1286
1287 $ case_desc="chained merges (conflict+change -> simple) - same content on both branch in the initial merge"
1287 $ case_desc="chained merges (conflict+change -> simple) - same content on both branch in the initial merge"
1288
1288
1289
1289
1290 (merge variant 1)
1290 (merge variant 1)
1291
1291
1292 $ hg up 'desc("mAE-change-m")'
1292 $ hg up 'desc("mAE-change-m")'
1293 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
1293 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
1294 $ hg merge 'desc("k-1")'
1294 $ hg merge 'desc("k-1")'
1295 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1295 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1296 (branch merge, don't forget to commit)
1296 (branch merge, don't forget to commit)
1297 $ hg ci -m "mAE-change,Km: $case_desc"
1297 $ hg ci -m "mAE-change,Km: $case_desc"
1298
1298
1299 (merge variant 2)
1299 (merge variant 2)
1300
1300
1301 $ hg up 'desc("k-1")'
1301 $ hg up 'desc("k-1")'
1302 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1302 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1303
1303
1304 $ hg merge 'desc("mAE-change-m")'
1304 $ hg merge 'desc("mAE-change-m")'
1305 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1305 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1306 (branch merge, don't forget to commit)
1306 (branch merge, don't forget to commit)
1307 $ hg ci -m "mK,AE-change-m: $case_desc"
1307 $ hg ci -m "mK,AE-change-m: $case_desc"
1308 created new head
1308 created new head
1309
1309
1310 (merge variant 3)
1310 (merge variant 3)
1311
1311
1312 $ hg up 'desc("mEA-change-m")'
1312 $ hg up 'desc("mEA-change-m")'
1313 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1313 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1314 $ hg merge 'desc("j-1")'
1314 $ hg merge 'desc("j-1")'
1315 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1315 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1316 (branch merge, don't forget to commit)
1316 (branch merge, don't forget to commit)
1317 $ hg ci -m "mEA-change,Jm: $case_desc"
1317 $ hg ci -m "mEA-change,Jm: $case_desc"
1318
1318
1319 (merge variant 4)
1319 (merge variant 4)
1320
1320
1321 $ hg up 'desc("j-1")'
1321 $ hg up 'desc("j-1")'
1322 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1322 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1323 $ hg merge 'desc("mEA-change-m")'
1323 $ hg merge 'desc("mEA-change-m")'
1324 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1324 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1325 (branch merge, don't forget to commit)
1325 (branch merge, don't forget to commit)
1326 $ hg ci -m "mJ,EA-change-m: $case_desc"
1326 $ hg ci -m "mJ,EA-change-m: $case_desc"
1327 created new head
1327 created new head
1328
1328
1329
1329
1330 $ hg log -G --rev '::(desc("mAE-change,Km") + desc("mK,AE-change-m") + desc("mEA-change,Jm") + desc("mJ,EA-change-m"))'
1330 $ hg log -G --rev '::(desc("mAE-change,Km") + desc("mK,AE-change-m") + desc("mEA-change,Jm") + desc("mJ,EA-change-m"))'
1331 @ mJ,EA-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1331 @ mJ,EA-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1332 |\
1332 |\
1333 +---o mEA-change,Jm: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1333 +---o mEA-change,Jm: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1334 | |/
1334 | |/
1335 | | o mK,AE-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1335 | | o mK,AE-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1336 | | |\
1336 | | |\
1337 | | +---o mAE-change,Km: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1337 | | +---o mAE-change,Km: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1338 | | | |/
1338 | | | |/
1339 | | | o k-1: unrelated changes (based on "e" changes)
1339 | | | o k-1: unrelated changes (based on "e" changes)
1340 | | | |
1340 | | | |
1341 | o | | j-1: unrelated changes (based on the "a" series of changes)
1341 | o | | j-1: unrelated changes (based on the "a" series of changes)
1342 | | | |
1342 | | | |
1343 o-----+ mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
1343 o-----+ mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
1344 |/ / /
1344 |/ / /
1345 | o / mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
1345 | o / mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
1346 |/|/
1346 |/|/
1347 | o e-2 g -move-> f
1347 | o e-2 g -move-> f
1348 | |
1348 | |
1349 | o e-1 b -move-> g
1349 | o e-1 b -move-> g
1350 | |
1350 | |
1351 o | a-2: e -move-> f
1351 o | a-2: e -move-> f
1352 | |
1352 | |
1353 o | a-1: d -move-> e
1353 o | a-1: d -move-> e
1354 |/
1354 |/
1355 o i-2: c -move-> d, s -move-> t
1355 o i-2: c -move-> d, s -move-> t
1356 |
1356 |
1357 o i-1: a -move-> c, p -move-> s
1357 o i-1: a -move-> c, p -move-> s
1358 |
1358 |
1359 o i-0 initial commit: a b h p q r
1359 o i-0 initial commit: a b h p q r
1360
1360
1361
1361
1362 Summary of all created cases
1362 Summary of all created cases
1363 ----------------------------
1363 ----------------------------
1364
1364
1365 $ hg up --quiet null
1365 $ hg up --quiet null
1366
1366
1367 (This exists to help keeping a compact list of the various cases we have built)
1367 (This exists to help keeping a compact list of the various cases we have built)
1368
1368
1369 $ hg log -T '{desc|firstline}\n'| sort
1369 $ hg log -T '{desc|firstline}\n'| sort
1370 a-1: d -move-> e
1370 a-1: d -move-> e
1371 a-2: e -move-> f
1371 a-2: e -move-> f
1372 b-1: b update
1372 b-1: b update
1373 c-1 delete d
1373 c-1 delete d
1374 d-1 delete d
1374 d-1 delete d
1375 d-2 re-add d
1375 d-2 re-add d
1376 e-1 b -move-> g
1376 e-1 b -move-> g
1377 e-2 g -move-> f
1377 e-2 g -move-> f
1378 f-1: rename h -> i
1378 f-1: rename h -> i
1379 f-2: rename i -> d
1379 f-2: rename i -> d
1380 g-1: update d
1380 g-1: update d
1381 h-1: b -(move)-> d
1381 h-1: b -(move)-> d
1382 i-0 initial commit: a b h p q r
1382 i-0 initial commit: a b h p q r
1383 i-1: a -move-> c, p -move-> s
1383 i-1: a -move-> c, p -move-> s
1384 i-2: c -move-> d, s -move-> t
1384 i-2: c -move-> d, s -move-> t
1385 j-1: unrelated changes (based on the "a" series of changes)
1385 j-1: unrelated changes (based on the "a" series of changes)
1386 k-1: unrelated changes (based on "e" changes)
1386 k-1: unrelated changes (based on "e" changes)
1387 l-1: unrelated changes (based on "c" changes)
1387 l-1: unrelated changes (based on "c" changes)
1388 mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
1388 mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
1389 mAE,Km: chained merges (conflict -> simple) - same content everywhere
1389 mAE,Km: chained merges (conflict -> simple) - same content everywhere
1390 mAE-change,Km: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1390 mAE-change,Km: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1391 mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
1391 mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
1392 mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
1392 mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
1393 mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
1393 mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
1394 mBC+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1394 mBC+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1395 mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1395 mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1396 mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
1396 mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
1397 mBCm-1 re-add d
1397 mBCm-1 re-add d
1398 mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
1398 mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
1399 mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
1399 mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
1400 mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
1400 mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
1401 mCB+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1401 mCB+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1402 mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1402 mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1403 mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
1403 mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
1404 mCBm-1 re-add d
1404 mCBm-1 re-add d
1405 mCGm-0 merge updated/deleted - revive the file (updated content) - one way
1405 mCGm-0 merge updated/deleted - revive the file (updated content) - one way
1406 mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
1406 mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
1407 mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
1407 mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
1408 mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
1408 mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
1409 mEA,Jm: chained merges (conflict -> simple) - same content everywhere
1409 mEA,Jm: chained merges (conflict -> simple) - same content everywhere
1410 mEA-change,Jm: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1410 mEA-change,Jm: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1411 mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
1411 mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
1412 mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
1412 mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
1413 mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
1413 mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
1414 mFG,Om: chained merges (copy-overwrite -> simple) - same content
1414 mFG,Om: chained merges (copy-overwrite -> simple) - same content
1415 mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
1415 mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
1416 mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
1416 mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
1417 mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
1417 mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
1418 mGF,Nm: chained merges (copy-overwrite -> simple) - same content
1418 mGF,Nm: chained merges (copy-overwrite -> simple) - same content
1419 mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
1419 mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
1420 mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
1420 mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
1421 mJ,EA-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1421 mJ,EA-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1422 mJ,EAm: chained merges (conflict -> simple) - same content everywhere
1422 mJ,EAm: chained merges (conflict -> simple) - same content everywhere
1423 mK,AE-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1423 mK,AE-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1424 mK,AEm: chained merges (conflict -> simple) - same content everywhere
1424 mK,AEm: chained merges (conflict -> simple) - same content everywhere
1425 mL,BC+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1425 mL,BC+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1426 mL,CB+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1426 mL,CB+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1427 mN,GFm: chained merges (copy-overwrite -> simple) - same content
1427 mN,GFm: chained merges (copy-overwrite -> simple) - same content
1428 mO,FGm: chained merges (copy-overwrite -> simple) - same content
1428 mO,FGm: chained merges (copy-overwrite -> simple) - same content
1429 mPQ,Tm: chained merges (conflict -> simple) - different content
1429 mPQ,Tm: chained merges (conflict -> simple) - different content
1430 mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
1430 mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
1431 mQP,Sm: chained merges (conflict -> simple) - different content
1431 mQP,Sm: chained merges (conflict -> simple) - different content
1432 mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
1432 mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
1433 mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
1433 mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
1434 mS,QPm: chained merges (conflict -> simple) - different content
1434 mS,QPm: chained merges (conflict -> simple) - different content
1435 mT,PQm: chained merges (conflict -> simple) - different content
1435 mT,PQm: chained merges (conflict -> simple) - different content
1436 n-1: unrelated changes (based on the "f" series of changes)
1436 n-1: unrelated changes (based on the "f" series of changes)
1437 o-1: unrelated changes (based on "g" changes)
1437 o-1: unrelated changes (based on "g" changes)
1438 p-1: t -move-> u
1438 p-1: t -move-> u
1439 p-2: u -move-> v
1439 p-2: u -move-> v
1440 q-1 r -move-> w
1440 q-1 r -move-> w
1441 q-2 w -move-> v
1441 q-2 w -move-> v
1442 r-1: rename r -> x
1442 r-1: rename r -> x
1443 r-2: rename t -> x
1443 r-2: rename t -> x
1444 s-1: unrelated changes (based on the "p" series of changes)
1444 s-1: unrelated changes (based on the "p" series of changes)
1445 t-1: unrelated changes (based on "q" changes)
1445 t-1: unrelated changes (based on "q" changes)
1446
1446
1447
1447
1448 Test that sidedata computations during upgrades are correct
1448 Test that sidedata computations during upgrades are correct
1449 ===========================================================
1449 ===========================================================
1450
1450
1451 We upgrade a repository that is not using sidedata (the filelog case) and
1451 We upgrade a repository that is not using sidedata (the filelog case) and
1452 check that the same side data have been generated as if they were computed at
1452 check that the same side data have been generated as if they were computed at
1453 commit time.
1453 commit time.
1454
1454
1455
1455
1456 #if upgraded
1456 #if upgraded
1457 $ cat >> $HGRCPATH << EOF
1457 $ cat >> $HGRCPATH << EOF
1458 > [format]
1458 > [format]
1459 > exp-use-side-data = yes
1459 > exp-use-side-data = yes
1460 > exp-use-copies-side-data-changeset = yes
1460 > exp-use-copies-side-data-changeset = yes
1461 > EOF
1461 > EOF
1462 $ hg debugformat -v
1462 $ hg debugformat -v
1463 format-variant repo config default
1463 format-variant repo config default
1464 fncache: yes yes yes
1464 fncache: yes yes yes
1465 dotencode: yes yes yes
1465 dotencode: yes yes yes
1466 generaldelta: yes yes yes
1466 generaldelta: yes yes yes
1467 share-safe: no no no
1467 share-safe: no no no
1468 sparserevlog: yes yes yes
1468 sparserevlog: yes yes yes
1469 sidedata: no yes no
1469 sidedata: no yes no
1470 persistent-nodemap: no no no
1470 persistent-nodemap: no no no
1471 copies-sdc: no yes no
1471 copies-sdc: no yes no
1472 revlog-v2: no yes no
1472 plain-cl-delta: yes yes yes
1473 plain-cl-delta: yes yes yes
1473 compression: * (glob)
1474 compression: * (glob)
1474 compression-level: default default default
1475 compression-level: default default default
1475 $ hg debugupgraderepo --run --quiet
1476 $ hg debugupgraderepo --run --quiet
1476 upgrade will perform the following actions:
1477 upgrade will perform the following actions:
1477
1478
1478 requirements
1479 requirements
1479 preserved: * (glob)
1480 preserved: * (glob)
1480 added: exp-copies-sidedata-changeset, exp-sidedata-flag
1481 removed: revlogv1
1482 added: exp-copies-sidedata-changeset, exp-revlogv2.2, exp-sidedata-flag
1481
1483
1482 processed revlogs:
1484 processed revlogs:
1483 - all-filelogs
1485 - all-filelogs
1484 - changelog
1486 - changelog
1485 - manifest
1487 - manifest
1486
1488
1487 #endif
1489 #endif
1488
1490
1489 #if upgraded-parallel
1491 #if upgraded-parallel
1490 $ cat >> $HGRCPATH << EOF
1492 $ cat >> $HGRCPATH << EOF
1491 > [format]
1493 > [format]
1492 > exp-use-side-data = yes
1494 > exp-use-side-data = yes
1493 > exp-use-copies-side-data-changeset = yes
1495 > exp-use-copies-side-data-changeset = yes
1494 > [experimental]
1496 > [experimental]
1495 > worker.repository-upgrade=yes
1497 > worker.repository-upgrade=yes
1496 > [worker]
1498 > [worker]
1497 > enabled=yes
1499 > enabled=yes
1498 > numcpus=8
1500 > numcpus=8
1499 > EOF
1501 > EOF
1500 $ hg debugformat -v
1502 $ hg debugformat -v
1501 format-variant repo config default
1503 format-variant repo config default
1502 fncache: yes yes yes
1504 fncache: yes yes yes
1503 dotencode: yes yes yes
1505 dotencode: yes yes yes
1504 generaldelta: yes yes yes
1506 generaldelta: yes yes yes
1505 share-safe: no no no
1507 share-safe: no no no
1506 sparserevlog: yes yes yes
1508 sparserevlog: yes yes yes
1507 sidedata: no yes no
1509 sidedata: no yes no
1508 persistent-nodemap: no no no
1510 persistent-nodemap: no no no
1509 copies-sdc: no yes no
1511 copies-sdc: no yes no
1512 revlog-v2: no yes no
1510 plain-cl-delta: yes yes yes
1513 plain-cl-delta: yes yes yes
1511 compression: * (glob)
1514 compression: * (glob)
1512 compression-level: default default default
1515 compression-level: default default default
1513 $ hg debugupgraderepo --run --quiet
1516 $ hg debugupgraderepo --run --quiet
1514 upgrade will perform the following actions:
1517 upgrade will perform the following actions:
1515
1518
1516 requirements
1519 requirements
1517 preserved: * (glob)
1520 preserved: * (glob)
1518 added: exp-copies-sidedata-changeset, exp-sidedata-flag
1521 removed: revlogv1
1522 added: exp-copies-sidedata-changeset, exp-revlogv2.2, exp-sidedata-flag
1519
1523
1520 processed revlogs:
1524 processed revlogs:
1521 - all-filelogs
1525 - all-filelogs
1522 - changelog
1526 - changelog
1523 - manifest
1527 - manifest
1524
1528
1525 #endif
1529 #endif
1526
1530
1527
1531
1528 #if no-compatibility no-filelog no-changeset
1532 #if no-compatibility no-filelog no-changeset
1529
1533
1530 $ hg debugchangedfiles --compute 0
1534 $ hg debugchangedfiles --compute 0
1531 added : a, ;
1535 added : a, ;
1532 added : b, ;
1536 added : b, ;
1533 added : h, ;
1537 added : h, ;
1534 added : p, ;
1538 added : p, ;
1535 added : q, ;
1539 added : q, ;
1536 added : r, ;
1540 added : r, ;
1537
1541
1538 $ for rev in `hg log --rev 'all()' -T '{rev}\n'`; do
1542 $ for rev in `hg log --rev 'all()' -T '{rev}\n'`; do
1539 > case_id=`hg log -r $rev -T '{word(0, desc, ":")}\n'`
1543 > case_id=`hg log -r $rev -T '{word(0, desc, ":")}\n'`
1540 > echo "##### revision \"$case_id\" #####"
1544 > echo "##### revision \"$case_id\" #####"
1541 > hg debugsidedata -c -v -- $rev
1545 > hg debugsidedata -c -v -- $rev
1542 > hg debugchangedfiles $rev
1546 > hg debugchangedfiles $rev
1543 > done
1547 > done
1544 ##### revision "i-0 initial commit" #####
1548 ##### revision "i-0 initial commit" #####
1545 1 sidedata entries
1549 1 sidedata entries
1546 entry-0014 size 64
1550 entry-0014 size 64
1547 '\x00\x00\x00\x06\x04\x00\x00\x00\x01\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\x00abhpqr'
1551 '\x00\x00\x00\x06\x04\x00\x00\x00\x01\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\x00abhpqr'
1548 added : a, ;
1552 added : a, ;
1549 added : b, ;
1553 added : b, ;
1550 added : h, ;
1554 added : h, ;
1551 added : p, ;
1555 added : p, ;
1552 added : q, ;
1556 added : q, ;
1553 added : r, ;
1557 added : r, ;
1554 ##### revision "i-1" #####
1558 ##### revision "i-1" #####
1555 1 sidedata entries
1559 1 sidedata entries
1556 entry-0014 size 44
1560 entry-0014 size 44
1557 '\x00\x00\x00\x04\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x0c\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x02acps'
1561 '\x00\x00\x00\x04\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x0c\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x02acps'
1558 removed : a, ;
1562 removed : a, ;
1559 added p1: c, a;
1563 added p1: c, a;
1560 removed : p, ;
1564 removed : p, ;
1561 added p1: s, p;
1565 added p1: s, p;
1562 ##### revision "i-2" #####
1566 ##### revision "i-2" #####
1563 1 sidedata entries
1567 1 sidedata entries
1564 entry-0014 size 44
1568 entry-0014 size 44
1565 '\x00\x00\x00\x04\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x0c\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x02cdst'
1569 '\x00\x00\x00\x04\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x0c\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x02cdst'
1566 removed : c, ;
1570 removed : c, ;
1567 added p1: d, c;
1571 added p1: d, c;
1568 removed : s, ;
1572 removed : s, ;
1569 added p1: t, s;
1573 added p1: t, s;
1570 ##### revision "a-1" #####
1574 ##### revision "a-1" #####
1571 1 sidedata entries
1575 1 sidedata entries
1572 entry-0014 size 24
1576 entry-0014 size 24
1573 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00de'
1577 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00de'
1574 removed : d, ;
1578 removed : d, ;
1575 added p1: e, d;
1579 added p1: e, d;
1576 ##### revision "a-2" #####
1580 ##### revision "a-2" #####
1577 1 sidedata entries
1581 1 sidedata entries
1578 entry-0014 size 24
1582 entry-0014 size 24
1579 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00ef'
1583 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00ef'
1580 removed : e, ;
1584 removed : e, ;
1581 added p1: f, e;
1585 added p1: f, e;
1582 ##### revision "b-1" #####
1586 ##### revision "b-1" #####
1583 1 sidedata entries
1587 1 sidedata entries
1584 entry-0014 size 14
1588 entry-0014 size 14
1585 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00b'
1589 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00b'
1586 touched : b, ;
1590 touched : b, ;
1587 ##### revision "c-1 delete d" #####
1591 ##### revision "c-1 delete d" #####
1588 1 sidedata entries
1592 1 sidedata entries
1589 entry-0014 size 14
1593 entry-0014 size 14
1590 '\x00\x00\x00\x01\x0c\x00\x00\x00\x01\x00\x00\x00\x00d'
1594 '\x00\x00\x00\x01\x0c\x00\x00\x00\x01\x00\x00\x00\x00d'
1591 removed : d, ;
1595 removed : d, ;
1592 ##### revision "d-1 delete d" #####
1596 ##### revision "d-1 delete d" #####
1593 1 sidedata entries
1597 1 sidedata entries
1594 entry-0014 size 14
1598 entry-0014 size 14
1595 '\x00\x00\x00\x01\x0c\x00\x00\x00\x01\x00\x00\x00\x00d'
1599 '\x00\x00\x00\x01\x0c\x00\x00\x00\x01\x00\x00\x00\x00d'
1596 removed : d, ;
1600 removed : d, ;
1597 ##### revision "d-2 re-add d" #####
1601 ##### revision "d-2 re-add d" #####
1598 1 sidedata entries
1602 1 sidedata entries
1599 entry-0014 size 14
1603 entry-0014 size 14
1600 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1604 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1601 added : d, ;
1605 added : d, ;
1602 ##### revision "e-1 b -move-> g" #####
1606 ##### revision "e-1 b -move-> g" #####
1603 1 sidedata entries
1607 1 sidedata entries
1604 entry-0014 size 24
1608 entry-0014 size 24
1605 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bg'
1609 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bg'
1606 removed : b, ;
1610 removed : b, ;
1607 added p1: g, b;
1611 added p1: g, b;
1608 ##### revision "e-2 g -move-> f" #####
1612 ##### revision "e-2 g -move-> f" #####
1609 1 sidedata entries
1613 1 sidedata entries
1610 entry-0014 size 24
1614 entry-0014 size 24
1611 '\x00\x00\x00\x02\x06\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00fg'
1615 '\x00\x00\x00\x02\x06\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00fg'
1612 added p1: f, g;
1616 added p1: f, g;
1613 removed : g, ;
1617 removed : g, ;
1614 ##### revision "p-1" #####
1618 ##### revision "p-1" #####
1615 1 sidedata entries
1619 1 sidedata entries
1616 entry-0014 size 24
1620 entry-0014 size 24
1617 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00tu'
1621 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00tu'
1618 removed : t, ;
1622 removed : t, ;
1619 added p1: u, t;
1623 added p1: u, t;
1620 ##### revision "p-2" #####
1624 ##### revision "p-2" #####
1621 1 sidedata entries
1625 1 sidedata entries
1622 entry-0014 size 24
1626 entry-0014 size 24
1623 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00uv'
1627 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00uv'
1624 removed : u, ;
1628 removed : u, ;
1625 added p1: v, u;
1629 added p1: v, u;
1626 ##### revision "q-1 r -move-> w" #####
1630 ##### revision "q-1 r -move-> w" #####
1627 1 sidedata entries
1631 1 sidedata entries
1628 entry-0014 size 24
1632 entry-0014 size 24
1629 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00rw'
1633 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00rw'
1630 removed : r, ;
1634 removed : r, ;
1631 added p1: w, r;
1635 added p1: w, r;
1632 ##### revision "q-2 w -move-> v" #####
1636 ##### revision "q-2 w -move-> v" #####
1633 1 sidedata entries
1637 1 sidedata entries
1634 entry-0014 size 24
1638 entry-0014 size 24
1635 '\x00\x00\x00\x02\x06\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00vw'
1639 '\x00\x00\x00\x02\x06\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00vw'
1636 added p1: v, w;
1640 added p1: v, w;
1637 removed : w, ;
1641 removed : w, ;
1638 ##### revision "mBAm-0 simple merge - A side" #####
1642 ##### revision "mBAm-0 simple merge - A side" #####
1639 1 sidedata entries
1643 1 sidedata entries
1640 entry-0014 size 4
1644 entry-0014 size 4
1641 '\x00\x00\x00\x00'
1645 '\x00\x00\x00\x00'
1642 ##### revision "mABm-0 simple merge - A side" #####
1646 ##### revision "mABm-0 simple merge - A side" #####
1643 1 sidedata entries
1647 1 sidedata entries
1644 entry-0014 size 4
1648 entry-0014 size 4
1645 '\x00\x00\x00\x00'
1649 '\x00\x00\x00\x00'
1646 ##### revision "mBCm-0 simple merge - C side" #####
1650 ##### revision "mBCm-0 simple merge - C side" #####
1647 1 sidedata entries
1651 1 sidedata entries
1648 entry-0014 size 4
1652 entry-0014 size 4
1649 '\x00\x00\x00\x00'
1653 '\x00\x00\x00\x00'
1650 ##### revision "mBCm-1 re-add d" #####
1654 ##### revision "mBCm-1 re-add d" #####
1651 1 sidedata entries
1655 1 sidedata entries
1652 entry-0014 size 14
1656 entry-0014 size 14
1653 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1657 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1654 added : d, ;
1658 added : d, ;
1655 ##### revision "mCBm-0 simple merge - C side" #####
1659 ##### revision "mCBm-0 simple merge - C side" #####
1656 1 sidedata entries
1660 1 sidedata entries
1657 entry-0014 size 4
1661 entry-0014 size 4
1658 '\x00\x00\x00\x00'
1662 '\x00\x00\x00\x00'
1659 ##### revision "mCBm-1 re-add d" #####
1663 ##### revision "mCBm-1 re-add d" #####
1660 1 sidedata entries
1664 1 sidedata entries
1661 entry-0014 size 14
1665 entry-0014 size 14
1662 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1666 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1663 added : d, ;
1667 added : d, ;
1664 ##### revision "mBDm-0 simple merge - B side" #####
1668 ##### revision "mBDm-0 simple merge - B side" #####
1665 1 sidedata entries
1669 1 sidedata entries
1666 entry-0014 size 4
1670 entry-0014 size 4
1667 '\x00\x00\x00\x00'
1671 '\x00\x00\x00\x00'
1668 ##### revision "mDBm-0 simple merge - B side" #####
1672 ##### revision "mDBm-0 simple merge - B side" #####
1669 1 sidedata entries
1673 1 sidedata entries
1670 entry-0014 size 4
1674 entry-0014 size 4
1671 '\x00\x00\x00\x00'
1675 '\x00\x00\x00\x00'
1672 ##### revision "mAEm-0 merge with copies info on both side - A side" #####
1676 ##### revision "mAEm-0 merge with copies info on both side - A side" #####
1673 1 sidedata entries
1677 1 sidedata entries
1674 entry-0014 size 14
1678 entry-0014 size 14
1675 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1679 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1676 merged : f, ;
1680 merged : f, ;
1677 ##### revision "mEAm-0 merge with copies info on both side - A side" #####
1681 ##### revision "mEAm-0 merge with copies info on both side - A side" #####
1678 1 sidedata entries
1682 1 sidedata entries
1679 entry-0014 size 14
1683 entry-0014 size 14
1680 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1684 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1681 merged : f, ;
1685 merged : f, ;
1682 ##### revision "mPQm-0 merge with copies info on both side - P side" #####
1686 ##### revision "mPQm-0 merge with copies info on both side - P side" #####
1683 1 sidedata entries
1687 1 sidedata entries
1684 entry-0014 size 14
1688 entry-0014 size 14
1685 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00v'
1689 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00v'
1686 merged : v, ;
1690 merged : v, ;
1687 ##### revision "mQPm-0 merge with copies info on both side - P side" #####
1691 ##### revision "mQPm-0 merge with copies info on both side - P side" #####
1688 1 sidedata entries
1692 1 sidedata entries
1689 entry-0014 size 14
1693 entry-0014 size 14
1690 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00v'
1694 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00v'
1691 merged : v, ;
1695 merged : v, ;
1692 ##### revision "f-1" #####
1696 ##### revision "f-1" #####
1693 1 sidedata entries
1697 1 sidedata entries
1694 entry-0014 size 24
1698 entry-0014 size 24
1695 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00hi'
1699 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00hi'
1696 removed : h, ;
1700 removed : h, ;
1697 added p1: i, h;
1701 added p1: i, h;
1698 ##### revision "f-2" #####
1702 ##### revision "f-2" #####
1699 1 sidedata entries
1703 1 sidedata entries
1700 entry-0014 size 24
1704 entry-0014 size 24
1701 '\x00\x00\x00\x02\x16\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00di'
1705 '\x00\x00\x00\x02\x16\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00di'
1702 touched p1: d, i;
1706 touched p1: d, i;
1703 removed : i, ;
1707 removed : i, ;
1704 ##### revision "mBFm-0 simple merge - B side" #####
1708 ##### revision "mBFm-0 simple merge - B side" #####
1705 1 sidedata entries
1709 1 sidedata entries
1706 entry-0014 size 4
1710 entry-0014 size 4
1707 '\x00\x00\x00\x00'
1711 '\x00\x00\x00\x00'
1708 ##### revision "mFBm-0 simple merge - B side" #####
1712 ##### revision "mFBm-0 simple merge - B side" #####
1709 1 sidedata entries
1713 1 sidedata entries
1710 entry-0014 size 4
1714 entry-0014 size 4
1711 '\x00\x00\x00\x00'
1715 '\x00\x00\x00\x00'
1712 ##### revision "r-1" #####
1716 ##### revision "r-1" #####
1713 1 sidedata entries
1717 1 sidedata entries
1714 entry-0014 size 24
1718 entry-0014 size 24
1715 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00rx'
1719 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00rx'
1716 removed : r, ;
1720 removed : r, ;
1717 added p1: x, r;
1721 added p1: x, r;
1718 ##### revision "r-2" #####
1722 ##### revision "r-2" #####
1719 1 sidedata entries
1723 1 sidedata entries
1720 entry-0014 size 24
1724 entry-0014 size 24
1721 '\x00\x00\x00\x02\x16\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00tx'
1725 '\x00\x00\x00\x02\x16\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00tx'
1722 touched p1: t, x;
1726 touched p1: t, x;
1723 removed : x, ;
1727 removed : x, ;
1724 ##### revision "mBRm-0 simple merge - B side" #####
1728 ##### revision "mBRm-0 simple merge - B side" #####
1725 1 sidedata entries
1729 1 sidedata entries
1726 entry-0014 size 4
1730 entry-0014 size 4
1727 '\x00\x00\x00\x00'
1731 '\x00\x00\x00\x00'
1728 ##### revision "mRBm-0 simple merge - B side" #####
1732 ##### revision "mRBm-0 simple merge - B side" #####
1729 1 sidedata entries
1733 1 sidedata entries
1730 entry-0014 size 4
1734 entry-0014 size 4
1731 '\x00\x00\x00\x00'
1735 '\x00\x00\x00\x00'
1732 ##### revision "g-1" #####
1736 ##### revision "g-1" #####
1733 1 sidedata entries
1737 1 sidedata entries
1734 entry-0014 size 14
1738 entry-0014 size 14
1735 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d'
1739 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d'
1736 touched : d, ;
1740 touched : d, ;
1737 ##### revision "mDGm-0 actual content merge, copies on one side - D side" #####
1741 ##### revision "mDGm-0 actual content merge, copies on one side - D side" #####
1738 1 sidedata entries
1742 1 sidedata entries
1739 entry-0014 size 14
1743 entry-0014 size 14
1740 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1744 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1741 merged : d, ;
1745 merged : d, ;
1742 ##### revision "mGDm-0 actual content merge, copies on one side - D side" #####
1746 ##### revision "mGDm-0 actual content merge, copies on one side - D side" #####
1743 1 sidedata entries
1747 1 sidedata entries
1744 entry-0014 size 14
1748 entry-0014 size 14
1745 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1749 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1746 merged : d, ;
1750 merged : d, ;
1747 ##### revision "mFGm-0 merge - G side" #####
1751 ##### revision "mFGm-0 merge - G side" #####
1748 1 sidedata entries
1752 1 sidedata entries
1749 entry-0014 size 14
1753 entry-0014 size 14
1750 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1754 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1751 merged : d, ;
1755 merged : d, ;
1752 ##### revision "mGFm-0 merge - G side" #####
1756 ##### revision "mGFm-0 merge - G side" #####
1753 1 sidedata entries
1757 1 sidedata entries
1754 entry-0014 size 14
1758 entry-0014 size 14
1755 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1759 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1756 merged : d, ;
1760 merged : d, ;
1757 ##### revision "mCGm-0 merge updated/deleted - revive the file (updated content) - one way" #####
1761 ##### revision "mCGm-0 merge updated/deleted - revive the file (updated content) - one way" #####
1758 1 sidedata entries
1762 1 sidedata entries
1759 entry-0014 size 14
1763 entry-0014 size 14
1760 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1764 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1761 salvaged : d, ;
1765 salvaged : d, ;
1762 ##### revision "mGCm-0 merge updated/deleted - revive the file (updated content) - the other way" #####
1766 ##### revision "mGCm-0 merge updated/deleted - revive the file (updated content) - the other way" #####
1763 1 sidedata entries
1767 1 sidedata entries
1764 entry-0014 size 14
1768 entry-0014 size 14
1765 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1769 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1766 salvaged : d, ;
1770 salvaged : d, ;
1767 ##### revision "mCB-revert-m-0 merge explicitely revive deleted file - B side" #####
1771 ##### revision "mCB-revert-m-0 merge explicitely revive deleted file - B side" #####
1768 1 sidedata entries
1772 1 sidedata entries
1769 entry-0014 size 14
1773 entry-0014 size 14
1770 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1774 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1771 salvaged : d, ;
1775 salvaged : d, ;
1772 ##### revision "mBC-revert-m-0 merge explicitely revive deleted file - B side" #####
1776 ##### revision "mBC-revert-m-0 merge explicitely revive deleted file - B side" #####
1773 1 sidedata entries
1777 1 sidedata entries
1774 entry-0014 size 14
1778 entry-0014 size 14
1775 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1779 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1776 salvaged : d, ;
1780 salvaged : d, ;
1777 ##### revision "h-1" #####
1781 ##### revision "h-1" #####
1778 1 sidedata entries
1782 1 sidedata entries
1779 entry-0014 size 24
1783 entry-0014 size 24
1780 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bd'
1784 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bd'
1781 removed : b, ;
1785 removed : b, ;
1782 added p1: d, b;
1786 added p1: d, b;
1783 ##### revision "mCH-delete-before-conflict-m-0 simple merge - C side" #####
1787 ##### revision "mCH-delete-before-conflict-m-0 simple merge - C side" #####
1784 1 sidedata entries
1788 1 sidedata entries
1785 entry-0014 size 4
1789 entry-0014 size 4
1786 '\x00\x00\x00\x00'
1790 '\x00\x00\x00\x00'
1787 ##### revision "mHC-delete-before-conflict-m-0 simple merge - C side" #####
1791 ##### revision "mHC-delete-before-conflict-m-0 simple merge - C side" #####
1788 1 sidedata entries
1792 1 sidedata entries
1789 entry-0014 size 4
1793 entry-0014 size 4
1790 '\x00\x00\x00\x00'
1794 '\x00\x00\x00\x00'
1791 ##### revision "mAE-change-m-0 merge with file update and copies info on both side - A side" #####
1795 ##### revision "mAE-change-m-0 merge with file update and copies info on both side - A side" #####
1792 1 sidedata entries
1796 1 sidedata entries
1793 entry-0014 size 14
1797 entry-0014 size 14
1794 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1798 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1795 merged : f, ;
1799 merged : f, ;
1796 ##### revision "mEA-change-m-0 merge with file update and copies info on both side - A side" #####
1800 ##### revision "mEA-change-m-0 merge with file update and copies info on both side - A side" #####
1797 1 sidedata entries
1801 1 sidedata entries
1798 entry-0014 size 14
1802 entry-0014 size 14
1799 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1803 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1800 merged : f, ;
1804 merged : f, ;
1801 ##### revision "j-1" #####
1805 ##### revision "j-1" #####
1802 1 sidedata entries
1806 1 sidedata entries
1803 entry-0014 size 24
1807 entry-0014 size 24
1804 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-j'
1808 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-j'
1805 added : unrelated-j, ;
1809 added : unrelated-j, ;
1806 ##### revision "k-1" #####
1810 ##### revision "k-1" #####
1807 1 sidedata entries
1811 1 sidedata entries
1808 entry-0014 size 24
1812 entry-0014 size 24
1809 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-k'
1813 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-k'
1810 added : unrelated-k, ;
1814 added : unrelated-k, ;
1811 ##### revision "mAE,Km" #####
1815 ##### revision "mAE,Km" #####
1812 1 sidedata entries
1816 1 sidedata entries
1813 entry-0014 size 4
1817 entry-0014 size 4
1814 '\x00\x00\x00\x00'
1818 '\x00\x00\x00\x00'
1815 ##### revision "mK,AEm" #####
1819 ##### revision "mK,AEm" #####
1816 1 sidedata entries
1820 1 sidedata entries
1817 entry-0014 size 4
1821 entry-0014 size 4
1818 '\x00\x00\x00\x00'
1822 '\x00\x00\x00\x00'
1819 ##### revision "mEA,Jm" #####
1823 ##### revision "mEA,Jm" #####
1820 1 sidedata entries
1824 1 sidedata entries
1821 entry-0014 size 4
1825 entry-0014 size 4
1822 '\x00\x00\x00\x00'
1826 '\x00\x00\x00\x00'
1823 ##### revision "mJ,EAm" #####
1827 ##### revision "mJ,EAm" #####
1824 1 sidedata entries
1828 1 sidedata entries
1825 entry-0014 size 4
1829 entry-0014 size 4
1826 '\x00\x00\x00\x00'
1830 '\x00\x00\x00\x00'
1827 ##### revision "s-1" #####
1831 ##### revision "s-1" #####
1828 1 sidedata entries
1832 1 sidedata entries
1829 entry-0014 size 24
1833 entry-0014 size 24
1830 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-s'
1834 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-s'
1831 added : unrelated-s, ;
1835 added : unrelated-s, ;
1832 ##### revision "t-1" #####
1836 ##### revision "t-1" #####
1833 1 sidedata entries
1837 1 sidedata entries
1834 entry-0014 size 24
1838 entry-0014 size 24
1835 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-t'
1839 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-t'
1836 added : unrelated-t, ;
1840 added : unrelated-t, ;
1837 ##### revision "mPQ,Tm" #####
1841 ##### revision "mPQ,Tm" #####
1838 1 sidedata entries
1842 1 sidedata entries
1839 entry-0014 size 4
1843 entry-0014 size 4
1840 '\x00\x00\x00\x00'
1844 '\x00\x00\x00\x00'
1841 ##### revision "mT,PQm" #####
1845 ##### revision "mT,PQm" #####
1842 1 sidedata entries
1846 1 sidedata entries
1843 entry-0014 size 4
1847 entry-0014 size 4
1844 '\x00\x00\x00\x00'
1848 '\x00\x00\x00\x00'
1845 ##### revision "mQP,Sm" #####
1849 ##### revision "mQP,Sm" #####
1846 1 sidedata entries
1850 1 sidedata entries
1847 entry-0014 size 4
1851 entry-0014 size 4
1848 '\x00\x00\x00\x00'
1852 '\x00\x00\x00\x00'
1849 ##### revision "mS,QPm" #####
1853 ##### revision "mS,QPm" #####
1850 1 sidedata entries
1854 1 sidedata entries
1851 entry-0014 size 4
1855 entry-0014 size 4
1852 '\x00\x00\x00\x00'
1856 '\x00\x00\x00\x00'
1853 ##### revision "l-1" #####
1857 ##### revision "l-1" #####
1854 1 sidedata entries
1858 1 sidedata entries
1855 entry-0014 size 24
1859 entry-0014 size 24
1856 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-l'
1860 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-l'
1857 added : unrelated-l, ;
1861 added : unrelated-l, ;
1858 ##### revision "mBC+revert,Lm" #####
1862 ##### revision "mBC+revert,Lm" #####
1859 1 sidedata entries
1863 1 sidedata entries
1860 entry-0014 size 4
1864 entry-0014 size 4
1861 '\x00\x00\x00\x00'
1865 '\x00\x00\x00\x00'
1862 ##### revision "mCB+revert,Lm" #####
1866 ##### revision "mCB+revert,Lm" #####
1863 1 sidedata entries
1867 1 sidedata entries
1864 entry-0014 size 4
1868 entry-0014 size 4
1865 '\x00\x00\x00\x00'
1869 '\x00\x00\x00\x00'
1866 ##### revision "mL,BC+revertm" #####
1870 ##### revision "mL,BC+revertm" #####
1867 1 sidedata entries
1871 1 sidedata entries
1868 entry-0014 size 4
1872 entry-0014 size 4
1869 '\x00\x00\x00\x00'
1873 '\x00\x00\x00\x00'
1870 ##### revision "mL,CB+revertm" #####
1874 ##### revision "mL,CB+revertm" #####
1871 1 sidedata entries
1875 1 sidedata entries
1872 entry-0014 size 4
1876 entry-0014 size 4
1873 '\x00\x00\x00\x00'
1877 '\x00\x00\x00\x00'
1874 ##### revision "n-1" #####
1878 ##### revision "n-1" #####
1875 1 sidedata entries
1879 1 sidedata entries
1876 entry-0014 size 24
1880 entry-0014 size 24
1877 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-n'
1881 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-n'
1878 added : unrelated-n, ;
1882 added : unrelated-n, ;
1879 ##### revision "o-1" #####
1883 ##### revision "o-1" #####
1880 1 sidedata entries
1884 1 sidedata entries
1881 entry-0014 size 24
1885 entry-0014 size 24
1882 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-o'
1886 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-o'
1883 added : unrelated-o, ;
1887 added : unrelated-o, ;
1884 ##### revision "mFG,Om" #####
1888 ##### revision "mFG,Om" #####
1885 1 sidedata entries
1889 1 sidedata entries
1886 entry-0014 size 4
1890 entry-0014 size 4
1887 '\x00\x00\x00\x00'
1891 '\x00\x00\x00\x00'
1888 ##### revision "mO,FGm" #####
1892 ##### revision "mO,FGm" #####
1889 1 sidedata entries
1893 1 sidedata entries
1890 entry-0014 size 4
1894 entry-0014 size 4
1891 '\x00\x00\x00\x00'
1895 '\x00\x00\x00\x00'
1892 ##### revision "mGF,Nm" #####
1896 ##### revision "mGF,Nm" #####
1893 1 sidedata entries
1897 1 sidedata entries
1894 entry-0014 size 4
1898 entry-0014 size 4
1895 '\x00\x00\x00\x00'
1899 '\x00\x00\x00\x00'
1896 ##### revision "mN,GFm" #####
1900 ##### revision "mN,GFm" #####
1897 1 sidedata entries
1901 1 sidedata entries
1898 entry-0014 size 4
1902 entry-0014 size 4
1899 '\x00\x00\x00\x00'
1903 '\x00\x00\x00\x00'
1900 ##### revision "mAE-change,Km" #####
1904 ##### revision "mAE-change,Km" #####
1901 1 sidedata entries
1905 1 sidedata entries
1902 entry-0014 size 4
1906 entry-0014 size 4
1903 '\x00\x00\x00\x00'
1907 '\x00\x00\x00\x00'
1904 ##### revision "mK,AE-change-m" #####
1908 ##### revision "mK,AE-change-m" #####
1905 1 sidedata entries
1909 1 sidedata entries
1906 entry-0014 size 4
1910 entry-0014 size 4
1907 '\x00\x00\x00\x00'
1911 '\x00\x00\x00\x00'
1908 ##### revision "mEA-change,Jm" #####
1912 ##### revision "mEA-change,Jm" #####
1909 1 sidedata entries
1913 1 sidedata entries
1910 entry-0014 size 4
1914 entry-0014 size 4
1911 '\x00\x00\x00\x00'
1915 '\x00\x00\x00\x00'
1912 ##### revision "mJ,EA-change-m" #####
1916 ##### revision "mJ,EA-change-m" #####
1913 1 sidedata entries
1917 1 sidedata entries
1914 entry-0014 size 4
1918 entry-0014 size 4
1915 '\x00\x00\x00\x00'
1919 '\x00\x00\x00\x00'
1916
1920
1917 #endif
1921 #endif
1918
1922
1919
1923
1920 Test copy information chaining
1924 Test copy information chaining
1921 ==============================
1925 ==============================
1922
1926
1923 Check that matching only affect the destination and not intermediate path
1927 Check that matching only affect the destination and not intermediate path
1924 -------------------------------------------------------------------------
1928 -------------------------------------------------------------------------
1925
1929
1926 The two status call should give the same value for f
1930 The two status call should give the same value for f
1927
1931
1928 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("a-2")'
1932 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("a-2")'
1929 A f
1933 A f
1930 a
1934 a
1931 A t
1935 A t
1932 p
1936 p
1933 R a
1937 R a
1934 R p
1938 R p
1935 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("a-2")' f
1939 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("a-2")' f
1936 A f
1940 A f
1937 a (no-changeset no-compatibility !)
1941 a (no-changeset no-compatibility !)
1938
1942
1939 merging with unrelated change does not interfere with the renames
1943 merging with unrelated change does not interfere with the renames
1940 ---------------------------------------------------------------
1944 ---------------------------------------------------------------
1941
1945
1942 - rename on one side
1946 - rename on one side
1943 - unrelated change on the other side
1947 - unrelated change on the other side
1944
1948
1945 $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))'
1949 $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))'
1946 o mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
1950 o mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
1947 |\
1951 |\
1948 +---o mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
1952 +---o mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
1949 | |/
1953 | |/
1950 | o b-1: b update
1954 | o b-1: b update
1951 | |
1955 | |
1952 o | a-2: e -move-> f
1956 o | a-2: e -move-> f
1953 | |
1957 | |
1954 o | a-1: d -move-> e
1958 o | a-1: d -move-> e
1955 |/
1959 |/
1956 o i-2: c -move-> d, s -move-> t
1960 o i-2: c -move-> d, s -move-> t
1957 |
1961 |
1958 o i-1: a -move-> c, p -move-> s
1962 o i-1: a -move-> c, p -move-> s
1959 |
1963 |
1960 o i-0 initial commit: a b h p q r
1964 o i-0 initial commit: a b h p q r
1961
1965
1962
1966
1963 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mABm")'
1967 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mABm")'
1964 A f
1968 A f
1965 d
1969 d
1966 R d
1970 R d
1967 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBAm")'
1971 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBAm")'
1968 A f
1972 A f
1969 d
1973 d
1970 R d
1974 R d
1971 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mABm")'
1975 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mABm")'
1972 M b
1976 M b
1973 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mBAm")'
1977 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mBAm")'
1974 M b
1978 M b
1975 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mABm")'
1979 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mABm")'
1976 M b
1980 M b
1977 A f
1981 A f
1978 d
1982 d
1979 R d
1983 R d
1980 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBAm")'
1984 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBAm")'
1981 M b
1985 M b
1982 A f
1986 A f
1983 d
1987 d
1984 R d
1988 R d
1985 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mABm")'
1989 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mABm")'
1986 M b
1990 M b
1987 A f
1991 A f
1988 a
1992 a
1989 A t
1993 A t
1990 p
1994 p
1991 R a
1995 R a
1992 R p
1996 R p
1993 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBAm")'
1997 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBAm")'
1994 M b
1998 M b
1995 A f
1999 A f
1996 a
2000 a
1997 A t
2001 A t
1998 p
2002 p
1999 R a
2003 R a
2000 R p
2004 R p
2001
2005
2002 merging with the side having a delete
2006 merging with the side having a delete
2003 -------------------------------------
2007 -------------------------------------
2004
2008
2005 case summary:
2009 case summary:
2006 - one with change to an unrelated file
2010 - one with change to an unrelated file
2007 - one deleting the change
2011 - one deleting the change
2008 and recreate an unrelated file after the merge
2012 and recreate an unrelated file after the merge
2009
2013
2010 $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))'
2014 $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))'
2011 o mCBm-1 re-add d
2015 o mCBm-1 re-add d
2012 |
2016 |
2013 o mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
2017 o mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
2014 |\
2018 |\
2015 | | o mBCm-1 re-add d
2019 | | o mBCm-1 re-add d
2016 | | |
2020 | | |
2017 +---o mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
2021 +---o mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
2018 | |/
2022 | |/
2019 | o c-1 delete d
2023 | o c-1 delete d
2020 | |
2024 | |
2021 o | b-1: b update
2025 o | b-1: b update
2022 |/
2026 |/
2023 o i-2: c -move-> d, s -move-> t
2027 o i-2: c -move-> d, s -move-> t
2024 |
2028 |
2025 o i-1: a -move-> c, p -move-> s
2029 o i-1: a -move-> c, p -move-> s
2026 |
2030 |
2027 o i-0 initial commit: a b h p q r
2031 o i-0 initial commit: a b h p q r
2028
2032
2029 - comparing from the merge
2033 - comparing from the merge
2030
2034
2031 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-0")'
2035 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-0")'
2032 R d
2036 R d
2033 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-0")'
2037 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-0")'
2034 R d
2038 R d
2035 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-0")'
2039 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-0")'
2036 M b
2040 M b
2037 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-0")'
2041 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-0")'
2038 M b
2042 M b
2039 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-0")'
2043 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-0")'
2040 M b
2044 M b
2041 R d
2045 R d
2042 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-0")'
2046 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-0")'
2043 M b
2047 M b
2044 R d
2048 R d
2045 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-0")'
2049 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-0")'
2046 M b
2050 M b
2047 A t
2051 A t
2048 p
2052 p
2049 R a
2053 R a
2050 R p
2054 R p
2051 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-0")'
2055 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-0")'
2052 M b
2056 M b
2053 A t
2057 A t
2054 p
2058 p
2055 R a
2059 R a
2056 R p
2060 R p
2057
2061
2058 - comparing with the merge children re-adding the file
2062 - comparing with the merge children re-adding the file
2059
2063
2060 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-1")'
2064 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-1")'
2061 M d
2065 M d
2062 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-1")'
2066 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-1")'
2063 M d
2067 M d
2064 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-1")'
2068 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-1")'
2065 M b
2069 M b
2066 A d
2070 A d
2067 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-1")'
2071 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-1")'
2068 M b
2072 M b
2069 A d
2073 A d
2070 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-1")'
2074 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-1")'
2071 M b
2075 M b
2072 M d
2076 M d
2073 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-1")'
2077 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-1")'
2074 M b
2078 M b
2075 M d
2079 M d
2076 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-1")'
2080 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-1")'
2077 M b
2081 M b
2078 A d
2082 A d
2079 A t
2083 A t
2080 p
2084 p
2081 R a
2085 R a
2082 R p
2086 R p
2083 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-1")'
2087 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-1")'
2084 M b
2088 M b
2085 A d
2089 A d
2086 A t
2090 A t
2087 p
2091 p
2088 R a
2092 R a
2089 R p
2093 R p
2090
2094
2091 Comparing with a merge re-adding the file afterward
2095 Comparing with a merge re-adding the file afterward
2092 ---------------------------------------------------
2096 ---------------------------------------------------
2093
2097
2094 Merge:
2098 Merge:
2095 - one with change to an unrelated file
2099 - one with change to an unrelated file
2096 - one deleting and recreating the change
2100 - one deleting and recreating the change
2097
2101
2098 $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))'
2102 $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))'
2099 o mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
2103 o mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
2100 |\
2104 |\
2101 +---o mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
2105 +---o mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
2102 | |/
2106 | |/
2103 | o d-2 re-add d
2107 | o d-2 re-add d
2104 | |
2108 | |
2105 | o d-1 delete d
2109 | o d-1 delete d
2106 | |
2110 | |
2107 o | b-1: b update
2111 o | b-1: b update
2108 |/
2112 |/
2109 o i-2: c -move-> d, s -move-> t
2113 o i-2: c -move-> d, s -move-> t
2110 |
2114 |
2111 o i-1: a -move-> c, p -move-> s
2115 o i-1: a -move-> c, p -move-> s
2112 |
2116 |
2113 o i-0 initial commit: a b h p q r
2117 o i-0 initial commit: a b h p q r
2114
2118
2115 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBDm-0")'
2119 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBDm-0")'
2116 M d
2120 M d
2117 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mDBm-0")'
2121 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mDBm-0")'
2118 M d
2122 M d
2119 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mBDm-0")'
2123 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mBDm-0")'
2120 M b
2124 M b
2121 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDBm-0")'
2125 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDBm-0")'
2122 M b
2126 M b
2123 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBDm-0")'
2127 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBDm-0")'
2124 M b
2128 M b
2125 M d
2129 M d
2126 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mDBm-0")'
2130 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mDBm-0")'
2127 M b
2131 M b
2128 M d
2132 M d
2129
2133
2130 The bugs makes recorded copy is different depending of where we started the merge from since
2134 The bugs makes recorded copy is different depending of where we started the merge from since
2131
2135
2132 $ hg manifest --debug --rev 'desc("mBDm-0")' | grep '644 d'
2136 $ hg manifest --debug --rev 'desc("mBDm-0")' | grep '644 d'
2133 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2137 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2134 $ hg manifest --debug --rev 'desc("mDBm-0")' | grep '644 d'
2138 $ hg manifest --debug --rev 'desc("mDBm-0")' | grep '644 d'
2135 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2139 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2136
2140
2137 $ hg manifest --debug --rev 'desc("d-2")' | grep '644 d'
2141 $ hg manifest --debug --rev 'desc("d-2")' | grep '644 d'
2138 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2142 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2139 $ hg manifest --debug --rev 'desc("b-1")' | grep '644 d'
2143 $ hg manifest --debug --rev 'desc("b-1")' | grep '644 d'
2140 d8252ab2e760b0d4e5288fd44cbd15a0fa567e16 644 d (no-changeset !)
2144 d8252ab2e760b0d4e5288fd44cbd15a0fa567e16 644 d (no-changeset !)
2141 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !)
2145 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !)
2142 $ hg debugindex d | head -n 4 | ../no-linkrev
2146 $ hg debugindex d | head -n 4 | ../no-linkrev
2143 rev linkrev nodeid p1 p2
2147 rev linkrev nodeid p1 p2
2144 0 * d8252ab2e760 000000000000 000000000000 (no-changeset !)
2148 0 * d8252ab2e760 000000000000 000000000000 (no-changeset !)
2145 0 * ae258f702dfe 000000000000 000000000000 (changeset !)
2149 0 * ae258f702dfe 000000000000 000000000000 (changeset !)
2146 1 * b004912a8510 000000000000 000000000000
2150 1 * b004912a8510 000000000000 000000000000
2147 2 * 7b79e2fe0c89 000000000000 000000000000 (no-changeset !)
2151 2 * 7b79e2fe0c89 000000000000 000000000000 (no-changeset !)
2148 2 * 5cce88bf349f ae258f702dfe 000000000000 (changeset !)
2152 2 * 5cce88bf349f ae258f702dfe 000000000000 (changeset !)
2149
2153
2150 Log output should not include a merge commit as it did not happen
2154 Log output should not include a merge commit as it did not happen
2151
2155
2152 $ hg log -Gfr 'desc("mBDm-0")' d
2156 $ hg log -Gfr 'desc("mBDm-0")' d
2153 o d-2 re-add d
2157 o d-2 re-add d
2154 |
2158 |
2155 ~
2159 ~
2156
2160
2157 $ hg log -Gfr 'desc("mDBm-0")' d
2161 $ hg log -Gfr 'desc("mDBm-0")' d
2158 o d-2 re-add d
2162 o d-2 re-add d
2159 |
2163 |
2160 ~
2164 ~
2161
2165
2162 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBDm-0")'
2166 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBDm-0")'
2163 M b
2167 M b
2164 A d
2168 A d
2165 A t
2169 A t
2166 p
2170 p
2167 R a
2171 R a
2168 R p
2172 R p
2169 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDBm-0")'
2173 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDBm-0")'
2170 M b
2174 M b
2171 A d
2175 A d
2172 A t
2176 A t
2173 p
2177 p
2174 R a
2178 R a
2175 R p
2179 R p
2176
2180
2177
2181
2178 Comparing with a merge with colliding rename
2182 Comparing with a merge with colliding rename
2179 --------------------------------------------
2183 --------------------------------------------
2180
2184
2181 Subcase: new copy information on both side
2185 Subcase: new copy information on both side
2182 ``````````````````````````````````````````
2186 ``````````````````````````````````````````
2183
2187
2184 - the "e-" branch renaming b to f (through 'g')
2188 - the "e-" branch renaming b to f (through 'g')
2185 - the "a-" branch renaming d to f (through e)
2189 - the "a-" branch renaming d to f (through e)
2186
2190
2187 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
2191 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
2188 o mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
2192 o mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
2189 |\
2193 |\
2190 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
2194 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
2191 | |/
2195 | |/
2192 | o e-2 g -move-> f
2196 | o e-2 g -move-> f
2193 | |
2197 | |
2194 | o e-1 b -move-> g
2198 | o e-1 b -move-> g
2195 | |
2199 | |
2196 o | a-2: e -move-> f
2200 o | a-2: e -move-> f
2197 | |
2201 | |
2198 o | a-1: d -move-> e
2202 o | a-1: d -move-> e
2199 |/
2203 |/
2200 o i-2: c -move-> d, s -move-> t
2204 o i-2: c -move-> d, s -move-> t
2201 |
2205 |
2202 o i-1: a -move-> c, p -move-> s
2206 o i-1: a -move-> c, p -move-> s
2203 |
2207 |
2204 o i-0 initial commit: a b h p q r
2208 o i-0 initial commit: a b h p q r
2205
2209
2206 #if no-changeset
2210 #if no-changeset
2207 $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f'
2211 $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f'
2208 2ff93c643948464ee1f871867910ae43a45b0bea 644 f
2212 2ff93c643948464ee1f871867910ae43a45b0bea 644 f
2209 $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f'
2213 $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f'
2210 2ff93c643948464ee1f871867910ae43a45b0bea 644 f
2214 2ff93c643948464ee1f871867910ae43a45b0bea 644 f
2211 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
2215 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
2212 b76eb76580df486c3d51d63c5c210d4dd43a8ac7 644 f
2216 b76eb76580df486c3d51d63c5c210d4dd43a8ac7 644 f
2213 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
2217 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
2214 e8825b386367b29fec957283a80bb47b47483fe1 644 f
2218 e8825b386367b29fec957283a80bb47b47483fe1 644 f
2215 $ hg debugindex f | ../no-linkrev
2219 $ hg debugindex f | ../no-linkrev
2216 rev linkrev nodeid p1 p2
2220 rev linkrev nodeid p1 p2
2217 0 * b76eb76580df 000000000000 000000000000
2221 0 * b76eb76580df 000000000000 000000000000
2218 1 * e8825b386367 000000000000 000000000000
2222 1 * e8825b386367 000000000000 000000000000
2219 2 * 2ff93c643948 b76eb76580df e8825b386367
2223 2 * 2ff93c643948 b76eb76580df e8825b386367
2220 3 * 2f649fba7eb2 b76eb76580df e8825b386367
2224 3 * 2f649fba7eb2 b76eb76580df e8825b386367
2221 4 * 774e7c1637d5 e8825b386367 b76eb76580df
2225 4 * 774e7c1637d5 e8825b386367 b76eb76580df
2222 #else
2226 #else
2223 $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f'
2227 $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f'
2224 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2228 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2225 $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f'
2229 $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f'
2226 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2230 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2227 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
2231 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
2228 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2232 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2229 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
2233 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
2230 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2234 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2231 $ hg debugindex f | ../no-linkrev
2235 $ hg debugindex f | ../no-linkrev
2232 rev linkrev nodeid p1 p2
2236 rev linkrev nodeid p1 p2
2233 0 * ae258f702dfe 000000000000 000000000000
2237 0 * ae258f702dfe 000000000000 000000000000
2234 1 * d3613c1ec831 ae258f702dfe 000000000000
2238 1 * d3613c1ec831 ae258f702dfe 000000000000
2235 2 * 05e03c868bbc ae258f702dfe 000000000000
2239 2 * 05e03c868bbc ae258f702dfe 000000000000
2236 #endif
2240 #endif
2237
2241
2238 # Here the filelog based implementation is not looking at the rename
2242 # Here the filelog based implementation is not looking at the rename
2239 # information (because the file exist on both side). However the changelog
2243 # information (because the file exist on both side). However the changelog
2240 # based on works fine. We have different output.
2244 # based on works fine. We have different output.
2241
2245
2242 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAEm-0")'
2246 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAEm-0")'
2243 M f (no-changeset !)
2247 M f (no-changeset !)
2244 b (no-filelog no-changeset !)
2248 b (no-filelog no-changeset !)
2245 R b
2249 R b
2246 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEAm-0")'
2250 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEAm-0")'
2247 M f (no-changeset !)
2251 M f (no-changeset !)
2248 b (no-filelog no-changeset !)
2252 b (no-filelog no-changeset !)
2249 R b
2253 R b
2250 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAEm-0")'
2254 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAEm-0")'
2251 M f (no-changeset !)
2255 M f (no-changeset !)
2252 d (no-filelog no-changeset !)
2256 d (no-filelog no-changeset !)
2253 R d
2257 R d
2254 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEAm-0")'
2258 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEAm-0")'
2255 M f (no-changeset !)
2259 M f (no-changeset !)
2256 d (no-filelog no-changeset !)
2260 d (no-filelog no-changeset !)
2257 R d
2261 R d
2258 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
2262 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
2259 A f
2263 A f
2260 d
2264 d
2261 R d
2265 R d
2262 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")'
2266 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")'
2263 A f
2267 A f
2264 b
2268 b
2265 R b
2269 R b
2266
2270
2267 # From here, we run status against revision where both source file exists.
2271 # From here, we run status against revision where both source file exists.
2268 #
2272 #
2269 # The filelog based implementation picks an arbitrary side based on revision
2273 # The filelog based implementation picks an arbitrary side based on revision
2270 # numbers. So the same side "wins" whatever the parents order is. This is
2274 # numbers. So the same side "wins" whatever the parents order is. This is
2271 # sub-optimal because depending on revision numbers means the result can be
2275 # sub-optimal because depending on revision numbers means the result can be
2272 # different from one repository to the next.
2276 # different from one repository to the next.
2273 #
2277 #
2274 # The changeset based algorithm use the parent order to break tie on conflicting
2278 # The changeset based algorithm use the parent order to break tie on conflicting
2275 # information and will have a different order depending on who is p1 and p2.
2279 # information and will have a different order depending on who is p1 and p2.
2276 # That order is stable accross repositories. (data from p1 prevails)
2280 # That order is stable accross repositories. (data from p1 prevails)
2277
2281
2278 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAEm-0")'
2282 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAEm-0")'
2279 A f
2283 A f
2280 d
2284 d
2281 R b
2285 R b
2282 R d
2286 R d
2283 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEAm-0")'
2287 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEAm-0")'
2284 A f
2288 A f
2285 d (filelog !)
2289 d (filelog !)
2286 b (no-filelog !)
2290 b (no-filelog !)
2287 R b
2291 R b
2288 R d
2292 R d
2289 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm-0")'
2293 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm-0")'
2290 A f
2294 A f
2291 a
2295 a
2292 A t
2296 A t
2293 p
2297 p
2294 R a
2298 R a
2295 R b
2299 R b
2296 R p
2300 R p
2297 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm-0")'
2301 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm-0")'
2298 A f
2302 A f
2299 a (filelog !)
2303 a (filelog !)
2300 b (no-filelog !)
2304 b (no-filelog !)
2301 A t
2305 A t
2302 p
2306 p
2303 R a
2307 R a
2304 R b
2308 R b
2305 R p
2309 R p
2306
2310
2307
2311
2308 Subcase: existing copy information overwritten on one branch
2312 Subcase: existing copy information overwritten on one branch
2309 ````````````````````````````````````````````````````````````
2313 ````````````````````````````````````````````````````````````
2310
2314
2311 Note:
2315 Note:
2312 | In this case, one of the merge wrongly record a merge while there is none.
2316 | In this case, one of the merge wrongly record a merge while there is none.
2313 | This lead to bad copy tracing information to be dug up.
2317 | This lead to bad copy tracing information to be dug up.
2314
2318
2315
2319
2316 Merge:
2320 Merge:
2317 - one with change to an unrelated file (b)
2321 - one with change to an unrelated file (b)
2318 - one overwriting a file (d) with a rename (from h to i to d)
2322 - one overwriting a file (d) with a rename (from h to i to d)
2319
2323
2320 $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))'
2324 $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))'
2321 o mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
2325 o mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
2322 |\
2326 |\
2323 +---o mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
2327 +---o mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
2324 | |/
2328 | |/
2325 | o f-2: rename i -> d
2329 | o f-2: rename i -> d
2326 | |
2330 | |
2327 | o f-1: rename h -> i
2331 | o f-1: rename h -> i
2328 | |
2332 | |
2329 o | b-1: b update
2333 o | b-1: b update
2330 |/
2334 |/
2331 o i-2: c -move-> d, s -move-> t
2335 o i-2: c -move-> d, s -move-> t
2332 |
2336 |
2333 o i-1: a -move-> c, p -move-> s
2337 o i-1: a -move-> c, p -move-> s
2334 |
2338 |
2335 o i-0 initial commit: a b h p q r
2339 o i-0 initial commit: a b h p q r
2336
2340
2337 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBFm-0")'
2341 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBFm-0")'
2338 M b
2342 M b
2339 A d
2343 A d
2340 h
2344 h
2341 A t
2345 A t
2342 p
2346 p
2343 R a
2347 R a
2344 R h
2348 R h
2345 R p
2349 R p
2346 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFBm-0")'
2350 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFBm-0")'
2347 M b
2351 M b
2348 A d
2352 A d
2349 h
2353 h
2350 A t
2354 A t
2351 p
2355 p
2352 R a
2356 R a
2353 R h
2357 R h
2354 R p
2358 R p
2355 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBFm-0")'
2359 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBFm-0")'
2356 M d (no-changeset !)
2360 M d (no-changeset !)
2357 h (no-filelog no-changeset !)
2361 h (no-filelog no-changeset !)
2358 R h
2362 R h
2359 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBFm-0")'
2363 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBFm-0")'
2360 M b
2364 M b
2361 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBFm-0")'
2365 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBFm-0")'
2362 M b
2366 M b
2363 M d (no-changeset !)
2367 M d (no-changeset !)
2364 i (no-filelog no-changeset !)
2368 i (no-filelog no-changeset !)
2365 R i
2369 R i
2366 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mFBm-0")'
2370 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mFBm-0")'
2367 M d (no-changeset !)
2371 M d (no-changeset !)
2368 h (no-filelog no-changeset !)
2372 h (no-filelog no-changeset !)
2369 R h
2373 R h
2370 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFBm-0")'
2374 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFBm-0")'
2371 M b
2375 M b
2372 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFBm-0")'
2376 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFBm-0")'
2373 M b
2377 M b
2374 M d (no-changeset !)
2378 M d (no-changeset !)
2375 i (no-filelog no-changeset !)
2379 i (no-filelog no-changeset !)
2376 R i
2380 R i
2377
2381
2378 #if no-changeset
2382 #if no-changeset
2379 $ hg log -Gfr 'desc("mBFm-0")' d
2383 $ hg log -Gfr 'desc("mBFm-0")' d
2380 o f-2: rename i -> d
2384 o f-2: rename i -> d
2381 |
2385 |
2382 o f-1: rename h -> i
2386 o f-1: rename h -> i
2383 :
2387 :
2384 o i-0 initial commit: a b h p q r
2388 o i-0 initial commit: a b h p q r
2385
2389
2386 #else
2390 #else
2387 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2391 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2388 $ hg log -Gfr 'desc("mBFm-0")' d
2392 $ hg log -Gfr 'desc("mBFm-0")' d
2389 o i-2: c -move-> d, s -move-> t
2393 o i-2: c -move-> d, s -move-> t
2390 |
2394 |
2391 ~
2395 ~
2392 #endif
2396 #endif
2393
2397
2394 #if no-changeset
2398 #if no-changeset
2395 $ hg log -Gfr 'desc("mFBm-0")' d
2399 $ hg log -Gfr 'desc("mFBm-0")' d
2396 o f-2: rename i -> d
2400 o f-2: rename i -> d
2397 |
2401 |
2398 o f-1: rename h -> i
2402 o f-1: rename h -> i
2399 :
2403 :
2400 o i-0 initial commit: a b h p q r
2404 o i-0 initial commit: a b h p q r
2401
2405
2402 #else
2406 #else
2403 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2407 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2404 $ hg log -Gfr 'desc("mFBm-0")' d
2408 $ hg log -Gfr 'desc("mFBm-0")' d
2405 o i-2: c -move-> d, s -move-> t
2409 o i-2: c -move-> d, s -move-> t
2406 |
2410 |
2407 ~
2411 ~
2408 #endif
2412 #endif
2409
2413
2410
2414
2411 Subcase: existing copy information overwritten on one branch, with different content)
2415 Subcase: existing copy information overwritten on one branch, with different content)
2412 `````````````````````````````````````````````````````````````````````````````````````
2416 `````````````````````````````````````````````````````````````````````````````````````
2413
2417
2414 Merge:
2418 Merge:
2415 - one with change to an unrelated file (b)
2419 - one with change to an unrelated file (b)
2416 - one overwriting a file (t) with a rename (from r to x to t), v content is not the same as on the other branch
2420 - one overwriting a file (t) with a rename (from r to x to t), v content is not the same as on the other branch
2417
2421
2418 $ hg log -G --rev '::(desc("mBRm")+desc("mRBm"))'
2422 $ hg log -G --rev '::(desc("mBRm")+desc("mRBm"))'
2419 o mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
2423 o mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
2420 |\
2424 |\
2421 +---o mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
2425 +---o mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
2422 | |/
2426 | |/
2423 | o r-2: rename t -> x
2427 | o r-2: rename t -> x
2424 | |
2428 | |
2425 | o r-1: rename r -> x
2429 | o r-1: rename r -> x
2426 | |
2430 | |
2427 o | b-1: b update
2431 o | b-1: b update
2428 |/
2432 |/
2429 o i-2: c -move-> d, s -move-> t
2433 o i-2: c -move-> d, s -move-> t
2430 |
2434 |
2431 o i-1: a -move-> c, p -move-> s
2435 o i-1: a -move-> c, p -move-> s
2432 |
2436 |
2433 o i-0 initial commit: a b h p q r
2437 o i-0 initial commit: a b h p q r
2434
2438
2435 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBRm-0")'
2439 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBRm-0")'
2436 M b
2440 M b
2437 A d
2441 A d
2438 a
2442 a
2439 A t
2443 A t
2440 r
2444 r
2441 R a
2445 R a
2442 R p
2446 R p
2443 R r
2447 R r
2444 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mRBm-0")'
2448 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mRBm-0")'
2445 M b
2449 M b
2446 A d
2450 A d
2447 a
2451 a
2448 A t
2452 A t
2449 r
2453 r
2450 R a
2454 R a
2451 R p
2455 R p
2452 R r
2456 R r
2453 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBRm-0")'
2457 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBRm-0")'
2454 M t
2458 M t
2455 r (no-filelog !)
2459 r (no-filelog !)
2456 R r
2460 R r
2457 $ hg status --copies --rev 'desc("r-2")' --rev 'desc("mBRm-0")'
2461 $ hg status --copies --rev 'desc("r-2")' --rev 'desc("mBRm-0")'
2458 M b
2462 M b
2459 $ hg status --copies --rev 'desc("r-1")' --rev 'desc("mBRm-0")'
2463 $ hg status --copies --rev 'desc("r-1")' --rev 'desc("mBRm-0")'
2460 M b
2464 M b
2461 M t
2465 M t
2462 x (no-filelog !)
2466 x (no-filelog !)
2463 R x
2467 R x
2464 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mRBm-0")'
2468 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mRBm-0")'
2465 M t
2469 M t
2466 r (no-filelog !)
2470 r (no-filelog !)
2467 R r
2471 R r
2468 $ hg status --copies --rev 'desc("r-2")' --rev 'desc("mRBm-0")'
2472 $ hg status --copies --rev 'desc("r-2")' --rev 'desc("mRBm-0")'
2469 M b
2473 M b
2470 $ hg status --copies --rev 'desc("r-1")' --rev 'desc("mRBm-0")'
2474 $ hg status --copies --rev 'desc("r-1")' --rev 'desc("mRBm-0")'
2471 M b
2475 M b
2472 M t
2476 M t
2473 x (no-filelog !)
2477 x (no-filelog !)
2474 R x
2478 R x
2475
2479
2476 #if no-changeset
2480 #if no-changeset
2477 $ hg log -Gfr 'desc("mBRm-0")' d
2481 $ hg log -Gfr 'desc("mBRm-0")' d
2478 o i-2: c -move-> d, s -move-> t
2482 o i-2: c -move-> d, s -move-> t
2479 |
2483 |
2480 o i-1: a -move-> c, p -move-> s
2484 o i-1: a -move-> c, p -move-> s
2481 |
2485 |
2482 o i-0 initial commit: a b h p q r
2486 o i-0 initial commit: a b h p q r
2483
2487
2484 #else
2488 #else
2485 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2489 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2486 $ hg log -Gfr 'desc("mBRm-0")' d
2490 $ hg log -Gfr 'desc("mBRm-0")' d
2487 o i-2: c -move-> d, s -move-> t
2491 o i-2: c -move-> d, s -move-> t
2488 |
2492 |
2489 ~
2493 ~
2490 #endif
2494 #endif
2491
2495
2492 #if no-changeset
2496 #if no-changeset
2493 $ hg log -Gfr 'desc("mRBm-0")' d
2497 $ hg log -Gfr 'desc("mRBm-0")' d
2494 o i-2: c -move-> d, s -move-> t
2498 o i-2: c -move-> d, s -move-> t
2495 |
2499 |
2496 o i-1: a -move-> c, p -move-> s
2500 o i-1: a -move-> c, p -move-> s
2497 |
2501 |
2498 o i-0 initial commit: a b h p q r
2502 o i-0 initial commit: a b h p q r
2499
2503
2500 #else
2504 #else
2501 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2505 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2502 $ hg log -Gfr 'desc("mRBm-0")' d
2506 $ hg log -Gfr 'desc("mRBm-0")' d
2503 o i-2: c -move-> d, s -move-> t
2507 o i-2: c -move-> d, s -move-> t
2504 |
2508 |
2505 ~
2509 ~
2506 #endif
2510 #endif
2507
2511
2508 Subcase: reset of the copy history on one side
2512 Subcase: reset of the copy history on one side
2509 ``````````````````````````````````````````````
2513 ``````````````````````````````````````````````
2510
2514
2511 Merge:
2515 Merge:
2512 - one with change to a file
2516 - one with change to a file
2513 - one deleting and recreating the file
2517 - one deleting and recreating the file
2514
2518
2515 Unlike in the 'BD/DB' cases, an actual merge happened here. So we should
2519 Unlike in the 'BD/DB' cases, an actual merge happened here. So we should
2516 consider history and rename on both branch of the merge.
2520 consider history and rename on both branch of the merge.
2517
2521
2518 $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))'
2522 $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))'
2519 o mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
2523 o mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
2520 |\
2524 |\
2521 +---o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2525 +---o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2522 | |/
2526 | |/
2523 | o g-1: update d
2527 | o g-1: update d
2524 | |
2528 | |
2525 o | d-2 re-add d
2529 o | d-2 re-add d
2526 | |
2530 | |
2527 o | d-1 delete d
2531 o | d-1 delete d
2528 |/
2532 |/
2529 o i-2: c -move-> d, s -move-> t
2533 o i-2: c -move-> d, s -move-> t
2530 |
2534 |
2531 o i-1: a -move-> c, p -move-> s
2535 o i-1: a -move-> c, p -move-> s
2532 |
2536 |
2533 o i-0 initial commit: a b h p q r
2537 o i-0 initial commit: a b h p q r
2534
2538
2535 One side of the merge have a long history with rename. The other side of the
2539 One side of the merge have a long history with rename. The other side of the
2536 merge point to a new file with a smaller history. Each side is "valid".
2540 merge point to a new file with a smaller history. Each side is "valid".
2537
2541
2538 (and again the filelog based algorithm only explore one, with a pick based on
2542 (and again the filelog based algorithm only explore one, with a pick based on
2539 revision numbers)
2543 revision numbers)
2540
2544
2541 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDGm-0")'
2545 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDGm-0")'
2542 A d
2546 A d
2543 a (filelog !)
2547 a (filelog !)
2544 A t
2548 A t
2545 p
2549 p
2546 R a
2550 R a
2547 R p
2551 R p
2548 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGDm-0")'
2552 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGDm-0")'
2549 A d
2553 A d
2550 a
2554 a
2551 A t
2555 A t
2552 p
2556 p
2553 R a
2557 R a
2554 R p
2558 R p
2555 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDGm-0")'
2559 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDGm-0")'
2556 M d
2560 M d
2557 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mGDm-0")'
2561 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mGDm-0")'
2558 M d
2562 M d
2559 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mDGm-0")'
2563 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mDGm-0")'
2560 M d
2564 M d
2561 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGDm-0")'
2565 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGDm-0")'
2562 M d
2566 M d
2563
2567
2564 #if no-changeset
2568 #if no-changeset
2565 $ hg log -Gfr 'desc("mDGm-0")' d
2569 $ hg log -Gfr 'desc("mDGm-0")' d
2566 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2570 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2567 |\
2571 |\
2568 | o g-1: update d
2572 | o g-1: update d
2569 | |
2573 | |
2570 o | d-2 re-add d
2574 o | d-2 re-add d
2571 |/
2575 |/
2572 o i-2: c -move-> d, s -move-> t
2576 o i-2: c -move-> d, s -move-> t
2573 |
2577 |
2574 o i-1: a -move-> c, p -move-> s
2578 o i-1: a -move-> c, p -move-> s
2575 |
2579 |
2576 o i-0 initial commit: a b h p q r
2580 o i-0 initial commit: a b h p q r
2577
2581
2578 #else
2582 #else
2579 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2583 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2580 $ hg log -Gfr 'desc("mDGm-0")' d
2584 $ hg log -Gfr 'desc("mDGm-0")' d
2581 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2585 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2582 |\
2586 |\
2583 | o g-1: update d
2587 | o g-1: update d
2584 | |
2588 | |
2585 o | d-2 re-add d
2589 o | d-2 re-add d
2586 |/
2590 |/
2587 o i-2: c -move-> d, s -move-> t
2591 o i-2: c -move-> d, s -move-> t
2588 |
2592 |
2589 ~
2593 ~
2590 #endif
2594 #endif
2591
2595
2592
2596
2593 #if no-changeset
2597 #if no-changeset
2594 $ hg log -Gfr 'desc("mDGm-0")' d
2598 $ hg log -Gfr 'desc("mDGm-0")' d
2595 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2599 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2596 |\
2600 |\
2597 | o g-1: update d
2601 | o g-1: update d
2598 | |
2602 | |
2599 o | d-2 re-add d
2603 o | d-2 re-add d
2600 |/
2604 |/
2601 o i-2: c -move-> d, s -move-> t
2605 o i-2: c -move-> d, s -move-> t
2602 |
2606 |
2603 o i-1: a -move-> c, p -move-> s
2607 o i-1: a -move-> c, p -move-> s
2604 |
2608 |
2605 o i-0 initial commit: a b h p q r
2609 o i-0 initial commit: a b h p q r
2606
2610
2607 #else
2611 #else
2608 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2612 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2609 $ hg log -Gfr 'desc("mDGm-0")' d
2613 $ hg log -Gfr 'desc("mDGm-0")' d
2610 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2614 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2611 |\
2615 |\
2612 | o g-1: update d
2616 | o g-1: update d
2613 | |
2617 | |
2614 o | d-2 re-add d
2618 o | d-2 re-add d
2615 |/
2619 |/
2616 o i-2: c -move-> d, s -move-> t
2620 o i-2: c -move-> d, s -move-> t
2617 |
2621 |
2618 ~
2622 ~
2619 #endif
2623 #endif
2620
2624
2621 Subcase: merging a change to a file with a "copy overwrite" to that file from another branch
2625 Subcase: merging a change to a file with a "copy overwrite" to that file from another branch
2622 ````````````````````````````````````````````````````````````````````````````````````````````
2626 ````````````````````````````````````````````````````````````````````````````````````````````
2623
2627
2624 Merge:
2628 Merge:
2625 - one with change to a file (d)
2629 - one with change to a file (d)
2626 - one overwriting that file with a rename (from h to i, to d)
2630 - one overwriting that file with a rename (from h to i, to d)
2627
2631
2628 This case is similar to BF/FB, but an actual merge happens, so both side of the
2632 This case is similar to BF/FB, but an actual merge happens, so both side of the
2629 history are relevant.
2633 history are relevant.
2630
2634
2631
2635
2632 $ hg log -G --rev '::(desc("mGFm")+desc("mFGm"))'
2636 $ hg log -G --rev '::(desc("mGFm")+desc("mFGm"))'
2633 o mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
2637 o mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
2634 |\
2638 |\
2635 +---o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
2639 +---o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
2636 | |/
2640 | |/
2637 | o g-1: update d
2641 | o g-1: update d
2638 | |
2642 | |
2639 o | f-2: rename i -> d
2643 o | f-2: rename i -> d
2640 | |
2644 | |
2641 o | f-1: rename h -> i
2645 o | f-1: rename h -> i
2642 |/
2646 |/
2643 o i-2: c -move-> d, s -move-> t
2647 o i-2: c -move-> d, s -move-> t
2644 |
2648 |
2645 o i-1: a -move-> c, p -move-> s
2649 o i-1: a -move-> c, p -move-> s
2646 |
2650 |
2647 o i-0 initial commit: a b h p q r
2651 o i-0 initial commit: a b h p q r
2648
2652
2649
2653
2650 Note:
2654 Note:
2651 | In this case, the merge get conflicting information since on one side we have
2655 | In this case, the merge get conflicting information since on one side we have
2652 | "a -> c -> d". and one the other one we have "h -> i -> d".
2656 | "a -> c -> d". and one the other one we have "h -> i -> d".
2653 |
2657 |
2654 | The current code arbitrarily pick one side depending the ordering of the merged hash:
2658 | The current code arbitrarily pick one side depending the ordering of the merged hash:
2655
2659
2656 In this case, the file hash from "f-2" is lower, so it will be `p1` of the resulting filenode its copy tracing information will win (and trace back to "h"):
2660 In this case, the file hash from "f-2" is lower, so it will be `p1` of the resulting filenode its copy tracing information will win (and trace back to "h"):
2657
2661
2658 Details on this hash ordering pick:
2662 Details on this hash ordering pick:
2659
2663
2660 $ hg manifest --debug 'desc("g-1")' | egrep 'd$'
2664 $ hg manifest --debug 'desc("g-1")' | egrep 'd$'
2661 17ec97e605773eb44a117d1136b3849bcdc1924f 644 d (no-changeset !)
2665 17ec97e605773eb44a117d1136b3849bcdc1924f 644 d (no-changeset !)
2662 5cce88bf349f7c742bb440f2c53f81db9c294279 644 d (changeset !)
2666 5cce88bf349f7c742bb440f2c53f81db9c294279 644 d (changeset !)
2663 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("g-1")' d
2667 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("g-1")' d
2664 A d
2668 A d
2665 a (no-changeset no-compatibility !)
2669 a (no-changeset no-compatibility !)
2666
2670
2667 $ hg manifest --debug 'desc("f-2")' | egrep 'd$'
2671 $ hg manifest --debug 'desc("f-2")' | egrep 'd$'
2668 7b79e2fe0c8924e0e598a82f048a7b024afa4d96 644 d (no-changeset !)
2672 7b79e2fe0c8924e0e598a82f048a7b024afa4d96 644 d (no-changeset !)
2669 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !)
2673 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !)
2670 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("f-2")' d
2674 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("f-2")' d
2671 A d
2675 A d
2672 h (no-changeset no-compatibility !)
2676 h (no-changeset no-compatibility !)
2673
2677
2674 Copy tracing data on the resulting merge:
2678 Copy tracing data on the resulting merge:
2675
2679
2676 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm-0")'
2680 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm-0")'
2677 A d
2681 A d
2678 h (no-filelog !)
2682 h (no-filelog !)
2679 a (filelog !)
2683 a (filelog !)
2680 A t
2684 A t
2681 p
2685 p
2682 R a
2686 R a
2683 R h
2687 R h
2684 R p
2688 R p
2685 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm-0")'
2689 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm-0")'
2686 A d
2690 A d
2687 a (no-changeset !)
2691 a (no-changeset !)
2688 h (changeset !)
2692 h (changeset !)
2689 A t
2693 A t
2690 p
2694 p
2691 R a
2695 R a
2692 R h
2696 R h
2693 R p
2697 R p
2694 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFGm-0")'
2698 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFGm-0")'
2695 M d
2699 M d
2696 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mGFm-0")'
2700 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mGFm-0")'
2697 M d
2701 M d
2698 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFGm-0")'
2702 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFGm-0")'
2699 M d
2703 M d
2700 i (no-filelog !)
2704 i (no-filelog !)
2701 R i
2705 R i
2702 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mGFm-0")'
2706 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mGFm-0")'
2703 M d
2707 M d
2704 i (no-filelog !)
2708 i (no-filelog !)
2705 R i
2709 R i
2706 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mFGm-0")'
2710 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mFGm-0")'
2707 M d (no-changeset !)
2711 M d (no-changeset !)
2708 h (no-filelog no-changeset !)
2712 h (no-filelog no-changeset !)
2709 R h
2713 R h
2710 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGFm-0")'
2714 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGFm-0")'
2711 M d (no-changeset !)
2715 M d (no-changeset !)
2712 h (no-filelog no-changeset !)
2716 h (no-filelog no-changeset !)
2713 R h
2717 R h
2714
2718
2715 #if no-changeset
2719 #if no-changeset
2716 $ hg log -Gfr 'desc("mFGm-0")' d
2720 $ hg log -Gfr 'desc("mFGm-0")' d
2717 o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
2721 o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
2718 |\
2722 |\
2719 | o g-1: update d
2723 | o g-1: update d
2720 | |
2724 | |
2721 o | f-2: rename i -> d
2725 o | f-2: rename i -> d
2722 | |
2726 | |
2723 o | f-1: rename h -> i
2727 o | f-1: rename h -> i
2724 |/
2728 |/
2725 o i-2: c -move-> d, s -move-> t
2729 o i-2: c -move-> d, s -move-> t
2726 |
2730 |
2727 o i-1: a -move-> c, p -move-> s
2731 o i-1: a -move-> c, p -move-> s
2728 |
2732 |
2729 o i-0 initial commit: a b h p q r
2733 o i-0 initial commit: a b h p q r
2730
2734
2731 #else
2735 #else
2732 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2736 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2733 $ hg log -Gfr 'desc("mFGm-0")' d
2737 $ hg log -Gfr 'desc("mFGm-0")' d
2734 o g-1: update d
2738 o g-1: update d
2735 |
2739 |
2736 o i-2: c -move-> d, s -move-> t
2740 o i-2: c -move-> d, s -move-> t
2737 |
2741 |
2738 ~
2742 ~
2739 #endif
2743 #endif
2740
2744
2741 #if no-changeset
2745 #if no-changeset
2742 $ hg log -Gfr 'desc("mGFm-0")' d
2746 $ hg log -Gfr 'desc("mGFm-0")' d
2743 o mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
2747 o mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
2744 |\
2748 |\
2745 | o g-1: update d
2749 | o g-1: update d
2746 | |
2750 | |
2747 o | f-2: rename i -> d
2751 o | f-2: rename i -> d
2748 | |
2752 | |
2749 o | f-1: rename h -> i
2753 o | f-1: rename h -> i
2750 |/
2754 |/
2751 o i-2: c -move-> d, s -move-> t
2755 o i-2: c -move-> d, s -move-> t
2752 |
2756 |
2753 o i-1: a -move-> c, p -move-> s
2757 o i-1: a -move-> c, p -move-> s
2754 |
2758 |
2755 o i-0 initial commit: a b h p q r
2759 o i-0 initial commit: a b h p q r
2756
2760
2757 #else
2761 #else
2758 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2762 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2759 $ hg log -Gfr 'desc("mGFm-0")' d
2763 $ hg log -Gfr 'desc("mGFm-0")' d
2760 o g-1: update d
2764 o g-1: update d
2761 |
2765 |
2762 o i-2: c -move-> d, s -move-> t
2766 o i-2: c -move-> d, s -move-> t
2763 |
2767 |
2764 ~
2768 ~
2765 #endif
2769 #endif
2766
2770
2767 Subcase: new copy information on both side with an actual merge happening
2771 Subcase: new copy information on both side with an actual merge happening
2768 `````````````````````````````````````````````````````````````````````````
2772 `````````````````````````````````````````````````````````````````````````
2769
2773
2770 - the "p-" branch renaming 't' to 'v' (through 'u')
2774 - the "p-" branch renaming 't' to 'v' (through 'u')
2771 - the "q-" branch renaming 'r' to 'v' (through 'w')
2775 - the "q-" branch renaming 'r' to 'v' (through 'w')
2772
2776
2773
2777
2774 $ hg log -G --rev '::(desc("mPQm")+desc("mQPm"))'
2778 $ hg log -G --rev '::(desc("mPQm")+desc("mQPm"))'
2775 o mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
2779 o mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
2776 |\
2780 |\
2777 +---o mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
2781 +---o mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
2778 | |/
2782 | |/
2779 | o q-2 w -move-> v
2783 | o q-2 w -move-> v
2780 | |
2784 | |
2781 | o q-1 r -move-> w
2785 | o q-1 r -move-> w
2782 | |
2786 | |
2783 o | p-2: u -move-> v
2787 o | p-2: u -move-> v
2784 | |
2788 | |
2785 o | p-1: t -move-> u
2789 o | p-1: t -move-> u
2786 |/
2790 |/
2787 o i-2: c -move-> d, s -move-> t
2791 o i-2: c -move-> d, s -move-> t
2788 |
2792 |
2789 o i-1: a -move-> c, p -move-> s
2793 o i-1: a -move-> c, p -move-> s
2790 |
2794 |
2791 o i-0 initial commit: a b h p q r
2795 o i-0 initial commit: a b h p q r
2792
2796
2793
2797
2794 #if no-changeset
2798 #if no-changeset
2795 $ hg manifest --debug --rev 'desc("mPQm-0")' | grep '644 v'
2799 $ hg manifest --debug --rev 'desc("mPQm-0")' | grep '644 v'
2796 0946c662ef16e4e67397fd717389eb6693d41749 644 v
2800 0946c662ef16e4e67397fd717389eb6693d41749 644 v
2797 $ hg manifest --debug --rev 'desc("mQPm-0")' | grep '644 v'
2801 $ hg manifest --debug --rev 'desc("mQPm-0")' | grep '644 v'
2798 0db3aad7fcc1ec27fab57060e327b9e864ea0cc9 644 v
2802 0db3aad7fcc1ec27fab57060e327b9e864ea0cc9 644 v
2799 $ hg manifest --debug --rev 'desc("p-2")' | grep '644 v'
2803 $ hg manifest --debug --rev 'desc("p-2")' | grep '644 v'
2800 3f91841cd75cadc9a1f1b4e7c1aa6d411f76032e 644 v
2804 3f91841cd75cadc9a1f1b4e7c1aa6d411f76032e 644 v
2801 $ hg manifest --debug --rev 'desc("q-2")' | grep '644 v'
2805 $ hg manifest --debug --rev 'desc("q-2")' | grep '644 v'
2802 c43c088b811fd27983c0a9aadf44f3343cd4cd7e 644 v
2806 c43c088b811fd27983c0a9aadf44f3343cd4cd7e 644 v
2803 $ hg debugindex v | ../no-linkrev
2807 $ hg debugindex v | ../no-linkrev
2804 rev linkrev nodeid p1 p2
2808 rev linkrev nodeid p1 p2
2805 0 * 3f91841cd75c 000000000000 000000000000
2809 0 * 3f91841cd75c 000000000000 000000000000
2806 1 * c43c088b811f 000000000000 000000000000
2810 1 * c43c088b811f 000000000000 000000000000
2807 2 * 0946c662ef16 3f91841cd75c c43c088b811f
2811 2 * 0946c662ef16 3f91841cd75c c43c088b811f
2808 3 * 0db3aad7fcc1 c43c088b811f 3f91841cd75c
2812 3 * 0db3aad7fcc1 c43c088b811f 3f91841cd75c
2809 #else
2813 #else
2810 $ hg manifest --debug --rev 'desc("mPQm-0")' | grep '644 v'
2814 $ hg manifest --debug --rev 'desc("mPQm-0")' | grep '644 v'
2811 65fde9f6e4d4da23b3f610e07b53673ea9541d75 644 v
2815 65fde9f6e4d4da23b3f610e07b53673ea9541d75 644 v
2812 $ hg manifest --debug --rev 'desc("mQPm-0")' | grep '644 v'
2816 $ hg manifest --debug --rev 'desc("mQPm-0")' | grep '644 v'
2813 a098dda6413aecf154eefc976afc38b295acb7e5 644 v
2817 a098dda6413aecf154eefc976afc38b295acb7e5 644 v
2814 $ hg manifest --debug --rev 'desc("p-2")' | grep '644 v'
2818 $ hg manifest --debug --rev 'desc("p-2")' | grep '644 v'
2815 5aed6a8dbff0301328c08360d24354d3d064cf0d 644 v
2819 5aed6a8dbff0301328c08360d24354d3d064cf0d 644 v
2816 $ hg manifest --debug --rev 'desc("q-2")' | grep '644 v'
2820 $ hg manifest --debug --rev 'desc("q-2")' | grep '644 v'
2817 a38b2fa170219750dac9bc7d19df831f213ba708 644 v
2821 a38b2fa170219750dac9bc7d19df831f213ba708 644 v
2818 $ hg debugindex v | ../no-linkrev
2822 $ hg debugindex v | ../no-linkrev
2819 rev linkrev nodeid p1 p2
2823 rev linkrev nodeid p1 p2
2820 0 * 5aed6a8dbff0 000000000000 000000000000
2824 0 * 5aed6a8dbff0 000000000000 000000000000
2821 1 * a38b2fa17021 000000000000 000000000000
2825 1 * a38b2fa17021 000000000000 000000000000
2822 2 * 65fde9f6e4d4 5aed6a8dbff0 a38b2fa17021
2826 2 * 65fde9f6e4d4 5aed6a8dbff0 a38b2fa17021
2823 3 * a098dda6413a a38b2fa17021 5aed6a8dbff0
2827 3 * a098dda6413a a38b2fa17021 5aed6a8dbff0
2824 #endif
2828 #endif
2825
2829
2826 # Here the filelog based implementation is not looking at the rename
2830 # Here the filelog based implementation is not looking at the rename
2827 # information (because the file exist on both side). However the changelog
2831 # information (because the file exist on both side). However the changelog
2828 # based on works fine. We have different output.
2832 # based on works fine. We have different output.
2829
2833
2830 $ hg status --copies --rev 'desc("p-2")' --rev 'desc("mPQm-0")'
2834 $ hg status --copies --rev 'desc("p-2")' --rev 'desc("mPQm-0")'
2831 M v
2835 M v
2832 r (no-filelog !)
2836 r (no-filelog !)
2833 R r
2837 R r
2834 $ hg status --copies --rev 'desc("p-2")' --rev 'desc("mQPm-0")'
2838 $ hg status --copies --rev 'desc("p-2")' --rev 'desc("mQPm-0")'
2835 M v
2839 M v
2836 r (no-filelog !)
2840 r (no-filelog !)
2837 R r
2841 R r
2838 $ hg status --copies --rev 'desc("q-2")' --rev 'desc("mPQm-0")'
2842 $ hg status --copies --rev 'desc("q-2")' --rev 'desc("mPQm-0")'
2839 M v
2843 M v
2840 t (no-filelog !)
2844 t (no-filelog !)
2841 R t
2845 R t
2842 $ hg status --copies --rev 'desc("q-2")' --rev 'desc("mQPm-0")'
2846 $ hg status --copies --rev 'desc("q-2")' --rev 'desc("mQPm-0")'
2843 M v
2847 M v
2844 t (no-filelog !)
2848 t (no-filelog !)
2845 R t
2849 R t
2846 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("p-2")'
2850 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("p-2")'
2847 A v
2851 A v
2848 t
2852 t
2849 R t
2853 R t
2850 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("q-2")'
2854 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("q-2")'
2851 A v
2855 A v
2852 r
2856 r
2853 R r
2857 R r
2854
2858
2855 # From here, we run status against revision where both source file exists.
2859 # From here, we run status against revision where both source file exists.
2856 #
2860 #
2857 # The filelog based implementation picks an arbitrary side based on revision
2861 # The filelog based implementation picks an arbitrary side based on revision
2858 # numbers. So the same side "wins" whatever the parents order is. This is
2862 # numbers. So the same side "wins" whatever the parents order is. This is
2859 # sub-optimal because depending on revision numbers means the result can be
2863 # sub-optimal because depending on revision numbers means the result can be
2860 # different from one repository to the next.
2864 # different from one repository to the next.
2861 #
2865 #
2862 # The changeset based algorithm use the parent order to break tie on conflicting
2866 # The changeset based algorithm use the parent order to break tie on conflicting
2863 # information and will have a different order depending on who is p1 and p2.
2867 # information and will have a different order depending on who is p1 and p2.
2864 # That order is stable accross repositories. (data from p1 prevails)
2868 # That order is stable accross repositories. (data from p1 prevails)
2865
2869
2866 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mPQm-0")'
2870 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mPQm-0")'
2867 A v
2871 A v
2868 t
2872 t
2869 R r
2873 R r
2870 R t
2874 R t
2871 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mQPm-0")'
2875 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mQPm-0")'
2872 A v
2876 A v
2873 t (filelog !)
2877 t (filelog !)
2874 r (no-filelog !)
2878 r (no-filelog !)
2875 R r
2879 R r
2876 R t
2880 R t
2877 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQm-0")'
2881 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQm-0")'
2878 A d
2882 A d
2879 a
2883 a
2880 A v
2884 A v
2881 r (filelog !)
2885 r (filelog !)
2882 p (no-filelog !)
2886 p (no-filelog !)
2883 R a
2887 R a
2884 R p
2888 R p
2885 R r
2889 R r
2886 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQPm-0")'
2890 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQPm-0")'
2887 A d
2891 A d
2888 a
2892 a
2889 A v
2893 A v
2890 r
2894 r
2891 R a
2895 R a
2892 R p
2896 R p
2893 R r
2897 R r
2894
2898
2895
2899
2896 Comparing with merging with a deletion (and keeping the file)
2900 Comparing with merging with a deletion (and keeping the file)
2897 -------------------------------------------------------------
2901 -------------------------------------------------------------
2898
2902
2899 Merge:
2903 Merge:
2900 - one removing a file (d)
2904 - one removing a file (d)
2901 - one updating that file
2905 - one updating that file
2902 - the merge keep the modified version of the file (canceling the delete)
2906 - the merge keep the modified version of the file (canceling the delete)
2903
2907
2904 In this case, the file keep on living after the merge. So we should not drop its
2908 In this case, the file keep on living after the merge. So we should not drop its
2905 copy tracing chain.
2909 copy tracing chain.
2906
2910
2907 $ hg log -G --rev '::(desc("mCGm")+desc("mGCm"))'
2911 $ hg log -G --rev '::(desc("mCGm")+desc("mGCm"))'
2908 o mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
2912 o mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
2909 |\
2913 |\
2910 +---o mCGm-0 merge updated/deleted - revive the file (updated content) - one way
2914 +---o mCGm-0 merge updated/deleted - revive the file (updated content) - one way
2911 | |/
2915 | |/
2912 | o g-1: update d
2916 | o g-1: update d
2913 | |
2917 | |
2914 o | c-1 delete d
2918 o | c-1 delete d
2915 |/
2919 |/
2916 o i-2: c -move-> d, s -move-> t
2920 o i-2: c -move-> d, s -move-> t
2917 |
2921 |
2918 o i-1: a -move-> c, p -move-> s
2922 o i-1: a -move-> c, p -move-> s
2919 |
2923 |
2920 o i-0 initial commit: a b h p q r
2924 o i-0 initial commit: a b h p q r
2921
2925
2922
2926
2923 'a' is the copy source of 'd'
2927 'a' is the copy source of 'd'
2924
2928
2925 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCGm-0")'
2929 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCGm-0")'
2926 A d
2930 A d
2927 a (no-compatibility no-changeset !)
2931 a (no-compatibility no-changeset !)
2928 A t
2932 A t
2929 p
2933 p
2930 R a
2934 R a
2931 R p
2935 R p
2932 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGCm-0")'
2936 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGCm-0")'
2933 A d
2937 A d
2934 a (no-compatibility no-changeset !)
2938 a (no-compatibility no-changeset !)
2935 A t
2939 A t
2936 p
2940 p
2937 R a
2941 R a
2938 R p
2942 R p
2939 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCGm-0")'
2943 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCGm-0")'
2940 A d
2944 A d
2941 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mGCm-0")'
2945 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mGCm-0")'
2942 A d
2946 A d
2943 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mCGm-0")'
2947 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mCGm-0")'
2944 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGCm-0")'
2948 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGCm-0")'
2945
2949
2946
2950
2947 Comparing with merge restoring an untouched deleted file
2951 Comparing with merge restoring an untouched deleted file
2948 --------------------------------------------------------
2952 --------------------------------------------------------
2949
2953
2950 Merge:
2954 Merge:
2951 - one removing a file (d)
2955 - one removing a file (d)
2952 - one leaving the file untouched
2956 - one leaving the file untouched
2953 - the merge actively restore the file to the same content.
2957 - the merge actively restore the file to the same content.
2954
2958
2955 In this case, the file keep on living after the merge. So we should not drop its
2959 In this case, the file keep on living after the merge. So we should not drop its
2956 copy tracing chain.
2960 copy tracing chain.
2957
2961
2958 $ hg log -G --rev '::(desc("mCB-revert-m")+desc("mBC-revert-m"))'
2962 $ hg log -G --rev '::(desc("mCB-revert-m")+desc("mBC-revert-m"))'
2959 o mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
2963 o mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
2960 |\
2964 |\
2961 +---o mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
2965 +---o mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
2962 | |/
2966 | |/
2963 | o c-1 delete d
2967 | o c-1 delete d
2964 | |
2968 | |
2965 o | b-1: b update
2969 o | b-1: b update
2966 |/
2970 |/
2967 o i-2: c -move-> d, s -move-> t
2971 o i-2: c -move-> d, s -move-> t
2968 |
2972 |
2969 o i-1: a -move-> c, p -move-> s
2973 o i-1: a -move-> c, p -move-> s
2970 |
2974 |
2971 o i-0 initial commit: a b h p q r
2975 o i-0 initial commit: a b h p q r
2972
2976
2973
2977
2974 'a' is the the copy source of 'd'
2978 'a' is the the copy source of 'd'
2975
2979
2976 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
2980 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
2977 M b
2981 M b
2978 A d
2982 A d
2979 a (no-compatibility no-changeset !)
2983 a (no-compatibility no-changeset !)
2980 A t
2984 A t
2981 p
2985 p
2982 R a
2986 R a
2983 R p
2987 R p
2984 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
2988 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
2985 M b
2989 M b
2986 A d
2990 A d
2987 a (no-compatibility no-changeset !)
2991 a (no-compatibility no-changeset !)
2988 A t
2992 A t
2989 p
2993 p
2990 R a
2994 R a
2991 R p
2995 R p
2992 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCB-revert-m-0")'
2996 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCB-revert-m-0")'
2993 M b
2997 M b
2994 A d
2998 A d
2995 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBC-revert-m-0")'
2999 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBC-revert-m-0")'
2996 M b
3000 M b
2997 A d
3001 A d
2998 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCB-revert-m-0")'
3002 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCB-revert-m-0")'
2999 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBC-revert-m-0")'
3003 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBC-revert-m-0")'
3000
3004
3001
3005
3002 Merging a branch where a rename was deleted with a branch where the same file was renamed
3006 Merging a branch where a rename was deleted with a branch where the same file was renamed
3003 ------------------------------------------------------------------------------------------
3007 ------------------------------------------------------------------------------------------
3004
3008
3005 Create a "conflicting" merge where `d` get removed on one branch before its
3009 Create a "conflicting" merge where `d` get removed on one branch before its
3006 rename information actually conflict with the other branch.
3010 rename information actually conflict with the other branch.
3007
3011
3008 (the copy information from the branch that was not deleted should win).
3012 (the copy information from the branch that was not deleted should win).
3009
3013
3010 $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))'
3014 $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))'
3011 o mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
3015 o mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
3012 |\
3016 |\
3013 +---o mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
3017 +---o mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
3014 | |/
3018 | |/
3015 | o h-1: b -(move)-> d
3019 | o h-1: b -(move)-> d
3016 | |
3020 | |
3017 o | c-1 delete d
3021 o | c-1 delete d
3018 | |
3022 | |
3019 o | i-2: c -move-> d, s -move-> t
3023 o | i-2: c -move-> d, s -move-> t
3020 | |
3024 | |
3021 o | i-1: a -move-> c, p -move-> s
3025 o | i-1: a -move-> c, p -move-> s
3022 |/
3026 |/
3023 o i-0 initial commit: a b h p q r
3027 o i-0 initial commit: a b h p q r
3024
3028
3025
3029
3026 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCH-delete-before-conflict-m")'
3030 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCH-delete-before-conflict-m")'
3027 A d
3031 A d
3028 b (no-compatibility no-changeset !)
3032 b (no-compatibility no-changeset !)
3029 A t
3033 A t
3030 p
3034 p
3031 R a
3035 R a
3032 R b
3036 R b
3033 R p
3037 R p
3034 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mHC-delete-before-conflict-m")'
3038 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mHC-delete-before-conflict-m")'
3035 A d
3039 A d
3036 b
3040 b
3037 A t
3041 A t
3038 p
3042 p
3039 R a
3043 R a
3040 R b
3044 R b
3041 R p
3045 R p
3042 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCH-delete-before-conflict-m")'
3046 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCH-delete-before-conflict-m")'
3043 A d
3047 A d
3044 b
3048 b
3045 R b
3049 R b
3046 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mHC-delete-before-conflict-m")'
3050 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mHC-delete-before-conflict-m")'
3047 A d
3051 A d
3048 b
3052 b
3049 R b
3053 R b
3050 $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mCH-delete-before-conflict-m")'
3054 $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mCH-delete-before-conflict-m")'
3051 A t
3055 A t
3052 p
3056 p
3053 R a
3057 R a
3054 R p
3058 R p
3055 $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mHC-delete-before-conflict-m")'
3059 $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mHC-delete-before-conflict-m")'
3056 A t
3060 A t
3057 p
3061 p
3058 R a
3062 R a
3059 R p
3063 R p
3060
3064
3061 Variant of previous with extra changes introduced by the merge
3065 Variant of previous with extra changes introduced by the merge
3062 --------------------------------------------------------------
3066 --------------------------------------------------------------
3063
3067
3064 (see case declaration for details)
3068 (see case declaration for details)
3065
3069
3066 Subcase: merge has same initial content on both side, but merge introduced a change
3070 Subcase: merge has same initial content on both side, but merge introduced a change
3067 ```````````````````````````````````````````````````````````````````````````````````
3071 ```````````````````````````````````````````````````````````````````````````````````
3068
3072
3069 - the "e-" branch renaming b to f (through 'g')
3073 - the "e-" branch renaming b to f (through 'g')
3070 - the "a-" branch renaming d to f (through e)
3074 - the "a-" branch renaming d to f (through e)
3071 - the merge add new change to b
3075 - the merge add new change to b
3072
3076
3073 $ hg log -G --rev '::(desc("mAE-change-m")+desc("mEA-change-m"))'
3077 $ hg log -G --rev '::(desc("mAE-change-m")+desc("mEA-change-m"))'
3074 o mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
3078 o mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
3075 |\
3079 |\
3076 +---o mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
3080 +---o mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
3077 | |/
3081 | |/
3078 | o e-2 g -move-> f
3082 | o e-2 g -move-> f
3079 | |
3083 | |
3080 | o e-1 b -move-> g
3084 | o e-1 b -move-> g
3081 | |
3085 | |
3082 o | a-2: e -move-> f
3086 o | a-2: e -move-> f
3083 | |
3087 | |
3084 o | a-1: d -move-> e
3088 o | a-1: d -move-> e
3085 |/
3089 |/
3086 o i-2: c -move-> d, s -move-> t
3090 o i-2: c -move-> d, s -move-> t
3087 |
3091 |
3088 o i-1: a -move-> c, p -move-> s
3092 o i-1: a -move-> c, p -move-> s
3089 |
3093 |
3090 o i-0 initial commit: a b h p q r
3094 o i-0 initial commit: a b h p q r
3091
3095
3092 #if no-changeset
3096 #if no-changeset
3093 $ hg manifest --debug --rev 'desc("mAE-change-m-0")' | grep '644 f'
3097 $ hg manifest --debug --rev 'desc("mAE-change-m-0")' | grep '644 f'
3094 2f649fba7eb284e720d02b61f0546fcef694c045 644 f
3098 2f649fba7eb284e720d02b61f0546fcef694c045 644 f
3095 $ hg manifest --debug --rev 'desc("mEA-change-m-0")' | grep '644 f'
3099 $ hg manifest --debug --rev 'desc("mEA-change-m-0")' | grep '644 f'
3096 774e7c1637d536b99e2d8ef16fd731f87a82bd09 644 f
3100 774e7c1637d536b99e2d8ef16fd731f87a82bd09 644 f
3097 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
3101 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
3098 b76eb76580df486c3d51d63c5c210d4dd43a8ac7 644 f
3102 b76eb76580df486c3d51d63c5c210d4dd43a8ac7 644 f
3099 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
3103 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
3100 e8825b386367b29fec957283a80bb47b47483fe1 644 f
3104 e8825b386367b29fec957283a80bb47b47483fe1 644 f
3101 $ hg debugindex f | ../no-linkrev
3105 $ hg debugindex f | ../no-linkrev
3102 rev linkrev nodeid p1 p2
3106 rev linkrev nodeid p1 p2
3103 0 * b76eb76580df 000000000000 000000000000
3107 0 * b76eb76580df 000000000000 000000000000
3104 1 * e8825b386367 000000000000 000000000000
3108 1 * e8825b386367 000000000000 000000000000
3105 2 * 2ff93c643948 b76eb76580df e8825b386367
3109 2 * 2ff93c643948 b76eb76580df e8825b386367
3106 3 * 2f649fba7eb2 b76eb76580df e8825b386367
3110 3 * 2f649fba7eb2 b76eb76580df e8825b386367
3107 4 * 774e7c1637d5 e8825b386367 b76eb76580df
3111 4 * 774e7c1637d5 e8825b386367 b76eb76580df
3108 #else
3112 #else
3109 $ hg manifest --debug --rev 'desc("mAE-change-m-0")' | grep '644 f'
3113 $ hg manifest --debug --rev 'desc("mAE-change-m-0")' | grep '644 f'
3110 d3613c1ec8310a812ac4268fd853ac576b6caea5 644 f
3114 d3613c1ec8310a812ac4268fd853ac576b6caea5 644 f
3111 $ hg manifest --debug --rev 'desc("mEA-change-m-0")' | grep '644 f'
3115 $ hg manifest --debug --rev 'desc("mEA-change-m-0")' | grep '644 f'
3112 05e03c868bbcab4a649cb33a238d7aa07398a469 644 f
3116 05e03c868bbcab4a649cb33a238d7aa07398a469 644 f
3113 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
3117 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
3114 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
3118 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
3115 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
3119 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
3116 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
3120 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
3117 $ hg debugindex f | ../no-linkrev
3121 $ hg debugindex f | ../no-linkrev
3118 rev linkrev nodeid p1 p2
3122 rev linkrev nodeid p1 p2
3119 0 * ae258f702dfe 000000000000 000000000000
3123 0 * ae258f702dfe 000000000000 000000000000
3120 1 * d3613c1ec831 ae258f702dfe 000000000000
3124 1 * d3613c1ec831 ae258f702dfe 000000000000
3121 2 * 05e03c868bbc ae258f702dfe 000000000000
3125 2 * 05e03c868bbc ae258f702dfe 000000000000
3122 #endif
3126 #endif
3123
3127
3124 # Here the filelog based implementation is not looking at the rename
3128 # Here the filelog based implementation is not looking at the rename
3125 # information (because the file exist on both side). However the changelog
3129 # information (because the file exist on both side). However the changelog
3126 # based on works fine. We have different output.
3130 # based on works fine. We have different output.
3127
3131
3128 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAE-change-m-0")'
3132 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAE-change-m-0")'
3129 M f
3133 M f
3130 b (no-filelog !)
3134 b (no-filelog !)
3131 R b
3135 R b
3132 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEA-change-m-0")'
3136 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEA-change-m-0")'
3133 M f
3137 M f
3134 b (no-filelog !)
3138 b (no-filelog !)
3135 R b
3139 R b
3136 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAE-change-m-0")'
3140 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAE-change-m-0")'
3137 M f
3141 M f
3138 d (no-filelog !)
3142 d (no-filelog !)
3139 R d
3143 R d
3140 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEA-change-m-0")'
3144 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEA-change-m-0")'
3141 M f
3145 M f
3142 d (no-filelog !)
3146 d (no-filelog !)
3143 R d
3147 R d
3144 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
3148 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
3145 A f
3149 A f
3146 d
3150 d
3147 R d
3151 R d
3148 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")'
3152 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")'
3149 A f
3153 A f
3150 b
3154 b
3151 R b
3155 R b
3152
3156
3153 # From here, we run status against revision where both source file exists.
3157 # From here, we run status against revision where both source file exists.
3154 #
3158 #
3155 # The filelog based implementation picks an arbitrary side based on revision
3159 # The filelog based implementation picks an arbitrary side based on revision
3156 # numbers. So the same side "wins" whatever the parents order is. This is
3160 # numbers. So the same side "wins" whatever the parents order is. This is
3157 # sub-optimal because depending on revision numbers means the result can be
3161 # sub-optimal because depending on revision numbers means the result can be
3158 # different from one repository to the next.
3162 # different from one repository to the next.
3159 #
3163 #
3160 # The changeset based algorithm use the parent order to break tie on conflicting
3164 # The changeset based algorithm use the parent order to break tie on conflicting
3161 # information and will have a different order depending on who is p1 and p2.
3165 # information and will have a different order depending on who is p1 and p2.
3162 # That order is stable accross repositories. (data from p1 prevails)
3166 # That order is stable accross repositories. (data from p1 prevails)
3163
3167
3164 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAE-change-m-0")'
3168 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAE-change-m-0")'
3165 A f
3169 A f
3166 d
3170 d
3167 R b
3171 R b
3168 R d
3172 R d
3169 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEA-change-m-0")'
3173 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEA-change-m-0")'
3170 A f
3174 A f
3171 d (filelog !)
3175 d (filelog !)
3172 b (no-filelog !)
3176 b (no-filelog !)
3173 R b
3177 R b
3174 R d
3178 R d
3175 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change-m-0")'
3179 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change-m-0")'
3176 A f
3180 A f
3177 a
3181 a
3178 A t
3182 A t
3179 p
3183 p
3180 R a
3184 R a
3181 R b
3185 R b
3182 R p
3186 R p
3183 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change-m-0")'
3187 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change-m-0")'
3184 A f
3188 A f
3185 a (filelog !)
3189 a (filelog !)
3186 b (no-filelog !)
3190 b (no-filelog !)
3187 A t
3191 A t
3188 p
3192 p
3189 R a
3193 R a
3190 R b
3194 R b
3191 R p
3195 R p
3192
3196
3193
3197
3194 Decision from previous merge are properly chained with later merge
3198 Decision from previous merge are properly chained with later merge
3195 ------------------------------------------------------------------
3199 ------------------------------------------------------------------
3196
3200
3197
3201
3198 Subcase: chaining conflicting rename resolution
3202 Subcase: chaining conflicting rename resolution
3199 ```````````````````````````````````````````````
3203 ```````````````````````````````````````````````
3200
3204
3201 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
3205 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
3202 add more change on the respective branch and merge again. These second merge
3206 add more change on the respective branch and merge again. These second merge
3203 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
3207 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
3204 about that file should stay unchanged.
3208 about that file should stay unchanged.
3205
3209
3206 The result from mAEm is the same for the subsequent merge:
3210 The result from mAEm is the same for the subsequent merge:
3207
3211
3208 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm")' f
3212 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm")' f
3209 A f
3213 A f
3210 a (filelog !)
3214 a (filelog !)
3211 a (sidedata !)
3215 a (sidedata !)
3212 a (upgraded !)
3216 a (upgraded !)
3213 a (upgraded-parallel !)
3217 a (upgraded-parallel !)
3214
3218
3215 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE,Km")' f
3219 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE,Km")' f
3216 A f
3220 A f
3217 a (filelog !)
3221 a (filelog !)
3218 a (sidedata !)
3222 a (sidedata !)
3219 a (upgraded !)
3223 a (upgraded !)
3220 a (upgraded-parallel !)
3224 a (upgraded-parallel !)
3221
3225
3222 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AEm")' f
3226 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AEm")' f
3223 A f
3227 A f
3224 a (filelog !)
3228 a (filelog !)
3225 a (sidedata !)
3229 a (sidedata !)
3226 a (upgraded !)
3230 a (upgraded !)
3227 a (upgraded-parallel !)
3231 a (upgraded-parallel !)
3228
3232
3229
3233
3230 The result from mEAm is the same for the subsequent merge:
3234 The result from mEAm is the same for the subsequent merge:
3231
3235
3232 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm")' f
3236 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm")' f
3233 A f
3237 A f
3234 a (filelog !)
3238 a (filelog !)
3235 b (sidedata !)
3239 b (sidedata !)
3236 b (upgraded !)
3240 b (upgraded !)
3237 b (upgraded-parallel !)
3241 b (upgraded-parallel !)
3238
3242
3239 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA,Jm")' f
3243 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA,Jm")' f
3240 A f
3244 A f
3241 a (filelog !)
3245 a (filelog !)
3242 b (sidedata !)
3246 b (sidedata !)
3243 b (upgraded !)
3247 b (upgraded !)
3244 b (upgraded-parallel !)
3248 b (upgraded-parallel !)
3245
3249
3246 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EAm")' f
3250 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EAm")' f
3247 A f
3251 A f
3248 a (filelog !)
3252 a (filelog !)
3249 b (sidedata !)
3253 b (sidedata !)
3250 b (upgraded !)
3254 b (upgraded !)
3251 b (upgraded-parallel !)
3255 b (upgraded-parallel !)
3252
3256
3253 Subcase: chaining conflicting rename resolution
3257 Subcase: chaining conflicting rename resolution
3254 ```````````````````````````````````````````````
3258 ```````````````````````````````````````````````
3255
3259
3256 The "mPQm" and "mQPm" case create a rename tracking conflict on file 'v'. We
3260 The "mPQm" and "mQPm" case create a rename tracking conflict on file 'v'. We
3257 add more change on the respective branch and merge again. These second merge
3261 add more change on the respective branch and merge again. These second merge
3258 does not involve the file 'v' and the arbitration done within "mPQm" and "mQP"
3262 does not involve the file 'v' and the arbitration done within "mPQm" and "mQP"
3259 about that file should stay unchanged.
3263 about that file should stay unchanged.
3260
3264
3261 The result from mPQm is the same for the subsequent merge:
3265 The result from mPQm is the same for the subsequent merge:
3262
3266
3263 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQm")' v
3267 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQm")' v
3264 A v
3268 A v
3265 r (filelog !)
3269 r (filelog !)
3266 p (sidedata !)
3270 p (sidedata !)
3267 p (upgraded !)
3271 p (upgraded !)
3268 p (upgraded-parallel !)
3272 p (upgraded-parallel !)
3269
3273
3270 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQ,Tm")' v
3274 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQ,Tm")' v
3271 A v
3275 A v
3272 r (filelog !)
3276 r (filelog !)
3273 p (sidedata !)
3277 p (sidedata !)
3274 p (upgraded !)
3278 p (upgraded !)
3275 p (upgraded-parallel !)
3279 p (upgraded-parallel !)
3276
3280
3277 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mT,PQm")' v
3281 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mT,PQm")' v
3278 A v
3282 A v
3279 r (filelog !)
3283 r (filelog !)
3280 p (sidedata !)
3284 p (sidedata !)
3281 p (upgraded !)
3285 p (upgraded !)
3282 p (upgraded-parallel !)
3286 p (upgraded-parallel !)
3283
3287
3284
3288
3285 The result from mQPm is the same for the subsequent merge:
3289 The result from mQPm is the same for the subsequent merge:
3286
3290
3287 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQPm")' v
3291 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQPm")' v
3288 A v
3292 A v
3289 r (no-changeset no-compatibility !)
3293 r (no-changeset no-compatibility !)
3290
3294
3291 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQP,Sm")' v
3295 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQP,Sm")' v
3292 A v
3296 A v
3293 r (no-changeset no-compatibility !)
3297 r (no-changeset no-compatibility !)
3294
3298
3295 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mS,QPm")' v
3299 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mS,QPm")' v
3296 A v
3300 A v
3297 r (filelog !)
3301 r (filelog !)
3298 r (sidedata !)
3302 r (sidedata !)
3299 r (upgraded !)
3303 r (upgraded !)
3300 r (upgraded-parallel !)
3304 r (upgraded-parallel !)
3301
3305
3302
3306
3303 Subcase: chaining salvage information during a merge
3307 Subcase: chaining salvage information during a merge
3304 ````````````````````````````````````````````````````
3308 ````````````````````````````````````````````````````
3305
3309
3306 We add more change on the branch were the file was deleted. merging again
3310 We add more change on the branch were the file was deleted. merging again
3307 should preserve the fact eh file was salvaged.
3311 should preserve the fact eh file was salvaged.
3308
3312
3309 reference output:
3313 reference output:
3310
3314
3311 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
3315 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
3312 M b
3316 M b
3313 A d
3317 A d
3314 a (no-changeset no-compatibility !)
3318 a (no-changeset no-compatibility !)
3315 A t
3319 A t
3316 p
3320 p
3317 R a
3321 R a
3318 R p
3322 R p
3319 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
3323 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
3320 M b
3324 M b
3321 A d
3325 A d
3322 a (no-changeset no-compatibility !)
3326 a (no-changeset no-compatibility !)
3323 A t
3327 A t
3324 p
3328 p
3325 R a
3329 R a
3326 R p
3330 R p
3327
3331
3328 chained output
3332 chained output
3329 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC+revert,Lm")'
3333 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC+revert,Lm")'
3330 M b
3334 M b
3331 A d
3335 A d
3332 a (no-changeset no-compatibility !)
3336 a (no-changeset no-compatibility !)
3333 A t
3337 A t
3334 p
3338 p
3335 A unrelated-l
3339 A unrelated-l
3336 R a
3340 R a
3337 R p
3341 R p
3338 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB+revert,Lm")'
3342 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB+revert,Lm")'
3339 M b
3343 M b
3340 A d
3344 A d
3341 a (no-changeset no-compatibility !)
3345 a (no-changeset no-compatibility !)
3342 A t
3346 A t
3343 p
3347 p
3344 A unrelated-l
3348 A unrelated-l
3345 R a
3349 R a
3346 R p
3350 R p
3347 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,BC+revertm")'
3351 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,BC+revertm")'
3348 M b
3352 M b
3349 A d
3353 A d
3350 a (no-changeset no-compatibility !)
3354 a (no-changeset no-compatibility !)
3351 A t
3355 A t
3352 p
3356 p
3353 A unrelated-l
3357 A unrelated-l
3354 R a
3358 R a
3355 R p
3359 R p
3356 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,CB+revertm")'
3360 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,CB+revertm")'
3357 M b
3361 M b
3358 A d
3362 A d
3359 a (no-changeset no-compatibility !)
3363 a (no-changeset no-compatibility !)
3360 A t
3364 A t
3361 p
3365 p
3362 A unrelated-l
3366 A unrelated-l
3363 R a
3367 R a
3364 R p
3368 R p
3365
3369
3366 Subcase: chaining "merged" information during a merge
3370 Subcase: chaining "merged" information during a merge
3367 ``````````````````````````````````````````````````````
3371 ``````````````````````````````````````````````````````
3368
3372
3369 When a non-rename change are merged with a copy overwrite, the merge pick the copy source from (p1) as the reference. We should preserve this information in subsequent merges.
3373 When a non-rename change are merged with a copy overwrite, the merge pick the copy source from (p1) as the reference. We should preserve this information in subsequent merges.
3370
3374
3371
3375
3372 reference output:
3376 reference output:
3373
3377
3374 (for details about the filelog pick, check the mFGm/mGFm case)
3378 (for details about the filelog pick, check the mFGm/mGFm case)
3375
3379
3376 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm")' d
3380 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm")' d
3377 A d
3381 A d
3378 a (filelog !)
3382 a (filelog !)
3379 h (sidedata !)
3383 h (sidedata !)
3380 h (upgraded !)
3384 h (upgraded !)
3381 h (upgraded-parallel !)
3385 h (upgraded-parallel !)
3382 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm")' d
3386 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm")' d
3383 A d
3387 A d
3384 a (filelog !)
3388 a (filelog !)
3385 a (sidedata !)
3389 a (sidedata !)
3386 a (upgraded !)
3390 a (upgraded !)
3387 a (upgraded-parallel !)
3391 a (upgraded-parallel !)
3388
3392
3389 Chained output
3393 Chained output
3390
3394
3391 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mO,FGm")' d
3395 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mO,FGm")' d
3392 A d
3396 A d
3393 a (filelog !)
3397 a (filelog !)
3394 h (sidedata !)
3398 h (sidedata !)
3395 h (upgraded !)
3399 h (upgraded !)
3396 h (upgraded-parallel !)
3400 h (upgraded-parallel !)
3397 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFG,Om")' d
3401 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFG,Om")' d
3398 A d
3402 A d
3399 a (filelog !)
3403 a (filelog !)
3400 h (sidedata !)
3404 h (sidedata !)
3401 h (upgraded !)
3405 h (upgraded !)
3402 h (upgraded-parallel !)
3406 h (upgraded-parallel !)
3403
3407
3404
3408
3405 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGF,Nm")' d
3409 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGF,Nm")' d
3406 A d
3410 A d
3407 a (no-changeset no-compatibility !)
3411 a (no-changeset no-compatibility !)
3408 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mN,GFm")' d
3412 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mN,GFm")' d
3409 A d
3413 A d
3410 a (no-changeset no-compatibility !)
3414 a (no-changeset no-compatibility !)
3411
3415
3412
3416
3413 Subcase: chaining conflicting rename resolution, with extra change during the merge
3417 Subcase: chaining conflicting rename resolution, with extra change during the merge
3414 ```````````````````````````````````````````````````````````````````````````````````
3418 ```````````````````````````````````````````````````````````````````````````````````
3415
3419
3416 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
3420 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
3417 add more change on the respective branch and merge again. These second merge
3421 add more change on the respective branch and merge again. These second merge
3418 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
3422 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
3419 about that file should stay unchanged.
3423 about that file should stay unchanged.
3420
3424
3421 The result from mAEm is the same for the subsequent merge:
3425 The result from mAEm is the same for the subsequent merge:
3422
3426
3423 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change-m")' f
3427 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change-m")' f
3424 A f
3428 A f
3425 a (filelog !)
3429 a (filelog !)
3426 a (sidedata !)
3430 a (sidedata !)
3427 a (upgraded !)
3431 a (upgraded !)
3428 a (upgraded-parallel !)
3432 a (upgraded-parallel !)
3429
3433
3430 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change,Km")' f
3434 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change,Km")' f
3431 A f
3435 A f
3432 a (filelog !)
3436 a (filelog !)
3433 a (sidedata !)
3437 a (sidedata !)
3434 a (upgraded !)
3438 a (upgraded !)
3435 a (upgraded-parallel !)
3439 a (upgraded-parallel !)
3436
3440
3437 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AE-change-m")' f
3441 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AE-change-m")' f
3438 A f
3442 A f
3439 a (no-changeset no-compatibility !)
3443 a (no-changeset no-compatibility !)
3440
3444
3441
3445
3442 The result from mEAm is the same for the subsequent merge:
3446 The result from mEAm is the same for the subsequent merge:
3443
3447
3444 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change-m")' f
3448 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change-m")' f
3445 A f
3449 A f
3446 a (filelog !)
3450 a (filelog !)
3447 b (sidedata !)
3451 b (sidedata !)
3448 b (upgraded !)
3452 b (upgraded !)
3449 b (upgraded-parallel !)
3453 b (upgraded-parallel !)
3450
3454
3451 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change,Jm")' f
3455 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change,Jm")' f
3452 A f
3456 A f
3453 a (filelog !)
3457 a (filelog !)
3454 b (sidedata !)
3458 b (sidedata !)
3455 b (upgraded !)
3459 b (upgraded !)
3456 b (upgraded-parallel !)
3460 b (upgraded-parallel !)
3457
3461
3458 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EA-change-m")' f
3462 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EA-change-m")' f
3459 A f
3463 A f
3460 a (filelog !)
3464 a (filelog !)
3461 b (sidedata !)
3465 b (sidedata !)
3462 b (upgraded !)
3466 b (upgraded !)
3463 b (upgraded-parallel !)
3467 b (upgraded-parallel !)
@@ -1,497 +1,502 b''
1 #testcases extra sidedata
1 #testcases extra sidedata
2
2
3 #if extra
3 #if extra
4 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [experimental]
5 > [experimental]
6 > copies.write-to=changeset-only
6 > copies.write-to=changeset-only
7 > copies.read-from=changeset-only
7 > copies.read-from=changeset-only
8 > [alias]
8 > [alias]
9 > changesetcopies = log -r . -T 'files: {files}
9 > changesetcopies = log -r . -T 'files: {files}
10 > {extras % "{ifcontains("files", key, "{key}: {value}\n")}"}
10 > {extras % "{ifcontains("files", key, "{key}: {value}\n")}"}
11 > {extras % "{ifcontains("copies", key, "{key}: {value}\n")}"}'
11 > {extras % "{ifcontains("copies", key, "{key}: {value}\n")}"}'
12 > EOF
12 > EOF
13 #endif
13 #endif
14
14
15 #if sidedata
15 #if sidedata
16 $ cat >> $HGRCPATH << EOF
16 $ cat >> $HGRCPATH << EOF
17 > [format]
17 > [format]
18 > exp-use-copies-side-data-changeset = yes
18 > exp-use-copies-side-data-changeset = yes
19 > EOF
19 > EOF
20 #endif
20 #endif
21
21
22 $ cat >> $HGRCPATH << EOF
22 $ cat >> $HGRCPATH << EOF
23 > [alias]
23 > [alias]
24 > showcopies = log -r . -T '{file_copies % "{source} -> {name}\n"}'
24 > showcopies = log -r . -T '{file_copies % "{source} -> {name}\n"}'
25 > [extensions]
25 > [extensions]
26 > rebase =
26 > rebase =
27 > split =
27 > split =
28 > EOF
28 > EOF
29
29
30 Check that copies are recorded correctly
30 Check that copies are recorded correctly
31
31
32 $ hg init repo
32 $ hg init repo
33 $ cd repo
33 $ cd repo
34 #if sidedata
34 #if sidedata
35 $ hg debugformat -v
35 $ hg debugformat -v
36 format-variant repo config default
36 format-variant repo config default
37 fncache: yes yes yes
37 fncache: yes yes yes
38 dotencode: yes yes yes
38 dotencode: yes yes yes
39 generaldelta: yes yes yes
39 generaldelta: yes yes yes
40 share-safe: no no no
40 share-safe: no no no
41 sparserevlog: yes yes yes
41 sparserevlog: yes yes yes
42 sidedata: yes yes no
42 sidedata: yes yes no
43 persistent-nodemap: no no no
43 persistent-nodemap: no no no
44 copies-sdc: yes yes no
44 copies-sdc: yes yes no
45 revlog-v2: yes yes no
45 plain-cl-delta: yes yes yes
46 plain-cl-delta: yes yes yes
46 compression: zlib zlib zlib
47 compression: zlib zlib zlib
47 compression-level: default default default
48 compression-level: default default default
48 #else
49 #else
49 $ hg debugformat -v
50 $ hg debugformat -v
50 format-variant repo config default
51 format-variant repo config default
51 fncache: yes yes yes
52 fncache: yes yes yes
52 dotencode: yes yes yes
53 dotencode: yes yes yes
53 generaldelta: yes yes yes
54 generaldelta: yes yes yes
54 share-safe: no no no
55 share-safe: no no no
55 sparserevlog: yes yes yes
56 sparserevlog: yes yes yes
56 sidedata: no no no
57 sidedata: no no no
57 persistent-nodemap: no no no
58 persistent-nodemap: no no no
58 copies-sdc: no no no
59 copies-sdc: no no no
60 revlog-v2: no no no
59 plain-cl-delta: yes yes yes
61 plain-cl-delta: yes yes yes
60 compression: zlib zlib zlib
62 compression: zlib zlib zlib
61 compression-level: default default default
63 compression-level: default default default
62 #endif
64 #endif
63 $ echo a > a
65 $ echo a > a
64 $ hg add a
66 $ hg add a
65 $ hg ci -m initial
67 $ hg ci -m initial
66 $ hg cp a b
68 $ hg cp a b
67 $ hg cp a c
69 $ hg cp a c
68 $ hg cp a d
70 $ hg cp a d
69 $ hg ci -m 'copy a to b, c, and d'
71 $ hg ci -m 'copy a to b, c, and d'
70
72
71 #if extra
73 #if extra
72
74
73 $ hg changesetcopies
75 $ hg changesetcopies
74 files: b c d
76 files: b c d
75 filesadded: 0
77 filesadded: 0
76 1
78 1
77 2
79 2
78
80
79 p1copies: 0\x00a (esc)
81 p1copies: 0\x00a (esc)
80 1\x00a (esc)
82 1\x00a (esc)
81 2\x00a (esc)
83 2\x00a (esc)
82 #else
84 #else
83 $ hg debugsidedata -c -v -- -1
85 $ hg debugsidedata -c -v -- -1
84 1 sidedata entries
86 1 sidedata entries
85 entry-0014 size 44
87 entry-0014 size 44
86 '\x00\x00\x00\x04\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x00abcd'
88 '\x00\x00\x00\x04\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x00abcd'
87 #endif
89 #endif
88
90
89 $ hg showcopies
91 $ hg showcopies
90 a -> b
92 a -> b
91 a -> c
93 a -> c
92 a -> d
94 a -> d
93
95
94 #if extra
96 #if extra
95
97
96 $ hg showcopies --config experimental.copies.read-from=compatibility
98 $ hg showcopies --config experimental.copies.read-from=compatibility
97 a -> b
99 a -> b
98 a -> c
100 a -> c
99 a -> d
101 a -> d
100 $ hg showcopies --config experimental.copies.read-from=filelog-only
102 $ hg showcopies --config experimental.copies.read-from=filelog-only
101
103
102 #endif
104 #endif
103
105
104 Check that renames are recorded correctly
106 Check that renames are recorded correctly
105
107
106 $ hg mv b b2
108 $ hg mv b b2
107 $ hg ci -m 'rename b to b2'
109 $ hg ci -m 'rename b to b2'
108
110
109 #if extra
111 #if extra
110
112
111 $ hg changesetcopies
113 $ hg changesetcopies
112 files: b b2
114 files: b b2
113 filesadded: 1
115 filesadded: 1
114 filesremoved: 0
116 filesremoved: 0
115
117
116 p1copies: 1\x00b (esc)
118 p1copies: 1\x00b (esc)
117
119
118 #else
120 #else
119 $ hg debugsidedata -c -v -- -1
121 $ hg debugsidedata -c -v -- -1
120 1 sidedata entries
122 1 sidedata entries
121 entry-0014 size 25
123 entry-0014 size 25
122 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x00bb2'
124 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x00bb2'
123 #endif
125 #endif
124
126
125 $ hg showcopies
127 $ hg showcopies
126 b -> b2
128 b -> b2
127
129
128
130
129 Rename onto existing file. This should get recorded in the changeset files list and in the extras,
131 Rename onto existing file. This should get recorded in the changeset files list and in the extras,
130 even though there is no filelog entry.
132 even though there is no filelog entry.
131
133
132 $ hg cp b2 c --force
134 $ hg cp b2 c --force
133 $ hg st --copies
135 $ hg st --copies
134 M c
136 M c
135 b2
137 b2
136
138
137 #if extra
139 #if extra
138
140
139 $ hg debugindex c
141 $ hg debugindex c
140 rev linkrev nodeid p1 p2
142 rev linkrev nodeid p1 p2
141 0 1 b789fdd96dc2 000000000000 000000000000
143 0 1 b789fdd96dc2 000000000000 000000000000
142
144
143 #else
145 #else
144
146
145 $ hg debugindex c
147 $ hg debugindex c
146 rev linkrev nodeid p1 p2
148 rev linkrev nodeid p1 p2
147 0 1 37d9b5d994ea 000000000000 000000000000
149 0 1 37d9b5d994ea 000000000000 000000000000
148
150
149 #endif
151 #endif
150
152
151
153
152 $ hg ci -m 'move b onto d'
154 $ hg ci -m 'move b onto d'
153
155
154 #if extra
156 #if extra
155
157
156 $ hg changesetcopies
158 $ hg changesetcopies
157 files: c
159 files: c
158
160
159 p1copies: 0\x00b2 (esc)
161 p1copies: 0\x00b2 (esc)
160
162
161 #else
163 #else
162 $ hg debugsidedata -c -v -- -1
164 $ hg debugsidedata -c -v -- -1
163 1 sidedata entries
165 1 sidedata entries
164 entry-0014 size 25
166 entry-0014 size 25
165 '\x00\x00\x00\x02\x00\x00\x00\x00\x02\x00\x00\x00\x00\x16\x00\x00\x00\x03\x00\x00\x00\x00b2c'
167 '\x00\x00\x00\x02\x00\x00\x00\x00\x02\x00\x00\x00\x00\x16\x00\x00\x00\x03\x00\x00\x00\x00b2c'
166 #endif
168 #endif
167
169
168 $ hg showcopies
170 $ hg showcopies
169 b2 -> c
171 b2 -> c
170
172
171 #if extra
173 #if extra
172
174
173 $ hg debugindex c
175 $ hg debugindex c
174 rev linkrev nodeid p1 p2
176 rev linkrev nodeid p1 p2
175 0 1 b789fdd96dc2 000000000000 000000000000
177 0 1 b789fdd96dc2 000000000000 000000000000
176
178
177 #else
179 #else
178
180
179 $ hg debugindex c
181 $ hg debugindex c
180 rev linkrev nodeid p1 p2
182 rev linkrev nodeid p1 p2
181 0 1 37d9b5d994ea 000000000000 000000000000
183 0 1 37d9b5d994ea 000000000000 000000000000
182 1 3 029625640347 000000000000 000000000000
184 1 3 029625640347 000000000000 000000000000
183
185
184 #endif
186 #endif
185
187
186 Create a merge commit with copying done during merge.
188 Create a merge commit with copying done during merge.
187
189
188 $ hg co 0
190 $ hg co 0
189 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
191 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
190 $ hg cp a e
192 $ hg cp a e
191 $ hg cp a f
193 $ hg cp a f
192 $ hg ci -m 'copy a to e and f'
194 $ hg ci -m 'copy a to e and f'
193 created new head
195 created new head
194 $ hg merge 3
196 $ hg merge 3
195 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
196 (branch merge, don't forget to commit)
198 (branch merge, don't forget to commit)
197 File 'a' exists on both sides, so 'g' could be recorded as being from p1 or p2, but we currently
199 File 'a' exists on both sides, so 'g' could be recorded as being from p1 or p2, but we currently
198 always record it as being from p1
200 always record it as being from p1
199 $ hg cp a g
201 $ hg cp a g
200 File 'd' exists only in p2, so 'h' should be from p2
202 File 'd' exists only in p2, so 'h' should be from p2
201 $ hg cp d h
203 $ hg cp d h
202 File 'f' exists only in p1, so 'i' should be from p1
204 File 'f' exists only in p1, so 'i' should be from p1
203 $ hg cp f i
205 $ hg cp f i
204 $ hg ci -m 'merge'
206 $ hg ci -m 'merge'
205
207
206 #if extra
208 #if extra
207
209
208 $ hg changesetcopies
210 $ hg changesetcopies
209 files: g h i
211 files: g h i
210 filesadded: 0
212 filesadded: 0
211 1
213 1
212 2
214 2
213
215
214 p1copies: 0\x00a (esc)
216 p1copies: 0\x00a (esc)
215 2\x00f (esc)
217 2\x00f (esc)
216 p2copies: 1\x00d (esc)
218 p2copies: 1\x00d (esc)
217
219
218 #else
220 #else
219 $ hg debugsidedata -c -v -- -1
221 $ hg debugsidedata -c -v -- -1
220 1 sidedata entries
222 1 sidedata entries
221 entry-0014 size 64
223 entry-0014 size 64
222 '\x00\x00\x00\x06\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x00\x07\x00\x00\x00\x05\x00\x00\x00\x01\x06\x00\x00\x00\x06\x00\x00\x00\x02adfghi'
224 '\x00\x00\x00\x06\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x00\x07\x00\x00\x00\x05\x00\x00\x00\x01\x06\x00\x00\x00\x06\x00\x00\x00\x02adfghi'
223 #endif
225 #endif
224
226
225 $ hg showcopies
227 $ hg showcopies
226 a -> g
228 a -> g
227 d -> h
229 d -> h
228 f -> i
230 f -> i
229
231
230 Test writing to both changeset and filelog
232 Test writing to both changeset and filelog
231
233
232 $ hg cp a j
234 $ hg cp a j
233 #if extra
235 #if extra
234 $ hg ci -m 'copy a to j' --config experimental.copies.write-to=compatibility
236 $ hg ci -m 'copy a to j' --config experimental.copies.write-to=compatibility
235 $ hg changesetcopies
237 $ hg changesetcopies
236 files: j
238 files: j
237 filesadded: 0
239 filesadded: 0
238 filesremoved:
240 filesremoved:
239
241
240 p1copies: 0\x00a (esc)
242 p1copies: 0\x00a (esc)
241 p2copies:
243 p2copies:
242 #else
244 #else
243 $ hg ci -m 'copy a to j'
245 $ hg ci -m 'copy a to j'
244 $ hg debugsidedata -c -v -- -1
246 $ hg debugsidedata -c -v -- -1
245 1 sidedata entries
247 1 sidedata entries
246 entry-0014 size 24
248 entry-0014 size 24
247 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj'
249 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj'
248 #endif
250 #endif
249 $ hg debugdata j 0
251 $ hg debugdata j 0
250 \x01 (esc)
252 \x01 (esc)
251 copy: a
253 copy: a
252 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
254 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
253 \x01 (esc)
255 \x01 (esc)
254 a
256 a
255 $ hg showcopies
257 $ hg showcopies
256 a -> j
258 a -> j
257 $ hg showcopies --config experimental.copies.read-from=compatibility
259 $ hg showcopies --config experimental.copies.read-from=compatibility
258 a -> j
260 a -> j
259 $ hg showcopies --config experimental.copies.read-from=filelog-only
261 $ hg showcopies --config experimental.copies.read-from=filelog-only
260 a -> j
262 a -> j
261 Existing copy information in the changeset gets removed on amend and writing
263 Existing copy information in the changeset gets removed on amend and writing
262 copy information on to the filelog
264 copy information on to the filelog
263 #if extra
265 #if extra
264 $ hg ci --amend -m 'copy a to j, v2' \
266 $ hg ci --amend -m 'copy a to j, v2' \
265 > --config experimental.copies.write-to=filelog-only
267 > --config experimental.copies.write-to=filelog-only
266 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
268 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
267 $ hg changesetcopies
269 $ hg changesetcopies
268 files: j
270 files: j
269
271
270 #else
272 #else
271 $ hg ci --amend -m 'copy a to j, v2'
273 $ hg ci --amend -m 'copy a to j, v2'
272 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
274 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
273 $ hg debugsidedata -c -v -- -1
275 $ hg debugsidedata -c -v -- -1
274 1 sidedata entries
276 1 sidedata entries
275 entry-0014 size 24
277 entry-0014 size 24
276 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj'
278 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj'
277 #endif
279 #endif
278 $ hg showcopies --config experimental.copies.read-from=filelog-only
280 $ hg showcopies --config experimental.copies.read-from=filelog-only
279 a -> j
281 a -> j
280 The entries should be written to extras even if they're empty (so the client
282 The entries should be written to extras even if they're empty (so the client
281 won't have to fall back to reading from filelogs)
283 won't have to fall back to reading from filelogs)
282 $ echo x >> j
284 $ echo x >> j
283 #if extra
285 #if extra
284 $ hg ci -m 'modify j' --config experimental.copies.write-to=compatibility
286 $ hg ci -m 'modify j' --config experimental.copies.write-to=compatibility
285 $ hg changesetcopies
287 $ hg changesetcopies
286 files: j
288 files: j
287 filesadded:
289 filesadded:
288 filesremoved:
290 filesremoved:
289
291
290 p1copies:
292 p1copies:
291 p2copies:
293 p2copies:
292 #else
294 #else
293 $ hg ci -m 'modify j'
295 $ hg ci -m 'modify j'
294 $ hg debugsidedata -c -v -- -1
296 $ hg debugsidedata -c -v -- -1
295 1 sidedata entries
297 1 sidedata entries
296 entry-0014 size 14
298 entry-0014 size 14
297 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00j'
299 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00j'
298 #endif
300 #endif
299
301
300 Test writing only to filelog
302 Test writing only to filelog
301
303
302 $ hg cp a k
304 $ hg cp a k
303 #if extra
305 #if extra
304 $ hg ci -m 'copy a to k' --config experimental.copies.write-to=filelog-only
306 $ hg ci -m 'copy a to k' --config experimental.copies.write-to=filelog-only
305
307
306 $ hg changesetcopies
308 $ hg changesetcopies
307 files: k
309 files: k
308
310
309 #else
311 #else
310 $ hg ci -m 'copy a to k'
312 $ hg ci -m 'copy a to k'
311 $ hg debugsidedata -c -v -- -1
313 $ hg debugsidedata -c -v -- -1
312 1 sidedata entries
314 1 sidedata entries
313 entry-0014 size 24
315 entry-0014 size 24
314 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00ak'
316 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00ak'
315 #endif
317 #endif
316
318
317 $ hg debugdata k 0
319 $ hg debugdata k 0
318 \x01 (esc)
320 \x01 (esc)
319 copy: a
321 copy: a
320 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
322 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
321 \x01 (esc)
323 \x01 (esc)
322 a
324 a
323 #if extra
325 #if extra
324 $ hg showcopies
326 $ hg showcopies
325
327
326 $ hg showcopies --config experimental.copies.read-from=compatibility
328 $ hg showcopies --config experimental.copies.read-from=compatibility
327 a -> k
329 a -> k
328 $ hg showcopies --config experimental.copies.read-from=filelog-only
330 $ hg showcopies --config experimental.copies.read-from=filelog-only
329 a -> k
331 a -> k
330 #else
332 #else
331 $ hg showcopies
333 $ hg showcopies
332 a -> k
334 a -> k
333 #endif
335 #endif
334
336
335 $ cd ..
337 $ cd ..
336
338
337 Test rebasing a commit with copy information
339 Test rebasing a commit with copy information
338
340
339 $ hg init rebase-rename
341 $ hg init rebase-rename
340 $ cd rebase-rename
342 $ cd rebase-rename
341 $ echo a > a
343 $ echo a > a
342 $ hg ci -Aqm 'add a'
344 $ hg ci -Aqm 'add a'
343 $ echo a2 > a
345 $ echo a2 > a
344 $ hg ci -m 'modify a'
346 $ hg ci -m 'modify a'
345 $ hg co -q 0
347 $ hg co -q 0
346 $ hg mv a b
348 $ hg mv a b
347 $ hg ci -qm 'rename a to b'
349 $ hg ci -qm 'rename a to b'
348 Not only do we want this to run in-memory, it shouldn't fall back to
350 Not only do we want this to run in-memory, it shouldn't fall back to
349 on-disk merge (no conflicts), so we force it to be in-memory
351 on-disk merge (no conflicts), so we force it to be in-memory
350 with no fallback.
352 with no fallback.
351 $ hg rebase -d 1 --config rebase.experimental.inmemory=yes --config devel.rebase.force-in-memory-merge=yes
353 $ hg rebase -d 1 --config rebase.experimental.inmemory=yes --config devel.rebase.force-in-memory-merge=yes
352 rebasing 2:* tip "rename a to b" (glob)
354 rebasing 2:* tip "rename a to b" (glob)
353 merging a and b to b
355 merging a and b to b
354 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob)
356 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob)
355 $ hg st --change . --copies
357 $ hg st --change . --copies
356 A b
358 A b
357 a
359 a
358 R a
360 R a
359 $ cd ..
361 $ cd ..
360
362
361 Test splitting a commit
363 Test splitting a commit
362
364
363 $ hg init split
365 $ hg init split
364 $ cd split
366 $ cd split
365 $ echo a > a
367 $ echo a > a
366 $ echo b > b
368 $ echo b > b
367 $ hg ci -Aqm 'add a and b'
369 $ hg ci -Aqm 'add a and b'
368 $ echo a2 > a
370 $ echo a2 > a
369 $ hg mv b c
371 $ hg mv b c
370 $ hg ci -m 'modify a, move b to c'
372 $ hg ci -m 'modify a, move b to c'
371 $ hg --config ui.interactive=yes split <<EOF
373 $ hg --config ui.interactive=yes split <<EOF
372 > y
374 > y
373 > y
375 > y
374 > n
376 > n
375 > y
377 > y
376 > EOF
378 > EOF
377 diff --git a/a b/a
379 diff --git a/a b/a
378 1 hunks, 1 lines changed
380 1 hunks, 1 lines changed
379 examine changes to 'a'?
381 examine changes to 'a'?
380 (enter ? for help) [Ynesfdaq?] y
382 (enter ? for help) [Ynesfdaq?] y
381
383
382 @@ -1,1 +1,1 @@
384 @@ -1,1 +1,1 @@
383 -a
385 -a
384 +a2
386 +a2
385 record this change to 'a'?
387 record this change to 'a'?
386 (enter ? for help) [Ynesfdaq?] y
388 (enter ? for help) [Ynesfdaq?] y
387
389
388 diff --git a/b b/c
390 diff --git a/b b/c
389 rename from b
391 rename from b
390 rename to c
392 rename to c
391 examine changes to 'b' and 'c'?
393 examine changes to 'b' and 'c'?
392 (enter ? for help) [Ynesfdaq?] n
394 (enter ? for help) [Ynesfdaq?] n
393
395
394 created new head
396 created new head
395 diff --git a/b b/c
397 diff --git a/b b/c
396 rename from b
398 rename from b
397 rename to c
399 rename to c
398 examine changes to 'b' and 'c'?
400 examine changes to 'b' and 'c'?
399 (enter ? for help) [Ynesfdaq?] y
401 (enter ? for help) [Ynesfdaq?] y
400
402
401 saved backup bundle to $TESTTMP/split/.hg/strip-backup/*-*-split.hg (glob)
403 saved backup bundle to $TESTTMP/split/.hg/strip-backup/*-*-split.hg (glob)
402 $ cd ..
404 $ cd ..
403
405
404 Test committing half a rename
406 Test committing half a rename
405
407
406 $ hg init partial
408 $ hg init partial
407 $ cd partial
409 $ cd partial
408 $ echo a > a
410 $ echo a > a
409 $ hg ci -Aqm 'add a'
411 $ hg ci -Aqm 'add a'
410 $ hg mv a b
412 $ hg mv a b
411 $ hg ci -m 'remove a' a
413 $ hg ci -m 'remove a' a
412
414
413 #if sidedata
415 #if sidedata
414
416
415 Test upgrading/downgrading to sidedata storage
417 Test upgrading/downgrading to sidedata storage
416 ==============================================
418 ==============================================
417
419
418 downgrading (keeping some sidedata)
420 downgrading (keeping some sidedata)
419
421
420 $ hg debugformat -v
422 $ hg debugformat -v
421 format-variant repo config default
423 format-variant repo config default
422 fncache: yes yes yes
424 fncache: yes yes yes
423 dotencode: yes yes yes
425 dotencode: yes yes yes
424 generaldelta: yes yes yes
426 generaldelta: yes yes yes
425 share-safe: no no no
427 share-safe: no no no
426 sparserevlog: yes yes yes
428 sparserevlog: yes yes yes
427 sidedata: yes yes no
429 sidedata: yes yes no
428 persistent-nodemap: no no no
430 persistent-nodemap: no no no
429 copies-sdc: yes yes no
431 copies-sdc: yes yes no
432 revlog-v2: yes yes no
430 plain-cl-delta: yes yes yes
433 plain-cl-delta: yes yes yes
431 compression: zlib zlib zlib
434 compression: zlib zlib zlib
432 compression-level: default default default
435 compression-level: default default default
433 $ hg debugsidedata -c -- 0
436 $ hg debugsidedata -c -- 0
434 1 sidedata entries
437 1 sidedata entries
435 entry-0014 size 14
438 entry-0014 size 14
436 $ hg debugsidedata -c -- 1
439 $ hg debugsidedata -c -- 1
437 1 sidedata entries
440 1 sidedata entries
438 entry-0014 size 14
441 entry-0014 size 14
439 $ hg debugsidedata -m -- 0
442 $ hg debugsidedata -m -- 0
440 $ cat << EOF > .hg/hgrc
443 $ cat << EOF > .hg/hgrc
441 > [format]
444 > [format]
442 > exp-use-side-data = yes
445 > exp-use-side-data = yes
443 > exp-use-copies-side-data-changeset = no
446 > exp-use-copies-side-data-changeset = no
444 > EOF
447 > EOF
445 $ hg debugupgraderepo --run --quiet --no-backup > /dev/null
448 $ hg debugupgraderepo --run --quiet --no-backup > /dev/null
446 $ hg debugformat -v
449 $ hg debugformat -v
447 format-variant repo config default
450 format-variant repo config default
448 fncache: yes yes yes
451 fncache: yes yes yes
449 dotencode: yes yes yes
452 dotencode: yes yes yes
450 generaldelta: yes yes yes
453 generaldelta: yes yes yes
451 share-safe: no no no
454 share-safe: no no no
452 sparserevlog: yes yes yes
455 sparserevlog: yes yes yes
453 sidedata: yes yes no
456 sidedata: yes yes no
454 persistent-nodemap: no no no
457 persistent-nodemap: no no no
455 copies-sdc: no no no
458 copies-sdc: no no no
459 revlog-v2: yes yes no
456 plain-cl-delta: yes yes yes
460 plain-cl-delta: yes yes yes
457 compression: zlib zlib zlib
461 compression: zlib zlib zlib
458 compression-level: default default default
462 compression-level: default default default
459 $ hg debugsidedata -c -- 0
463 $ hg debugsidedata -c -- 0
460 1 sidedata entries
464 1 sidedata entries
461 entry-0014 size 14
465 entry-0014 size 14
462 $ hg debugsidedata -c -- 1
466 $ hg debugsidedata -c -- 1
463 1 sidedata entries
467 1 sidedata entries
464 entry-0014 size 14
468 entry-0014 size 14
465 $ hg debugsidedata -m -- 0
469 $ hg debugsidedata -m -- 0
466
470
467 upgrading
471 upgrading
468
472
469 $ cat << EOF > .hg/hgrc
473 $ cat << EOF > .hg/hgrc
470 > [format]
474 > [format]
471 > exp-use-copies-side-data-changeset = yes
475 > exp-use-copies-side-data-changeset = yes
472 > EOF
476 > EOF
473 $ hg debugupgraderepo --run --quiet --no-backup > /dev/null
477 $ hg debugupgraderepo --run --quiet --no-backup > /dev/null
474 $ hg debugformat -v
478 $ hg debugformat -v
475 format-variant repo config default
479 format-variant repo config default
476 fncache: yes yes yes
480 fncache: yes yes yes
477 dotencode: yes yes yes
481 dotencode: yes yes yes
478 generaldelta: yes yes yes
482 generaldelta: yes yes yes
479 share-safe: no no no
483 share-safe: no no no
480 sparserevlog: yes yes yes
484 sparserevlog: yes yes yes
481 sidedata: yes yes no
485 sidedata: yes yes no
482 persistent-nodemap: no no no
486 persistent-nodemap: no no no
483 copies-sdc: yes yes no
487 copies-sdc: yes yes no
488 revlog-v2: yes yes no
484 plain-cl-delta: yes yes yes
489 plain-cl-delta: yes yes yes
485 compression: zlib zlib zlib
490 compression: zlib zlib zlib
486 compression-level: default default default
491 compression-level: default default default
487 $ hg debugsidedata -c -- 0
492 $ hg debugsidedata -c -- 0
488 1 sidedata entries
493 1 sidedata entries
489 entry-0014 size 14
494 entry-0014 size 14
490 $ hg debugsidedata -c -- 1
495 $ hg debugsidedata -c -- 1
491 1 sidedata entries
496 1 sidedata entries
492 entry-0014 size 14
497 entry-0014 size 14
493 $ hg debugsidedata -m -- 0
498 $ hg debugsidedata -m -- 0
494
499
495 #endif
500 #endif
496
501
497 $ cd ..
502 $ cd ..
@@ -1,764 +1,767 b''
1 ===================================
1 ===================================
2 Test the persistent on-disk nodemap
2 Test the persistent on-disk nodemap
3 ===================================
3 ===================================
4
4
5 $ cat << EOF >> $HGRCPATH
5 $ cat << EOF >> $HGRCPATH
6 > [format]
6 > [format]
7 > use-persistent-nodemap=yes
7 > use-persistent-nodemap=yes
8 > [devel]
8 > [devel]
9 > persistent-nodemap=yes
9 > persistent-nodemap=yes
10 > EOF
10 > EOF
11
11
12 $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow
12 $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow
13 $ cd test-repo
13 $ cd test-repo
14
14
15 Check handling of the default slow-path value
15 Check handling of the default slow-path value
16
16
17 #if no-pure no-rust
17 #if no-pure no-rust
18
18
19 $ hg id
19 $ hg id
20 abort: accessing `persistent-nodemap` repository without associated fast implementation.
20 abort: accessing `persistent-nodemap` repository without associated fast implementation.
21 (check `hg help config.format.use-persistent-nodemap` for details)
21 (check `hg help config.format.use-persistent-nodemap` for details)
22 [255]
22 [255]
23
23
24 Unlock further check (we are here to test the feature)
24 Unlock further check (we are here to test the feature)
25
25
26 $ cat << EOF >> $HGRCPATH
26 $ cat << EOF >> $HGRCPATH
27 > [storage]
27 > [storage]
28 > # to avoid spamming the test
28 > # to avoid spamming the test
29 > revlog.persistent-nodemap.slow-path=allow
29 > revlog.persistent-nodemap.slow-path=allow
30 > EOF
30 > EOF
31
31
32 #endif
32 #endif
33
33
34 #if rust
34 #if rust
35
35
36 Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule:
36 Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule:
37 in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t`
37 in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t`
38 (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs`
38 (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs`
39 incorrectly used `libc::c_int` (32 bits).
39 incorrectly used `libc::c_int` (32 bits).
40 As a result, -1 passed from Rust for the null revision became 4294967295 in C.
40 As a result, -1 passed from Rust for the null revision became 4294967295 in C.
41
41
42 $ hg log -r 00000000
42 $ hg log -r 00000000
43 changeset: -1:000000000000
43 changeset: -1:000000000000
44 tag: tip
44 tag: tip
45 user:
45 user:
46 date: Thu Jan 01 00:00:00 1970 +0000
46 date: Thu Jan 01 00:00:00 1970 +0000
47
47
48
48
49 #endif
49 #endif
50
50
51
51
52 $ hg debugformat
52 $ hg debugformat
53 format-variant repo
53 format-variant repo
54 fncache: yes
54 fncache: yes
55 dotencode: yes
55 dotencode: yes
56 generaldelta: yes
56 generaldelta: yes
57 share-safe: no
57 share-safe: no
58 sparserevlog: yes
58 sparserevlog: yes
59 sidedata: no
59 sidedata: no
60 persistent-nodemap: yes
60 persistent-nodemap: yes
61 copies-sdc: no
61 copies-sdc: no
62 revlog-v2: no
62 plain-cl-delta: yes
63 plain-cl-delta: yes
63 compression: zlib
64 compression: zlib
64 compression-level: default
65 compression-level: default
65 $ hg debugbuilddag .+5000 --new-file
66 $ hg debugbuilddag .+5000 --new-file
66
67
67 $ hg debugnodemap --metadata
68 $ hg debugnodemap --metadata
68 uid: ???????????????? (glob)
69 uid: ???????????????? (glob)
69 tip-rev: 5000
70 tip-rev: 5000
70 tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c
71 tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c
71 data-length: 121088
72 data-length: 121088
72 data-unused: 0
73 data-unused: 0
73 data-unused: 0.000%
74 data-unused: 0.000%
74 $ f --size .hg/store/00changelog.n
75 $ f --size .hg/store/00changelog.n
75 .hg/store/00changelog.n: size=70
76 .hg/store/00changelog.n: size=70
76
77
77 Simple lookup works
78 Simple lookup works
78
79
79 $ ANYNODE=`hg log --template '{node|short}\n' --rev tip`
80 $ ANYNODE=`hg log --template '{node|short}\n' --rev tip`
80 $ hg log -r "$ANYNODE" --template '{rev}\n'
81 $ hg log -r "$ANYNODE" --template '{rev}\n'
81 5000
82 5000
82
83
83
84
84 #if rust
85 #if rust
85
86
86 $ f --sha256 .hg/store/00changelog-*.nd
87 $ f --sha256 .hg/store/00changelog-*.nd
87 .hg/store/00changelog-????????????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob)
88 .hg/store/00changelog-????????????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob)
88
89
89 $ f --sha256 .hg/store/00manifest-*.nd
90 $ f --sha256 .hg/store/00manifest-*.nd
90 .hg/store/00manifest-????????????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob)
91 .hg/store/00manifest-????????????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob)
91 $ hg debugnodemap --dump-new | f --sha256 --size
92 $ hg debugnodemap --dump-new | f --sha256 --size
92 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
93 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
93 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
94 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
94 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
95 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
95 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........|
96 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........|
96 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."|
97 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."|
97 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^|
98 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^|
98 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....|
99 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....|
99 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8|
100 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8|
100 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i|
101 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i|
101 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....|
102 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....|
102 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........|
103 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........|
103 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....|
104 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....|
104 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................|
105 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................|
105 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+|
106 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+|
106 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................|
107 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................|
107 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5|
108 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5|
108 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U|
109 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U|
109 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................|
110 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................|
110 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................|
111 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................|
111
112
112
113
113 #else
114 #else
114
115
115 $ f --sha256 .hg/store/00changelog-*.nd
116 $ f --sha256 .hg/store/00changelog-*.nd
116 .hg/store/00changelog-????????????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob)
117 .hg/store/00changelog-????????????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob)
117 $ hg debugnodemap --dump-new | f --sha256 --size
118 $ hg debugnodemap --dump-new | f --sha256 --size
118 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
119 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
119 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
120 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
120 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
121 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
121 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
122 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
122 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
123 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
123 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................|
124 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................|
124 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................|
125 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................|
125 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
126 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
126 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................|
127 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................|
127 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............|
128 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............|
128 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
129 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
129 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
130 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
130 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................|
131 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................|
131 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........|
132 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........|
132 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
133 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
133 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
134 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
134 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
135 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
135 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................|
136 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................|
136 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................|
137 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................|
137
138
138 #endif
139 #endif
139
140
140 $ hg debugnodemap --check
141 $ hg debugnodemap --check
141 revision in index: 5001
142 revision in index: 5001
142 revision in nodemap: 5001
143 revision in nodemap: 5001
143
144
144 add a new commit
145 add a new commit
145
146
146 $ hg up
147 $ hg up
147 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
148 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
148 $ echo foo > foo
149 $ echo foo > foo
149 $ hg add foo
150 $ hg add foo
150
151
151
152
152 Check slow-path config value handling
153 Check slow-path config value handling
153 -------------------------------------
154 -------------------------------------
154
155
155 #if no-pure no-rust
156 #if no-pure no-rust
156
157
157 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
158 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
158 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
159 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
159 falling back to default value: abort
160 falling back to default value: abort
160 abort: accessing `persistent-nodemap` repository without associated fast implementation.
161 abort: accessing `persistent-nodemap` repository without associated fast implementation.
161 (check `hg help config.format.use-persistent-nodemap` for details)
162 (check `hg help config.format.use-persistent-nodemap` for details)
162 [255]
163 [255]
163
164
164 $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn"
165 $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn"
165 warning: accessing `persistent-nodemap` repository without associated fast implementation.
166 warning: accessing `persistent-nodemap` repository without associated fast implementation.
166 (check `hg help config.format.use-persistent-nodemap` for details)
167 (check `hg help config.format.use-persistent-nodemap` for details)
167 changeset: 5000:6b02b8c7b966
168 changeset: 5000:6b02b8c7b966
168 tag: tip
169 tag: tip
169 user: debugbuilddag
170 user: debugbuilddag
170 date: Thu Jan 01 01:23:20 1970 +0000
171 date: Thu Jan 01 01:23:20 1970 +0000
171 summary: r5000
172 summary: r5000
172
173
173 $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort"
174 $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort"
174 abort: accessing `persistent-nodemap` repository without associated fast implementation.
175 abort: accessing `persistent-nodemap` repository without associated fast implementation.
175 (check `hg help config.format.use-persistent-nodemap` for details)
176 (check `hg help config.format.use-persistent-nodemap` for details)
176 [255]
177 [255]
177
178
178 #else
179 #else
179
180
180 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
181 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
181 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
182 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
182 falling back to default value: abort
183 falling back to default value: abort
183 6b02b8c7b966+ tip
184 6b02b8c7b966+ tip
184
185
185 #endif
186 #endif
186
187
187 $ hg ci -m 'foo'
188 $ hg ci -m 'foo'
188
189
189 #if no-pure no-rust
190 #if no-pure no-rust
190 $ hg debugnodemap --metadata
191 $ hg debugnodemap --metadata
191 uid: ???????????????? (glob)
192 uid: ???????????????? (glob)
192 tip-rev: 5001
193 tip-rev: 5001
193 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
194 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
194 data-length: 121088
195 data-length: 121088
195 data-unused: 0
196 data-unused: 0
196 data-unused: 0.000%
197 data-unused: 0.000%
197 #else
198 #else
198 $ hg debugnodemap --metadata
199 $ hg debugnodemap --metadata
199 uid: ???????????????? (glob)
200 uid: ???????????????? (glob)
200 tip-rev: 5001
201 tip-rev: 5001
201 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
202 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
202 data-length: 121344
203 data-length: 121344
203 data-unused: 256
204 data-unused: 256
204 data-unused: 0.211%
205 data-unused: 0.211%
205 #endif
206 #endif
206
207
207 $ f --size .hg/store/00changelog.n
208 $ f --size .hg/store/00changelog.n
208 .hg/store/00changelog.n: size=70
209 .hg/store/00changelog.n: size=70
209
210
210 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)
211 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)
211
212
212 #if pure
213 #if pure
213 $ f --sha256 .hg/store/00changelog-*.nd --size
214 $ f --sha256 .hg/store/00changelog-*.nd --size
214 .hg/store/00changelog-????????????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob)
215 .hg/store/00changelog-????????????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob)
215 #endif
216 #endif
216
217
217 #if rust
218 #if rust
218 $ f --sha256 .hg/store/00changelog-*.nd --size
219 $ f --sha256 .hg/store/00changelog-*.nd --size
219 .hg/store/00changelog-????????????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob)
220 .hg/store/00changelog-????????????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob)
220 #endif
221 #endif
221
222
222 #if no-pure no-rust
223 #if no-pure no-rust
223 $ f --sha256 .hg/store/00changelog-*.nd --size
224 $ f --sha256 .hg/store/00changelog-*.nd --size
224 .hg/store/00changelog-????????????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob)
225 .hg/store/00changelog-????????????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob)
225 #endif
226 #endif
226
227
227 $ hg debugnodemap --check
228 $ hg debugnodemap --check
228 revision in index: 5002
229 revision in index: 5002
229 revision in nodemap: 5002
230 revision in nodemap: 5002
230
231
231 Test code path without mmap
232 Test code path without mmap
232 ---------------------------
233 ---------------------------
233
234
234 $ echo bar > bar
235 $ echo bar > bar
235 $ hg add bar
236 $ hg add bar
236 $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no
237 $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no
237
238
238 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes
239 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes
239 revision in index: 5003
240 revision in index: 5003
240 revision in nodemap: 5003
241 revision in nodemap: 5003
241 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no
242 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no
242 revision in index: 5003
243 revision in index: 5003
243 revision in nodemap: 5003
244 revision in nodemap: 5003
244
245
245
246
246 #if pure
247 #if pure
247 $ hg debugnodemap --metadata
248 $ hg debugnodemap --metadata
248 uid: ???????????????? (glob)
249 uid: ???????????????? (glob)
249 tip-rev: 5002
250 tip-rev: 5002
250 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
251 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
251 data-length: 121600
252 data-length: 121600
252 data-unused: 512
253 data-unused: 512
253 data-unused: 0.421%
254 data-unused: 0.421%
254 $ f --sha256 .hg/store/00changelog-*.nd --size
255 $ f --sha256 .hg/store/00changelog-*.nd --size
255 .hg/store/00changelog-????????????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob)
256 .hg/store/00changelog-????????????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob)
256 #endif
257 #endif
257 #if rust
258 #if rust
258 $ hg debugnodemap --metadata
259 $ hg debugnodemap --metadata
259 uid: ???????????????? (glob)
260 uid: ???????????????? (glob)
260 tip-rev: 5002
261 tip-rev: 5002
261 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
262 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
262 data-length: 121600
263 data-length: 121600
263 data-unused: 512
264 data-unused: 512
264 data-unused: 0.421%
265 data-unused: 0.421%
265 $ f --sha256 .hg/store/00changelog-*.nd --size
266 $ f --sha256 .hg/store/00changelog-*.nd --size
266 .hg/store/00changelog-????????????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob)
267 .hg/store/00changelog-????????????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob)
267 #endif
268 #endif
268 #if no-pure no-rust
269 #if no-pure no-rust
269 $ hg debugnodemap --metadata
270 $ hg debugnodemap --metadata
270 uid: ???????????????? (glob)
271 uid: ???????????????? (glob)
271 tip-rev: 5002
272 tip-rev: 5002
272 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
273 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
273 data-length: 121088
274 data-length: 121088
274 data-unused: 0
275 data-unused: 0
275 data-unused: 0.000%
276 data-unused: 0.000%
276 $ f --sha256 .hg/store/00changelog-*.nd --size
277 $ f --sha256 .hg/store/00changelog-*.nd --size
277 .hg/store/00changelog-????????????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob)
278 .hg/store/00changelog-????????????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob)
278 #endif
279 #endif
279
280
280 Test force warming the cache
281 Test force warming the cache
281
282
282 $ rm .hg/store/00changelog.n
283 $ rm .hg/store/00changelog.n
283 $ hg debugnodemap --metadata
284 $ hg debugnodemap --metadata
284 $ hg debugupdatecache
285 $ hg debugupdatecache
285 #if pure
286 #if pure
286 $ hg debugnodemap --metadata
287 $ hg debugnodemap --metadata
287 uid: ???????????????? (glob)
288 uid: ???????????????? (glob)
288 tip-rev: 5002
289 tip-rev: 5002
289 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
290 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
290 data-length: 121088
291 data-length: 121088
291 data-unused: 0
292 data-unused: 0
292 data-unused: 0.000%
293 data-unused: 0.000%
293 #else
294 #else
294 $ hg debugnodemap --metadata
295 $ hg debugnodemap --metadata
295 uid: ???????????????? (glob)
296 uid: ???????????????? (glob)
296 tip-rev: 5002
297 tip-rev: 5002
297 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
298 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
298 data-length: 121088
299 data-length: 121088
299 data-unused: 0
300 data-unused: 0
300 data-unused: 0.000%
301 data-unused: 0.000%
301 #endif
302 #endif
302
303
303 Check out of sync nodemap
304 Check out of sync nodemap
304 =========================
305 =========================
305
306
306 First copy old data on the side.
307 First copy old data on the side.
307
308
308 $ mkdir ../tmp-copies
309 $ mkdir ../tmp-copies
309 $ cp .hg/store/00changelog-????????????????.nd .hg/store/00changelog.n ../tmp-copies
310 $ cp .hg/store/00changelog-????????????????.nd .hg/store/00changelog.n ../tmp-copies
310
311
311 Nodemap lagging behind
312 Nodemap lagging behind
312 ----------------------
313 ----------------------
313
314
314 make a new commit
315 make a new commit
315
316
316 $ echo bar2 > bar
317 $ echo bar2 > bar
317 $ hg ci -m 'bar2'
318 $ hg ci -m 'bar2'
318 $ NODE=`hg log -r tip -T '{node}\n'`
319 $ NODE=`hg log -r tip -T '{node}\n'`
319 $ hg log -r "$NODE" -T '{rev}\n'
320 $ hg log -r "$NODE" -T '{rev}\n'
320 5003
321 5003
321
322
322 If the nodemap is lagging behind, it can catch up fine
323 If the nodemap is lagging behind, it can catch up fine
323
324
324 $ hg debugnodemap --metadata
325 $ hg debugnodemap --metadata
325 uid: ???????????????? (glob)
326 uid: ???????????????? (glob)
326 tip-rev: 5003
327 tip-rev: 5003
327 tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3
328 tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3
328 data-length: 121344 (pure !)
329 data-length: 121344 (pure !)
329 data-length: 121344 (rust !)
330 data-length: 121344 (rust !)
330 data-length: 121152 (no-rust no-pure !)
331 data-length: 121152 (no-rust no-pure !)
331 data-unused: 192 (pure !)
332 data-unused: 192 (pure !)
332 data-unused: 192 (rust !)
333 data-unused: 192 (rust !)
333 data-unused: 0 (no-rust no-pure !)
334 data-unused: 0 (no-rust no-pure !)
334 data-unused: 0.158% (pure !)
335 data-unused: 0.158% (pure !)
335 data-unused: 0.158% (rust !)
336 data-unused: 0.158% (rust !)
336 data-unused: 0.000% (no-rust no-pure !)
337 data-unused: 0.000% (no-rust no-pure !)
337 $ cp -f ../tmp-copies/* .hg/store/
338 $ cp -f ../tmp-copies/* .hg/store/
338 $ hg debugnodemap --metadata
339 $ hg debugnodemap --metadata
339 uid: ???????????????? (glob)
340 uid: ???????????????? (glob)
340 tip-rev: 5002
341 tip-rev: 5002
341 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
342 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
342 data-length: 121088
343 data-length: 121088
343 data-unused: 0
344 data-unused: 0
344 data-unused: 0.000%
345 data-unused: 0.000%
345 $ hg log -r "$NODE" -T '{rev}\n'
346 $ hg log -r "$NODE" -T '{rev}\n'
346 5003
347 5003
347
348
348 changelog altered
349 changelog altered
349 -----------------
350 -----------------
350
351
351 If the nodemap is not gated behind a requirements, an unaware client can alter
352 If the nodemap is not gated behind a requirements, an unaware client can alter
352 the repository so the revlog used to generate the nodemap is not longer
353 the repository so the revlog used to generate the nodemap is not longer
353 compatible with the persistent nodemap. We need to detect that.
354 compatible with the persistent nodemap. We need to detect that.
354
355
355 $ hg up "$NODE~5"
356 $ hg up "$NODE~5"
356 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
357 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
357 $ echo bar > babar
358 $ echo bar > babar
358 $ hg add babar
359 $ hg add babar
359 $ hg ci -m 'babar'
360 $ hg ci -m 'babar'
360 created new head
361 created new head
361 $ OTHERNODE=`hg log -r tip -T '{node}\n'`
362 $ OTHERNODE=`hg log -r tip -T '{node}\n'`
362 $ hg log -r "$OTHERNODE" -T '{rev}\n'
363 $ hg log -r "$OTHERNODE" -T '{rev}\n'
363 5004
364 5004
364
365
365 $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
366 $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
366
367
367 the nodemap should detect the changelog have been tampered with and recover.
368 the nodemap should detect the changelog have been tampered with and recover.
368
369
369 $ hg debugnodemap --metadata
370 $ hg debugnodemap --metadata
370 uid: ???????????????? (glob)
371 uid: ???????????????? (glob)
371 tip-rev: 5002
372 tip-rev: 5002
372 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
373 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
373 data-length: 121536 (pure !)
374 data-length: 121536 (pure !)
374 data-length: 121088 (rust !)
375 data-length: 121088 (rust !)
375 data-length: 121088 (no-pure no-rust !)
376 data-length: 121088 (no-pure no-rust !)
376 data-unused: 448 (pure !)
377 data-unused: 448 (pure !)
377 data-unused: 0 (rust !)
378 data-unused: 0 (rust !)
378 data-unused: 0 (no-pure no-rust !)
379 data-unused: 0 (no-pure no-rust !)
379 data-unused: 0.000% (rust !)
380 data-unused: 0.000% (rust !)
380 data-unused: 0.369% (pure !)
381 data-unused: 0.369% (pure !)
381 data-unused: 0.000% (no-pure no-rust !)
382 data-unused: 0.000% (no-pure no-rust !)
382
383
383 $ cp -f ../tmp-copies/* .hg/store/
384 $ cp -f ../tmp-copies/* .hg/store/
384 $ hg debugnodemap --metadata
385 $ hg debugnodemap --metadata
385 uid: ???????????????? (glob)
386 uid: ???????????????? (glob)
386 tip-rev: 5002
387 tip-rev: 5002
387 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
388 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
388 data-length: 121088
389 data-length: 121088
389 data-unused: 0
390 data-unused: 0
390 data-unused: 0.000%
391 data-unused: 0.000%
391 $ hg log -r "$OTHERNODE" -T '{rev}\n'
392 $ hg log -r "$OTHERNODE" -T '{rev}\n'
392 5002
393 5002
393
394
394 missing data file
395 missing data file
395 -----------------
396 -----------------
396
397
397 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
398 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
398 > sed 's/uid: //'`
399 > sed 's/uid: //'`
399 $ FILE=.hg/store/00changelog-"${UUID}".nd
400 $ FILE=.hg/store/00changelog-"${UUID}".nd
400 $ mv $FILE ../tmp-data-file
401 $ mv $FILE ../tmp-data-file
401 $ cp .hg/store/00changelog.n ../tmp-docket
402 $ cp .hg/store/00changelog.n ../tmp-docket
402
403
403 mercurial don't crash
404 mercurial don't crash
404
405
405 $ hg log -r .
406 $ hg log -r .
406 changeset: 5002:b355ef8adce0
407 changeset: 5002:b355ef8adce0
407 tag: tip
408 tag: tip
408 parent: 4998:d918ad6d18d3
409 parent: 4998:d918ad6d18d3
409 user: test
410 user: test
410 date: Thu Jan 01 00:00:00 1970 +0000
411 date: Thu Jan 01 00:00:00 1970 +0000
411 summary: babar
412 summary: babar
412
413
413 $ hg debugnodemap --metadata
414 $ hg debugnodemap --metadata
414
415
415 $ hg debugupdatecache
416 $ hg debugupdatecache
416 $ hg debugnodemap --metadata
417 $ hg debugnodemap --metadata
417 uid: * (glob)
418 uid: * (glob)
418 tip-rev: 5002
419 tip-rev: 5002
419 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
420 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
420 data-length: 121088
421 data-length: 121088
421 data-unused: 0
422 data-unused: 0
422 data-unused: 0.000%
423 data-unused: 0.000%
423 $ mv ../tmp-data-file $FILE
424 $ mv ../tmp-data-file $FILE
424 $ mv ../tmp-docket .hg/store/00changelog.n
425 $ mv ../tmp-docket .hg/store/00changelog.n
425
426
426 Check transaction related property
427 Check transaction related property
427 ==================================
428 ==================================
428
429
429 An up to date nodemap should be available to shell hooks,
430 An up to date nodemap should be available to shell hooks,
430
431
431 $ echo dsljfl > a
432 $ echo dsljfl > a
432 $ hg add a
433 $ hg add a
433 $ hg ci -m a
434 $ hg ci -m a
434 $ hg debugnodemap --metadata
435 $ hg debugnodemap --metadata
435 uid: ???????????????? (glob)
436 uid: ???????????????? (glob)
436 tip-rev: 5003
437 tip-rev: 5003
437 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
438 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
438 data-length: 121088
439 data-length: 121088
439 data-unused: 0
440 data-unused: 0
440 data-unused: 0.000%
441 data-unused: 0.000%
441 $ echo babar2 > babar
442 $ echo babar2 > babar
442 $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
443 $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
443 uid: ???????????????? (glob)
444 uid: ???????????????? (glob)
444 tip-rev: 5004
445 tip-rev: 5004
445 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
446 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
446 data-length: 121280 (pure !)
447 data-length: 121280 (pure !)
447 data-length: 121280 (rust !)
448 data-length: 121280 (rust !)
448 data-length: 121088 (no-pure no-rust !)
449 data-length: 121088 (no-pure no-rust !)
449 data-unused: 192 (pure !)
450 data-unused: 192 (pure !)
450 data-unused: 192 (rust !)
451 data-unused: 192 (rust !)
451 data-unused: 0 (no-pure no-rust !)
452 data-unused: 0 (no-pure no-rust !)
452 data-unused: 0.158% (pure !)
453 data-unused: 0.158% (pure !)
453 data-unused: 0.158% (rust !)
454 data-unused: 0.158% (rust !)
454 data-unused: 0.000% (no-pure no-rust !)
455 data-unused: 0.000% (no-pure no-rust !)
455 $ hg debugnodemap --metadata
456 $ hg debugnodemap --metadata
456 uid: ???????????????? (glob)
457 uid: ???????????????? (glob)
457 tip-rev: 5004
458 tip-rev: 5004
458 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
459 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
459 data-length: 121280 (pure !)
460 data-length: 121280 (pure !)
460 data-length: 121280 (rust !)
461 data-length: 121280 (rust !)
461 data-length: 121088 (no-pure no-rust !)
462 data-length: 121088 (no-pure no-rust !)
462 data-unused: 192 (pure !)
463 data-unused: 192 (pure !)
463 data-unused: 192 (rust !)
464 data-unused: 192 (rust !)
464 data-unused: 0 (no-pure no-rust !)
465 data-unused: 0 (no-pure no-rust !)
465 data-unused: 0.158% (pure !)
466 data-unused: 0.158% (pure !)
466 data-unused: 0.158% (rust !)
467 data-unused: 0.158% (rust !)
467 data-unused: 0.000% (no-pure no-rust !)
468 data-unused: 0.000% (no-pure no-rust !)
468
469
469 Another process does not see the pending nodemap content during run.
470 Another process does not see the pending nodemap content during run.
470
471
471 $ PATH=$RUNTESTDIR/testlib/:$PATH
472 $ PATH=$RUNTESTDIR/testlib/:$PATH
472 $ echo qpoasp > a
473 $ echo qpoasp > a
473 $ hg ci -m a2 \
474 $ hg ci -m a2 \
474 > --config "hooks.pretxnclose=wait-on-file 20 sync-repo-read sync-txn-pending" \
475 > --config "hooks.pretxnclose=wait-on-file 20 sync-repo-read sync-txn-pending" \
475 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
476 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
476
477
477 (read the repository while the commit transaction is pending)
478 (read the repository while the commit transaction is pending)
478
479
479 $ wait-on-file 20 sync-txn-pending && \
480 $ wait-on-file 20 sync-txn-pending && \
480 > hg debugnodemap --metadata && \
481 > hg debugnodemap --metadata && \
481 > wait-on-file 20 sync-txn-close sync-repo-read
482 > wait-on-file 20 sync-txn-close sync-repo-read
482 uid: ???????????????? (glob)
483 uid: ???????????????? (glob)
483 tip-rev: 5004
484 tip-rev: 5004
484 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
485 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
485 data-length: 121280 (pure !)
486 data-length: 121280 (pure !)
486 data-length: 121280 (rust !)
487 data-length: 121280 (rust !)
487 data-length: 121088 (no-pure no-rust !)
488 data-length: 121088 (no-pure no-rust !)
488 data-unused: 192 (pure !)
489 data-unused: 192 (pure !)
489 data-unused: 192 (rust !)
490 data-unused: 192 (rust !)
490 data-unused: 0 (no-pure no-rust !)
491 data-unused: 0 (no-pure no-rust !)
491 data-unused: 0.158% (pure !)
492 data-unused: 0.158% (pure !)
492 data-unused: 0.158% (rust !)
493 data-unused: 0.158% (rust !)
493 data-unused: 0.000% (no-pure no-rust !)
494 data-unused: 0.000% (no-pure no-rust !)
494 $ hg debugnodemap --metadata
495 $ hg debugnodemap --metadata
495 uid: ???????????????? (glob)
496 uid: ???????????????? (glob)
496 tip-rev: 5005
497 tip-rev: 5005
497 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
498 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
498 data-length: 121536 (pure !)
499 data-length: 121536 (pure !)
499 data-length: 121536 (rust !)
500 data-length: 121536 (rust !)
500 data-length: 121088 (no-pure no-rust !)
501 data-length: 121088 (no-pure no-rust !)
501 data-unused: 448 (pure !)
502 data-unused: 448 (pure !)
502 data-unused: 448 (rust !)
503 data-unused: 448 (rust !)
503 data-unused: 0 (no-pure no-rust !)
504 data-unused: 0 (no-pure no-rust !)
504 data-unused: 0.369% (pure !)
505 data-unused: 0.369% (pure !)
505 data-unused: 0.369% (rust !)
506 data-unused: 0.369% (rust !)
506 data-unused: 0.000% (no-pure no-rust !)
507 data-unused: 0.000% (no-pure no-rust !)
507
508
508 $ cat output.txt
509 $ cat output.txt
509
510
510 Check that a failing transaction will properly revert the data
511 Check that a failing transaction will properly revert the data
511
512
512 $ echo plakfe > a
513 $ echo plakfe > a
513 $ f --size --sha256 .hg/store/00changelog-*.nd
514 $ f --size --sha256 .hg/store/00changelog-*.nd
514 .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
515 .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
515 .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
516 .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
516 .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
517 .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
517 $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
518 $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
518 transaction abort!
519 transaction abort!
519 rollback completed
520 rollback completed
520 abort: This is a late abort
521 abort: This is a late abort
521 [255]
522 [255]
522 $ hg debugnodemap --metadata
523 $ hg debugnodemap --metadata
523 uid: ???????????????? (glob)
524 uid: ???????????????? (glob)
524 tip-rev: 5005
525 tip-rev: 5005
525 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
526 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
526 data-length: 121536 (pure !)
527 data-length: 121536 (pure !)
527 data-length: 121536 (rust !)
528 data-length: 121536 (rust !)
528 data-length: 121088 (no-pure no-rust !)
529 data-length: 121088 (no-pure no-rust !)
529 data-unused: 448 (pure !)
530 data-unused: 448 (pure !)
530 data-unused: 448 (rust !)
531 data-unused: 448 (rust !)
531 data-unused: 0 (no-pure no-rust !)
532 data-unused: 0 (no-pure no-rust !)
532 data-unused: 0.369% (pure !)
533 data-unused: 0.369% (pure !)
533 data-unused: 0.369% (rust !)
534 data-unused: 0.369% (rust !)
534 data-unused: 0.000% (no-pure no-rust !)
535 data-unused: 0.000% (no-pure no-rust !)
535 $ f --size --sha256 .hg/store/00changelog-*.nd
536 $ f --size --sha256 .hg/store/00changelog-*.nd
536 .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
537 .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
537 .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
538 .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
538 .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
539 .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
539
540
540 Check that removing content does not confuse the nodemap
541 Check that removing content does not confuse the nodemap
541 --------------------------------------------------------
542 --------------------------------------------------------
542
543
543 removing data with rollback
544 removing data with rollback
544
545
545 $ echo aso > a
546 $ echo aso > a
546 $ hg ci -m a4
547 $ hg ci -m a4
547 $ hg rollback
548 $ hg rollback
548 repository tip rolled back to revision 5005 (undo commit)
549 repository tip rolled back to revision 5005 (undo commit)
549 working directory now based on revision 5005
550 working directory now based on revision 5005
550 $ hg id -r .
551 $ hg id -r .
551 90d5d3ba2fc4 tip
552 90d5d3ba2fc4 tip
552
553
553 roming data with strip
554 roming data with strip
554
555
555 $ echo aso > a
556 $ echo aso > a
556 $ hg ci -m a4
557 $ hg ci -m a4
557 $ hg --config extensions.strip= strip -r . --no-backup
558 $ hg --config extensions.strip= strip -r . --no-backup
558 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
559 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
559 $ hg id -r . --traceback
560 $ hg id -r . --traceback
560 90d5d3ba2fc4 tip
561 90d5d3ba2fc4 tip
561
562
562 Test upgrade / downgrade
563 Test upgrade / downgrade
563 ========================
564 ========================
564
565
565 downgrading
566 downgrading
566
567
567 $ cat << EOF >> .hg/hgrc
568 $ cat << EOF >> .hg/hgrc
568 > [format]
569 > [format]
569 > use-persistent-nodemap=no
570 > use-persistent-nodemap=no
570 > EOF
571 > EOF
571 $ hg debugformat -v
572 $ hg debugformat -v
572 format-variant repo config default
573 format-variant repo config default
573 fncache: yes yes yes
574 fncache: yes yes yes
574 dotencode: yes yes yes
575 dotencode: yes yes yes
575 generaldelta: yes yes yes
576 generaldelta: yes yes yes
576 share-safe: no no no
577 share-safe: no no no
577 sparserevlog: yes yes yes
578 sparserevlog: yes yes yes
578 sidedata: no no no
579 sidedata: no no no
579 persistent-nodemap: yes no no
580 persistent-nodemap: yes no no
580 copies-sdc: no no no
581 copies-sdc: no no no
582 revlog-v2: no no no
581 plain-cl-delta: yes yes yes
583 plain-cl-delta: yes yes yes
582 compression: zlib zlib zlib
584 compression: zlib zlib zlib
583 compression-level: default default default
585 compression-level: default default default
584 $ hg debugupgraderepo --run --no-backup
586 $ hg debugupgraderepo --run --no-backup
585 upgrade will perform the following actions:
587 upgrade will perform the following actions:
586
588
587 requirements
589 requirements
588 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
590 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
589 removed: persistent-nodemap
591 removed: persistent-nodemap
590
592
591 processed revlogs:
593 processed revlogs:
592 - all-filelogs
594 - all-filelogs
593 - changelog
595 - changelog
594 - manifest
596 - manifest
595
597
596 beginning upgrade...
598 beginning upgrade...
597 repository locked and read-only
599 repository locked and read-only
598 creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob)
600 creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob)
599 (it is safe to interrupt this process any time before data migration completes)
601 (it is safe to interrupt this process any time before data migration completes)
600 downgrading repository to not use persistent nodemap feature
602 downgrading repository to not use persistent nodemap feature
601 removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob)
603 removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob)
602 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
604 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
603 00changelog-*.nd (glob)
605 00changelog-*.nd (glob)
604 00manifest-*.nd (glob)
606 00manifest-*.nd (glob)
605 undo.backup.00changelog.n
607 undo.backup.00changelog.n
606 undo.backup.00manifest.n
608 undo.backup.00manifest.n
607 $ hg debugnodemap --metadata
609 $ hg debugnodemap --metadata
608
610
609
611
610 upgrading
612 upgrading
611
613
612 $ cat << EOF >> .hg/hgrc
614 $ cat << EOF >> .hg/hgrc
613 > [format]
615 > [format]
614 > use-persistent-nodemap=yes
616 > use-persistent-nodemap=yes
615 > EOF
617 > EOF
616 $ hg debugformat -v
618 $ hg debugformat -v
617 format-variant repo config default
619 format-variant repo config default
618 fncache: yes yes yes
620 fncache: yes yes yes
619 dotencode: yes yes yes
621 dotencode: yes yes yes
620 generaldelta: yes yes yes
622 generaldelta: yes yes yes
621 share-safe: no no no
623 share-safe: no no no
622 sparserevlog: yes yes yes
624 sparserevlog: yes yes yes
623 sidedata: no no no
625 sidedata: no no no
624 persistent-nodemap: no yes no
626 persistent-nodemap: no yes no
625 copies-sdc: no no no
627 copies-sdc: no no no
628 revlog-v2: no no no
626 plain-cl-delta: yes yes yes
629 plain-cl-delta: yes yes yes
627 compression: zlib zlib zlib
630 compression: zlib zlib zlib
628 compression-level: default default default
631 compression-level: default default default
629 $ hg debugupgraderepo --run --no-backup
632 $ hg debugupgraderepo --run --no-backup
630 upgrade will perform the following actions:
633 upgrade will perform the following actions:
631
634
632 requirements
635 requirements
633 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
636 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
634 added: persistent-nodemap
637 added: persistent-nodemap
635
638
636 persistent-nodemap
639 persistent-nodemap
637 Speedup revision lookup by node id.
640 Speedup revision lookup by node id.
638
641
639 processed revlogs:
642 processed revlogs:
640 - all-filelogs
643 - all-filelogs
641 - changelog
644 - changelog
642 - manifest
645 - manifest
643
646
644 beginning upgrade...
647 beginning upgrade...
645 repository locked and read-only
648 repository locked and read-only
646 creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob)
649 creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob)
647 (it is safe to interrupt this process any time before data migration completes)
650 (it is safe to interrupt this process any time before data migration completes)
648 upgrading repository to use persistent nodemap feature
651 upgrading repository to use persistent nodemap feature
649 removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob)
652 removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob)
650 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
653 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
651 00changelog-*.nd (glob)
654 00changelog-*.nd (glob)
652 00changelog.n
655 00changelog.n
653 00manifest-*.nd (glob)
656 00manifest-*.nd (glob)
654 00manifest.n
657 00manifest.n
655 undo.backup.00changelog.n
658 undo.backup.00changelog.n
656 undo.backup.00manifest.n
659 undo.backup.00manifest.n
657
660
658 $ hg debugnodemap --metadata
661 $ hg debugnodemap --metadata
659 uid: * (glob)
662 uid: * (glob)
660 tip-rev: 5005
663 tip-rev: 5005
661 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
664 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
662 data-length: 121088
665 data-length: 121088
663 data-unused: 0
666 data-unused: 0
664 data-unused: 0.000%
667 data-unused: 0.000%
665
668
666 Running unrelated upgrade
669 Running unrelated upgrade
667
670
668 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
671 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
669 upgrade will perform the following actions:
672 upgrade will perform the following actions:
670
673
671 requirements
674 requirements
672 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, sparserevlog, store
675 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, sparserevlog, store
673
676
674 optimisations: re-delta-all
677 optimisations: re-delta-all
675
678
676 processed revlogs:
679 processed revlogs:
677 - all-filelogs
680 - all-filelogs
678 - changelog
681 - changelog
679 - manifest
682 - manifest
680
683
681 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
684 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
682 00changelog-*.nd (glob)
685 00changelog-*.nd (glob)
683 00changelog.n
686 00changelog.n
684 00manifest-*.nd (glob)
687 00manifest-*.nd (glob)
685 00manifest.n
688 00manifest.n
686
689
687 $ hg debugnodemap --metadata
690 $ hg debugnodemap --metadata
688 uid: * (glob)
691 uid: * (glob)
689 tip-rev: 5005
692 tip-rev: 5005
690 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
693 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
691 data-length: 121088
694 data-length: 121088
692 data-unused: 0
695 data-unused: 0
693 data-unused: 0.000%
696 data-unused: 0.000%
694
697
695 Persistent nodemap and local/streaming clone
698 Persistent nodemap and local/streaming clone
696 ============================================
699 ============================================
697
700
698 $ cd ..
701 $ cd ..
699
702
700 standard clone
703 standard clone
701 --------------
704 --------------
702
705
703 The persistent nodemap should exist after a streaming clone
706 The persistent nodemap should exist after a streaming clone
704
707
705 $ hg clone --pull --quiet -U test-repo standard-clone
708 $ hg clone --pull --quiet -U test-repo standard-clone
706 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
709 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
707 00changelog-*.nd (glob)
710 00changelog-*.nd (glob)
708 00changelog.n
711 00changelog.n
709 00manifest-*.nd (glob)
712 00manifest-*.nd (glob)
710 00manifest.n
713 00manifest.n
711 $ hg -R standard-clone debugnodemap --metadata
714 $ hg -R standard-clone debugnodemap --metadata
712 uid: * (glob)
715 uid: * (glob)
713 tip-rev: 5005
716 tip-rev: 5005
714 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
717 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
715 data-length: 121088
718 data-length: 121088
716 data-unused: 0
719 data-unused: 0
717 data-unused: 0.000%
720 data-unused: 0.000%
718
721
719
722
720 local clone
723 local clone
721 ------------
724 ------------
722
725
723 The persistent nodemap should exist after a streaming clone
726 The persistent nodemap should exist after a streaming clone
724
727
725 $ hg clone -U test-repo local-clone
728 $ hg clone -U test-repo local-clone
726 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
729 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
727 00changelog-*.nd (glob)
730 00changelog-*.nd (glob)
728 00changelog.n
731 00changelog.n
729 00manifest-*.nd (glob)
732 00manifest-*.nd (glob)
730 00manifest.n
733 00manifest.n
731 $ hg -R local-clone debugnodemap --metadata
734 $ hg -R local-clone debugnodemap --metadata
732 uid: * (glob)
735 uid: * (glob)
733 tip-rev: 5005
736 tip-rev: 5005
734 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
737 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
735 data-length: 121088
738 data-length: 121088
736 data-unused: 0
739 data-unused: 0
737 data-unused: 0.000%
740 data-unused: 0.000%
738
741
739 stream clone
742 stream clone
740 ------------
743 ------------
741
744
742 The persistent nodemap should exist after a streaming clone
745 The persistent nodemap should exist after a streaming clone
743
746
744 $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
747 $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
745 adding [s] 00manifest.n (70 bytes)
748 adding [s] 00manifest.n (70 bytes)
746 adding [s] 00manifest.i (313 KB)
749 adding [s] 00manifest.i (313 KB)
747 adding [s] 00manifest.d (452 KB)
750 adding [s] 00manifest.d (452 KB)
748 adding [s] 00manifest-*.nd (118 KB) (glob)
751 adding [s] 00manifest-*.nd (118 KB) (glob)
749 adding [s] 00changelog.n (70 bytes)
752 adding [s] 00changelog.n (70 bytes)
750 adding [s] 00changelog.i (313 KB)
753 adding [s] 00changelog.i (313 KB)
751 adding [s] 00changelog.d (360 KB)
754 adding [s] 00changelog.d (360 KB)
752 adding [s] 00changelog-*.nd (118 KB) (glob)
755 adding [s] 00changelog-*.nd (118 KB) (glob)
753 $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
756 $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
754 00changelog-*.nd (glob)
757 00changelog-*.nd (glob)
755 00changelog.n
758 00changelog.n
756 00manifest-*.nd (glob)
759 00manifest-*.nd (glob)
757 00manifest.n
760 00manifest.n
758 $ hg -R stream-clone debugnodemap --metadata
761 $ hg -R stream-clone debugnodemap --metadata
759 uid: * (glob)
762 uid: * (glob)
760 tip-rev: 5005
763 tip-rev: 5005
761 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
764 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
762 data-length: 121088
765 data-length: 121088
763 data-unused: 0
766 data-unused: 0
764 data-unused: 0.000%
767 data-unused: 0.000%
@@ -1,110 +1,114 b''
1 ==========================================================
1 ==========================================================
2 Test file dedicated to checking side-data related behavior
2 Test file dedicated to checking side-data related behavior
3 ==========================================================
3 ==========================================================
4
4
5 Check data can be written/read from sidedata
5 Check data can be written/read from sidedata
6 ============================================
6 ============================================
7
7
8 $ cat << EOF >> $HGRCPATH
8 $ cat << EOF >> $HGRCPATH
9 > [extensions]
9 > [extensions]
10 > testsidedata=$TESTDIR/testlib/ext-sidedata.py
10 > testsidedata=$TESTDIR/testlib/ext-sidedata.py
11 > EOF
11 > EOF
12
12
13 $ hg init test-sidedata --config format.exp-use-side-data=yes
13 $ hg init test-sidedata --config format.exp-use-side-data=yes
14 $ cd test-sidedata
14 $ cd test-sidedata
15 $ echo aaa > a
15 $ echo aaa > a
16 $ hg add a
16 $ hg add a
17 $ hg commit -m a --traceback
17 $ hg commit -m a --traceback
18 $ echo aaa > b
18 $ echo aaa > b
19 $ hg add b
19 $ hg add b
20 $ hg commit -m b
20 $ hg commit -m b
21 $ echo xxx >> a
21 $ echo xxx >> a
22 $ hg commit -m aa
22 $ hg commit -m aa
23
23
24 $ hg debugsidedata -c 0
24 $ hg debugsidedata -c 0
25 2 sidedata entries
25 2 sidedata entries
26 entry-0001 size 4
26 entry-0001 size 4
27 entry-0002 size 32
27 entry-0002 size 32
28 $ hg debugsidedata -c 1 -v
28 $ hg debugsidedata -c 1 -v
29 2 sidedata entries
29 2 sidedata entries
30 entry-0001 size 4
30 entry-0001 size 4
31 '\x00\x00\x006'
31 '\x00\x00\x006'
32 entry-0002 size 32
32 entry-0002 size 32
33 '\x98\t\xf9\xc4v\xf0\xc5P\x90\xf7wRf\xe8\xe27e\xfc\xc1\x93\xa4\x96\xd0\x1d\x97\xaaG\x1d\xd7t\xfa\xde'
33 '\x98\t\xf9\xc4v\xf0\xc5P\x90\xf7wRf\xe8\xe27e\xfc\xc1\x93\xa4\x96\xd0\x1d\x97\xaaG\x1d\xd7t\xfa\xde'
34 $ hg debugsidedata -m 2
34 $ hg debugsidedata -m 2
35 2 sidedata entries
35 2 sidedata entries
36 entry-0001 size 4
36 entry-0001 size 4
37 entry-0002 size 32
37 entry-0002 size 32
38 $ hg debugsidedata a 1
38 $ hg debugsidedata a 1
39 2 sidedata entries
39 2 sidedata entries
40 entry-0001 size 4
40 entry-0001 size 4
41 entry-0002 size 32
41 entry-0002 size 32
42
42
43 Check upgrade behavior
43 Check upgrade behavior
44 ======================
44 ======================
45
45
46 Right now, sidedata has not upgrade support
46 Right now, sidedata has not upgrade support
47
47
48 Check that we can upgrade to sidedata
48 Check that we can upgrade to sidedata
49 -------------------------------------
49 -------------------------------------
50
50
51 $ hg init up-no-side-data --config format.exp-use-side-data=no
51 $ hg init up-no-side-data --config format.exp-use-side-data=no
52 $ hg debugformat -v -R up-no-side-data
52 $ hg debugformat -v -R up-no-side-data
53 format-variant repo config default
53 format-variant repo config default
54 fncache: yes yes yes
54 fncache: yes yes yes
55 dotencode: yes yes yes
55 dotencode: yes yes yes
56 generaldelta: yes yes yes
56 generaldelta: yes yes yes
57 share-safe: no no no
57 share-safe: no no no
58 sparserevlog: yes yes yes
58 sparserevlog: yes yes yes
59 sidedata: no no no
59 sidedata: no no no
60 persistent-nodemap: no no no
60 persistent-nodemap: no no no
61 copies-sdc: no no no
61 copies-sdc: no no no
62 revlog-v2: no no no
62 plain-cl-delta: yes yes yes
63 plain-cl-delta: yes yes yes
63 compression: zlib zlib zlib
64 compression: zlib zlib zlib
64 compression-level: default default default
65 compression-level: default default default
65 $ hg debugformat -v -R up-no-side-data --config format.exp-use-side-data=yes
66 $ hg debugformat -v -R up-no-side-data --config format.exp-use-side-data=yes
66 format-variant repo config default
67 format-variant repo config default
67 fncache: yes yes yes
68 fncache: yes yes yes
68 dotencode: yes yes yes
69 dotencode: yes yes yes
69 generaldelta: yes yes yes
70 generaldelta: yes yes yes
70 share-safe: no no no
71 share-safe: no no no
71 sparserevlog: yes yes yes
72 sparserevlog: yes yes yes
72 sidedata: no yes no
73 sidedata: no yes no
73 persistent-nodemap: no no no
74 persistent-nodemap: no no no
74 copies-sdc: no no no
75 copies-sdc: no no no
76 revlog-v2: no yes no
75 plain-cl-delta: yes yes yes
77 plain-cl-delta: yes yes yes
76 compression: zlib zlib zlib
78 compression: zlib zlib zlib
77 compression-level: default default default
79 compression-level: default default default
78 $ hg debugupgraderepo -R up-no-side-data --config format.exp-use-side-data=yes > /dev/null
80 $ hg debugupgraderepo -R up-no-side-data --config format.exp-use-side-data=yes > /dev/null
79
81
80 Check that we can downgrade from sidedata
82 Check that we can downgrade from sidedata
81 -----------------------------------------
83 -----------------------------------------
82
84
83 $ hg init up-side-data --config format.exp-use-side-data=yes
85 $ hg init up-side-data --config format.exp-use-side-data=yes
84 $ hg debugformat -v -R up-side-data
86 $ hg debugformat -v -R up-side-data
85 format-variant repo config default
87 format-variant repo config default
86 fncache: yes yes yes
88 fncache: yes yes yes
87 dotencode: yes yes yes
89 dotencode: yes yes yes
88 generaldelta: yes yes yes
90 generaldelta: yes yes yes
89 share-safe: no no no
91 share-safe: no no no
90 sparserevlog: yes yes yes
92 sparserevlog: yes yes yes
91 sidedata: yes no no
93 sidedata: yes no no
92 persistent-nodemap: no no no
94 persistent-nodemap: no no no
93 copies-sdc: no no no
95 copies-sdc: no no no
96 revlog-v2: yes no no
94 plain-cl-delta: yes yes yes
97 plain-cl-delta: yes yes yes
95 compression: zlib zlib zlib
98 compression: zlib zlib zlib
96 compression-level: default default default
99 compression-level: default default default
97 $ hg debugformat -v -R up-side-data --config format.exp-use-side-data=no
100 $ hg debugformat -v -R up-side-data --config format.exp-use-side-data=no
98 format-variant repo config default
101 format-variant repo config default
99 fncache: yes yes yes
102 fncache: yes yes yes
100 dotencode: yes yes yes
103 dotencode: yes yes yes
101 generaldelta: yes yes yes
104 generaldelta: yes yes yes
102 share-safe: no no no
105 share-safe: no no no
103 sparserevlog: yes yes yes
106 sparserevlog: yes yes yes
104 sidedata: yes no no
107 sidedata: yes no no
105 persistent-nodemap: no no no
108 persistent-nodemap: no no no
106 copies-sdc: no no no
109 copies-sdc: no no no
110 revlog-v2: yes no no
107 plain-cl-delta: yes yes yes
111 plain-cl-delta: yes yes yes
108 compression: zlib zlib zlib
112 compression: zlib zlib zlib
109 compression-level: default default default
113 compression-level: default default default
110 $ hg debugupgraderepo -R up-side-data --config format.exp-use-side-data=no > /dev/null
114 $ hg debugupgraderepo -R up-side-data --config format.exp-use-side-data=no > /dev/null
@@ -1,1513 +1,1536 b''
1 #require no-reposimplestore
1 #require no-reposimplestore
2
2
3 $ cat >> $HGRCPATH << EOF
3 $ cat >> $HGRCPATH << EOF
4 > [extensions]
4 > [extensions]
5 > share =
5 > share =
6 > EOF
6 > EOF
7
7
8 store and revlogv1 are required in source
8 store and revlogv1 are required in source
9
9
10 $ hg --config format.usestore=false init no-store
10 $ hg --config format.usestore=false init no-store
11 $ hg -R no-store debugupgraderepo
11 $ hg -R no-store debugupgraderepo
12 abort: cannot upgrade repository; requirement missing: store
12 abort: cannot upgrade repository; requirement missing: store
13 [255]
13 [255]
14
14
15 $ hg init no-revlogv1
15 $ hg init no-revlogv1
16 $ cat > no-revlogv1/.hg/requires << EOF
16 $ cat > no-revlogv1/.hg/requires << EOF
17 > dotencode
17 > dotencode
18 > fncache
18 > fncache
19 > generaldelta
19 > generaldelta
20 > store
20 > store
21 > EOF
21 > EOF
22
22
23 $ hg -R no-revlogv1 debugupgraderepo
23 $ hg -R no-revlogv1 debugupgraderepo
24 abort: cannot upgrade repository; requirement missing: revlogv1
24 abort: cannot upgrade repository; missing a revlog version
25 [255]
25 [255]
26
26
27 Cannot upgrade shared repositories
27 Cannot upgrade shared repositories
28
28
29 $ hg init share-parent
29 $ hg init share-parent
30 $ hg -q share share-parent share-child
30 $ hg -q share share-parent share-child
31
31
32 $ hg -R share-child debugupgraderepo
32 $ hg -R share-child debugupgraderepo
33 abort: cannot upgrade repository; unsupported source requirement: shared
33 abort: cannot upgrade repository; unsupported source requirement: shared
34 [255]
34 [255]
35
35
36 Do not yet support upgrading treemanifest repos
36 Do not yet support upgrading treemanifest repos
37
37
38 $ hg --config experimental.treemanifest=true init treemanifest
38 $ hg --config experimental.treemanifest=true init treemanifest
39 $ hg -R treemanifest debugupgraderepo
39 $ hg -R treemanifest debugupgraderepo
40 abort: cannot upgrade repository; unsupported source requirement: treemanifest
40 abort: cannot upgrade repository; unsupported source requirement: treemanifest
41 [255]
41 [255]
42
42
43 Cannot add treemanifest requirement during upgrade
43 Cannot add treemanifest requirement during upgrade
44
44
45 $ hg init disallowaddedreq
45 $ hg init disallowaddedreq
46 $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo
46 $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo
47 abort: cannot upgrade repository; do not support adding requirement: treemanifest
47 abort: cannot upgrade repository; do not support adding requirement: treemanifest
48 [255]
48 [255]
49
49
50 An upgrade of a repository created with recommended settings only suggests optimizations
50 An upgrade of a repository created with recommended settings only suggests optimizations
51
51
52 $ hg init empty
52 $ hg init empty
53 $ cd empty
53 $ cd empty
54 $ hg debugformat
54 $ hg debugformat
55 format-variant repo
55 format-variant repo
56 fncache: yes
56 fncache: yes
57 dotencode: yes
57 dotencode: yes
58 generaldelta: yes
58 generaldelta: yes
59 share-safe: no
59 share-safe: no
60 sparserevlog: yes
60 sparserevlog: yes
61 sidedata: no
61 sidedata: no
62 persistent-nodemap: no
62 persistent-nodemap: no
63 copies-sdc: no
63 copies-sdc: no
64 revlog-v2: no
64 plain-cl-delta: yes
65 plain-cl-delta: yes
65 compression: zlib
66 compression: zlib
66 compression-level: default
67 compression-level: default
67 $ hg debugformat --verbose
68 $ hg debugformat --verbose
68 format-variant repo config default
69 format-variant repo config default
69 fncache: yes yes yes
70 fncache: yes yes yes
70 dotencode: yes yes yes
71 dotencode: yes yes yes
71 generaldelta: yes yes yes
72 generaldelta: yes yes yes
72 share-safe: no no no
73 share-safe: no no no
73 sparserevlog: yes yes yes
74 sparserevlog: yes yes yes
74 sidedata: no no no
75 sidedata: no no no
75 persistent-nodemap: no no no
76 persistent-nodemap: no no no
76 copies-sdc: no no no
77 copies-sdc: no no no
78 revlog-v2: no no no
77 plain-cl-delta: yes yes yes
79 plain-cl-delta: yes yes yes
78 compression: zlib zlib zlib
80 compression: zlib zlib zlib
79 compression-level: default default default
81 compression-level: default default default
80 $ hg debugformat --verbose --config format.usefncache=no
82 $ hg debugformat --verbose --config format.usefncache=no
81 format-variant repo config default
83 format-variant repo config default
82 fncache: yes no yes
84 fncache: yes no yes
83 dotencode: yes no yes
85 dotencode: yes no yes
84 generaldelta: yes yes yes
86 generaldelta: yes yes yes
85 share-safe: no no no
87 share-safe: no no no
86 sparserevlog: yes yes yes
88 sparserevlog: yes yes yes
87 sidedata: no no no
89 sidedata: no no no
88 persistent-nodemap: no no no
90 persistent-nodemap: no no no
89 copies-sdc: no no no
91 copies-sdc: no no no
92 revlog-v2: no no no
90 plain-cl-delta: yes yes yes
93 plain-cl-delta: yes yes yes
91 compression: zlib zlib zlib
94 compression: zlib zlib zlib
92 compression-level: default default default
95 compression-level: default default default
93 $ hg debugformat --verbose --config format.usefncache=no --color=debug
96 $ hg debugformat --verbose --config format.usefncache=no --color=debug
94 format-variant repo config default
97 format-variant repo config default
95 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
98 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
96 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
99 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
97 [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
100 [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
98 [formatvariant.name.uptodate|share-safe: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
101 [formatvariant.name.uptodate|share-safe: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
99 [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
102 [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
100 [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
103 [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
101 [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
104 [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
102 [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
105 [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
106 [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
103 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
107 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
104 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
108 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
105 [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
109 [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
106 $ hg debugformat -Tjson
110 $ hg debugformat -Tjson
107 [
111 [
108 {
112 {
109 "config": true,
113 "config": true,
110 "default": true,
114 "default": true,
111 "name": "fncache",
115 "name": "fncache",
112 "repo": true
116 "repo": true
113 },
117 },
114 {
118 {
115 "config": true,
119 "config": true,
116 "default": true,
120 "default": true,
117 "name": "dotencode",
121 "name": "dotencode",
118 "repo": true
122 "repo": true
119 },
123 },
120 {
124 {
121 "config": true,
125 "config": true,
122 "default": true,
126 "default": true,
123 "name": "generaldelta",
127 "name": "generaldelta",
124 "repo": true
128 "repo": true
125 },
129 },
126 {
130 {
127 "config": false,
131 "config": false,
128 "default": false,
132 "default": false,
129 "name": "share-safe",
133 "name": "share-safe",
130 "repo": false
134 "repo": false
131 },
135 },
132 {
136 {
133 "config": true,
137 "config": true,
134 "default": true,
138 "default": true,
135 "name": "sparserevlog",
139 "name": "sparserevlog",
136 "repo": true
140 "repo": true
137 },
141 },
138 {
142 {
139 "config": false,
143 "config": false,
140 "default": false,
144 "default": false,
141 "name": "sidedata",
145 "name": "sidedata",
142 "repo": false
146 "repo": false
143 },
147 },
144 {
148 {
145 "config": false,
149 "config": false,
146 "default": false,
150 "default": false,
147 "name": "persistent-nodemap",
151 "name": "persistent-nodemap",
148 "repo": false
152 "repo": false
149 },
153 },
150 {
154 {
151 "config": false,
155 "config": false,
152 "default": false,
156 "default": false,
153 "name": "copies-sdc",
157 "name": "copies-sdc",
154 "repo": false
158 "repo": false
155 },
159 },
156 {
160 {
161 "config": false,
162 "default": false,
163 "name": "revlog-v2",
164 "repo": false
165 },
166 {
157 "config": true,
167 "config": true,
158 "default": true,
168 "default": true,
159 "name": "plain-cl-delta",
169 "name": "plain-cl-delta",
160 "repo": true
170 "repo": true
161 },
171 },
162 {
172 {
163 "config": "zlib",
173 "config": "zlib",
164 "default": "zlib",
174 "default": "zlib",
165 "name": "compression",
175 "name": "compression",
166 "repo": "zlib"
176 "repo": "zlib"
167 },
177 },
168 {
178 {
169 "config": "default",
179 "config": "default",
170 "default": "default",
180 "default": "default",
171 "name": "compression-level",
181 "name": "compression-level",
172 "repo": "default"
182 "repo": "default"
173 }
183 }
174 ]
184 ]
175 $ hg debugupgraderepo
185 $ hg debugupgraderepo
176 (no format upgrades found in existing repository)
186 (no format upgrades found in existing repository)
177 performing an upgrade with "--run" will make the following changes:
187 performing an upgrade with "--run" will make the following changes:
178
188
179 requirements
189 requirements
180 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
190 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
181
191
182 processed revlogs:
192 processed revlogs:
183 - all-filelogs
193 - all-filelogs
184 - changelog
194 - changelog
185 - manifest
195 - manifest
186
196
187 additional optimizations are available by specifying "--optimize <name>":
197 additional optimizations are available by specifying "--optimize <name>":
188
198
189 re-delta-parent
199 re-delta-parent
190 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
200 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
191
201
192 re-delta-multibase
202 re-delta-multibase
193 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
203 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
194
204
195 re-delta-all
205 re-delta-all
196 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
206 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
197
207
198 re-delta-fulladd
208 re-delta-fulladd
199 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
209 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
200
210
201
211
202 $ hg debugupgraderepo --quiet
212 $ hg debugupgraderepo --quiet
203 requirements
213 requirements
204 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
214 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
205
215
206 processed revlogs:
216 processed revlogs:
207 - all-filelogs
217 - all-filelogs
208 - changelog
218 - changelog
209 - manifest
219 - manifest
210
220
211
221
212 --optimize can be used to add optimizations
222 --optimize can be used to add optimizations
213
223
214 $ hg debugupgrade --optimize 're-delta-parent'
224 $ hg debugupgrade --optimize 're-delta-parent'
215 (no format upgrades found in existing repository)
225 (no format upgrades found in existing repository)
216 performing an upgrade with "--run" will make the following changes:
226 performing an upgrade with "--run" will make the following changes:
217
227
218 requirements
228 requirements
219 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
229 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
220
230
221 optimisations: re-delta-parent
231 optimisations: re-delta-parent
222
232
223 re-delta-parent
233 re-delta-parent
224 deltas within internal storage will choose a new base revision if needed
234 deltas within internal storage will choose a new base revision if needed
225
235
226 processed revlogs:
236 processed revlogs:
227 - all-filelogs
237 - all-filelogs
228 - changelog
238 - changelog
229 - manifest
239 - manifest
230
240
231 additional optimizations are available by specifying "--optimize <name>":
241 additional optimizations are available by specifying "--optimize <name>":
232
242
233 re-delta-multibase
243 re-delta-multibase
234 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
244 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
235
245
236 re-delta-all
246 re-delta-all
237 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
247 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
238
248
239 re-delta-fulladd
249 re-delta-fulladd
240 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
250 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
241
251
242
252
243 modern form of the option
253 modern form of the option
244
254
245 $ hg debugupgrade --optimize re-delta-parent
255 $ hg debugupgrade --optimize re-delta-parent
246 (no format upgrades found in existing repository)
256 (no format upgrades found in existing repository)
247 performing an upgrade with "--run" will make the following changes:
257 performing an upgrade with "--run" will make the following changes:
248
258
249 requirements
259 requirements
250 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
260 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
251
261
252 optimisations: re-delta-parent
262 optimisations: re-delta-parent
253
263
254 re-delta-parent
264 re-delta-parent
255 deltas within internal storage will choose a new base revision if needed
265 deltas within internal storage will choose a new base revision if needed
256
266
257 processed revlogs:
267 processed revlogs:
258 - all-filelogs
268 - all-filelogs
259 - changelog
269 - changelog
260 - manifest
270 - manifest
261
271
262 additional optimizations are available by specifying "--optimize <name>":
272 additional optimizations are available by specifying "--optimize <name>":
263
273
264 re-delta-multibase
274 re-delta-multibase
265 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
275 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
266
276
267 re-delta-all
277 re-delta-all
268 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
278 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
269
279
270 re-delta-fulladd
280 re-delta-fulladd
271 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
281 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
272
282
273 $ hg debugupgrade --optimize re-delta-parent --quiet
283 $ hg debugupgrade --optimize re-delta-parent --quiet
274 requirements
284 requirements
275 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
285 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
276
286
277 optimisations: re-delta-parent
287 optimisations: re-delta-parent
278
288
279 processed revlogs:
289 processed revlogs:
280 - all-filelogs
290 - all-filelogs
281 - changelog
291 - changelog
282 - manifest
292 - manifest
283
293
284
294
285 unknown optimization:
295 unknown optimization:
286
296
287 $ hg debugupgrade --optimize foobar
297 $ hg debugupgrade --optimize foobar
288 abort: unknown optimization action requested: foobar
298 abort: unknown optimization action requested: foobar
289 (run without arguments to see valid optimizations)
299 (run without arguments to see valid optimizations)
290 [255]
300 [255]
291
301
292 Various sub-optimal detections work
302 Various sub-optimal detections work
293
303
294 $ cat > .hg/requires << EOF
304 $ cat > .hg/requires << EOF
295 > revlogv1
305 > revlogv1
296 > store
306 > store
297 > EOF
307 > EOF
298
308
299 $ hg debugformat
309 $ hg debugformat
300 format-variant repo
310 format-variant repo
301 fncache: no
311 fncache: no
302 dotencode: no
312 dotencode: no
303 generaldelta: no
313 generaldelta: no
304 share-safe: no
314 share-safe: no
305 sparserevlog: no
315 sparserevlog: no
306 sidedata: no
316 sidedata: no
307 persistent-nodemap: no
317 persistent-nodemap: no
308 copies-sdc: no
318 copies-sdc: no
319 revlog-v2: no
309 plain-cl-delta: yes
320 plain-cl-delta: yes
310 compression: zlib
321 compression: zlib
311 compression-level: default
322 compression-level: default
312 $ hg debugformat --verbose
323 $ hg debugformat --verbose
313 format-variant repo config default
324 format-variant repo config default
314 fncache: no yes yes
325 fncache: no yes yes
315 dotencode: no yes yes
326 dotencode: no yes yes
316 generaldelta: no yes yes
327 generaldelta: no yes yes
317 share-safe: no no no
328 share-safe: no no no
318 sparserevlog: no yes yes
329 sparserevlog: no yes yes
319 sidedata: no no no
330 sidedata: no no no
320 persistent-nodemap: no no no
331 persistent-nodemap: no no no
321 copies-sdc: no no no
332 copies-sdc: no no no
333 revlog-v2: no no no
322 plain-cl-delta: yes yes yes
334 plain-cl-delta: yes yes yes
323 compression: zlib zlib zlib
335 compression: zlib zlib zlib
324 compression-level: default default default
336 compression-level: default default default
325 $ hg debugformat --verbose --config format.usegeneraldelta=no
337 $ hg debugformat --verbose --config format.usegeneraldelta=no
326 format-variant repo config default
338 format-variant repo config default
327 fncache: no yes yes
339 fncache: no yes yes
328 dotencode: no yes yes
340 dotencode: no yes yes
329 generaldelta: no no yes
341 generaldelta: no no yes
330 share-safe: no no no
342 share-safe: no no no
331 sparserevlog: no no yes
343 sparserevlog: no no yes
332 sidedata: no no no
344 sidedata: no no no
333 persistent-nodemap: no no no
345 persistent-nodemap: no no no
334 copies-sdc: no no no
346 copies-sdc: no no no
347 revlog-v2: no no no
335 plain-cl-delta: yes yes yes
348 plain-cl-delta: yes yes yes
336 compression: zlib zlib zlib
349 compression: zlib zlib zlib
337 compression-level: default default default
350 compression-level: default default default
338 $ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug
351 $ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug
339 format-variant repo config default
352 format-variant repo config default
340 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
353 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
341 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
354 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
342 [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
355 [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
343 [formatvariant.name.uptodate|share-safe: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
356 [formatvariant.name.uptodate|share-safe: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
344 [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
357 [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
345 [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
358 [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
346 [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
359 [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
347 [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
360 [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
361 [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
348 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
362 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
349 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
363 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
350 [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
364 [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
351 $ hg debugupgraderepo
365 $ hg debugupgraderepo
352 repository lacks features recommended by current config options:
366 repository lacks features recommended by current config options:
353
367
354 fncache
368 fncache
355 long and reserved filenames may not work correctly; repository performance is sub-optimal
369 long and reserved filenames may not work correctly; repository performance is sub-optimal
356
370
357 dotencode
371 dotencode
358 storage of filenames beginning with a period or space may not work correctly
372 storage of filenames beginning with a period or space may not work correctly
359
373
360 generaldelta
374 generaldelta
361 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
375 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
362
376
363 sparserevlog
377 sparserevlog
364 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
378 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
365
379
366
380
367 performing an upgrade with "--run" will make the following changes:
381 performing an upgrade with "--run" will make the following changes:
368
382
369 requirements
383 requirements
370 preserved: revlogv1, store
384 preserved: revlogv1, store
371 added: dotencode, fncache, generaldelta, sparserevlog
385 added: dotencode, fncache, generaldelta, sparserevlog
372
386
373 fncache
387 fncache
374 repository will be more resilient to storing certain paths and performance of certain operations should be improved
388 repository will be more resilient to storing certain paths and performance of certain operations should be improved
375
389
376 dotencode
390 dotencode
377 repository will be better able to store files beginning with a space or period
391 repository will be better able to store files beginning with a space or period
378
392
379 generaldelta
393 generaldelta
380 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
394 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
381
395
382 sparserevlog
396 sparserevlog
383 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
397 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
384
398
385 processed revlogs:
399 processed revlogs:
386 - all-filelogs
400 - all-filelogs
387 - changelog
401 - changelog
388 - manifest
402 - manifest
389
403
390 additional optimizations are available by specifying "--optimize <name>":
404 additional optimizations are available by specifying "--optimize <name>":
391
405
392 re-delta-parent
406 re-delta-parent
393 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
407 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
394
408
395 re-delta-multibase
409 re-delta-multibase
396 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
410 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
397
411
398 re-delta-all
412 re-delta-all
399 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
413 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
400
414
401 re-delta-fulladd
415 re-delta-fulladd
402 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
416 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
403
417
404 $ hg debugupgraderepo --quiet
418 $ hg debugupgraderepo --quiet
405 requirements
419 requirements
406 preserved: revlogv1, store
420 preserved: revlogv1, store
407 added: dotencode, fncache, generaldelta, sparserevlog
421 added: dotencode, fncache, generaldelta, sparserevlog
408
422
409 processed revlogs:
423 processed revlogs:
410 - all-filelogs
424 - all-filelogs
411 - changelog
425 - changelog
412 - manifest
426 - manifest
413
427
414
428
415 $ hg --config format.dotencode=false debugupgraderepo
429 $ hg --config format.dotencode=false debugupgraderepo
416 repository lacks features recommended by current config options:
430 repository lacks features recommended by current config options:
417
431
418 fncache
432 fncache
419 long and reserved filenames may not work correctly; repository performance is sub-optimal
433 long and reserved filenames may not work correctly; repository performance is sub-optimal
420
434
421 generaldelta
435 generaldelta
422 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
436 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
423
437
424 sparserevlog
438 sparserevlog
425 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
439 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
426
440
427 repository lacks features used by the default config options:
441 repository lacks features used by the default config options:
428
442
429 dotencode
443 dotencode
430 storage of filenames beginning with a period or space may not work correctly
444 storage of filenames beginning with a period or space may not work correctly
431
445
432
446
433 performing an upgrade with "--run" will make the following changes:
447 performing an upgrade with "--run" will make the following changes:
434
448
435 requirements
449 requirements
436 preserved: revlogv1, store
450 preserved: revlogv1, store
437 added: fncache, generaldelta, sparserevlog
451 added: fncache, generaldelta, sparserevlog
438
452
439 fncache
453 fncache
440 repository will be more resilient to storing certain paths and performance of certain operations should be improved
454 repository will be more resilient to storing certain paths and performance of certain operations should be improved
441
455
442 generaldelta
456 generaldelta
443 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
457 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
444
458
445 sparserevlog
459 sparserevlog
446 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
460 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
447
461
448 processed revlogs:
462 processed revlogs:
449 - all-filelogs
463 - all-filelogs
450 - changelog
464 - changelog
451 - manifest
465 - manifest
452
466
453 additional optimizations are available by specifying "--optimize <name>":
467 additional optimizations are available by specifying "--optimize <name>":
454
468
455 re-delta-parent
469 re-delta-parent
456 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
470 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
457
471
458 re-delta-multibase
472 re-delta-multibase
459 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
473 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
460
474
461 re-delta-all
475 re-delta-all
462 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
476 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
463
477
464 re-delta-fulladd
478 re-delta-fulladd
465 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
479 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
466
480
467
481
468 $ cd ..
482 $ cd ..
469
483
470 Upgrading a repository that is already modern essentially no-ops
484 Upgrading a repository that is already modern essentially no-ops
471
485
472 $ hg init modern
486 $ hg init modern
473 $ hg -R modern debugupgraderepo --run
487 $ hg -R modern debugupgraderepo --run
474 nothing to do
488 nothing to do
475
489
476 Upgrading a repository to generaldelta works
490 Upgrading a repository to generaldelta works
477
491
478 $ hg --config format.usegeneraldelta=false init upgradegd
492 $ hg --config format.usegeneraldelta=false init upgradegd
479 $ cd upgradegd
493 $ cd upgradegd
480 $ touch f0
494 $ touch f0
481 $ hg -q commit -A -m initial
495 $ hg -q commit -A -m initial
482 $ mkdir FooBarDirectory.d
496 $ mkdir FooBarDirectory.d
483 $ touch FooBarDirectory.d/f1
497 $ touch FooBarDirectory.d/f1
484 $ hg -q commit -A -m 'add f1'
498 $ hg -q commit -A -m 'add f1'
485 $ hg -q up -r 0
499 $ hg -q up -r 0
486 >>> from __future__ import absolute_import, print_function
500 >>> from __future__ import absolute_import, print_function
487 >>> import random
501 >>> import random
488 >>> random.seed(0) # have a reproducible content
502 >>> random.seed(0) # have a reproducible content
489 >>> with open("f2", "wb") as f:
503 >>> with open("f2", "wb") as f:
490 ... for i in range(100000):
504 ... for i in range(100000):
491 ... f.write(b"%d\n" % random.randint(1000000000, 9999999999)) and None
505 ... f.write(b"%d\n" % random.randint(1000000000, 9999999999)) and None
492 $ hg -q commit -A -m 'add f2'
506 $ hg -q commit -A -m 'add f2'
493
507
494 make sure we have a .d file
508 make sure we have a .d file
495
509
496 $ ls -d .hg/store/data/*
510 $ ls -d .hg/store/data/*
497 .hg/store/data/_foo_bar_directory.d.hg
511 .hg/store/data/_foo_bar_directory.d.hg
498 .hg/store/data/f0.i
512 .hg/store/data/f0.i
499 .hg/store/data/f2.d
513 .hg/store/data/f2.d
500 .hg/store/data/f2.i
514 .hg/store/data/f2.i
501
515
502 $ hg debugupgraderepo --run --config format.sparse-revlog=false
516 $ hg debugupgraderepo --run --config format.sparse-revlog=false
503 upgrade will perform the following actions:
517 upgrade will perform the following actions:
504
518
505 requirements
519 requirements
506 preserved: dotencode, fncache, revlogv1, store
520 preserved: dotencode, fncache, revlogv1, store
507 added: generaldelta
521 added: generaldelta
508
522
509 generaldelta
523 generaldelta
510 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
524 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
511
525
512 processed revlogs:
526 processed revlogs:
513 - all-filelogs
527 - all-filelogs
514 - changelog
528 - changelog
515 - manifest
529 - manifest
516
530
517 beginning upgrade...
531 beginning upgrade...
518 repository locked and read-only
532 repository locked and read-only
519 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
533 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
520 (it is safe to interrupt this process any time before data migration completes)
534 (it is safe to interrupt this process any time before data migration completes)
521 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
535 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
522 migrating 519 KB in store; 1.05 MB tracked data
536 migrating 519 KB in store; 1.05 MB tracked data
523 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
537 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
524 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
538 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
525 migrating 1 manifests containing 3 revisions (384 bytes in store; 238 bytes tracked data)
539 migrating 1 manifests containing 3 revisions (384 bytes in store; 238 bytes tracked data)
526 finished migrating 3 manifest revisions across 1 manifests; change in size: -17 bytes
540 finished migrating 3 manifest revisions across 1 manifests; change in size: -17 bytes
527 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
541 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
528 finished migrating 3 changelog revisions; change in size: 0 bytes
542 finished migrating 3 changelog revisions; change in size: 0 bytes
529 finished migrating 9 total revisions; total change in store size: -17 bytes
543 finished migrating 9 total revisions; total change in store size: -17 bytes
530 copying phaseroots
544 copying phaseroots
531 data fully upgraded in a temporary repository
545 data fully upgraded in a temporary repository
532 marking source repository as being upgraded; clients will be unable to read from repository
546 marking source repository as being upgraded; clients will be unable to read from repository
533 starting in-place swap of repository data
547 starting in-place swap of repository data
534 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
548 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
535 replacing store...
549 replacing store...
536 store replacement complete; repository was inconsistent for *s (glob)
550 store replacement complete; repository was inconsistent for *s (glob)
537 finalizing requirements file and making repository readable again
551 finalizing requirements file and making repository readable again
538 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
552 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
539 copy of old repository backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
553 copy of old repository backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
540 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
554 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
541
555
542 Original requirements backed up
556 Original requirements backed up
543
557
544 $ cat .hg/upgradebackup.*/requires
558 $ cat .hg/upgradebackup.*/requires
545 dotencode
559 dotencode
546 fncache
560 fncache
547 revlogv1
561 revlogv1
548 store
562 store
549
563
550 generaldelta added to original requirements files
564 generaldelta added to original requirements files
551
565
552 $ cat .hg/requires
566 $ cat .hg/requires
553 dotencode
567 dotencode
554 fncache
568 fncache
555 generaldelta
569 generaldelta
556 revlogv1
570 revlogv1
557 store
571 store
558
572
559 store directory has files we expect
573 store directory has files we expect
560
574
561 $ ls .hg/store
575 $ ls .hg/store
562 00changelog.i
576 00changelog.i
563 00manifest.i
577 00manifest.i
564 data
578 data
565 fncache
579 fncache
566 phaseroots
580 phaseroots
567 undo
581 undo
568 undo.backupfiles
582 undo.backupfiles
569 undo.phaseroots
583 undo.phaseroots
570
584
571 manifest should be generaldelta
585 manifest should be generaldelta
572
586
573 $ hg debugrevlog -m | grep flags
587 $ hg debugrevlog -m | grep flags
574 flags : inline, generaldelta
588 flags : inline, generaldelta
575
589
576 verify should be happy
590 verify should be happy
577
591
578 $ hg verify
592 $ hg verify
579 checking changesets
593 checking changesets
580 checking manifests
594 checking manifests
581 crosschecking files in changesets and manifests
595 crosschecking files in changesets and manifests
582 checking files
596 checking files
583 checked 3 changesets with 3 changes to 3 files
597 checked 3 changesets with 3 changes to 3 files
584
598
585 old store should be backed up
599 old store should be backed up
586
600
587 $ ls -d .hg/upgradebackup.*/
601 $ ls -d .hg/upgradebackup.*/
588 .hg/upgradebackup.*/ (glob)
602 .hg/upgradebackup.*/ (glob)
589 $ ls .hg/upgradebackup.*/store
603 $ ls .hg/upgradebackup.*/store
590 00changelog.i
604 00changelog.i
591 00manifest.i
605 00manifest.i
592 data
606 data
593 fncache
607 fncache
594 phaseroots
608 phaseroots
595 undo
609 undo
596 undo.backup.fncache
610 undo.backup.fncache
597 undo.backupfiles
611 undo.backupfiles
598 undo.phaseroots
612 undo.phaseroots
599
613
600 unless --no-backup is passed
614 unless --no-backup is passed
601
615
602 $ rm -rf .hg/upgradebackup.*/
616 $ rm -rf .hg/upgradebackup.*/
603 $ hg debugupgraderepo --run --no-backup
617 $ hg debugupgraderepo --run --no-backup
604 upgrade will perform the following actions:
618 upgrade will perform the following actions:
605
619
606 requirements
620 requirements
607 preserved: dotencode, fncache, generaldelta, revlogv1, store
621 preserved: dotencode, fncache, generaldelta, revlogv1, store
608 added: sparserevlog
622 added: sparserevlog
609
623
610 sparserevlog
624 sparserevlog
611 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
625 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
612
626
613 processed revlogs:
627 processed revlogs:
614 - all-filelogs
628 - all-filelogs
615 - changelog
629 - changelog
616 - manifest
630 - manifest
617
631
618 beginning upgrade...
632 beginning upgrade...
619 repository locked and read-only
633 repository locked and read-only
620 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
634 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
621 (it is safe to interrupt this process any time before data migration completes)
635 (it is safe to interrupt this process any time before data migration completes)
622 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
636 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
623 migrating 519 KB in store; 1.05 MB tracked data
637 migrating 519 KB in store; 1.05 MB tracked data
624 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
638 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
625 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
639 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
626 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
640 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
627 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
641 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
628 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
642 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
629 finished migrating 3 changelog revisions; change in size: 0 bytes
643 finished migrating 3 changelog revisions; change in size: 0 bytes
630 finished migrating 9 total revisions; total change in store size: 0 bytes
644 finished migrating 9 total revisions; total change in store size: 0 bytes
631 copying phaseroots
645 copying phaseroots
632 data fully upgraded in a temporary repository
646 data fully upgraded in a temporary repository
633 marking source repository as being upgraded; clients will be unable to read from repository
647 marking source repository as being upgraded; clients will be unable to read from repository
634 starting in-place swap of repository data
648 starting in-place swap of repository data
635 replacing store...
649 replacing store...
636 store replacement complete; repository was inconsistent for * (glob)
650 store replacement complete; repository was inconsistent for * (glob)
637 finalizing requirements file and making repository readable again
651 finalizing requirements file and making repository readable again
638 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
652 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
639 $ ls -1 .hg/ | grep upgradebackup
653 $ ls -1 .hg/ | grep upgradebackup
640 [1]
654 [1]
641
655
642 We can restrict optimization to some revlog:
656 We can restrict optimization to some revlog:
643
657
644 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
658 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
645 upgrade will perform the following actions:
659 upgrade will perform the following actions:
646
660
647 requirements
661 requirements
648 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
662 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
649
663
650 optimisations: re-delta-parent
664 optimisations: re-delta-parent
651
665
652 re-delta-parent
666 re-delta-parent
653 deltas within internal storage will choose a new base revision if needed
667 deltas within internal storage will choose a new base revision if needed
654
668
655 processed revlogs:
669 processed revlogs:
656 - manifest
670 - manifest
657
671
658 beginning upgrade...
672 beginning upgrade...
659 repository locked and read-only
673 repository locked and read-only
660 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
674 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
661 (it is safe to interrupt this process any time before data migration completes)
675 (it is safe to interrupt this process any time before data migration completes)
662 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
676 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
663 migrating 519 KB in store; 1.05 MB tracked data
677 migrating 519 KB in store; 1.05 MB tracked data
664 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
678 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
665 blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions
679 blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions
666 blindly copying data/f0.i containing 1 revisions
680 blindly copying data/f0.i containing 1 revisions
667 blindly copying data/f2.i containing 1 revisions
681 blindly copying data/f2.i containing 1 revisions
668 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
682 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
669 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
683 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
670 cloning 3 revisions from 00manifest.i
684 cloning 3 revisions from 00manifest.i
671 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
685 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
672 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
686 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
673 blindly copying 00changelog.i containing 3 revisions
687 blindly copying 00changelog.i containing 3 revisions
674 finished migrating 3 changelog revisions; change in size: 0 bytes
688 finished migrating 3 changelog revisions; change in size: 0 bytes
675 finished migrating 9 total revisions; total change in store size: 0 bytes
689 finished migrating 9 total revisions; total change in store size: 0 bytes
676 copying phaseroots
690 copying phaseroots
677 data fully upgraded in a temporary repository
691 data fully upgraded in a temporary repository
678 marking source repository as being upgraded; clients will be unable to read from repository
692 marking source repository as being upgraded; clients will be unable to read from repository
679 starting in-place swap of repository data
693 starting in-place swap of repository data
680 replacing store...
694 replacing store...
681 store replacement complete; repository was inconsistent for *s (glob)
695 store replacement complete; repository was inconsistent for *s (glob)
682 finalizing requirements file and making repository readable again
696 finalizing requirements file and making repository readable again
683 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
697 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
684
698
685 Check that the repo still works fine
699 Check that the repo still works fine
686
700
687 $ hg log -G --stat
701 $ hg log -G --stat
688 @ changeset: 2:76d4395f5413 (no-py3 !)
702 @ changeset: 2:76d4395f5413 (no-py3 !)
689 @ changeset: 2:fca376863211 (py3 !)
703 @ changeset: 2:fca376863211 (py3 !)
690 | tag: tip
704 | tag: tip
691 | parent: 0:ba592bf28da2
705 | parent: 0:ba592bf28da2
692 | user: test
706 | user: test
693 | date: Thu Jan 01 00:00:00 1970 +0000
707 | date: Thu Jan 01 00:00:00 1970 +0000
694 | summary: add f2
708 | summary: add f2
695 |
709 |
696 | f2 | 100000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
710 | f2 | 100000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
697 | 1 files changed, 100000 insertions(+), 0 deletions(-)
711 | 1 files changed, 100000 insertions(+), 0 deletions(-)
698 |
712 |
699 | o changeset: 1:2029ce2354e2
713 | o changeset: 1:2029ce2354e2
700 |/ user: test
714 |/ user: test
701 | date: Thu Jan 01 00:00:00 1970 +0000
715 | date: Thu Jan 01 00:00:00 1970 +0000
702 | summary: add f1
716 | summary: add f1
703 |
717 |
704 |
718 |
705 o changeset: 0:ba592bf28da2
719 o changeset: 0:ba592bf28da2
706 user: test
720 user: test
707 date: Thu Jan 01 00:00:00 1970 +0000
721 date: Thu Jan 01 00:00:00 1970 +0000
708 summary: initial
722 summary: initial
709
723
710
724
711
725
712 $ hg verify
726 $ hg verify
713 checking changesets
727 checking changesets
714 checking manifests
728 checking manifests
715 crosschecking files in changesets and manifests
729 crosschecking files in changesets and manifests
716 checking files
730 checking files
717 checked 3 changesets with 3 changes to 3 files
731 checked 3 changesets with 3 changes to 3 files
718
732
719 Check we can select negatively
733 Check we can select negatively
720
734
721 $ hg debugupgrade --optimize re-delta-parent --run --no-manifest --no-backup --debug --traceback
735 $ hg debugupgrade --optimize re-delta-parent --run --no-manifest --no-backup --debug --traceback
722 upgrade will perform the following actions:
736 upgrade will perform the following actions:
723
737
724 requirements
738 requirements
725 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
739 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
726
740
727 optimisations: re-delta-parent
741 optimisations: re-delta-parent
728
742
729 re-delta-parent
743 re-delta-parent
730 deltas within internal storage will choose a new base revision if needed
744 deltas within internal storage will choose a new base revision if needed
731
745
732 processed revlogs:
746 processed revlogs:
733 - all-filelogs
747 - all-filelogs
734 - changelog
748 - changelog
735
749
736 beginning upgrade...
750 beginning upgrade...
737 repository locked and read-only
751 repository locked and read-only
738 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
752 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
739 (it is safe to interrupt this process any time before data migration completes)
753 (it is safe to interrupt this process any time before data migration completes)
740 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
754 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
741 migrating 519 KB in store; 1.05 MB tracked data
755 migrating 519 KB in store; 1.05 MB tracked data
742 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
756 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
743 cloning 1 revisions from data/FooBarDirectory.d/f1.i
757 cloning 1 revisions from data/FooBarDirectory.d/f1.i
744 cloning 1 revisions from data/f0.i
758 cloning 1 revisions from data/f0.i
745 cloning 1 revisions from data/f2.i
759 cloning 1 revisions from data/f2.i
746 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
760 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
747 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
761 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
748 blindly copying 00manifest.i containing 3 revisions
762 blindly copying 00manifest.i containing 3 revisions
749 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
763 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
750 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
764 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
751 cloning 3 revisions from 00changelog.i
765 cloning 3 revisions from 00changelog.i
752 finished migrating 3 changelog revisions; change in size: 0 bytes
766 finished migrating 3 changelog revisions; change in size: 0 bytes
753 finished migrating 9 total revisions; total change in store size: 0 bytes
767 finished migrating 9 total revisions; total change in store size: 0 bytes
754 copying phaseroots
768 copying phaseroots
755 data fully upgraded in a temporary repository
769 data fully upgraded in a temporary repository
756 marking source repository as being upgraded; clients will be unable to read from repository
770 marking source repository as being upgraded; clients will be unable to read from repository
757 starting in-place swap of repository data
771 starting in-place swap of repository data
758 replacing store...
772 replacing store...
759 store replacement complete; repository was inconsistent for *s (glob)
773 store replacement complete; repository was inconsistent for *s (glob)
760 finalizing requirements file and making repository readable again
774 finalizing requirements file and making repository readable again
761 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
775 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
762 $ hg verify
776 $ hg verify
763 checking changesets
777 checking changesets
764 checking manifests
778 checking manifests
765 crosschecking files in changesets and manifests
779 crosschecking files in changesets and manifests
766 checking files
780 checking files
767 checked 3 changesets with 3 changes to 3 files
781 checked 3 changesets with 3 changes to 3 files
768
782
769 Check that we can select changelog only
783 Check that we can select changelog only
770
784
771 $ hg debugupgrade --optimize re-delta-parent --run --changelog --no-backup --debug --traceback
785 $ hg debugupgrade --optimize re-delta-parent --run --changelog --no-backup --debug --traceback
772 upgrade will perform the following actions:
786 upgrade will perform the following actions:
773
787
774 requirements
788 requirements
775 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
789 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
776
790
777 optimisations: re-delta-parent
791 optimisations: re-delta-parent
778
792
779 re-delta-parent
793 re-delta-parent
780 deltas within internal storage will choose a new base revision if needed
794 deltas within internal storage will choose a new base revision if needed
781
795
782 processed revlogs:
796 processed revlogs:
783 - changelog
797 - changelog
784
798
785 beginning upgrade...
799 beginning upgrade...
786 repository locked and read-only
800 repository locked and read-only
787 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
801 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
788 (it is safe to interrupt this process any time before data migration completes)
802 (it is safe to interrupt this process any time before data migration completes)
789 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
803 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
790 migrating 519 KB in store; 1.05 MB tracked data
804 migrating 519 KB in store; 1.05 MB tracked data
791 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
805 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
792 blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions
806 blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions
793 blindly copying data/f0.i containing 1 revisions
807 blindly copying data/f0.i containing 1 revisions
794 blindly copying data/f2.i containing 1 revisions
808 blindly copying data/f2.i containing 1 revisions
795 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
809 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
796 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
810 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
797 blindly copying 00manifest.i containing 3 revisions
811 blindly copying 00manifest.i containing 3 revisions
798 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
812 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
799 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
813 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
800 cloning 3 revisions from 00changelog.i
814 cloning 3 revisions from 00changelog.i
801 finished migrating 3 changelog revisions; change in size: 0 bytes
815 finished migrating 3 changelog revisions; change in size: 0 bytes
802 finished migrating 9 total revisions; total change in store size: 0 bytes
816 finished migrating 9 total revisions; total change in store size: 0 bytes
803 copying phaseroots
817 copying phaseroots
804 data fully upgraded in a temporary repository
818 data fully upgraded in a temporary repository
805 marking source repository as being upgraded; clients will be unable to read from repository
819 marking source repository as being upgraded; clients will be unable to read from repository
806 starting in-place swap of repository data
820 starting in-place swap of repository data
807 replacing store...
821 replacing store...
808 store replacement complete; repository was inconsistent for *s (glob)
822 store replacement complete; repository was inconsistent for *s (glob)
809 finalizing requirements file and making repository readable again
823 finalizing requirements file and making repository readable again
810 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
824 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
811 $ hg verify
825 $ hg verify
812 checking changesets
826 checking changesets
813 checking manifests
827 checking manifests
814 crosschecking files in changesets and manifests
828 crosschecking files in changesets and manifests
815 checking files
829 checking files
816 checked 3 changesets with 3 changes to 3 files
830 checked 3 changesets with 3 changes to 3 files
817
831
818 Check that we can select filelog only
832 Check that we can select filelog only
819
833
820 $ hg debugupgrade --optimize re-delta-parent --run --no-changelog --no-manifest --no-backup --debug --traceback
834 $ hg debugupgrade --optimize re-delta-parent --run --no-changelog --no-manifest --no-backup --debug --traceback
821 upgrade will perform the following actions:
835 upgrade will perform the following actions:
822
836
823 requirements
837 requirements
824 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
838 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
825
839
826 optimisations: re-delta-parent
840 optimisations: re-delta-parent
827
841
828 re-delta-parent
842 re-delta-parent
829 deltas within internal storage will choose a new base revision if needed
843 deltas within internal storage will choose a new base revision if needed
830
844
831 processed revlogs:
845 processed revlogs:
832 - all-filelogs
846 - all-filelogs
833
847
834 beginning upgrade...
848 beginning upgrade...
835 repository locked and read-only
849 repository locked and read-only
836 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
850 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
837 (it is safe to interrupt this process any time before data migration completes)
851 (it is safe to interrupt this process any time before data migration completes)
838 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
852 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
839 migrating 519 KB in store; 1.05 MB tracked data
853 migrating 519 KB in store; 1.05 MB tracked data
840 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
854 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
841 cloning 1 revisions from data/FooBarDirectory.d/f1.i
855 cloning 1 revisions from data/FooBarDirectory.d/f1.i
842 cloning 1 revisions from data/f0.i
856 cloning 1 revisions from data/f0.i
843 cloning 1 revisions from data/f2.i
857 cloning 1 revisions from data/f2.i
844 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
858 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
845 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
859 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
846 blindly copying 00manifest.i containing 3 revisions
860 blindly copying 00manifest.i containing 3 revisions
847 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
861 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
848 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
862 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
849 blindly copying 00changelog.i containing 3 revisions
863 blindly copying 00changelog.i containing 3 revisions
850 finished migrating 3 changelog revisions; change in size: 0 bytes
864 finished migrating 3 changelog revisions; change in size: 0 bytes
851 finished migrating 9 total revisions; total change in store size: 0 bytes
865 finished migrating 9 total revisions; total change in store size: 0 bytes
852 copying phaseroots
866 copying phaseroots
853 data fully upgraded in a temporary repository
867 data fully upgraded in a temporary repository
854 marking source repository as being upgraded; clients will be unable to read from repository
868 marking source repository as being upgraded; clients will be unable to read from repository
855 starting in-place swap of repository data
869 starting in-place swap of repository data
856 replacing store...
870 replacing store...
857 store replacement complete; repository was inconsistent for *s (glob)
871 store replacement complete; repository was inconsistent for *s (glob)
858 finalizing requirements file and making repository readable again
872 finalizing requirements file and making repository readable again
859 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
873 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
860 $ hg verify
874 $ hg verify
861 checking changesets
875 checking changesets
862 checking manifests
876 checking manifests
863 crosschecking files in changesets and manifests
877 crosschecking files in changesets and manifests
864 checking files
878 checking files
865 checked 3 changesets with 3 changes to 3 files
879 checked 3 changesets with 3 changes to 3 files
866
880
867
881
868 Check you can't skip revlog clone during important format downgrade
882 Check you can't skip revlog clone during important format downgrade
869
883
870 $ echo "[format]" > .hg/hgrc
884 $ echo "[format]" > .hg/hgrc
871 $ echo "sparse-revlog=no" >> .hg/hgrc
885 $ echo "sparse-revlog=no" >> .hg/hgrc
872 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
886 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
873 ignoring revlogs selection flags, format requirements change: sparserevlog
887 ignoring revlogs selection flags, format requirements change: sparserevlog
874 upgrade will perform the following actions:
888 upgrade will perform the following actions:
875
889
876 requirements
890 requirements
877 preserved: dotencode, fncache, generaldelta, revlogv1, store
891 preserved: dotencode, fncache, generaldelta, revlogv1, store
878 removed: sparserevlog
892 removed: sparserevlog
879
893
880 optimisations: re-delta-parent
894 optimisations: re-delta-parent
881
895
882 re-delta-parent
896 re-delta-parent
883 deltas within internal storage will choose a new base revision if needed
897 deltas within internal storage will choose a new base revision if needed
884
898
885 processed revlogs:
899 processed revlogs:
886 - all-filelogs
900 - all-filelogs
887 - changelog
901 - changelog
888 - manifest
902 - manifest
889
903
890 beginning upgrade...
904 beginning upgrade...
891 repository locked and read-only
905 repository locked and read-only
892 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
906 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
893 (it is safe to interrupt this process any time before data migration completes)
907 (it is safe to interrupt this process any time before data migration completes)
894 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
908 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
895 migrating 519 KB in store; 1.05 MB tracked data
909 migrating 519 KB in store; 1.05 MB tracked data
896 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
910 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
897 cloning 1 revisions from data/FooBarDirectory.d/f1.i
911 cloning 1 revisions from data/FooBarDirectory.d/f1.i
898 cloning 1 revisions from data/f0.i
912 cloning 1 revisions from data/f0.i
899 cloning 1 revisions from data/f2.i
913 cloning 1 revisions from data/f2.i
900 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
914 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
901 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
915 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
902 cloning 3 revisions from 00manifest.i
916 cloning 3 revisions from 00manifest.i
903 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
917 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
904 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
918 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
905 cloning 3 revisions from 00changelog.i
919 cloning 3 revisions from 00changelog.i
906 finished migrating 3 changelog revisions; change in size: 0 bytes
920 finished migrating 3 changelog revisions; change in size: 0 bytes
907 finished migrating 9 total revisions; total change in store size: 0 bytes
921 finished migrating 9 total revisions; total change in store size: 0 bytes
908 copying phaseroots
922 copying phaseroots
909 data fully upgraded in a temporary repository
923 data fully upgraded in a temporary repository
910 marking source repository as being upgraded; clients will be unable to read from repository
924 marking source repository as being upgraded; clients will be unable to read from repository
911 starting in-place swap of repository data
925 starting in-place swap of repository data
912 replacing store...
926 replacing store...
913 store replacement complete; repository was inconsistent for *s (glob)
927 store replacement complete; repository was inconsistent for *s (glob)
914 finalizing requirements file and making repository readable again
928 finalizing requirements file and making repository readable again
915 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
929 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
916 $ hg verify
930 $ hg verify
917 checking changesets
931 checking changesets
918 checking manifests
932 checking manifests
919 crosschecking files in changesets and manifests
933 crosschecking files in changesets and manifests
920 checking files
934 checking files
921 checked 3 changesets with 3 changes to 3 files
935 checked 3 changesets with 3 changes to 3 files
922
936
923 Check you can't skip revlog clone during important format upgrade
937 Check you can't skip revlog clone during important format upgrade
924
938
925 $ echo "sparse-revlog=yes" >> .hg/hgrc
939 $ echo "sparse-revlog=yes" >> .hg/hgrc
926 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
940 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
927 ignoring revlogs selection flags, format requirements change: sparserevlog
941 ignoring revlogs selection flags, format requirements change: sparserevlog
928 upgrade will perform the following actions:
942 upgrade will perform the following actions:
929
943
930 requirements
944 requirements
931 preserved: dotencode, fncache, generaldelta, revlogv1, store
945 preserved: dotencode, fncache, generaldelta, revlogv1, store
932 added: sparserevlog
946 added: sparserevlog
933
947
934 optimisations: re-delta-parent
948 optimisations: re-delta-parent
935
949
936 sparserevlog
950 sparserevlog
937 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
951 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
938
952
939 re-delta-parent
953 re-delta-parent
940 deltas within internal storage will choose a new base revision if needed
954 deltas within internal storage will choose a new base revision if needed
941
955
942 processed revlogs:
956 processed revlogs:
943 - all-filelogs
957 - all-filelogs
944 - changelog
958 - changelog
945 - manifest
959 - manifest
946
960
947 beginning upgrade...
961 beginning upgrade...
948 repository locked and read-only
962 repository locked and read-only
949 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
963 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
950 (it is safe to interrupt this process any time before data migration completes)
964 (it is safe to interrupt this process any time before data migration completes)
951 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
965 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
952 migrating 519 KB in store; 1.05 MB tracked data
966 migrating 519 KB in store; 1.05 MB tracked data
953 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
967 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
954 cloning 1 revisions from data/FooBarDirectory.d/f1.i
968 cloning 1 revisions from data/FooBarDirectory.d/f1.i
955 cloning 1 revisions from data/f0.i
969 cloning 1 revisions from data/f0.i
956 cloning 1 revisions from data/f2.i
970 cloning 1 revisions from data/f2.i
957 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
971 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
958 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
972 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
959 cloning 3 revisions from 00manifest.i
973 cloning 3 revisions from 00manifest.i
960 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
974 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
961 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
975 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
962 cloning 3 revisions from 00changelog.i
976 cloning 3 revisions from 00changelog.i
963 finished migrating 3 changelog revisions; change in size: 0 bytes
977 finished migrating 3 changelog revisions; change in size: 0 bytes
964 finished migrating 9 total revisions; total change in store size: 0 bytes
978 finished migrating 9 total revisions; total change in store size: 0 bytes
965 copying phaseroots
979 copying phaseroots
966 data fully upgraded in a temporary repository
980 data fully upgraded in a temporary repository
967 marking source repository as being upgraded; clients will be unable to read from repository
981 marking source repository as being upgraded; clients will be unable to read from repository
968 starting in-place swap of repository data
982 starting in-place swap of repository data
969 replacing store...
983 replacing store...
970 store replacement complete; repository was inconsistent for *s (glob)
984 store replacement complete; repository was inconsistent for *s (glob)
971 finalizing requirements file and making repository readable again
985 finalizing requirements file and making repository readable again
972 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
986 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
973 $ hg verify
987 $ hg verify
974 checking changesets
988 checking changesets
975 checking manifests
989 checking manifests
976 crosschecking files in changesets and manifests
990 crosschecking files in changesets and manifests
977 checking files
991 checking files
978 checked 3 changesets with 3 changes to 3 files
992 checked 3 changesets with 3 changes to 3 files
979
993
980 $ cd ..
994 $ cd ..
981
995
982 store files with special filenames aren't encoded during copy
996 store files with special filenames aren't encoded during copy
983
997
984 $ hg init store-filenames
998 $ hg init store-filenames
985 $ cd store-filenames
999 $ cd store-filenames
986 $ touch foo
1000 $ touch foo
987 $ hg -q commit -A -m initial
1001 $ hg -q commit -A -m initial
988 $ touch .hg/store/.XX_special_filename
1002 $ touch .hg/store/.XX_special_filename
989
1003
990 $ hg debugupgraderepo --run
1004 $ hg debugupgraderepo --run
991 nothing to do
1005 nothing to do
992 $ hg debugupgraderepo --run --optimize 're-delta-fulladd'
1006 $ hg debugupgraderepo --run --optimize 're-delta-fulladd'
993 upgrade will perform the following actions:
1007 upgrade will perform the following actions:
994
1008
995 requirements
1009 requirements
996 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1010 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
997
1011
998 optimisations: re-delta-fulladd
1012 optimisations: re-delta-fulladd
999
1013
1000 re-delta-fulladd
1014 re-delta-fulladd
1001 each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it
1015 each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it
1002
1016
1003 processed revlogs:
1017 processed revlogs:
1004 - all-filelogs
1018 - all-filelogs
1005 - changelog
1019 - changelog
1006 - manifest
1020 - manifest
1007
1021
1008 beginning upgrade...
1022 beginning upgrade...
1009 repository locked and read-only
1023 repository locked and read-only
1010 creating temporary repository to stage upgraded data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
1024 creating temporary repository to stage upgraded data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
1011 (it is safe to interrupt this process any time before data migration completes)
1025 (it is safe to interrupt this process any time before data migration completes)
1012 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
1026 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
1013 migrating 301 bytes in store; 107 bytes tracked data
1027 migrating 301 bytes in store; 107 bytes tracked data
1014 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
1028 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
1015 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
1029 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
1016 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
1030 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
1017 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
1031 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
1018 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
1032 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
1019 finished migrating 1 changelog revisions; change in size: 0 bytes
1033 finished migrating 1 changelog revisions; change in size: 0 bytes
1020 finished migrating 3 total revisions; total change in store size: 0 bytes
1034 finished migrating 3 total revisions; total change in store size: 0 bytes
1021 copying .XX_special_filename
1035 copying .XX_special_filename
1022 copying phaseroots
1036 copying phaseroots
1023 data fully upgraded in a temporary repository
1037 data fully upgraded in a temporary repository
1024 marking source repository as being upgraded; clients will be unable to read from repository
1038 marking source repository as being upgraded; clients will be unable to read from repository
1025 starting in-place swap of repository data
1039 starting in-place swap of repository data
1026 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
1040 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
1027 replacing store...
1041 replacing store...
1028 store replacement complete; repository was inconsistent for *s (glob)
1042 store replacement complete; repository was inconsistent for *s (glob)
1029 finalizing requirements file and making repository readable again
1043 finalizing requirements file and making repository readable again
1030 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
1044 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
1031 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
1045 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
1032 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
1046 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
1033
1047
1034 fncache is valid after upgrade
1048 fncache is valid after upgrade
1035
1049
1036 $ hg debugrebuildfncache
1050 $ hg debugrebuildfncache
1037 fncache already up to date
1051 fncache already up to date
1038
1052
1039 $ cd ..
1053 $ cd ..
1040
1054
1041 Check upgrading a large file repository
1055 Check upgrading a large file repository
1042 ---------------------------------------
1056 ---------------------------------------
1043
1057
1044 $ hg init largefilesrepo
1058 $ hg init largefilesrepo
1045 $ cat << EOF >> largefilesrepo/.hg/hgrc
1059 $ cat << EOF >> largefilesrepo/.hg/hgrc
1046 > [extensions]
1060 > [extensions]
1047 > largefiles =
1061 > largefiles =
1048 > EOF
1062 > EOF
1049
1063
1050 $ cd largefilesrepo
1064 $ cd largefilesrepo
1051 $ touch foo
1065 $ touch foo
1052 $ hg add --large foo
1066 $ hg add --large foo
1053 $ hg -q commit -m initial
1067 $ hg -q commit -m initial
1054 $ cat .hg/requires
1068 $ cat .hg/requires
1055 dotencode
1069 dotencode
1056 fncache
1070 fncache
1057 generaldelta
1071 generaldelta
1058 largefiles
1072 largefiles
1059 revlogv1
1073 revlogv1
1060 sparserevlog
1074 sparserevlog
1061 store
1075 store
1062
1076
1063 $ hg debugupgraderepo --run
1077 $ hg debugupgraderepo --run
1064 nothing to do
1078 nothing to do
1065 $ cat .hg/requires
1079 $ cat .hg/requires
1066 dotencode
1080 dotencode
1067 fncache
1081 fncache
1068 generaldelta
1082 generaldelta
1069 largefiles
1083 largefiles
1070 revlogv1
1084 revlogv1
1071 sparserevlog
1085 sparserevlog
1072 store
1086 store
1073
1087
1074 $ cat << EOF >> .hg/hgrc
1088 $ cat << EOF >> .hg/hgrc
1075 > [extensions]
1089 > [extensions]
1076 > lfs =
1090 > lfs =
1077 > [lfs]
1091 > [lfs]
1078 > threshold = 10
1092 > threshold = 10
1079 > EOF
1093 > EOF
1080 $ echo '123456789012345' > lfs.bin
1094 $ echo '123456789012345' > lfs.bin
1081 $ hg ci -Am 'lfs.bin'
1095 $ hg ci -Am 'lfs.bin'
1082 adding lfs.bin
1096 adding lfs.bin
1083 $ grep lfs .hg/requires
1097 $ grep lfs .hg/requires
1084 lfs
1098 lfs
1085 $ find .hg/store/lfs -type f
1099 $ find .hg/store/lfs -type f
1086 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1100 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1087
1101
1088 $ hg debugupgraderepo --run
1102 $ hg debugupgraderepo --run
1089 nothing to do
1103 nothing to do
1090
1104
1091 $ grep lfs .hg/requires
1105 $ grep lfs .hg/requires
1092 lfs
1106 lfs
1093 $ find .hg/store/lfs -type f
1107 $ find .hg/store/lfs -type f
1094 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1108 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1095 $ hg verify
1109 $ hg verify
1096 checking changesets
1110 checking changesets
1097 checking manifests
1111 checking manifests
1098 crosschecking files in changesets and manifests
1112 crosschecking files in changesets and manifests
1099 checking files
1113 checking files
1100 checked 2 changesets with 2 changes to 2 files
1114 checked 2 changesets with 2 changes to 2 files
1101 $ hg debugdata lfs.bin 0
1115 $ hg debugdata lfs.bin 0
1102 version https://git-lfs.github.com/spec/v1
1116 version https://git-lfs.github.com/spec/v1
1103 oid sha256:d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1117 oid sha256:d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1104 size 16
1118 size 16
1105 x-is-binary 0
1119 x-is-binary 0
1106
1120
1107 $ cd ..
1121 $ cd ..
1108
1122
1109 repository config is taken in account
1123 repository config is taken in account
1110 -------------------------------------
1124 -------------------------------------
1111
1125
1112 $ cat << EOF >> $HGRCPATH
1126 $ cat << EOF >> $HGRCPATH
1113 > [format]
1127 > [format]
1114 > maxchainlen = 1
1128 > maxchainlen = 1
1115 > EOF
1129 > EOF
1116
1130
1117 $ hg init localconfig
1131 $ hg init localconfig
1118 $ cd localconfig
1132 $ cd localconfig
1119 $ cat << EOF > file
1133 $ cat << EOF > file
1120 > some content
1134 > some content
1121 > with some length
1135 > with some length
1122 > to make sure we get a delta
1136 > to make sure we get a delta
1123 > after changes
1137 > after changes
1124 > very long
1138 > very long
1125 > very long
1139 > very long
1126 > very long
1140 > very long
1127 > very long
1141 > very long
1128 > very long
1142 > very long
1129 > very long
1143 > very long
1130 > very long
1144 > very long
1131 > very long
1145 > very long
1132 > very long
1146 > very long
1133 > very long
1147 > very long
1134 > very long
1148 > very long
1135 > EOF
1149 > EOF
1136 $ hg -q commit -A -m A
1150 $ hg -q commit -A -m A
1137 $ echo "new line" >> file
1151 $ echo "new line" >> file
1138 $ hg -q commit -m B
1152 $ hg -q commit -m B
1139 $ echo "new line" >> file
1153 $ echo "new line" >> file
1140 $ hg -q commit -m C
1154 $ hg -q commit -m C
1141
1155
1142 $ cat << EOF >> .hg/hgrc
1156 $ cat << EOF >> .hg/hgrc
1143 > [format]
1157 > [format]
1144 > maxchainlen = 9001
1158 > maxchainlen = 9001
1145 > EOF
1159 > EOF
1146 $ hg config format
1160 $ hg config format
1147 format.maxchainlen=9001
1161 format.maxchainlen=9001
1148 $ hg debugdeltachain file
1162 $ hg debugdeltachain file
1149 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
1163 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
1150 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
1164 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
1151 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
1165 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
1152 2 1 2 0 other 30 200 107 0.53500 128 21 0.19626 128 128 0.83594 1
1166 2 1 2 0 other 30 200 107 0.53500 128 21 0.19626 128 128 0.83594 1
1153
1167
1154 $ hg debugupgraderepo --run --optimize 're-delta-all'
1168 $ hg debugupgraderepo --run --optimize 're-delta-all'
1155 upgrade will perform the following actions:
1169 upgrade will perform the following actions:
1156
1170
1157 requirements
1171 requirements
1158 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1172 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1159
1173
1160 optimisations: re-delta-all
1174 optimisations: re-delta-all
1161
1175
1162 re-delta-all
1176 re-delta-all
1163 deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time
1177 deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time
1164
1178
1165 processed revlogs:
1179 processed revlogs:
1166 - all-filelogs
1180 - all-filelogs
1167 - changelog
1181 - changelog
1168 - manifest
1182 - manifest
1169
1183
1170 beginning upgrade...
1184 beginning upgrade...
1171 repository locked and read-only
1185 repository locked and read-only
1172 creating temporary repository to stage upgraded data: $TESTTMP/localconfig/.hg/upgrade.* (glob)
1186 creating temporary repository to stage upgraded data: $TESTTMP/localconfig/.hg/upgrade.* (glob)
1173 (it is safe to interrupt this process any time before data migration completes)
1187 (it is safe to interrupt this process any time before data migration completes)
1174 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1188 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1175 migrating 1019 bytes in store; 882 bytes tracked data
1189 migrating 1019 bytes in store; 882 bytes tracked data
1176 migrating 1 filelogs containing 3 revisions (320 bytes in store; 573 bytes tracked data)
1190 migrating 1 filelogs containing 3 revisions (320 bytes in store; 573 bytes tracked data)
1177 finished migrating 3 filelog revisions across 1 filelogs; change in size: -9 bytes
1191 finished migrating 3 filelog revisions across 1 filelogs; change in size: -9 bytes
1178 migrating 1 manifests containing 3 revisions (333 bytes in store; 138 bytes tracked data)
1192 migrating 1 manifests containing 3 revisions (333 bytes in store; 138 bytes tracked data)
1179 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1193 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1180 migrating changelog containing 3 revisions (366 bytes in store; 171 bytes tracked data)
1194 migrating changelog containing 3 revisions (366 bytes in store; 171 bytes tracked data)
1181 finished migrating 3 changelog revisions; change in size: 0 bytes
1195 finished migrating 3 changelog revisions; change in size: 0 bytes
1182 finished migrating 9 total revisions; total change in store size: -9 bytes
1196 finished migrating 9 total revisions; total change in store size: -9 bytes
1183 copying phaseroots
1197 copying phaseroots
1184 data fully upgraded in a temporary repository
1198 data fully upgraded in a temporary repository
1185 marking source repository as being upgraded; clients will be unable to read from repository
1199 marking source repository as being upgraded; clients will be unable to read from repository
1186 starting in-place swap of repository data
1200 starting in-place swap of repository data
1187 replaced files will be backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
1201 replaced files will be backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
1188 replacing store...
1202 replacing store...
1189 store replacement complete; repository was inconsistent for *s (glob)
1203 store replacement complete; repository was inconsistent for *s (glob)
1190 finalizing requirements file and making repository readable again
1204 finalizing requirements file and making repository readable again
1191 removing temporary repository $TESTTMP/localconfig/.hg/upgrade.* (glob)
1205 removing temporary repository $TESTTMP/localconfig/.hg/upgrade.* (glob)
1192 copy of old repository backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
1206 copy of old repository backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
1193 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
1207 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
1194 $ hg debugdeltachain file
1208 $ hg debugdeltachain file
1195 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
1209 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
1196 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
1210 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
1197 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
1211 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
1198 2 1 3 1 p1 21 200 119 0.59500 119 0 0.00000 119 119 1.00000 1
1212 2 1 3 1 p1 21 200 119 0.59500 119 0 0.00000 119 119 1.00000 1
1199 $ cd ..
1213 $ cd ..
1200
1214
1201 $ cat << EOF >> $HGRCPATH
1215 $ cat << EOF >> $HGRCPATH
1202 > [format]
1216 > [format]
1203 > maxchainlen = 9001
1217 > maxchainlen = 9001
1204 > EOF
1218 > EOF
1205
1219
1206 Check upgrading a sparse-revlog repository
1220 Check upgrading a sparse-revlog repository
1207 ---------------------------------------
1221 ---------------------------------------
1208
1222
1209 $ hg init sparserevlogrepo --config format.sparse-revlog=no
1223 $ hg init sparserevlogrepo --config format.sparse-revlog=no
1210 $ cd sparserevlogrepo
1224 $ cd sparserevlogrepo
1211 $ touch foo
1225 $ touch foo
1212 $ hg add foo
1226 $ hg add foo
1213 $ hg -q commit -m "foo"
1227 $ hg -q commit -m "foo"
1214 $ cat .hg/requires
1228 $ cat .hg/requires
1215 dotencode
1229 dotencode
1216 fncache
1230 fncache
1217 generaldelta
1231 generaldelta
1218 revlogv1
1232 revlogv1
1219 store
1233 store
1220
1234
1221 Check that we can add the sparse-revlog format requirement
1235 Check that we can add the sparse-revlog format requirement
1222 $ hg --config format.sparse-revlog=yes debugupgraderepo --run --quiet
1236 $ hg --config format.sparse-revlog=yes debugupgraderepo --run --quiet
1223 upgrade will perform the following actions:
1237 upgrade will perform the following actions:
1224
1238
1225 requirements
1239 requirements
1226 preserved: dotencode, fncache, generaldelta, revlogv1, store
1240 preserved: dotencode, fncache, generaldelta, revlogv1, store
1227 added: sparserevlog
1241 added: sparserevlog
1228
1242
1229 processed revlogs:
1243 processed revlogs:
1230 - all-filelogs
1244 - all-filelogs
1231 - changelog
1245 - changelog
1232 - manifest
1246 - manifest
1233
1247
1234 $ cat .hg/requires
1248 $ cat .hg/requires
1235 dotencode
1249 dotencode
1236 fncache
1250 fncache
1237 generaldelta
1251 generaldelta
1238 revlogv1
1252 revlogv1
1239 sparserevlog
1253 sparserevlog
1240 store
1254 store
1241
1255
1242 Check that we can remove the sparse-revlog format requirement
1256 Check that we can remove the sparse-revlog format requirement
1243 $ hg --config format.sparse-revlog=no debugupgraderepo --run --quiet
1257 $ hg --config format.sparse-revlog=no debugupgraderepo --run --quiet
1244 upgrade will perform the following actions:
1258 upgrade will perform the following actions:
1245
1259
1246 requirements
1260 requirements
1247 preserved: dotencode, fncache, generaldelta, revlogv1, store
1261 preserved: dotencode, fncache, generaldelta, revlogv1, store
1248 removed: sparserevlog
1262 removed: sparserevlog
1249
1263
1250 processed revlogs:
1264 processed revlogs:
1251 - all-filelogs
1265 - all-filelogs
1252 - changelog
1266 - changelog
1253 - manifest
1267 - manifest
1254
1268
1255 $ cat .hg/requires
1269 $ cat .hg/requires
1256 dotencode
1270 dotencode
1257 fncache
1271 fncache
1258 generaldelta
1272 generaldelta
1259 revlogv1
1273 revlogv1
1260 store
1274 store
1261
1275
1262 #if zstd
1276 #if zstd
1263
1277
1264 Check upgrading to a zstd revlog
1278 Check upgrading to a zstd revlog
1265 --------------------------------
1279 --------------------------------
1266
1280
1267 upgrade
1281 upgrade
1268
1282
1269 $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup --quiet
1283 $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup --quiet
1270 upgrade will perform the following actions:
1284 upgrade will perform the following actions:
1271
1285
1272 requirements
1286 requirements
1273 preserved: dotencode, fncache, generaldelta, revlogv1, store
1287 preserved: dotencode, fncache, generaldelta, revlogv1, store
1274 added: revlog-compression-zstd, sparserevlog
1288 added: revlog-compression-zstd, sparserevlog
1275
1289
1276 processed revlogs:
1290 processed revlogs:
1277 - all-filelogs
1291 - all-filelogs
1278 - changelog
1292 - changelog
1279 - manifest
1293 - manifest
1280
1294
1281 $ hg debugformat -v
1295 $ hg debugformat -v
1282 format-variant repo config default
1296 format-variant repo config default
1283 fncache: yes yes yes
1297 fncache: yes yes yes
1284 dotencode: yes yes yes
1298 dotencode: yes yes yes
1285 generaldelta: yes yes yes
1299 generaldelta: yes yes yes
1286 share-safe: no no no
1300 share-safe: no no no
1287 sparserevlog: yes yes yes
1301 sparserevlog: yes yes yes
1288 sidedata: no no no
1302 sidedata: no no no
1289 persistent-nodemap: no no no
1303 persistent-nodemap: no no no
1290 copies-sdc: no no no
1304 copies-sdc: no no no
1305 revlog-v2: no no no
1291 plain-cl-delta: yes yes yes
1306 plain-cl-delta: yes yes yes
1292 compression: zstd zlib zlib
1307 compression: zstd zlib zlib
1293 compression-level: default default default
1308 compression-level: default default default
1294 $ cat .hg/requires
1309 $ cat .hg/requires
1295 dotencode
1310 dotencode
1296 fncache
1311 fncache
1297 generaldelta
1312 generaldelta
1298 revlog-compression-zstd
1313 revlog-compression-zstd
1299 revlogv1
1314 revlogv1
1300 sparserevlog
1315 sparserevlog
1301 store
1316 store
1302
1317
1303 downgrade
1318 downgrade
1304
1319
1305 $ hg debugupgraderepo --run --no-backup --quiet
1320 $ hg debugupgraderepo --run --no-backup --quiet
1306 upgrade will perform the following actions:
1321 upgrade will perform the following actions:
1307
1322
1308 requirements
1323 requirements
1309 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1324 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1310 removed: revlog-compression-zstd
1325 removed: revlog-compression-zstd
1311
1326
1312 processed revlogs:
1327 processed revlogs:
1313 - all-filelogs
1328 - all-filelogs
1314 - changelog
1329 - changelog
1315 - manifest
1330 - manifest
1316
1331
1317 $ hg debugformat -v
1332 $ hg debugformat -v
1318 format-variant repo config default
1333 format-variant repo config default
1319 fncache: yes yes yes
1334 fncache: yes yes yes
1320 dotencode: yes yes yes
1335 dotencode: yes yes yes
1321 generaldelta: yes yes yes
1336 generaldelta: yes yes yes
1322 share-safe: no no no
1337 share-safe: no no no
1323 sparserevlog: yes yes yes
1338 sparserevlog: yes yes yes
1324 sidedata: no no no
1339 sidedata: no no no
1325 persistent-nodemap: no no no
1340 persistent-nodemap: no no no
1326 copies-sdc: no no no
1341 copies-sdc: no no no
1342 revlog-v2: no no no
1327 plain-cl-delta: yes yes yes
1343 plain-cl-delta: yes yes yes
1328 compression: zlib zlib zlib
1344 compression: zlib zlib zlib
1329 compression-level: default default default
1345 compression-level: default default default
1330 $ cat .hg/requires
1346 $ cat .hg/requires
1331 dotencode
1347 dotencode
1332 fncache
1348 fncache
1333 generaldelta
1349 generaldelta
1334 revlogv1
1350 revlogv1
1335 sparserevlog
1351 sparserevlog
1336 store
1352 store
1337
1353
1338 upgrade from hgrc
1354 upgrade from hgrc
1339
1355
1340 $ cat >> .hg/hgrc << EOF
1356 $ cat >> .hg/hgrc << EOF
1341 > [format]
1357 > [format]
1342 > revlog-compression=zstd
1358 > revlog-compression=zstd
1343 > EOF
1359 > EOF
1344 $ hg debugupgraderepo --run --no-backup --quiet
1360 $ hg debugupgraderepo --run --no-backup --quiet
1345 upgrade will perform the following actions:
1361 upgrade will perform the following actions:
1346
1362
1347 requirements
1363 requirements
1348 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1364 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
1349 added: revlog-compression-zstd
1365 added: revlog-compression-zstd
1350
1366
1351 processed revlogs:
1367 processed revlogs:
1352 - all-filelogs
1368 - all-filelogs
1353 - changelog
1369 - changelog
1354 - manifest
1370 - manifest
1355
1371
1356 $ hg debugformat -v
1372 $ hg debugformat -v
1357 format-variant repo config default
1373 format-variant repo config default
1358 fncache: yes yes yes
1374 fncache: yes yes yes
1359 dotencode: yes yes yes
1375 dotencode: yes yes yes
1360 generaldelta: yes yes yes
1376 generaldelta: yes yes yes
1361 share-safe: no no no
1377 share-safe: no no no
1362 sparserevlog: yes yes yes
1378 sparserevlog: yes yes yes
1363 sidedata: no no no
1379 sidedata: no no no
1364 persistent-nodemap: no no no
1380 persistent-nodemap: no no no
1365 copies-sdc: no no no
1381 copies-sdc: no no no
1382 revlog-v2: no no no
1366 plain-cl-delta: yes yes yes
1383 plain-cl-delta: yes yes yes
1367 compression: zstd zstd zlib
1384 compression: zstd zstd zlib
1368 compression-level: default default default
1385 compression-level: default default default
1369 $ cat .hg/requires
1386 $ cat .hg/requires
1370 dotencode
1387 dotencode
1371 fncache
1388 fncache
1372 generaldelta
1389 generaldelta
1373 revlog-compression-zstd
1390 revlog-compression-zstd
1374 revlogv1
1391 revlogv1
1375 sparserevlog
1392 sparserevlog
1376 store
1393 store
1377
1394
1378 #endif
1395 #endif
1379
1396
1380 Check upgrading to a side-data revlog
1397 Check upgrading to a side-data revlog
1381 -------------------------------------
1398 -------------------------------------
1382
1399
1383 upgrade
1400 upgrade
1384
1401
1385 $ hg --config format.exp-use-side-data=yes debugupgraderepo --run --no-backup --config "extensions.sidedata=$TESTDIR/testlib/ext-sidedata.py" --quiet
1402 $ hg --config format.exp-use-side-data=yes debugupgraderepo --run --no-backup --config "extensions.sidedata=$TESTDIR/testlib/ext-sidedata.py" --quiet
1386 upgrade will perform the following actions:
1403 upgrade will perform the following actions:
1387
1404
1388 requirements
1405 requirements
1389 preserved: dotencode, fncache, generaldelta, revlogv1, store (no-zstd !)
1406 preserved: dotencode, fncache, generaldelta, store (no-zstd !)
1390 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
1407 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, sparserevlog, store (zstd !)
1391 added: exp-sidedata-flag (zstd !)
1408 removed: revlogv1
1392 added: exp-sidedata-flag, sparserevlog (no-zstd !)
1409 added: exp-revlogv2.2, exp-sidedata-flag (zstd !)
1410 added: exp-revlogv2.2, exp-sidedata-flag, sparserevlog (no-zstd !)
1393
1411
1394 processed revlogs:
1412 processed revlogs:
1395 - all-filelogs
1413 - all-filelogs
1396 - changelog
1414 - changelog
1397 - manifest
1415 - manifest
1398
1416
1399 $ hg debugformat -v
1417 $ hg debugformat -v
1400 format-variant repo config default
1418 format-variant repo config default
1401 fncache: yes yes yes
1419 fncache: yes yes yes
1402 dotencode: yes yes yes
1420 dotencode: yes yes yes
1403 generaldelta: yes yes yes
1421 generaldelta: yes yes yes
1404 share-safe: no no no
1422 share-safe: no no no
1405 sparserevlog: yes yes yes
1423 sparserevlog: yes yes yes
1406 sidedata: yes no no
1424 sidedata: yes no no
1407 persistent-nodemap: no no no
1425 persistent-nodemap: no no no
1408 copies-sdc: no no no
1426 copies-sdc: no no no
1427 revlog-v2: yes no no
1409 plain-cl-delta: yes yes yes
1428 plain-cl-delta: yes yes yes
1410 compression: zlib zlib zlib (no-zstd !)
1429 compression: zlib zlib zlib (no-zstd !)
1411 compression: zstd zstd zlib (zstd !)
1430 compression: zstd zstd zlib (zstd !)
1412 compression-level: default default default
1431 compression-level: default default default
1413 $ cat .hg/requires
1432 $ cat .hg/requires
1414 dotencode
1433 dotencode
1434 exp-revlogv2.2
1415 exp-sidedata-flag
1435 exp-sidedata-flag
1416 fncache
1436 fncache
1417 generaldelta
1437 generaldelta
1418 revlog-compression-zstd (zstd !)
1438 revlog-compression-zstd (zstd !)
1419 revlogv1
1420 sparserevlog
1439 sparserevlog
1421 store
1440 store
1422 $ hg debugsidedata -c 0
1441 $ hg debugsidedata -c 0
1423 2 sidedata entries
1442 2 sidedata entries
1424 entry-0001 size 4
1443 entry-0001 size 4
1425 entry-0002 size 32
1444 entry-0002 size 32
1426
1445
1427 downgrade
1446 downgrade
1428
1447
1429 $ hg debugupgraderepo --config format.exp-use-side-data=no --run --no-backup --quiet
1448 $ hg debugupgraderepo --config format.exp-use-side-data=no --run --no-backup --quiet
1430 upgrade will perform the following actions:
1449 upgrade will perform the following actions:
1431
1450
1432 requirements
1451 requirements
1433 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd !)
1452 preserved: dotencode, fncache, generaldelta, sparserevlog, store (no-zstd !)
1434 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
1453 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, sparserevlog, store (zstd !)
1435 removed: exp-sidedata-flag
1454 removed: exp-revlogv2.2, exp-sidedata-flag
1455 added: revlogv1
1436
1456
1437 processed revlogs:
1457 processed revlogs:
1438 - all-filelogs
1458 - all-filelogs
1439 - changelog
1459 - changelog
1440 - manifest
1460 - manifest
1441
1461
1442 $ hg debugformat -v
1462 $ hg debugformat -v
1443 format-variant repo config default
1463 format-variant repo config default
1444 fncache: yes yes yes
1464 fncache: yes yes yes
1445 dotencode: yes yes yes
1465 dotencode: yes yes yes
1446 generaldelta: yes yes yes
1466 generaldelta: yes yes yes
1447 share-safe: no no no
1467 share-safe: no no no
1448 sparserevlog: yes yes yes
1468 sparserevlog: yes yes yes
1449 sidedata: no no no
1469 sidedata: no no no
1450 persistent-nodemap: no no no
1470 persistent-nodemap: no no no
1451 copies-sdc: no no no
1471 copies-sdc: no no no
1472 revlog-v2: no no no
1452 plain-cl-delta: yes yes yes
1473 plain-cl-delta: yes yes yes
1453 compression: zlib zlib zlib (no-zstd !)
1474 compression: zlib zlib zlib (no-zstd !)
1454 compression: zstd zstd zlib (zstd !)
1475 compression: zstd zstd zlib (zstd !)
1455 compression-level: default default default
1476 compression-level: default default default
1456 $ cat .hg/requires
1477 $ cat .hg/requires
1457 dotencode
1478 dotencode
1458 fncache
1479 fncache
1459 generaldelta
1480 generaldelta
1460 revlog-compression-zstd (zstd !)
1481 revlog-compression-zstd (zstd !)
1461 revlogv1
1482 revlogv1
1462 sparserevlog
1483 sparserevlog
1463 store
1484 store
1464 $ hg debugsidedata -c 0
1485 $ hg debugsidedata -c 0
1465
1486
1466 upgrade from hgrc
1487 upgrade from hgrc
1467
1488
1468 $ cat >> .hg/hgrc << EOF
1489 $ cat >> .hg/hgrc << EOF
1469 > [format]
1490 > [format]
1470 > exp-use-side-data=yes
1491 > exp-use-side-data=yes
1471 > EOF
1492 > EOF
1472 $ hg debugupgraderepo --run --no-backup --quiet
1493 $ hg debugupgraderepo --run --no-backup --quiet
1473 upgrade will perform the following actions:
1494 upgrade will perform the following actions:
1474
1495
1475 requirements
1496 requirements
1476 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd !)
1497 preserved: dotencode, fncache, generaldelta, sparserevlog, store (no-zstd !)
1477 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
1498 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, sparserevlog, store (zstd !)
1478 added: exp-sidedata-flag
1499 removed: revlogv1
1500 added: exp-revlogv2.2, exp-sidedata-flag
1479
1501
1480 processed revlogs:
1502 processed revlogs:
1481 - all-filelogs
1503 - all-filelogs
1482 - changelog
1504 - changelog
1483 - manifest
1505 - manifest
1484
1506
1485 $ hg debugformat -v
1507 $ hg debugformat -v
1486 format-variant repo config default
1508 format-variant repo config default
1487 fncache: yes yes yes
1509 fncache: yes yes yes
1488 dotencode: yes yes yes
1510 dotencode: yes yes yes
1489 generaldelta: yes yes yes
1511 generaldelta: yes yes yes
1490 share-safe: no no no
1512 share-safe: no no no
1491 sparserevlog: yes yes yes
1513 sparserevlog: yes yes yes
1492 sidedata: yes yes no
1514 sidedata: yes yes no
1493 persistent-nodemap: no no no
1515 persistent-nodemap: no no no
1494 copies-sdc: no no no
1516 copies-sdc: no no no
1517 revlog-v2: yes yes no
1495 plain-cl-delta: yes yes yes
1518 plain-cl-delta: yes yes yes
1496 compression: zlib zlib zlib (no-zstd !)
1519 compression: zlib zlib zlib (no-zstd !)
1497 compression: zstd zstd zlib (zstd !)
1520 compression: zstd zstd zlib (zstd !)
1498 compression-level: default default default
1521 compression-level: default default default
1499 $ cat .hg/requires
1522 $ cat .hg/requires
1500 dotencode
1523 dotencode
1524 exp-revlogv2.2
1501 exp-sidedata-flag
1525 exp-sidedata-flag
1502 fncache
1526 fncache
1503 generaldelta
1527 generaldelta
1504 revlog-compression-zstd (zstd !)
1528 revlog-compression-zstd (zstd !)
1505 revlogv1
1506 sparserevlog
1529 sparserevlog
1507 store
1530 store
1508 $ hg debugsidedata -c 0
1531 $ hg debugsidedata -c 0
1509
1532
1510 Demonstrate that nothing to perform upgrade will still run all the way through
1533 Demonstrate that nothing to perform upgrade will still run all the way through
1511
1534
1512 $ hg debugupgraderepo --run
1535 $ hg debugupgraderepo --run
1513 nothing to do
1536 nothing to do
General Comments 0
You need to be logged in to leave comments. Login now