##// END OF EJS Templates
phase: rename the requirement for internal-phase (BC)...
marmoute -
r50347:74fb1842 default
parent child Browse files
Show More
@@ -1,2874 +1,2877 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
8
9 import functools
9 import functools
10 import re
10 import re
11
11
12 from . import (
12 from . import (
13 encoding,
13 encoding,
14 error,
14 error,
15 )
15 )
16
16
17
17
18 def loadconfigtable(ui, extname, configtable):
18 def loadconfigtable(ui, extname, configtable):
19 """update config item known to the ui with the extension ones"""
19 """update config item known to the ui with the extension ones"""
20 for section, items in sorted(configtable.items()):
20 for section, items in sorted(configtable.items()):
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 knownkeys = set(knownitems)
22 knownkeys = set(knownitems)
23 newkeys = set(items)
23 newkeys = set(items)
24 for key in sorted(knownkeys & newkeys):
24 for key in sorted(knownkeys & newkeys):
25 msg = b"extension '%s' overwrite config item '%s.%s'"
25 msg = b"extension '%s' overwrite config item '%s.%s'"
26 msg %= (extname, section, key)
26 msg %= (extname, section, key)
27 ui.develwarn(msg, config=b'warn-config')
27 ui.develwarn(msg, config=b'warn-config')
28
28
29 knownitems.update(items)
29 knownitems.update(items)
30
30
31
31
32 class configitem:
32 class configitem:
33 """represent a known config item
33 """represent a known config item
34
34
35 :section: the official config section where to find this item,
35 :section: the official config section where to find this item,
36 :name: the official name within the section,
36 :name: the official name within the section,
37 :default: default value for this item,
37 :default: default value for this item,
38 :alias: optional list of tuples as alternatives,
38 :alias: optional list of tuples as alternatives,
39 :generic: this is a generic definition, match name using regular expression.
39 :generic: this is a generic definition, match name using regular expression.
40 """
40 """
41
41
42 def __init__(
42 def __init__(
43 self,
43 self,
44 section,
44 section,
45 name,
45 name,
46 default=None,
46 default=None,
47 alias=(),
47 alias=(),
48 generic=False,
48 generic=False,
49 priority=0,
49 priority=0,
50 experimental=False,
50 experimental=False,
51 ):
51 ):
52 self.section = section
52 self.section = section
53 self.name = name
53 self.name = name
54 self.default = default
54 self.default = default
55 self.alias = list(alias)
55 self.alias = list(alias)
56 self.generic = generic
56 self.generic = generic
57 self.priority = priority
57 self.priority = priority
58 self.experimental = experimental
58 self.experimental = experimental
59 self._re = None
59 self._re = None
60 if generic:
60 if generic:
61 self._re = re.compile(self.name)
61 self._re = re.compile(self.name)
62
62
63
63
64 class itemregister(dict):
64 class itemregister(dict):
65 """A specialized dictionary that can handle wild-card selection"""
65 """A specialized dictionary that can handle wild-card selection"""
66
66
67 def __init__(self):
67 def __init__(self):
68 super(itemregister, self).__init__()
68 super(itemregister, self).__init__()
69 self._generics = set()
69 self._generics = set()
70
70
71 def update(self, other):
71 def update(self, other):
72 super(itemregister, self).update(other)
72 super(itemregister, self).update(other)
73 self._generics.update(other._generics)
73 self._generics.update(other._generics)
74
74
75 def __setitem__(self, key, item):
75 def __setitem__(self, key, item):
76 super(itemregister, self).__setitem__(key, item)
76 super(itemregister, self).__setitem__(key, item)
77 if item.generic:
77 if item.generic:
78 self._generics.add(item)
78 self._generics.add(item)
79
79
80 def get(self, key):
80 def get(self, key):
81 baseitem = super(itemregister, self).get(key)
81 baseitem = super(itemregister, self).get(key)
82 if baseitem is not None and not baseitem.generic:
82 if baseitem is not None and not baseitem.generic:
83 return baseitem
83 return baseitem
84
84
85 # search for a matching generic item
85 # search for a matching generic item
86 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
86 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
87 for item in generics:
87 for item in generics:
88 # we use 'match' instead of 'search' to make the matching simpler
88 # we use 'match' instead of 'search' to make the matching simpler
89 # for people unfamiliar with regular expression. Having the match
89 # for people unfamiliar with regular expression. Having the match
90 # rooted to the start of the string will produce less surprising
90 # rooted to the start of the string will produce less surprising
91 # result for user writing simple regex for sub-attribute.
91 # result for user writing simple regex for sub-attribute.
92 #
92 #
93 # For example using "color\..*" match produces an unsurprising
93 # For example using "color\..*" match produces an unsurprising
94 # result, while using search could suddenly match apparently
94 # result, while using search could suddenly match apparently
95 # unrelated configuration that happens to contains "color."
95 # unrelated configuration that happens to contains "color."
96 # anywhere. This is a tradeoff where we favor requiring ".*" on
96 # anywhere. This is a tradeoff where we favor requiring ".*" on
97 # some match to avoid the need to prefix most pattern with "^".
97 # some match to avoid the need to prefix most pattern with "^".
98 # The "^" seems more error prone.
98 # The "^" seems more error prone.
99 if item._re.match(key):
99 if item._re.match(key):
100 return item
100 return item
101
101
102 return None
102 return None
103
103
104
104
105 coreitems = {}
105 coreitems = {}
106
106
107
107
108 def _register(configtable, *args, **kwargs):
108 def _register(configtable, *args, **kwargs):
109 item = configitem(*args, **kwargs)
109 item = configitem(*args, **kwargs)
110 section = configtable.setdefault(item.section, itemregister())
110 section = configtable.setdefault(item.section, itemregister())
111 if item.name in section:
111 if item.name in section:
112 msg = b"duplicated config item registration for '%s.%s'"
112 msg = b"duplicated config item registration for '%s.%s'"
113 raise error.ProgrammingError(msg % (item.section, item.name))
113 raise error.ProgrammingError(msg % (item.section, item.name))
114 section[item.name] = item
114 section[item.name] = item
115
115
116
116
117 # special value for case where the default is derived from other values
117 # special value for case where the default is derived from other values
118 dynamicdefault = object()
118 dynamicdefault = object()
119
119
120 # Registering actual config items
120 # Registering actual config items
121
121
122
122
123 def getitemregister(configtable):
123 def getitemregister(configtable):
124 f = functools.partial(_register, configtable)
124 f = functools.partial(_register, configtable)
125 # export pseudo enum as configitem.*
125 # export pseudo enum as configitem.*
126 f.dynamicdefault = dynamicdefault
126 f.dynamicdefault = dynamicdefault
127 return f
127 return f
128
128
129
129
130 coreconfigitem = getitemregister(coreitems)
130 coreconfigitem = getitemregister(coreitems)
131
131
132
132
133 def _registerdiffopts(section, configprefix=b''):
133 def _registerdiffopts(section, configprefix=b''):
134 coreconfigitem(
134 coreconfigitem(
135 section,
135 section,
136 configprefix + b'nodates',
136 configprefix + b'nodates',
137 default=False,
137 default=False,
138 )
138 )
139 coreconfigitem(
139 coreconfigitem(
140 section,
140 section,
141 configprefix + b'showfunc',
141 configprefix + b'showfunc',
142 default=False,
142 default=False,
143 )
143 )
144 coreconfigitem(
144 coreconfigitem(
145 section,
145 section,
146 configprefix + b'unified',
146 configprefix + b'unified',
147 default=None,
147 default=None,
148 )
148 )
149 coreconfigitem(
149 coreconfigitem(
150 section,
150 section,
151 configprefix + b'git',
151 configprefix + b'git',
152 default=False,
152 default=False,
153 )
153 )
154 coreconfigitem(
154 coreconfigitem(
155 section,
155 section,
156 configprefix + b'ignorews',
156 configprefix + b'ignorews',
157 default=False,
157 default=False,
158 )
158 )
159 coreconfigitem(
159 coreconfigitem(
160 section,
160 section,
161 configprefix + b'ignorewsamount',
161 configprefix + b'ignorewsamount',
162 default=False,
162 default=False,
163 )
163 )
164 coreconfigitem(
164 coreconfigitem(
165 section,
165 section,
166 configprefix + b'ignoreblanklines',
166 configprefix + b'ignoreblanklines',
167 default=False,
167 default=False,
168 )
168 )
169 coreconfigitem(
169 coreconfigitem(
170 section,
170 section,
171 configprefix + b'ignorewseol',
171 configprefix + b'ignorewseol',
172 default=False,
172 default=False,
173 )
173 )
174 coreconfigitem(
174 coreconfigitem(
175 section,
175 section,
176 configprefix + b'nobinary',
176 configprefix + b'nobinary',
177 default=False,
177 default=False,
178 )
178 )
179 coreconfigitem(
179 coreconfigitem(
180 section,
180 section,
181 configprefix + b'noprefix',
181 configprefix + b'noprefix',
182 default=False,
182 default=False,
183 )
183 )
184 coreconfigitem(
184 coreconfigitem(
185 section,
185 section,
186 configprefix + b'word-diff',
186 configprefix + b'word-diff',
187 default=False,
187 default=False,
188 )
188 )
189
189
190
190
191 coreconfigitem(
191 coreconfigitem(
192 b'alias',
192 b'alias',
193 b'.*',
193 b'.*',
194 default=dynamicdefault,
194 default=dynamicdefault,
195 generic=True,
195 generic=True,
196 )
196 )
197 coreconfigitem(
197 coreconfigitem(
198 b'auth',
198 b'auth',
199 b'cookiefile',
199 b'cookiefile',
200 default=None,
200 default=None,
201 )
201 )
202 _registerdiffopts(section=b'annotate')
202 _registerdiffopts(section=b'annotate')
203 # bookmarks.pushing: internal hack for discovery
203 # bookmarks.pushing: internal hack for discovery
204 coreconfigitem(
204 coreconfigitem(
205 b'bookmarks',
205 b'bookmarks',
206 b'pushing',
206 b'pushing',
207 default=list,
207 default=list,
208 )
208 )
209 # bundle.mainreporoot: internal hack for bundlerepo
209 # bundle.mainreporoot: internal hack for bundlerepo
210 coreconfigitem(
210 coreconfigitem(
211 b'bundle',
211 b'bundle',
212 b'mainreporoot',
212 b'mainreporoot',
213 default=b'',
213 default=b'',
214 )
214 )
215 coreconfigitem(
215 coreconfigitem(
216 b'censor',
216 b'censor',
217 b'policy',
217 b'policy',
218 default=b'abort',
218 default=b'abort',
219 experimental=True,
219 experimental=True,
220 )
220 )
221 coreconfigitem(
221 coreconfigitem(
222 b'chgserver',
222 b'chgserver',
223 b'idletimeout',
223 b'idletimeout',
224 default=3600,
224 default=3600,
225 )
225 )
226 coreconfigitem(
226 coreconfigitem(
227 b'chgserver',
227 b'chgserver',
228 b'skiphash',
228 b'skiphash',
229 default=False,
229 default=False,
230 )
230 )
231 coreconfigitem(
231 coreconfigitem(
232 b'cmdserver',
232 b'cmdserver',
233 b'log',
233 b'log',
234 default=None,
234 default=None,
235 )
235 )
236 coreconfigitem(
236 coreconfigitem(
237 b'cmdserver',
237 b'cmdserver',
238 b'max-log-files',
238 b'max-log-files',
239 default=7,
239 default=7,
240 )
240 )
241 coreconfigitem(
241 coreconfigitem(
242 b'cmdserver',
242 b'cmdserver',
243 b'max-log-size',
243 b'max-log-size',
244 default=b'1 MB',
244 default=b'1 MB',
245 )
245 )
246 coreconfigitem(
246 coreconfigitem(
247 b'cmdserver',
247 b'cmdserver',
248 b'max-repo-cache',
248 b'max-repo-cache',
249 default=0,
249 default=0,
250 experimental=True,
250 experimental=True,
251 )
251 )
252 coreconfigitem(
252 coreconfigitem(
253 b'cmdserver',
253 b'cmdserver',
254 b'message-encodings',
254 b'message-encodings',
255 default=list,
255 default=list,
256 )
256 )
257 coreconfigitem(
257 coreconfigitem(
258 b'cmdserver',
258 b'cmdserver',
259 b'track-log',
259 b'track-log',
260 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
260 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
261 )
261 )
262 coreconfigitem(
262 coreconfigitem(
263 b'cmdserver',
263 b'cmdserver',
264 b'shutdown-on-interrupt',
264 b'shutdown-on-interrupt',
265 default=True,
265 default=True,
266 )
266 )
267 coreconfigitem(
267 coreconfigitem(
268 b'color',
268 b'color',
269 b'.*',
269 b'.*',
270 default=None,
270 default=None,
271 generic=True,
271 generic=True,
272 )
272 )
273 coreconfigitem(
273 coreconfigitem(
274 b'color',
274 b'color',
275 b'mode',
275 b'mode',
276 default=b'auto',
276 default=b'auto',
277 )
277 )
278 coreconfigitem(
278 coreconfigitem(
279 b'color',
279 b'color',
280 b'pagermode',
280 b'pagermode',
281 default=dynamicdefault,
281 default=dynamicdefault,
282 )
282 )
283 coreconfigitem(
283 coreconfigitem(
284 b'command-templates',
284 b'command-templates',
285 b'graphnode',
285 b'graphnode',
286 default=None,
286 default=None,
287 alias=[(b'ui', b'graphnodetemplate')],
287 alias=[(b'ui', b'graphnodetemplate')],
288 )
288 )
289 coreconfigitem(
289 coreconfigitem(
290 b'command-templates',
290 b'command-templates',
291 b'log',
291 b'log',
292 default=None,
292 default=None,
293 alias=[(b'ui', b'logtemplate')],
293 alias=[(b'ui', b'logtemplate')],
294 )
294 )
295 coreconfigitem(
295 coreconfigitem(
296 b'command-templates',
296 b'command-templates',
297 b'mergemarker',
297 b'mergemarker',
298 default=(
298 default=(
299 b'{node|short} '
299 b'{node|short} '
300 b'{ifeq(tags, "tip", "", '
300 b'{ifeq(tags, "tip", "", '
301 b'ifeq(tags, "", "", "{tags} "))}'
301 b'ifeq(tags, "", "", "{tags} "))}'
302 b'{if(bookmarks, "{bookmarks} ")}'
302 b'{if(bookmarks, "{bookmarks} ")}'
303 b'{ifeq(branch, "default", "", "{branch} ")}'
303 b'{ifeq(branch, "default", "", "{branch} ")}'
304 b'- {author|user}: {desc|firstline}'
304 b'- {author|user}: {desc|firstline}'
305 ),
305 ),
306 alias=[(b'ui', b'mergemarkertemplate')],
306 alias=[(b'ui', b'mergemarkertemplate')],
307 )
307 )
308 coreconfigitem(
308 coreconfigitem(
309 b'command-templates',
309 b'command-templates',
310 b'pre-merge-tool-output',
310 b'pre-merge-tool-output',
311 default=None,
311 default=None,
312 alias=[(b'ui', b'pre-merge-tool-output-template')],
312 alias=[(b'ui', b'pre-merge-tool-output-template')],
313 )
313 )
314 coreconfigitem(
314 coreconfigitem(
315 b'command-templates',
315 b'command-templates',
316 b'oneline-summary',
316 b'oneline-summary',
317 default=None,
317 default=None,
318 )
318 )
319 coreconfigitem(
319 coreconfigitem(
320 b'command-templates',
320 b'command-templates',
321 b'oneline-summary.*',
321 b'oneline-summary.*',
322 default=dynamicdefault,
322 default=dynamicdefault,
323 generic=True,
323 generic=True,
324 )
324 )
325 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
325 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
326 coreconfigitem(
326 coreconfigitem(
327 b'commands',
327 b'commands',
328 b'commit.post-status',
328 b'commit.post-status',
329 default=False,
329 default=False,
330 )
330 )
331 coreconfigitem(
331 coreconfigitem(
332 b'commands',
332 b'commands',
333 b'grep.all-files',
333 b'grep.all-files',
334 default=False,
334 default=False,
335 experimental=True,
335 experimental=True,
336 )
336 )
337 coreconfigitem(
337 coreconfigitem(
338 b'commands',
338 b'commands',
339 b'merge.require-rev',
339 b'merge.require-rev',
340 default=False,
340 default=False,
341 )
341 )
342 coreconfigitem(
342 coreconfigitem(
343 b'commands',
343 b'commands',
344 b'push.require-revs',
344 b'push.require-revs',
345 default=False,
345 default=False,
346 )
346 )
347 coreconfigitem(
347 coreconfigitem(
348 b'commands',
348 b'commands',
349 b'resolve.confirm',
349 b'resolve.confirm',
350 default=False,
350 default=False,
351 )
351 )
352 coreconfigitem(
352 coreconfigitem(
353 b'commands',
353 b'commands',
354 b'resolve.explicit-re-merge',
354 b'resolve.explicit-re-merge',
355 default=False,
355 default=False,
356 )
356 )
357 coreconfigitem(
357 coreconfigitem(
358 b'commands',
358 b'commands',
359 b'resolve.mark-check',
359 b'resolve.mark-check',
360 default=b'none',
360 default=b'none',
361 )
361 )
362 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
362 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
363 coreconfigitem(
363 coreconfigitem(
364 b'commands',
364 b'commands',
365 b'show.aliasprefix',
365 b'show.aliasprefix',
366 default=list,
366 default=list,
367 )
367 )
368 coreconfigitem(
368 coreconfigitem(
369 b'commands',
369 b'commands',
370 b'status.relative',
370 b'status.relative',
371 default=False,
371 default=False,
372 )
372 )
373 coreconfigitem(
373 coreconfigitem(
374 b'commands',
374 b'commands',
375 b'status.skipstates',
375 b'status.skipstates',
376 default=[],
376 default=[],
377 experimental=True,
377 experimental=True,
378 )
378 )
379 coreconfigitem(
379 coreconfigitem(
380 b'commands',
380 b'commands',
381 b'status.terse',
381 b'status.terse',
382 default=b'',
382 default=b'',
383 )
383 )
384 coreconfigitem(
384 coreconfigitem(
385 b'commands',
385 b'commands',
386 b'status.verbose',
386 b'status.verbose',
387 default=False,
387 default=False,
388 )
388 )
389 coreconfigitem(
389 coreconfigitem(
390 b'commands',
390 b'commands',
391 b'update.check',
391 b'update.check',
392 default=None,
392 default=None,
393 )
393 )
394 coreconfigitem(
394 coreconfigitem(
395 b'commands',
395 b'commands',
396 b'update.requiredest',
396 b'update.requiredest',
397 default=False,
397 default=False,
398 )
398 )
399 coreconfigitem(
399 coreconfigitem(
400 b'committemplate',
400 b'committemplate',
401 b'.*',
401 b'.*',
402 default=None,
402 default=None,
403 generic=True,
403 generic=True,
404 )
404 )
405 coreconfigitem(
405 coreconfigitem(
406 b'convert',
406 b'convert',
407 b'bzr.saverev',
407 b'bzr.saverev',
408 default=True,
408 default=True,
409 )
409 )
410 coreconfigitem(
410 coreconfigitem(
411 b'convert',
411 b'convert',
412 b'cvsps.cache',
412 b'cvsps.cache',
413 default=True,
413 default=True,
414 )
414 )
415 coreconfigitem(
415 coreconfigitem(
416 b'convert',
416 b'convert',
417 b'cvsps.fuzz',
417 b'cvsps.fuzz',
418 default=60,
418 default=60,
419 )
419 )
420 coreconfigitem(
420 coreconfigitem(
421 b'convert',
421 b'convert',
422 b'cvsps.logencoding',
422 b'cvsps.logencoding',
423 default=None,
423 default=None,
424 )
424 )
425 coreconfigitem(
425 coreconfigitem(
426 b'convert',
426 b'convert',
427 b'cvsps.mergefrom',
427 b'cvsps.mergefrom',
428 default=None,
428 default=None,
429 )
429 )
430 coreconfigitem(
430 coreconfigitem(
431 b'convert',
431 b'convert',
432 b'cvsps.mergeto',
432 b'cvsps.mergeto',
433 default=None,
433 default=None,
434 )
434 )
435 coreconfigitem(
435 coreconfigitem(
436 b'convert',
436 b'convert',
437 b'git.committeractions',
437 b'git.committeractions',
438 default=lambda: [b'messagedifferent'],
438 default=lambda: [b'messagedifferent'],
439 )
439 )
440 coreconfigitem(
440 coreconfigitem(
441 b'convert',
441 b'convert',
442 b'git.extrakeys',
442 b'git.extrakeys',
443 default=list,
443 default=list,
444 )
444 )
445 coreconfigitem(
445 coreconfigitem(
446 b'convert',
446 b'convert',
447 b'git.findcopiesharder',
447 b'git.findcopiesharder',
448 default=False,
448 default=False,
449 )
449 )
450 coreconfigitem(
450 coreconfigitem(
451 b'convert',
451 b'convert',
452 b'git.remoteprefix',
452 b'git.remoteprefix',
453 default=b'remote',
453 default=b'remote',
454 )
454 )
455 coreconfigitem(
455 coreconfigitem(
456 b'convert',
456 b'convert',
457 b'git.renamelimit',
457 b'git.renamelimit',
458 default=400,
458 default=400,
459 )
459 )
460 coreconfigitem(
460 coreconfigitem(
461 b'convert',
461 b'convert',
462 b'git.saverev',
462 b'git.saverev',
463 default=True,
463 default=True,
464 )
464 )
465 coreconfigitem(
465 coreconfigitem(
466 b'convert',
466 b'convert',
467 b'git.similarity',
467 b'git.similarity',
468 default=50,
468 default=50,
469 )
469 )
470 coreconfigitem(
470 coreconfigitem(
471 b'convert',
471 b'convert',
472 b'git.skipsubmodules',
472 b'git.skipsubmodules',
473 default=False,
473 default=False,
474 )
474 )
475 coreconfigitem(
475 coreconfigitem(
476 b'convert',
476 b'convert',
477 b'hg.clonebranches',
477 b'hg.clonebranches',
478 default=False,
478 default=False,
479 )
479 )
480 coreconfigitem(
480 coreconfigitem(
481 b'convert',
481 b'convert',
482 b'hg.ignoreerrors',
482 b'hg.ignoreerrors',
483 default=False,
483 default=False,
484 )
484 )
485 coreconfigitem(
485 coreconfigitem(
486 b'convert',
486 b'convert',
487 b'hg.preserve-hash',
487 b'hg.preserve-hash',
488 default=False,
488 default=False,
489 )
489 )
490 coreconfigitem(
490 coreconfigitem(
491 b'convert',
491 b'convert',
492 b'hg.revs',
492 b'hg.revs',
493 default=None,
493 default=None,
494 )
494 )
495 coreconfigitem(
495 coreconfigitem(
496 b'convert',
496 b'convert',
497 b'hg.saverev',
497 b'hg.saverev',
498 default=False,
498 default=False,
499 )
499 )
500 coreconfigitem(
500 coreconfigitem(
501 b'convert',
501 b'convert',
502 b'hg.sourcename',
502 b'hg.sourcename',
503 default=None,
503 default=None,
504 )
504 )
505 coreconfigitem(
505 coreconfigitem(
506 b'convert',
506 b'convert',
507 b'hg.startrev',
507 b'hg.startrev',
508 default=None,
508 default=None,
509 )
509 )
510 coreconfigitem(
510 coreconfigitem(
511 b'convert',
511 b'convert',
512 b'hg.tagsbranch',
512 b'hg.tagsbranch',
513 default=b'default',
513 default=b'default',
514 )
514 )
515 coreconfigitem(
515 coreconfigitem(
516 b'convert',
516 b'convert',
517 b'hg.usebranchnames',
517 b'hg.usebranchnames',
518 default=True,
518 default=True,
519 )
519 )
520 coreconfigitem(
520 coreconfigitem(
521 b'convert',
521 b'convert',
522 b'ignoreancestorcheck',
522 b'ignoreancestorcheck',
523 default=False,
523 default=False,
524 experimental=True,
524 experimental=True,
525 )
525 )
526 coreconfigitem(
526 coreconfigitem(
527 b'convert',
527 b'convert',
528 b'localtimezone',
528 b'localtimezone',
529 default=False,
529 default=False,
530 )
530 )
531 coreconfigitem(
531 coreconfigitem(
532 b'convert',
532 b'convert',
533 b'p4.encoding',
533 b'p4.encoding',
534 default=dynamicdefault,
534 default=dynamicdefault,
535 )
535 )
536 coreconfigitem(
536 coreconfigitem(
537 b'convert',
537 b'convert',
538 b'p4.startrev',
538 b'p4.startrev',
539 default=0,
539 default=0,
540 )
540 )
541 coreconfigitem(
541 coreconfigitem(
542 b'convert',
542 b'convert',
543 b'skiptags',
543 b'skiptags',
544 default=False,
544 default=False,
545 )
545 )
546 coreconfigitem(
546 coreconfigitem(
547 b'convert',
547 b'convert',
548 b'svn.debugsvnlog',
548 b'svn.debugsvnlog',
549 default=True,
549 default=True,
550 )
550 )
551 coreconfigitem(
551 coreconfigitem(
552 b'convert',
552 b'convert',
553 b'svn.trunk',
553 b'svn.trunk',
554 default=None,
554 default=None,
555 )
555 )
556 coreconfigitem(
556 coreconfigitem(
557 b'convert',
557 b'convert',
558 b'svn.tags',
558 b'svn.tags',
559 default=None,
559 default=None,
560 )
560 )
561 coreconfigitem(
561 coreconfigitem(
562 b'convert',
562 b'convert',
563 b'svn.branches',
563 b'svn.branches',
564 default=None,
564 default=None,
565 )
565 )
566 coreconfigitem(
566 coreconfigitem(
567 b'convert',
567 b'convert',
568 b'svn.startrev',
568 b'svn.startrev',
569 default=0,
569 default=0,
570 )
570 )
571 coreconfigitem(
571 coreconfigitem(
572 b'convert',
572 b'convert',
573 b'svn.dangerous-set-commit-dates',
573 b'svn.dangerous-set-commit-dates',
574 default=False,
574 default=False,
575 )
575 )
576 coreconfigitem(
576 coreconfigitem(
577 b'debug',
577 b'debug',
578 b'dirstate.delaywrite',
578 b'dirstate.delaywrite',
579 default=0,
579 default=0,
580 )
580 )
581 coreconfigitem(
581 coreconfigitem(
582 b'debug',
582 b'debug',
583 b'revlog.verifyposition.changelog',
583 b'revlog.verifyposition.changelog',
584 default=b'',
584 default=b'',
585 )
585 )
586 coreconfigitem(
586 coreconfigitem(
587 b'debug',
587 b'debug',
588 b'revlog.debug-delta',
588 b'revlog.debug-delta',
589 default=False,
589 default=False,
590 )
590 )
591 coreconfigitem(
591 coreconfigitem(
592 b'defaults',
592 b'defaults',
593 b'.*',
593 b'.*',
594 default=None,
594 default=None,
595 generic=True,
595 generic=True,
596 )
596 )
597 coreconfigitem(
597 coreconfigitem(
598 b'devel',
598 b'devel',
599 b'all-warnings',
599 b'all-warnings',
600 default=False,
600 default=False,
601 )
601 )
602 coreconfigitem(
602 coreconfigitem(
603 b'devel',
603 b'devel',
604 b'bundle2.debug',
604 b'bundle2.debug',
605 default=False,
605 default=False,
606 )
606 )
607 coreconfigitem(
607 coreconfigitem(
608 b'devel',
608 b'devel',
609 b'bundle.delta',
609 b'bundle.delta',
610 default=b'',
610 default=b'',
611 )
611 )
612 coreconfigitem(
612 coreconfigitem(
613 b'devel',
613 b'devel',
614 b'cache-vfs',
614 b'cache-vfs',
615 default=None,
615 default=None,
616 )
616 )
617 coreconfigitem(
617 coreconfigitem(
618 b'devel',
618 b'devel',
619 b'check-locks',
619 b'check-locks',
620 default=False,
620 default=False,
621 )
621 )
622 coreconfigitem(
622 coreconfigitem(
623 b'devel',
623 b'devel',
624 b'check-relroot',
624 b'check-relroot',
625 default=False,
625 default=False,
626 )
626 )
627 # Track copy information for all file, not just "added" one (very slow)
627 # Track copy information for all file, not just "added" one (very slow)
628 coreconfigitem(
628 coreconfigitem(
629 b'devel',
629 b'devel',
630 b'copy-tracing.trace-all-files',
630 b'copy-tracing.trace-all-files',
631 default=False,
631 default=False,
632 )
632 )
633 coreconfigitem(
633 coreconfigitem(
634 b'devel',
634 b'devel',
635 b'default-date',
635 b'default-date',
636 default=None,
636 default=None,
637 )
637 )
638 coreconfigitem(
638 coreconfigitem(
639 b'devel',
639 b'devel',
640 b'deprec-warn',
640 b'deprec-warn',
641 default=False,
641 default=False,
642 )
642 )
643 coreconfigitem(
643 coreconfigitem(
644 b'devel',
644 b'devel',
645 b'disableloaddefaultcerts',
645 b'disableloaddefaultcerts',
646 default=False,
646 default=False,
647 )
647 )
648 coreconfigitem(
648 coreconfigitem(
649 b'devel',
649 b'devel',
650 b'warn-empty-changegroup',
650 b'warn-empty-changegroup',
651 default=False,
651 default=False,
652 )
652 )
653 coreconfigitem(
653 coreconfigitem(
654 b'devel',
654 b'devel',
655 b'legacy.exchange',
655 b'legacy.exchange',
656 default=list,
656 default=list,
657 )
657 )
658 # When True, revlogs use a special reference version of the nodemap, that is not
658 # When True, revlogs use a special reference version of the nodemap, that is not
659 # performant but is "known" to behave properly.
659 # performant but is "known" to behave properly.
660 coreconfigitem(
660 coreconfigitem(
661 b'devel',
661 b'devel',
662 b'persistent-nodemap',
662 b'persistent-nodemap',
663 default=False,
663 default=False,
664 )
664 )
665 coreconfigitem(
665 coreconfigitem(
666 b'devel',
666 b'devel',
667 b'servercafile',
667 b'servercafile',
668 default=b'',
668 default=b'',
669 )
669 )
670 coreconfigitem(
670 coreconfigitem(
671 b'devel',
671 b'devel',
672 b'serverexactprotocol',
672 b'serverexactprotocol',
673 default=b'',
673 default=b'',
674 )
674 )
675 coreconfigitem(
675 coreconfigitem(
676 b'devel',
676 b'devel',
677 b'serverrequirecert',
677 b'serverrequirecert',
678 default=False,
678 default=False,
679 )
679 )
680 coreconfigitem(
680 coreconfigitem(
681 b'devel',
681 b'devel',
682 b'strip-obsmarkers',
682 b'strip-obsmarkers',
683 default=True,
683 default=True,
684 )
684 )
685 coreconfigitem(
685 coreconfigitem(
686 b'devel',
686 b'devel',
687 b'warn-config',
687 b'warn-config',
688 default=None,
688 default=None,
689 )
689 )
690 coreconfigitem(
690 coreconfigitem(
691 b'devel',
691 b'devel',
692 b'warn-config-default',
692 b'warn-config-default',
693 default=None,
693 default=None,
694 )
694 )
695 coreconfigitem(
695 coreconfigitem(
696 b'devel',
696 b'devel',
697 b'user.obsmarker',
697 b'user.obsmarker',
698 default=None,
698 default=None,
699 )
699 )
700 coreconfigitem(
700 coreconfigitem(
701 b'devel',
701 b'devel',
702 b'warn-config-unknown',
702 b'warn-config-unknown',
703 default=None,
703 default=None,
704 )
704 )
705 coreconfigitem(
705 coreconfigitem(
706 b'devel',
706 b'devel',
707 b'debug.copies',
707 b'debug.copies',
708 default=False,
708 default=False,
709 )
709 )
710 coreconfigitem(
710 coreconfigitem(
711 b'devel',
711 b'devel',
712 b'copy-tracing.multi-thread',
712 b'copy-tracing.multi-thread',
713 default=True,
713 default=True,
714 )
714 )
715 coreconfigitem(
715 coreconfigitem(
716 b'devel',
716 b'devel',
717 b'debug.extensions',
717 b'debug.extensions',
718 default=False,
718 default=False,
719 )
719 )
720 coreconfigitem(
720 coreconfigitem(
721 b'devel',
721 b'devel',
722 b'debug.repo-filters',
722 b'debug.repo-filters',
723 default=False,
723 default=False,
724 )
724 )
725 coreconfigitem(
725 coreconfigitem(
726 b'devel',
726 b'devel',
727 b'debug.peer-request',
727 b'debug.peer-request',
728 default=False,
728 default=False,
729 )
729 )
730 # If discovery.exchange-heads is False, the discovery will not start with
730 # If discovery.exchange-heads is False, the discovery will not start with
731 # remote head fetching and local head querying.
731 # remote head fetching and local head querying.
732 coreconfigitem(
732 coreconfigitem(
733 b'devel',
733 b'devel',
734 b'discovery.exchange-heads',
734 b'discovery.exchange-heads',
735 default=True,
735 default=True,
736 )
736 )
737 # If discovery.grow-sample is False, the sample size used in set discovery will
737 # If discovery.grow-sample is False, the sample size used in set discovery will
738 # not be increased through the process
738 # not be increased through the process
739 coreconfigitem(
739 coreconfigitem(
740 b'devel',
740 b'devel',
741 b'discovery.grow-sample',
741 b'discovery.grow-sample',
742 default=True,
742 default=True,
743 )
743 )
744 # When discovery.grow-sample.dynamic is True, the default, the sample size is
744 # When discovery.grow-sample.dynamic is True, the default, the sample size is
745 # adapted to the shape of the undecided set (it is set to the max of:
745 # adapted to the shape of the undecided set (it is set to the max of:
746 # <target-size>, len(roots(undecided)), len(heads(undecided)
746 # <target-size>, len(roots(undecided)), len(heads(undecided)
747 coreconfigitem(
747 coreconfigitem(
748 b'devel',
748 b'devel',
749 b'discovery.grow-sample.dynamic',
749 b'discovery.grow-sample.dynamic',
750 default=True,
750 default=True,
751 )
751 )
752 # discovery.grow-sample.rate control the rate at which the sample grow
752 # discovery.grow-sample.rate control the rate at which the sample grow
753 coreconfigitem(
753 coreconfigitem(
754 b'devel',
754 b'devel',
755 b'discovery.grow-sample.rate',
755 b'discovery.grow-sample.rate',
756 default=1.05,
756 default=1.05,
757 )
757 )
758 # If discovery.randomize is False, random sampling during discovery are
758 # If discovery.randomize is False, random sampling during discovery are
759 # deterministic. It is meant for integration tests.
759 # deterministic. It is meant for integration tests.
760 coreconfigitem(
760 coreconfigitem(
761 b'devel',
761 b'devel',
762 b'discovery.randomize',
762 b'discovery.randomize',
763 default=True,
763 default=True,
764 )
764 )
765 # Control the initial size of the discovery sample
765 # Control the initial size of the discovery sample
766 coreconfigitem(
766 coreconfigitem(
767 b'devel',
767 b'devel',
768 b'discovery.sample-size',
768 b'discovery.sample-size',
769 default=200,
769 default=200,
770 )
770 )
771 # Control the initial size of the discovery for initial change
771 # Control the initial size of the discovery for initial change
772 coreconfigitem(
772 coreconfigitem(
773 b'devel',
773 b'devel',
774 b'discovery.sample-size.initial',
774 b'discovery.sample-size.initial',
775 default=100,
775 default=100,
776 )
776 )
777 _registerdiffopts(section=b'diff')
777 _registerdiffopts(section=b'diff')
778 coreconfigitem(
778 coreconfigitem(
779 b'diff',
779 b'diff',
780 b'merge',
780 b'merge',
781 default=False,
781 default=False,
782 experimental=True,
782 experimental=True,
783 )
783 )
784 coreconfigitem(
784 coreconfigitem(
785 b'email',
785 b'email',
786 b'bcc',
786 b'bcc',
787 default=None,
787 default=None,
788 )
788 )
789 coreconfigitem(
789 coreconfigitem(
790 b'email',
790 b'email',
791 b'cc',
791 b'cc',
792 default=None,
792 default=None,
793 )
793 )
794 coreconfigitem(
794 coreconfigitem(
795 b'email',
795 b'email',
796 b'charsets',
796 b'charsets',
797 default=list,
797 default=list,
798 )
798 )
799 coreconfigitem(
799 coreconfigitem(
800 b'email',
800 b'email',
801 b'from',
801 b'from',
802 default=None,
802 default=None,
803 )
803 )
804 coreconfigitem(
804 coreconfigitem(
805 b'email',
805 b'email',
806 b'method',
806 b'method',
807 default=b'smtp',
807 default=b'smtp',
808 )
808 )
809 coreconfigitem(
809 coreconfigitem(
810 b'email',
810 b'email',
811 b'reply-to',
811 b'reply-to',
812 default=None,
812 default=None,
813 )
813 )
814 coreconfigitem(
814 coreconfigitem(
815 b'email',
815 b'email',
816 b'to',
816 b'to',
817 default=None,
817 default=None,
818 )
818 )
819 coreconfigitem(
819 coreconfigitem(
820 b'experimental',
820 b'experimental',
821 b'archivemetatemplate',
821 b'archivemetatemplate',
822 default=dynamicdefault,
822 default=dynamicdefault,
823 )
823 )
824 coreconfigitem(
824 coreconfigitem(
825 b'experimental',
825 b'experimental',
826 b'auto-publish',
826 b'auto-publish',
827 default=b'publish',
827 default=b'publish',
828 )
828 )
829 coreconfigitem(
829 coreconfigitem(
830 b'experimental',
830 b'experimental',
831 b'bundle-phases',
831 b'bundle-phases',
832 default=False,
832 default=False,
833 )
833 )
834 coreconfigitem(
834 coreconfigitem(
835 b'experimental',
835 b'experimental',
836 b'bundle2-advertise',
836 b'bundle2-advertise',
837 default=True,
837 default=True,
838 )
838 )
839 coreconfigitem(
839 coreconfigitem(
840 b'experimental',
840 b'experimental',
841 b'bundle2-output-capture',
841 b'bundle2-output-capture',
842 default=False,
842 default=False,
843 )
843 )
844 coreconfigitem(
844 coreconfigitem(
845 b'experimental',
845 b'experimental',
846 b'bundle2.pushback',
846 b'bundle2.pushback',
847 default=False,
847 default=False,
848 )
848 )
849 coreconfigitem(
849 coreconfigitem(
850 b'experimental',
850 b'experimental',
851 b'bundle2lazylocking',
851 b'bundle2lazylocking',
852 default=False,
852 default=False,
853 )
853 )
854 coreconfigitem(
854 coreconfigitem(
855 b'experimental',
855 b'experimental',
856 b'bundlecomplevel',
856 b'bundlecomplevel',
857 default=None,
857 default=None,
858 )
858 )
859 coreconfigitem(
859 coreconfigitem(
860 b'experimental',
860 b'experimental',
861 b'bundlecomplevel.bzip2',
861 b'bundlecomplevel.bzip2',
862 default=None,
862 default=None,
863 )
863 )
864 coreconfigitem(
864 coreconfigitem(
865 b'experimental',
865 b'experimental',
866 b'bundlecomplevel.gzip',
866 b'bundlecomplevel.gzip',
867 default=None,
867 default=None,
868 )
868 )
869 coreconfigitem(
869 coreconfigitem(
870 b'experimental',
870 b'experimental',
871 b'bundlecomplevel.none',
871 b'bundlecomplevel.none',
872 default=None,
872 default=None,
873 )
873 )
874 coreconfigitem(
874 coreconfigitem(
875 b'experimental',
875 b'experimental',
876 b'bundlecomplevel.zstd',
876 b'bundlecomplevel.zstd',
877 default=None,
877 default=None,
878 )
878 )
879 coreconfigitem(
879 coreconfigitem(
880 b'experimental',
880 b'experimental',
881 b'bundlecompthreads',
881 b'bundlecompthreads',
882 default=None,
882 default=None,
883 )
883 )
884 coreconfigitem(
884 coreconfigitem(
885 b'experimental',
885 b'experimental',
886 b'bundlecompthreads.bzip2',
886 b'bundlecompthreads.bzip2',
887 default=None,
887 default=None,
888 )
888 )
889 coreconfigitem(
889 coreconfigitem(
890 b'experimental',
890 b'experimental',
891 b'bundlecompthreads.gzip',
891 b'bundlecompthreads.gzip',
892 default=None,
892 default=None,
893 )
893 )
894 coreconfigitem(
894 coreconfigitem(
895 b'experimental',
895 b'experimental',
896 b'bundlecompthreads.none',
896 b'bundlecompthreads.none',
897 default=None,
897 default=None,
898 )
898 )
899 coreconfigitem(
899 coreconfigitem(
900 b'experimental',
900 b'experimental',
901 b'bundlecompthreads.zstd',
901 b'bundlecompthreads.zstd',
902 default=None,
902 default=None,
903 )
903 )
904 coreconfigitem(
904 coreconfigitem(
905 b'experimental',
905 b'experimental',
906 b'changegroup3',
906 b'changegroup3',
907 default=False,
907 default=False,
908 )
908 )
909 coreconfigitem(
909 coreconfigitem(
910 b'experimental',
910 b'experimental',
911 b'changegroup4',
911 b'changegroup4',
912 default=False,
912 default=False,
913 )
913 )
914 coreconfigitem(
914 coreconfigitem(
915 b'experimental',
915 b'experimental',
916 b'cleanup-as-archived',
916 b'cleanup-as-archived',
917 default=False,
917 default=False,
918 )
918 )
919 coreconfigitem(
919 coreconfigitem(
920 b'experimental',
920 b'experimental',
921 b'clientcompressionengines',
921 b'clientcompressionengines',
922 default=list,
922 default=list,
923 )
923 )
924 coreconfigitem(
924 coreconfigitem(
925 b'experimental',
925 b'experimental',
926 b'copytrace',
926 b'copytrace',
927 default=b'on',
927 default=b'on',
928 )
928 )
929 coreconfigitem(
929 coreconfigitem(
930 b'experimental',
930 b'experimental',
931 b'copytrace.movecandidateslimit',
931 b'copytrace.movecandidateslimit',
932 default=100,
932 default=100,
933 )
933 )
934 coreconfigitem(
934 coreconfigitem(
935 b'experimental',
935 b'experimental',
936 b'copytrace.sourcecommitlimit',
936 b'copytrace.sourcecommitlimit',
937 default=100,
937 default=100,
938 )
938 )
939 coreconfigitem(
939 coreconfigitem(
940 b'experimental',
940 b'experimental',
941 b'copies.read-from',
941 b'copies.read-from',
942 default=b"filelog-only",
942 default=b"filelog-only",
943 )
943 )
944 coreconfigitem(
944 coreconfigitem(
945 b'experimental',
945 b'experimental',
946 b'copies.write-to',
946 b'copies.write-to',
947 default=b'filelog-only',
947 default=b'filelog-only',
948 )
948 )
949 coreconfigitem(
949 coreconfigitem(
950 b'experimental',
950 b'experimental',
951 b'crecordtest',
951 b'crecordtest',
952 default=None,
952 default=None,
953 )
953 )
954 coreconfigitem(
954 coreconfigitem(
955 b'experimental',
955 b'experimental',
956 b'directaccess',
956 b'directaccess',
957 default=False,
957 default=False,
958 )
958 )
959 coreconfigitem(
959 coreconfigitem(
960 b'experimental',
960 b'experimental',
961 b'directaccess.revnums',
961 b'directaccess.revnums',
962 default=False,
962 default=False,
963 )
963 )
964 coreconfigitem(
964 coreconfigitem(
965 b'experimental',
965 b'experimental',
966 b'editortmpinhg',
966 b'editortmpinhg',
967 default=False,
967 default=False,
968 )
968 )
969 coreconfigitem(
969 coreconfigitem(
970 b'experimental',
970 b'experimental',
971 b'evolution',
971 b'evolution',
972 default=list,
972 default=list,
973 )
973 )
974 coreconfigitem(
974 coreconfigitem(
975 b'experimental',
975 b'experimental',
976 b'evolution.allowdivergence',
976 b'evolution.allowdivergence',
977 default=False,
977 default=False,
978 alias=[(b'experimental', b'allowdivergence')],
978 alias=[(b'experimental', b'allowdivergence')],
979 )
979 )
980 coreconfigitem(
980 coreconfigitem(
981 b'experimental',
981 b'experimental',
982 b'evolution.allowunstable',
982 b'evolution.allowunstable',
983 default=None,
983 default=None,
984 )
984 )
985 coreconfigitem(
985 coreconfigitem(
986 b'experimental',
986 b'experimental',
987 b'evolution.createmarkers',
987 b'evolution.createmarkers',
988 default=None,
988 default=None,
989 )
989 )
990 coreconfigitem(
990 coreconfigitem(
991 b'experimental',
991 b'experimental',
992 b'evolution.effect-flags',
992 b'evolution.effect-flags',
993 default=True,
993 default=True,
994 alias=[(b'experimental', b'effect-flags')],
994 alias=[(b'experimental', b'effect-flags')],
995 )
995 )
996 coreconfigitem(
996 coreconfigitem(
997 b'experimental',
997 b'experimental',
998 b'evolution.exchange',
998 b'evolution.exchange',
999 default=None,
999 default=None,
1000 )
1000 )
1001 coreconfigitem(
1001 coreconfigitem(
1002 b'experimental',
1002 b'experimental',
1003 b'evolution.bundle-obsmarker',
1003 b'evolution.bundle-obsmarker',
1004 default=False,
1004 default=False,
1005 )
1005 )
1006 coreconfigitem(
1006 coreconfigitem(
1007 b'experimental',
1007 b'experimental',
1008 b'evolution.bundle-obsmarker:mandatory',
1008 b'evolution.bundle-obsmarker:mandatory',
1009 default=True,
1009 default=True,
1010 )
1010 )
1011 coreconfigitem(
1011 coreconfigitem(
1012 b'experimental',
1012 b'experimental',
1013 b'log.topo',
1013 b'log.topo',
1014 default=False,
1014 default=False,
1015 )
1015 )
1016 coreconfigitem(
1016 coreconfigitem(
1017 b'experimental',
1017 b'experimental',
1018 b'evolution.report-instabilities',
1018 b'evolution.report-instabilities',
1019 default=True,
1019 default=True,
1020 )
1020 )
1021 coreconfigitem(
1021 coreconfigitem(
1022 b'experimental',
1022 b'experimental',
1023 b'evolution.track-operation',
1023 b'evolution.track-operation',
1024 default=True,
1024 default=True,
1025 )
1025 )
1026 # repo-level config to exclude a revset visibility
1026 # repo-level config to exclude a revset visibility
1027 #
1027 #
1028 # The target use case is to use `share` to expose different subset of the same
1028 # The target use case is to use `share` to expose different subset of the same
1029 # repository, especially server side. See also `server.view`.
1029 # repository, especially server side. See also `server.view`.
1030 coreconfigitem(
1030 coreconfigitem(
1031 b'experimental',
1031 b'experimental',
1032 b'extra-filter-revs',
1032 b'extra-filter-revs',
1033 default=None,
1033 default=None,
1034 )
1034 )
1035 coreconfigitem(
1035 coreconfigitem(
1036 b'experimental',
1036 b'experimental',
1037 b'maxdeltachainspan',
1037 b'maxdeltachainspan',
1038 default=-1,
1038 default=-1,
1039 )
1039 )
1040 # tracks files which were undeleted (merge might delete them but we explicitly
1040 # tracks files which were undeleted (merge might delete them but we explicitly
1041 # kept/undeleted them) and creates new filenodes for them
1041 # kept/undeleted them) and creates new filenodes for them
1042 coreconfigitem(
1042 coreconfigitem(
1043 b'experimental',
1043 b'experimental',
1044 b'merge-track-salvaged',
1044 b'merge-track-salvaged',
1045 default=False,
1045 default=False,
1046 )
1046 )
1047 coreconfigitem(
1047 coreconfigitem(
1048 b'experimental',
1048 b'experimental',
1049 b'mmapindexthreshold',
1049 b'mmapindexthreshold',
1050 default=None,
1050 default=None,
1051 )
1051 )
1052 coreconfigitem(
1052 coreconfigitem(
1053 b'experimental',
1053 b'experimental',
1054 b'narrow',
1054 b'narrow',
1055 default=False,
1055 default=False,
1056 )
1056 )
1057 coreconfigitem(
1057 coreconfigitem(
1058 b'experimental',
1058 b'experimental',
1059 b'nonnormalparanoidcheck',
1059 b'nonnormalparanoidcheck',
1060 default=False,
1060 default=False,
1061 )
1061 )
1062 coreconfigitem(
1062 coreconfigitem(
1063 b'experimental',
1063 b'experimental',
1064 b'exportableenviron',
1064 b'exportableenviron',
1065 default=list,
1065 default=list,
1066 )
1066 )
1067 coreconfigitem(
1067 coreconfigitem(
1068 b'experimental',
1068 b'experimental',
1069 b'extendedheader.index',
1069 b'extendedheader.index',
1070 default=None,
1070 default=None,
1071 )
1071 )
1072 coreconfigitem(
1072 coreconfigitem(
1073 b'experimental',
1073 b'experimental',
1074 b'extendedheader.similarity',
1074 b'extendedheader.similarity',
1075 default=False,
1075 default=False,
1076 )
1076 )
1077 coreconfigitem(
1077 coreconfigitem(
1078 b'experimental',
1078 b'experimental',
1079 b'graphshorten',
1079 b'graphshorten',
1080 default=False,
1080 default=False,
1081 )
1081 )
1082 coreconfigitem(
1082 coreconfigitem(
1083 b'experimental',
1083 b'experimental',
1084 b'graphstyle.parent',
1084 b'graphstyle.parent',
1085 default=dynamicdefault,
1085 default=dynamicdefault,
1086 )
1086 )
1087 coreconfigitem(
1087 coreconfigitem(
1088 b'experimental',
1088 b'experimental',
1089 b'graphstyle.missing',
1089 b'graphstyle.missing',
1090 default=dynamicdefault,
1090 default=dynamicdefault,
1091 )
1091 )
1092 coreconfigitem(
1092 coreconfigitem(
1093 b'experimental',
1093 b'experimental',
1094 b'graphstyle.grandparent',
1094 b'graphstyle.grandparent',
1095 default=dynamicdefault,
1095 default=dynamicdefault,
1096 )
1096 )
1097 coreconfigitem(
1097 coreconfigitem(
1098 b'experimental',
1098 b'experimental',
1099 b'hook-track-tags',
1099 b'hook-track-tags',
1100 default=False,
1100 default=False,
1101 )
1101 )
1102 coreconfigitem(
1102 coreconfigitem(
1103 b'experimental',
1103 b'experimental',
1104 b'httppostargs',
1104 b'httppostargs',
1105 default=False,
1105 default=False,
1106 )
1106 )
1107 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1107 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1108 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1108 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1109
1109
1110 coreconfigitem(
1110 coreconfigitem(
1111 b'experimental',
1111 b'experimental',
1112 b'obsmarkers-exchange-debug',
1112 b'obsmarkers-exchange-debug',
1113 default=False,
1113 default=False,
1114 )
1114 )
1115 coreconfigitem(
1115 coreconfigitem(
1116 b'experimental',
1116 b'experimental',
1117 b'remotenames',
1117 b'remotenames',
1118 default=False,
1118 default=False,
1119 )
1119 )
1120 coreconfigitem(
1120 coreconfigitem(
1121 b'experimental',
1121 b'experimental',
1122 b'removeemptydirs',
1122 b'removeemptydirs',
1123 default=True,
1123 default=True,
1124 )
1124 )
1125 coreconfigitem(
1125 coreconfigitem(
1126 b'experimental',
1126 b'experimental',
1127 b'revert.interactive.select-to-keep',
1127 b'revert.interactive.select-to-keep',
1128 default=False,
1128 default=False,
1129 )
1129 )
1130 coreconfigitem(
1130 coreconfigitem(
1131 b'experimental',
1131 b'experimental',
1132 b'revisions.prefixhexnode',
1132 b'revisions.prefixhexnode',
1133 default=False,
1133 default=False,
1134 )
1134 )
1135 # "out of experimental" todo list.
1135 # "out of experimental" todo list.
1136 #
1136 #
1137 # * include management of a persistent nodemap in the main docket
1137 # * include management of a persistent nodemap in the main docket
1138 # * enforce a "no-truncate" policy for mmap safety
1138 # * enforce a "no-truncate" policy for mmap safety
1139 # - for censoring operation
1139 # - for censoring operation
1140 # - for stripping operation
1140 # - for stripping operation
1141 # - for rollback operation
1141 # - for rollback operation
1142 # * proper streaming (race free) of the docket file
1142 # * proper streaming (race free) of the docket file
1143 # * track garbage data to evemtually allow rewriting -existing- sidedata.
1143 # * track garbage data to evemtually allow rewriting -existing- sidedata.
1144 # * Exchange-wise, we will also need to do something more efficient than
1144 # * Exchange-wise, we will also need to do something more efficient than
1145 # keeping references to the affected revlogs, especially memory-wise when
1145 # keeping references to the affected revlogs, especially memory-wise when
1146 # rewriting sidedata.
1146 # rewriting sidedata.
1147 # * introduce a proper solution to reduce the number of filelog related files.
1147 # * introduce a proper solution to reduce the number of filelog related files.
1148 # * use caching for reading sidedata (similar to what we do for data).
1148 # * use caching for reading sidedata (similar to what we do for data).
1149 # * no longer set offset=0 if sidedata_size=0 (simplify cutoff computation).
1149 # * no longer set offset=0 if sidedata_size=0 (simplify cutoff computation).
1150 # * Improvement to consider
1150 # * Improvement to consider
1151 # - avoid compression header in chunk using the default compression?
1151 # - avoid compression header in chunk using the default compression?
1152 # - forbid "inline" compression mode entirely?
1152 # - forbid "inline" compression mode entirely?
1153 # - split the data offset and flag field (the 2 bytes save are mostly trouble)
1153 # - split the data offset and flag field (the 2 bytes save are mostly trouble)
1154 # - keep track of uncompressed -chunk- size (to preallocate memory better)
1154 # - keep track of uncompressed -chunk- size (to preallocate memory better)
1155 # - keep track of chain base or size (probably not that useful anymore)
1155 # - keep track of chain base or size (probably not that useful anymore)
1156 coreconfigitem(
1156 coreconfigitem(
1157 b'experimental',
1157 b'experimental',
1158 b'revlogv2',
1158 b'revlogv2',
1159 default=None,
1159 default=None,
1160 )
1160 )
1161 coreconfigitem(
1161 coreconfigitem(
1162 b'experimental',
1162 b'experimental',
1163 b'revisions.disambiguatewithin',
1163 b'revisions.disambiguatewithin',
1164 default=None,
1164 default=None,
1165 )
1165 )
1166 coreconfigitem(
1166 coreconfigitem(
1167 b'experimental',
1167 b'experimental',
1168 b'rust.index',
1168 b'rust.index',
1169 default=False,
1169 default=False,
1170 )
1170 )
1171 coreconfigitem(
1171 coreconfigitem(
1172 b'experimental',
1172 b'experimental',
1173 b'server.filesdata.recommended-batch-size',
1173 b'server.filesdata.recommended-batch-size',
1174 default=50000,
1174 default=50000,
1175 )
1175 )
1176 coreconfigitem(
1176 coreconfigitem(
1177 b'experimental',
1177 b'experimental',
1178 b'server.manifestdata.recommended-batch-size',
1178 b'server.manifestdata.recommended-batch-size',
1179 default=100000,
1179 default=100000,
1180 )
1180 )
1181 coreconfigitem(
1181 coreconfigitem(
1182 b'experimental',
1182 b'experimental',
1183 b'server.stream-narrow-clones',
1183 b'server.stream-narrow-clones',
1184 default=False,
1184 default=False,
1185 )
1185 )
1186 coreconfigitem(
1186 coreconfigitem(
1187 b'experimental',
1187 b'experimental',
1188 b'single-head-per-branch',
1188 b'single-head-per-branch',
1189 default=False,
1189 default=False,
1190 )
1190 )
1191 coreconfigitem(
1191 coreconfigitem(
1192 b'experimental',
1192 b'experimental',
1193 b'single-head-per-branch:account-closed-heads',
1193 b'single-head-per-branch:account-closed-heads',
1194 default=False,
1194 default=False,
1195 )
1195 )
1196 coreconfigitem(
1196 coreconfigitem(
1197 b'experimental',
1197 b'experimental',
1198 b'single-head-per-branch:public-changes-only',
1198 b'single-head-per-branch:public-changes-only',
1199 default=False,
1199 default=False,
1200 )
1200 )
1201 coreconfigitem(
1201 coreconfigitem(
1202 b'experimental',
1202 b'experimental',
1203 b'sparse-read',
1203 b'sparse-read',
1204 default=False,
1204 default=False,
1205 )
1205 )
1206 coreconfigitem(
1206 coreconfigitem(
1207 b'experimental',
1207 b'experimental',
1208 b'sparse-read.density-threshold',
1208 b'sparse-read.density-threshold',
1209 default=0.50,
1209 default=0.50,
1210 )
1210 )
1211 coreconfigitem(
1211 coreconfigitem(
1212 b'experimental',
1212 b'experimental',
1213 b'sparse-read.min-gap-size',
1213 b'sparse-read.min-gap-size',
1214 default=b'65K',
1214 default=b'65K',
1215 )
1215 )
1216 coreconfigitem(
1216 coreconfigitem(
1217 b'experimental',
1217 b'experimental',
1218 b'treemanifest',
1218 b'treemanifest',
1219 default=False,
1219 default=False,
1220 )
1220 )
1221 coreconfigitem(
1221 coreconfigitem(
1222 b'experimental',
1222 b'experimental',
1223 b'update.atomic-file',
1223 b'update.atomic-file',
1224 default=False,
1224 default=False,
1225 )
1225 )
1226 coreconfigitem(
1226 coreconfigitem(
1227 b'experimental',
1227 b'experimental',
1228 b'web.full-garbage-collection-rate',
1228 b'web.full-garbage-collection-rate',
1229 default=1, # still forcing a full collection on each request
1229 default=1, # still forcing a full collection on each request
1230 )
1230 )
1231 coreconfigitem(
1231 coreconfigitem(
1232 b'experimental',
1232 b'experimental',
1233 b'worker.wdir-get-thread-safe',
1233 b'worker.wdir-get-thread-safe',
1234 default=False,
1234 default=False,
1235 )
1235 )
1236 coreconfigitem(
1236 coreconfigitem(
1237 b'experimental',
1237 b'experimental',
1238 b'worker.repository-upgrade',
1238 b'worker.repository-upgrade',
1239 default=False,
1239 default=False,
1240 )
1240 )
1241 coreconfigitem(
1241 coreconfigitem(
1242 b'experimental',
1242 b'experimental',
1243 b'xdiff',
1243 b'xdiff',
1244 default=False,
1244 default=False,
1245 )
1245 )
1246 coreconfigitem(
1246 coreconfigitem(
1247 b'extensions',
1247 b'extensions',
1248 b'[^:]*',
1248 b'[^:]*',
1249 default=None,
1249 default=None,
1250 generic=True,
1250 generic=True,
1251 )
1251 )
1252 coreconfigitem(
1252 coreconfigitem(
1253 b'extensions',
1253 b'extensions',
1254 b'[^:]*:required',
1254 b'[^:]*:required',
1255 default=False,
1255 default=False,
1256 generic=True,
1256 generic=True,
1257 )
1257 )
1258 coreconfigitem(
1258 coreconfigitem(
1259 b'extdata',
1259 b'extdata',
1260 b'.*',
1260 b'.*',
1261 default=None,
1261 default=None,
1262 generic=True,
1262 generic=True,
1263 )
1263 )
1264 coreconfigitem(
1264 coreconfigitem(
1265 b'format',
1265 b'format',
1266 b'bookmarks-in-store',
1266 b'bookmarks-in-store',
1267 default=False,
1267 default=False,
1268 )
1268 )
1269 coreconfigitem(
1269 coreconfigitem(
1270 b'format',
1270 b'format',
1271 b'chunkcachesize',
1271 b'chunkcachesize',
1272 default=None,
1272 default=None,
1273 experimental=True,
1273 experimental=True,
1274 )
1274 )
1275 coreconfigitem(
1275 coreconfigitem(
1276 # Enable this dirstate format *when creating a new repository*.
1276 # Enable this dirstate format *when creating a new repository*.
1277 # Which format to use for existing repos is controlled by .hg/requires
1277 # Which format to use for existing repos is controlled by .hg/requires
1278 b'format',
1278 b'format',
1279 b'use-dirstate-v2',
1279 b'use-dirstate-v2',
1280 default=False,
1280 default=False,
1281 experimental=True,
1281 experimental=True,
1282 alias=[(b'format', b'exp-rc-dirstate-v2')],
1282 alias=[(b'format', b'exp-rc-dirstate-v2')],
1283 )
1283 )
1284 coreconfigitem(
1284 coreconfigitem(
1285 b'format',
1285 b'format',
1286 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories',
1286 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories',
1287 default=False,
1287 default=False,
1288 experimental=True,
1288 experimental=True,
1289 )
1289 )
1290 coreconfigitem(
1290 coreconfigitem(
1291 b'format',
1291 b'format',
1292 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet',
1292 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet',
1293 default=False,
1293 default=False,
1294 experimental=True,
1294 experimental=True,
1295 )
1295 )
1296 coreconfigitem(
1296 coreconfigitem(
1297 b'format',
1297 b'format',
1298 b'use-dirstate-tracked-hint',
1298 b'use-dirstate-tracked-hint',
1299 default=False,
1299 default=False,
1300 experimental=True,
1300 experimental=True,
1301 )
1301 )
1302 coreconfigitem(
1302 coreconfigitem(
1303 b'format',
1303 b'format',
1304 b'use-dirstate-tracked-hint.version',
1304 b'use-dirstate-tracked-hint.version',
1305 default=1,
1305 default=1,
1306 experimental=True,
1306 experimental=True,
1307 )
1307 )
1308 coreconfigitem(
1308 coreconfigitem(
1309 b'format',
1309 b'format',
1310 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories',
1310 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories',
1311 default=False,
1311 default=False,
1312 experimental=True,
1312 experimental=True,
1313 )
1313 )
1314 coreconfigitem(
1314 coreconfigitem(
1315 b'format',
1315 b'format',
1316 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet',
1316 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet',
1317 default=False,
1317 default=False,
1318 experimental=True,
1318 experimental=True,
1319 )
1319 )
1320 coreconfigitem(
1320 coreconfigitem(
1321 b'format',
1321 b'format',
1322 b'dotencode',
1322 b'dotencode',
1323 default=True,
1323 default=True,
1324 )
1324 )
1325 coreconfigitem(
1325 coreconfigitem(
1326 b'format',
1326 b'format',
1327 b'generaldelta',
1327 b'generaldelta',
1328 default=False,
1328 default=False,
1329 experimental=True,
1329 experimental=True,
1330 )
1330 )
1331 coreconfigitem(
1331 coreconfigitem(
1332 b'format',
1332 b'format',
1333 b'manifestcachesize',
1333 b'manifestcachesize',
1334 default=None,
1334 default=None,
1335 experimental=True,
1335 experimental=True,
1336 )
1336 )
1337 coreconfigitem(
1337 coreconfigitem(
1338 b'format',
1338 b'format',
1339 b'maxchainlen',
1339 b'maxchainlen',
1340 default=dynamicdefault,
1340 default=dynamicdefault,
1341 experimental=True,
1341 experimental=True,
1342 )
1342 )
1343 coreconfigitem(
1343 coreconfigitem(
1344 b'format',
1344 b'format',
1345 b'obsstore-version',
1345 b'obsstore-version',
1346 default=None,
1346 default=None,
1347 )
1347 )
1348 coreconfigitem(
1348 coreconfigitem(
1349 b'format',
1349 b'format',
1350 b'sparse-revlog',
1350 b'sparse-revlog',
1351 default=True,
1351 default=True,
1352 )
1352 )
1353 coreconfigitem(
1353 coreconfigitem(
1354 b'format',
1354 b'format',
1355 b'revlog-compression',
1355 b'revlog-compression',
1356 default=lambda: [b'zstd', b'zlib'],
1356 default=lambda: [b'zstd', b'zlib'],
1357 alias=[(b'experimental', b'format.compression')],
1357 alias=[(b'experimental', b'format.compression')],
1358 )
1358 )
1359 # Experimental TODOs:
1359 # Experimental TODOs:
1360 #
1360 #
1361 # * Same as for revlogv2 (but for the reduction of the number of files)
1361 # * Same as for revlogv2 (but for the reduction of the number of files)
1362 # * Actually computing the rank of changesets
1362 # * Actually computing the rank of changesets
1363 # * Improvement to investigate
1363 # * Improvement to investigate
1364 # - storing .hgtags fnode
1364 # - storing .hgtags fnode
1365 # - storing branch related identifier
1365 # - storing branch related identifier
1366
1366
1367 coreconfigitem(
1367 coreconfigitem(
1368 b'format',
1368 b'format',
1369 b'exp-use-changelog-v2',
1369 b'exp-use-changelog-v2',
1370 default=None,
1370 default=None,
1371 experimental=True,
1371 experimental=True,
1372 )
1372 )
1373 coreconfigitem(
1373 coreconfigitem(
1374 b'format',
1374 b'format',
1375 b'usefncache',
1375 b'usefncache',
1376 default=True,
1376 default=True,
1377 )
1377 )
1378 coreconfigitem(
1378 coreconfigitem(
1379 b'format',
1379 b'format',
1380 b'usegeneraldelta',
1380 b'usegeneraldelta',
1381 default=True,
1381 default=True,
1382 )
1382 )
1383 coreconfigitem(
1383 coreconfigitem(
1384 b'format',
1384 b'format',
1385 b'usestore',
1385 b'usestore',
1386 default=True,
1386 default=True,
1387 )
1387 )
1388
1388
1389
1389
1390 def _persistent_nodemap_default():
1390 def _persistent_nodemap_default():
1391 """compute `use-persistent-nodemap` default value
1391 """compute `use-persistent-nodemap` default value
1392
1392
1393 The feature is disabled unless a fast implementation is available.
1393 The feature is disabled unless a fast implementation is available.
1394 """
1394 """
1395 from . import policy
1395 from . import policy
1396
1396
1397 return policy.importrust('revlog') is not None
1397 return policy.importrust('revlog') is not None
1398
1398
1399
1399
1400 coreconfigitem(
1400 coreconfigitem(
1401 b'format',
1401 b'format',
1402 b'use-persistent-nodemap',
1402 b'use-persistent-nodemap',
1403 default=_persistent_nodemap_default,
1403 default=_persistent_nodemap_default,
1404 )
1404 )
1405 coreconfigitem(
1405 coreconfigitem(
1406 b'format',
1406 b'format',
1407 b'exp-use-copies-side-data-changeset',
1407 b'exp-use-copies-side-data-changeset',
1408 default=False,
1408 default=False,
1409 experimental=True,
1409 experimental=True,
1410 )
1410 )
1411 coreconfigitem(
1411 coreconfigitem(
1412 b'format',
1412 b'format',
1413 b'use-share-safe',
1413 b'use-share-safe',
1414 default=True,
1414 default=True,
1415 )
1415 )
1416 coreconfigitem(
1416 coreconfigitem(
1417 b'format',
1417 b'format',
1418 b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
1418 b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
1419 default=False,
1419 default=False,
1420 experimental=True,
1420 experimental=True,
1421 )
1421 )
1422 coreconfigitem(
1422 coreconfigitem(
1423 b'format',
1423 b'format',
1424 b'use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet',
1424 b'use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet',
1425 default=False,
1425 default=False,
1426 experimental=True,
1426 experimental=True,
1427 )
1427 )
1428
1429 # Moving this on by default means we are confident about the scaling of phases.
1430 # This is not garanteed to be the case at the time this message is written.
1428 coreconfigitem(
1431 coreconfigitem(
1429 b'format',
1432 b'format',
1430 b'internal-phase',
1433 b'use-internal-phase',
1431 default=False,
1434 default=False,
1432 experimental=True,
1435 experimental=True,
1433 )
1436 )
1434 # The interaction between the archived phase and obsolescence markers needs to
1437 # The interaction between the archived phase and obsolescence markers needs to
1435 # be sorted out before wider usage of this are to be considered.
1438 # be sorted out before wider usage of this are to be considered.
1436 #
1439 #
1437 # At the time this message is written, behavior when archiving obsolete
1440 # At the time this message is written, behavior when archiving obsolete
1438 # changeset differ significantly from stripping. As part of stripping, we also
1441 # changeset differ significantly from stripping. As part of stripping, we also
1439 # remove the obsolescence marker associated to the stripped changesets,
1442 # remove the obsolescence marker associated to the stripped changesets,
1440 # revealing the precedecessors changesets when applicable. When archiving, we
1443 # revealing the precedecessors changesets when applicable. When archiving, we
1441 # don't touch the obsolescence markers, keeping everything hidden. This can
1444 # don't touch the obsolescence markers, keeping everything hidden. This can
1442 # result in quite confusing situation for people combining exchanging draft
1445 # result in quite confusing situation for people combining exchanging draft
1443 # with the archived phases. As some markers needed by others may be skipped
1446 # with the archived phases. As some markers needed by others may be skipped
1444 # during exchange.
1447 # during exchange.
1445 coreconfigitem(
1448 coreconfigitem(
1446 b'format',
1449 b'format',
1447 b'exp-archived-phase',
1450 b'exp-archived-phase',
1448 default=False,
1451 default=False,
1449 experimental=True,
1452 experimental=True,
1450 )
1453 )
1451 coreconfigitem(
1454 coreconfigitem(
1452 b'shelve',
1455 b'shelve',
1453 b'store',
1456 b'store',
1454 default='internal',
1457 default='internal',
1455 experimental=True,
1458 experimental=True,
1456 )
1459 )
1457 coreconfigitem(
1460 coreconfigitem(
1458 b'fsmonitor',
1461 b'fsmonitor',
1459 b'warn_when_unused',
1462 b'warn_when_unused',
1460 default=True,
1463 default=True,
1461 )
1464 )
1462 coreconfigitem(
1465 coreconfigitem(
1463 b'fsmonitor',
1466 b'fsmonitor',
1464 b'warn_update_file_count',
1467 b'warn_update_file_count',
1465 default=50000,
1468 default=50000,
1466 )
1469 )
1467 coreconfigitem(
1470 coreconfigitem(
1468 b'fsmonitor',
1471 b'fsmonitor',
1469 b'warn_update_file_count_rust',
1472 b'warn_update_file_count_rust',
1470 default=400000,
1473 default=400000,
1471 )
1474 )
1472 coreconfigitem(
1475 coreconfigitem(
1473 b'help',
1476 b'help',
1474 br'hidden-command\..*',
1477 br'hidden-command\..*',
1475 default=False,
1478 default=False,
1476 generic=True,
1479 generic=True,
1477 )
1480 )
1478 coreconfigitem(
1481 coreconfigitem(
1479 b'help',
1482 b'help',
1480 br'hidden-topic\..*',
1483 br'hidden-topic\..*',
1481 default=False,
1484 default=False,
1482 generic=True,
1485 generic=True,
1483 )
1486 )
1484 coreconfigitem(
1487 coreconfigitem(
1485 b'hooks',
1488 b'hooks',
1486 b'[^:]*',
1489 b'[^:]*',
1487 default=dynamicdefault,
1490 default=dynamicdefault,
1488 generic=True,
1491 generic=True,
1489 )
1492 )
1490 coreconfigitem(
1493 coreconfigitem(
1491 b'hooks',
1494 b'hooks',
1492 b'.*:run-with-plain',
1495 b'.*:run-with-plain',
1493 default=True,
1496 default=True,
1494 generic=True,
1497 generic=True,
1495 )
1498 )
1496 coreconfigitem(
1499 coreconfigitem(
1497 b'hgweb-paths',
1500 b'hgweb-paths',
1498 b'.*',
1501 b'.*',
1499 default=list,
1502 default=list,
1500 generic=True,
1503 generic=True,
1501 )
1504 )
1502 coreconfigitem(
1505 coreconfigitem(
1503 b'hostfingerprints',
1506 b'hostfingerprints',
1504 b'.*',
1507 b'.*',
1505 default=list,
1508 default=list,
1506 generic=True,
1509 generic=True,
1507 )
1510 )
1508 coreconfigitem(
1511 coreconfigitem(
1509 b'hostsecurity',
1512 b'hostsecurity',
1510 b'ciphers',
1513 b'ciphers',
1511 default=None,
1514 default=None,
1512 )
1515 )
1513 coreconfigitem(
1516 coreconfigitem(
1514 b'hostsecurity',
1517 b'hostsecurity',
1515 b'minimumprotocol',
1518 b'minimumprotocol',
1516 default=dynamicdefault,
1519 default=dynamicdefault,
1517 )
1520 )
1518 coreconfigitem(
1521 coreconfigitem(
1519 b'hostsecurity',
1522 b'hostsecurity',
1520 b'.*:minimumprotocol$',
1523 b'.*:minimumprotocol$',
1521 default=dynamicdefault,
1524 default=dynamicdefault,
1522 generic=True,
1525 generic=True,
1523 )
1526 )
1524 coreconfigitem(
1527 coreconfigitem(
1525 b'hostsecurity',
1528 b'hostsecurity',
1526 b'.*:ciphers$',
1529 b'.*:ciphers$',
1527 default=dynamicdefault,
1530 default=dynamicdefault,
1528 generic=True,
1531 generic=True,
1529 )
1532 )
1530 coreconfigitem(
1533 coreconfigitem(
1531 b'hostsecurity',
1534 b'hostsecurity',
1532 b'.*:fingerprints$',
1535 b'.*:fingerprints$',
1533 default=list,
1536 default=list,
1534 generic=True,
1537 generic=True,
1535 )
1538 )
1536 coreconfigitem(
1539 coreconfigitem(
1537 b'hostsecurity',
1540 b'hostsecurity',
1538 b'.*:verifycertsfile$',
1541 b'.*:verifycertsfile$',
1539 default=None,
1542 default=None,
1540 generic=True,
1543 generic=True,
1541 )
1544 )
1542
1545
1543 coreconfigitem(
1546 coreconfigitem(
1544 b'http_proxy',
1547 b'http_proxy',
1545 b'always',
1548 b'always',
1546 default=False,
1549 default=False,
1547 )
1550 )
1548 coreconfigitem(
1551 coreconfigitem(
1549 b'http_proxy',
1552 b'http_proxy',
1550 b'host',
1553 b'host',
1551 default=None,
1554 default=None,
1552 )
1555 )
1553 coreconfigitem(
1556 coreconfigitem(
1554 b'http_proxy',
1557 b'http_proxy',
1555 b'no',
1558 b'no',
1556 default=list,
1559 default=list,
1557 )
1560 )
1558 coreconfigitem(
1561 coreconfigitem(
1559 b'http_proxy',
1562 b'http_proxy',
1560 b'passwd',
1563 b'passwd',
1561 default=None,
1564 default=None,
1562 )
1565 )
1563 coreconfigitem(
1566 coreconfigitem(
1564 b'http_proxy',
1567 b'http_proxy',
1565 b'user',
1568 b'user',
1566 default=None,
1569 default=None,
1567 )
1570 )
1568
1571
1569 coreconfigitem(
1572 coreconfigitem(
1570 b'http',
1573 b'http',
1571 b'timeout',
1574 b'timeout',
1572 default=None,
1575 default=None,
1573 )
1576 )
1574
1577
1575 coreconfigitem(
1578 coreconfigitem(
1576 b'logtoprocess',
1579 b'logtoprocess',
1577 b'commandexception',
1580 b'commandexception',
1578 default=None,
1581 default=None,
1579 )
1582 )
1580 coreconfigitem(
1583 coreconfigitem(
1581 b'logtoprocess',
1584 b'logtoprocess',
1582 b'commandfinish',
1585 b'commandfinish',
1583 default=None,
1586 default=None,
1584 )
1587 )
1585 coreconfigitem(
1588 coreconfigitem(
1586 b'logtoprocess',
1589 b'logtoprocess',
1587 b'command',
1590 b'command',
1588 default=None,
1591 default=None,
1589 )
1592 )
1590 coreconfigitem(
1593 coreconfigitem(
1591 b'logtoprocess',
1594 b'logtoprocess',
1592 b'develwarn',
1595 b'develwarn',
1593 default=None,
1596 default=None,
1594 )
1597 )
1595 coreconfigitem(
1598 coreconfigitem(
1596 b'logtoprocess',
1599 b'logtoprocess',
1597 b'uiblocked',
1600 b'uiblocked',
1598 default=None,
1601 default=None,
1599 )
1602 )
1600 coreconfigitem(
1603 coreconfigitem(
1601 b'merge',
1604 b'merge',
1602 b'checkunknown',
1605 b'checkunknown',
1603 default=b'abort',
1606 default=b'abort',
1604 )
1607 )
1605 coreconfigitem(
1608 coreconfigitem(
1606 b'merge',
1609 b'merge',
1607 b'checkignored',
1610 b'checkignored',
1608 default=b'abort',
1611 default=b'abort',
1609 )
1612 )
1610 coreconfigitem(
1613 coreconfigitem(
1611 b'experimental',
1614 b'experimental',
1612 b'merge.checkpathconflicts',
1615 b'merge.checkpathconflicts',
1613 default=False,
1616 default=False,
1614 )
1617 )
1615 coreconfigitem(
1618 coreconfigitem(
1616 b'merge',
1619 b'merge',
1617 b'followcopies',
1620 b'followcopies',
1618 default=True,
1621 default=True,
1619 )
1622 )
1620 coreconfigitem(
1623 coreconfigitem(
1621 b'merge',
1624 b'merge',
1622 b'on-failure',
1625 b'on-failure',
1623 default=b'continue',
1626 default=b'continue',
1624 )
1627 )
1625 coreconfigitem(
1628 coreconfigitem(
1626 b'merge',
1629 b'merge',
1627 b'preferancestor',
1630 b'preferancestor',
1628 default=lambda: [b'*'],
1631 default=lambda: [b'*'],
1629 experimental=True,
1632 experimental=True,
1630 )
1633 )
1631 coreconfigitem(
1634 coreconfigitem(
1632 b'merge',
1635 b'merge',
1633 b'strict-capability-check',
1636 b'strict-capability-check',
1634 default=False,
1637 default=False,
1635 )
1638 )
1636 coreconfigitem(
1639 coreconfigitem(
1637 b'merge',
1640 b'merge',
1638 b'disable-partial-tools',
1641 b'disable-partial-tools',
1639 default=False,
1642 default=False,
1640 experimental=True,
1643 experimental=True,
1641 )
1644 )
1642 coreconfigitem(
1645 coreconfigitem(
1643 b'partial-merge-tools',
1646 b'partial-merge-tools',
1644 b'.*',
1647 b'.*',
1645 default=None,
1648 default=None,
1646 generic=True,
1649 generic=True,
1647 experimental=True,
1650 experimental=True,
1648 )
1651 )
1649 coreconfigitem(
1652 coreconfigitem(
1650 b'partial-merge-tools',
1653 b'partial-merge-tools',
1651 br'.*\.patterns',
1654 br'.*\.patterns',
1652 default=dynamicdefault,
1655 default=dynamicdefault,
1653 generic=True,
1656 generic=True,
1654 priority=-1,
1657 priority=-1,
1655 experimental=True,
1658 experimental=True,
1656 )
1659 )
1657 coreconfigitem(
1660 coreconfigitem(
1658 b'partial-merge-tools',
1661 b'partial-merge-tools',
1659 br'.*\.executable$',
1662 br'.*\.executable$',
1660 default=dynamicdefault,
1663 default=dynamicdefault,
1661 generic=True,
1664 generic=True,
1662 priority=-1,
1665 priority=-1,
1663 experimental=True,
1666 experimental=True,
1664 )
1667 )
1665 coreconfigitem(
1668 coreconfigitem(
1666 b'partial-merge-tools',
1669 b'partial-merge-tools',
1667 br'.*\.order',
1670 br'.*\.order',
1668 default=0,
1671 default=0,
1669 generic=True,
1672 generic=True,
1670 priority=-1,
1673 priority=-1,
1671 experimental=True,
1674 experimental=True,
1672 )
1675 )
1673 coreconfigitem(
1676 coreconfigitem(
1674 b'partial-merge-tools',
1677 b'partial-merge-tools',
1675 br'.*\.args',
1678 br'.*\.args',
1676 default=b"$local $base $other",
1679 default=b"$local $base $other",
1677 generic=True,
1680 generic=True,
1678 priority=-1,
1681 priority=-1,
1679 experimental=True,
1682 experimental=True,
1680 )
1683 )
1681 coreconfigitem(
1684 coreconfigitem(
1682 b'partial-merge-tools',
1685 b'partial-merge-tools',
1683 br'.*\.disable',
1686 br'.*\.disable',
1684 default=False,
1687 default=False,
1685 generic=True,
1688 generic=True,
1686 priority=-1,
1689 priority=-1,
1687 experimental=True,
1690 experimental=True,
1688 )
1691 )
1689 coreconfigitem(
1692 coreconfigitem(
1690 b'merge-tools',
1693 b'merge-tools',
1691 b'.*',
1694 b'.*',
1692 default=None,
1695 default=None,
1693 generic=True,
1696 generic=True,
1694 )
1697 )
1695 coreconfigitem(
1698 coreconfigitem(
1696 b'merge-tools',
1699 b'merge-tools',
1697 br'.*\.args$',
1700 br'.*\.args$',
1698 default=b"$local $base $other",
1701 default=b"$local $base $other",
1699 generic=True,
1702 generic=True,
1700 priority=-1,
1703 priority=-1,
1701 )
1704 )
1702 coreconfigitem(
1705 coreconfigitem(
1703 b'merge-tools',
1706 b'merge-tools',
1704 br'.*\.binary$',
1707 br'.*\.binary$',
1705 default=False,
1708 default=False,
1706 generic=True,
1709 generic=True,
1707 priority=-1,
1710 priority=-1,
1708 )
1711 )
1709 coreconfigitem(
1712 coreconfigitem(
1710 b'merge-tools',
1713 b'merge-tools',
1711 br'.*\.check$',
1714 br'.*\.check$',
1712 default=list,
1715 default=list,
1713 generic=True,
1716 generic=True,
1714 priority=-1,
1717 priority=-1,
1715 )
1718 )
1716 coreconfigitem(
1719 coreconfigitem(
1717 b'merge-tools',
1720 b'merge-tools',
1718 br'.*\.checkchanged$',
1721 br'.*\.checkchanged$',
1719 default=False,
1722 default=False,
1720 generic=True,
1723 generic=True,
1721 priority=-1,
1724 priority=-1,
1722 )
1725 )
1723 coreconfigitem(
1726 coreconfigitem(
1724 b'merge-tools',
1727 b'merge-tools',
1725 br'.*\.executable$',
1728 br'.*\.executable$',
1726 default=dynamicdefault,
1729 default=dynamicdefault,
1727 generic=True,
1730 generic=True,
1728 priority=-1,
1731 priority=-1,
1729 )
1732 )
1730 coreconfigitem(
1733 coreconfigitem(
1731 b'merge-tools',
1734 b'merge-tools',
1732 br'.*\.fixeol$',
1735 br'.*\.fixeol$',
1733 default=False,
1736 default=False,
1734 generic=True,
1737 generic=True,
1735 priority=-1,
1738 priority=-1,
1736 )
1739 )
1737 coreconfigitem(
1740 coreconfigitem(
1738 b'merge-tools',
1741 b'merge-tools',
1739 br'.*\.gui$',
1742 br'.*\.gui$',
1740 default=False,
1743 default=False,
1741 generic=True,
1744 generic=True,
1742 priority=-1,
1745 priority=-1,
1743 )
1746 )
1744 coreconfigitem(
1747 coreconfigitem(
1745 b'merge-tools',
1748 b'merge-tools',
1746 br'.*\.mergemarkers$',
1749 br'.*\.mergemarkers$',
1747 default=b'basic',
1750 default=b'basic',
1748 generic=True,
1751 generic=True,
1749 priority=-1,
1752 priority=-1,
1750 )
1753 )
1751 coreconfigitem(
1754 coreconfigitem(
1752 b'merge-tools',
1755 b'merge-tools',
1753 br'.*\.mergemarkertemplate$',
1756 br'.*\.mergemarkertemplate$',
1754 default=dynamicdefault, # take from command-templates.mergemarker
1757 default=dynamicdefault, # take from command-templates.mergemarker
1755 generic=True,
1758 generic=True,
1756 priority=-1,
1759 priority=-1,
1757 )
1760 )
1758 coreconfigitem(
1761 coreconfigitem(
1759 b'merge-tools',
1762 b'merge-tools',
1760 br'.*\.priority$',
1763 br'.*\.priority$',
1761 default=0,
1764 default=0,
1762 generic=True,
1765 generic=True,
1763 priority=-1,
1766 priority=-1,
1764 )
1767 )
1765 coreconfigitem(
1768 coreconfigitem(
1766 b'merge-tools',
1769 b'merge-tools',
1767 br'.*\.premerge$',
1770 br'.*\.premerge$',
1768 default=dynamicdefault,
1771 default=dynamicdefault,
1769 generic=True,
1772 generic=True,
1770 priority=-1,
1773 priority=-1,
1771 )
1774 )
1772 coreconfigitem(
1775 coreconfigitem(
1773 b'merge-tools',
1776 b'merge-tools',
1774 br'.*\.symlink$',
1777 br'.*\.symlink$',
1775 default=False,
1778 default=False,
1776 generic=True,
1779 generic=True,
1777 priority=-1,
1780 priority=-1,
1778 )
1781 )
1779 coreconfigitem(
1782 coreconfigitem(
1780 b'pager',
1783 b'pager',
1781 b'attend-.*',
1784 b'attend-.*',
1782 default=dynamicdefault,
1785 default=dynamicdefault,
1783 generic=True,
1786 generic=True,
1784 )
1787 )
1785 coreconfigitem(
1788 coreconfigitem(
1786 b'pager',
1789 b'pager',
1787 b'ignore',
1790 b'ignore',
1788 default=list,
1791 default=list,
1789 )
1792 )
1790 coreconfigitem(
1793 coreconfigitem(
1791 b'pager',
1794 b'pager',
1792 b'pager',
1795 b'pager',
1793 default=dynamicdefault,
1796 default=dynamicdefault,
1794 )
1797 )
1795 coreconfigitem(
1798 coreconfigitem(
1796 b'patch',
1799 b'patch',
1797 b'eol',
1800 b'eol',
1798 default=b'strict',
1801 default=b'strict',
1799 )
1802 )
1800 coreconfigitem(
1803 coreconfigitem(
1801 b'patch',
1804 b'patch',
1802 b'fuzz',
1805 b'fuzz',
1803 default=2,
1806 default=2,
1804 )
1807 )
1805 coreconfigitem(
1808 coreconfigitem(
1806 b'paths',
1809 b'paths',
1807 b'default',
1810 b'default',
1808 default=None,
1811 default=None,
1809 )
1812 )
1810 coreconfigitem(
1813 coreconfigitem(
1811 b'paths',
1814 b'paths',
1812 b'default-push',
1815 b'default-push',
1813 default=None,
1816 default=None,
1814 )
1817 )
1815 coreconfigitem(
1818 coreconfigitem(
1816 b'paths',
1819 b'paths',
1817 b'.*',
1820 b'.*',
1818 default=None,
1821 default=None,
1819 generic=True,
1822 generic=True,
1820 )
1823 )
1821 coreconfigitem(
1824 coreconfigitem(
1822 b'paths',
1825 b'paths',
1823 b'.*:bookmarks.mode',
1826 b'.*:bookmarks.mode',
1824 default='default',
1827 default='default',
1825 generic=True,
1828 generic=True,
1826 )
1829 )
1827 coreconfigitem(
1830 coreconfigitem(
1828 b'paths',
1831 b'paths',
1829 b'.*:multi-urls',
1832 b'.*:multi-urls',
1830 default=False,
1833 default=False,
1831 generic=True,
1834 generic=True,
1832 )
1835 )
1833 coreconfigitem(
1836 coreconfigitem(
1834 b'paths',
1837 b'paths',
1835 b'.*:pushrev',
1838 b'.*:pushrev',
1836 default=None,
1839 default=None,
1837 generic=True,
1840 generic=True,
1838 )
1841 )
1839 coreconfigitem(
1842 coreconfigitem(
1840 b'paths',
1843 b'paths',
1841 b'.*:pushurl',
1844 b'.*:pushurl',
1842 default=None,
1845 default=None,
1843 generic=True,
1846 generic=True,
1844 )
1847 )
1845 coreconfigitem(
1848 coreconfigitem(
1846 b'phases',
1849 b'phases',
1847 b'checksubrepos',
1850 b'checksubrepos',
1848 default=b'follow',
1851 default=b'follow',
1849 )
1852 )
1850 coreconfigitem(
1853 coreconfigitem(
1851 b'phases',
1854 b'phases',
1852 b'new-commit',
1855 b'new-commit',
1853 default=b'draft',
1856 default=b'draft',
1854 )
1857 )
1855 coreconfigitem(
1858 coreconfigitem(
1856 b'phases',
1859 b'phases',
1857 b'publish',
1860 b'publish',
1858 default=True,
1861 default=True,
1859 )
1862 )
1860 coreconfigitem(
1863 coreconfigitem(
1861 b'profiling',
1864 b'profiling',
1862 b'enabled',
1865 b'enabled',
1863 default=False,
1866 default=False,
1864 )
1867 )
1865 coreconfigitem(
1868 coreconfigitem(
1866 b'profiling',
1869 b'profiling',
1867 b'format',
1870 b'format',
1868 default=b'text',
1871 default=b'text',
1869 )
1872 )
1870 coreconfigitem(
1873 coreconfigitem(
1871 b'profiling',
1874 b'profiling',
1872 b'freq',
1875 b'freq',
1873 default=1000,
1876 default=1000,
1874 )
1877 )
1875 coreconfigitem(
1878 coreconfigitem(
1876 b'profiling',
1879 b'profiling',
1877 b'limit',
1880 b'limit',
1878 default=30,
1881 default=30,
1879 )
1882 )
1880 coreconfigitem(
1883 coreconfigitem(
1881 b'profiling',
1884 b'profiling',
1882 b'nested',
1885 b'nested',
1883 default=0,
1886 default=0,
1884 )
1887 )
1885 coreconfigitem(
1888 coreconfigitem(
1886 b'profiling',
1889 b'profiling',
1887 b'output',
1890 b'output',
1888 default=None,
1891 default=None,
1889 )
1892 )
1890 coreconfigitem(
1893 coreconfigitem(
1891 b'profiling',
1894 b'profiling',
1892 b'showmax',
1895 b'showmax',
1893 default=0.999,
1896 default=0.999,
1894 )
1897 )
1895 coreconfigitem(
1898 coreconfigitem(
1896 b'profiling',
1899 b'profiling',
1897 b'showmin',
1900 b'showmin',
1898 default=dynamicdefault,
1901 default=dynamicdefault,
1899 )
1902 )
1900 coreconfigitem(
1903 coreconfigitem(
1901 b'profiling',
1904 b'profiling',
1902 b'showtime',
1905 b'showtime',
1903 default=True,
1906 default=True,
1904 )
1907 )
1905 coreconfigitem(
1908 coreconfigitem(
1906 b'profiling',
1909 b'profiling',
1907 b'sort',
1910 b'sort',
1908 default=b'inlinetime',
1911 default=b'inlinetime',
1909 )
1912 )
1910 coreconfigitem(
1913 coreconfigitem(
1911 b'profiling',
1914 b'profiling',
1912 b'statformat',
1915 b'statformat',
1913 default=b'hotpath',
1916 default=b'hotpath',
1914 )
1917 )
1915 coreconfigitem(
1918 coreconfigitem(
1916 b'profiling',
1919 b'profiling',
1917 b'time-track',
1920 b'time-track',
1918 default=dynamicdefault,
1921 default=dynamicdefault,
1919 )
1922 )
1920 coreconfigitem(
1923 coreconfigitem(
1921 b'profiling',
1924 b'profiling',
1922 b'type',
1925 b'type',
1923 default=b'stat',
1926 default=b'stat',
1924 )
1927 )
1925 coreconfigitem(
1928 coreconfigitem(
1926 b'progress',
1929 b'progress',
1927 b'assume-tty',
1930 b'assume-tty',
1928 default=False,
1931 default=False,
1929 )
1932 )
1930 coreconfigitem(
1933 coreconfigitem(
1931 b'progress',
1934 b'progress',
1932 b'changedelay',
1935 b'changedelay',
1933 default=1,
1936 default=1,
1934 )
1937 )
1935 coreconfigitem(
1938 coreconfigitem(
1936 b'progress',
1939 b'progress',
1937 b'clear-complete',
1940 b'clear-complete',
1938 default=True,
1941 default=True,
1939 )
1942 )
1940 coreconfigitem(
1943 coreconfigitem(
1941 b'progress',
1944 b'progress',
1942 b'debug',
1945 b'debug',
1943 default=False,
1946 default=False,
1944 )
1947 )
1945 coreconfigitem(
1948 coreconfigitem(
1946 b'progress',
1949 b'progress',
1947 b'delay',
1950 b'delay',
1948 default=3,
1951 default=3,
1949 )
1952 )
1950 coreconfigitem(
1953 coreconfigitem(
1951 b'progress',
1954 b'progress',
1952 b'disable',
1955 b'disable',
1953 default=False,
1956 default=False,
1954 )
1957 )
1955 coreconfigitem(
1958 coreconfigitem(
1956 b'progress',
1959 b'progress',
1957 b'estimateinterval',
1960 b'estimateinterval',
1958 default=60.0,
1961 default=60.0,
1959 )
1962 )
1960 coreconfigitem(
1963 coreconfigitem(
1961 b'progress',
1964 b'progress',
1962 b'format',
1965 b'format',
1963 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1966 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1964 )
1967 )
1965 coreconfigitem(
1968 coreconfigitem(
1966 b'progress',
1969 b'progress',
1967 b'refresh',
1970 b'refresh',
1968 default=0.1,
1971 default=0.1,
1969 )
1972 )
1970 coreconfigitem(
1973 coreconfigitem(
1971 b'progress',
1974 b'progress',
1972 b'width',
1975 b'width',
1973 default=dynamicdefault,
1976 default=dynamicdefault,
1974 )
1977 )
1975 coreconfigitem(
1978 coreconfigitem(
1976 b'pull',
1979 b'pull',
1977 b'confirm',
1980 b'confirm',
1978 default=False,
1981 default=False,
1979 )
1982 )
1980 coreconfigitem(
1983 coreconfigitem(
1981 b'push',
1984 b'push',
1982 b'pushvars.server',
1985 b'pushvars.server',
1983 default=False,
1986 default=False,
1984 )
1987 )
1985 coreconfigitem(
1988 coreconfigitem(
1986 b'rewrite',
1989 b'rewrite',
1987 b'backup-bundle',
1990 b'backup-bundle',
1988 default=True,
1991 default=True,
1989 alias=[(b'ui', b'history-editing-backup')],
1992 alias=[(b'ui', b'history-editing-backup')],
1990 )
1993 )
1991 coreconfigitem(
1994 coreconfigitem(
1992 b'rewrite',
1995 b'rewrite',
1993 b'update-timestamp',
1996 b'update-timestamp',
1994 default=False,
1997 default=False,
1995 )
1998 )
1996 coreconfigitem(
1999 coreconfigitem(
1997 b'rewrite',
2000 b'rewrite',
1998 b'empty-successor',
2001 b'empty-successor',
1999 default=b'skip',
2002 default=b'skip',
2000 experimental=True,
2003 experimental=True,
2001 )
2004 )
2002 # experimental as long as format.use-dirstate-v2 is.
2005 # experimental as long as format.use-dirstate-v2 is.
2003 coreconfigitem(
2006 coreconfigitem(
2004 b'storage',
2007 b'storage',
2005 b'dirstate-v2.slow-path',
2008 b'dirstate-v2.slow-path',
2006 default=b"abort",
2009 default=b"abort",
2007 experimental=True,
2010 experimental=True,
2008 )
2011 )
2009 coreconfigitem(
2012 coreconfigitem(
2010 b'storage',
2013 b'storage',
2011 b'new-repo-backend',
2014 b'new-repo-backend',
2012 default=b'revlogv1',
2015 default=b'revlogv1',
2013 experimental=True,
2016 experimental=True,
2014 )
2017 )
2015 coreconfigitem(
2018 coreconfigitem(
2016 b'storage',
2019 b'storage',
2017 b'revlog.optimize-delta-parent-choice',
2020 b'revlog.optimize-delta-parent-choice',
2018 default=True,
2021 default=True,
2019 alias=[(b'format', b'aggressivemergedeltas')],
2022 alias=[(b'format', b'aggressivemergedeltas')],
2020 )
2023 )
2021 coreconfigitem(
2024 coreconfigitem(
2022 b'storage',
2025 b'storage',
2023 b'revlog.issue6528.fix-incoming',
2026 b'revlog.issue6528.fix-incoming',
2024 default=True,
2027 default=True,
2025 )
2028 )
2026 # experimental as long as rust is experimental (or a C version is implemented)
2029 # experimental as long as rust is experimental (or a C version is implemented)
2027 coreconfigitem(
2030 coreconfigitem(
2028 b'storage',
2031 b'storage',
2029 b'revlog.persistent-nodemap.mmap',
2032 b'revlog.persistent-nodemap.mmap',
2030 default=True,
2033 default=True,
2031 )
2034 )
2032 # experimental as long as format.use-persistent-nodemap is.
2035 # experimental as long as format.use-persistent-nodemap is.
2033 coreconfigitem(
2036 coreconfigitem(
2034 b'storage',
2037 b'storage',
2035 b'revlog.persistent-nodemap.slow-path',
2038 b'revlog.persistent-nodemap.slow-path',
2036 default=b"abort",
2039 default=b"abort",
2037 )
2040 )
2038
2041
2039 coreconfigitem(
2042 coreconfigitem(
2040 b'storage',
2043 b'storage',
2041 b'revlog.reuse-external-delta',
2044 b'revlog.reuse-external-delta',
2042 default=True,
2045 default=True,
2043 )
2046 )
2044 coreconfigitem(
2047 coreconfigitem(
2045 b'storage',
2048 b'storage',
2046 b'revlog.reuse-external-delta-parent',
2049 b'revlog.reuse-external-delta-parent',
2047 default=None,
2050 default=None,
2048 )
2051 )
2049 coreconfigitem(
2052 coreconfigitem(
2050 b'storage',
2053 b'storage',
2051 b'revlog.zlib.level',
2054 b'revlog.zlib.level',
2052 default=None,
2055 default=None,
2053 )
2056 )
2054 coreconfigitem(
2057 coreconfigitem(
2055 b'storage',
2058 b'storage',
2056 b'revlog.zstd.level',
2059 b'revlog.zstd.level',
2057 default=None,
2060 default=None,
2058 )
2061 )
2059 coreconfigitem(
2062 coreconfigitem(
2060 b'server',
2063 b'server',
2061 b'bookmarks-pushkey-compat',
2064 b'bookmarks-pushkey-compat',
2062 default=True,
2065 default=True,
2063 )
2066 )
2064 coreconfigitem(
2067 coreconfigitem(
2065 b'server',
2068 b'server',
2066 b'bundle1',
2069 b'bundle1',
2067 default=True,
2070 default=True,
2068 )
2071 )
2069 coreconfigitem(
2072 coreconfigitem(
2070 b'server',
2073 b'server',
2071 b'bundle1gd',
2074 b'bundle1gd',
2072 default=None,
2075 default=None,
2073 )
2076 )
2074 coreconfigitem(
2077 coreconfigitem(
2075 b'server',
2078 b'server',
2076 b'bundle1.pull',
2079 b'bundle1.pull',
2077 default=None,
2080 default=None,
2078 )
2081 )
2079 coreconfigitem(
2082 coreconfigitem(
2080 b'server',
2083 b'server',
2081 b'bundle1gd.pull',
2084 b'bundle1gd.pull',
2082 default=None,
2085 default=None,
2083 )
2086 )
2084 coreconfigitem(
2087 coreconfigitem(
2085 b'server',
2088 b'server',
2086 b'bundle1.push',
2089 b'bundle1.push',
2087 default=None,
2090 default=None,
2088 )
2091 )
2089 coreconfigitem(
2092 coreconfigitem(
2090 b'server',
2093 b'server',
2091 b'bundle1gd.push',
2094 b'bundle1gd.push',
2092 default=None,
2095 default=None,
2093 )
2096 )
2094 coreconfigitem(
2097 coreconfigitem(
2095 b'server',
2098 b'server',
2096 b'bundle2.stream',
2099 b'bundle2.stream',
2097 default=True,
2100 default=True,
2098 alias=[(b'experimental', b'bundle2.stream')],
2101 alias=[(b'experimental', b'bundle2.stream')],
2099 )
2102 )
2100 coreconfigitem(
2103 coreconfigitem(
2101 b'server',
2104 b'server',
2102 b'compressionengines',
2105 b'compressionengines',
2103 default=list,
2106 default=list,
2104 )
2107 )
2105 coreconfigitem(
2108 coreconfigitem(
2106 b'server',
2109 b'server',
2107 b'concurrent-push-mode',
2110 b'concurrent-push-mode',
2108 default=b'check-related',
2111 default=b'check-related',
2109 )
2112 )
2110 coreconfigitem(
2113 coreconfigitem(
2111 b'server',
2114 b'server',
2112 b'disablefullbundle',
2115 b'disablefullbundle',
2113 default=False,
2116 default=False,
2114 )
2117 )
2115 coreconfigitem(
2118 coreconfigitem(
2116 b'server',
2119 b'server',
2117 b'maxhttpheaderlen',
2120 b'maxhttpheaderlen',
2118 default=1024,
2121 default=1024,
2119 )
2122 )
2120 coreconfigitem(
2123 coreconfigitem(
2121 b'server',
2124 b'server',
2122 b'pullbundle',
2125 b'pullbundle',
2123 default=False,
2126 default=False,
2124 )
2127 )
2125 coreconfigitem(
2128 coreconfigitem(
2126 b'server',
2129 b'server',
2127 b'preferuncompressed',
2130 b'preferuncompressed',
2128 default=False,
2131 default=False,
2129 )
2132 )
2130 coreconfigitem(
2133 coreconfigitem(
2131 b'server',
2134 b'server',
2132 b'streamunbundle',
2135 b'streamunbundle',
2133 default=False,
2136 default=False,
2134 )
2137 )
2135 coreconfigitem(
2138 coreconfigitem(
2136 b'server',
2139 b'server',
2137 b'uncompressed',
2140 b'uncompressed',
2138 default=True,
2141 default=True,
2139 )
2142 )
2140 coreconfigitem(
2143 coreconfigitem(
2141 b'server',
2144 b'server',
2142 b'uncompressedallowsecret',
2145 b'uncompressedallowsecret',
2143 default=False,
2146 default=False,
2144 )
2147 )
2145 coreconfigitem(
2148 coreconfigitem(
2146 b'server',
2149 b'server',
2147 b'view',
2150 b'view',
2148 default=b'served',
2151 default=b'served',
2149 )
2152 )
2150 coreconfigitem(
2153 coreconfigitem(
2151 b'server',
2154 b'server',
2152 b'validate',
2155 b'validate',
2153 default=False,
2156 default=False,
2154 )
2157 )
2155 coreconfigitem(
2158 coreconfigitem(
2156 b'server',
2159 b'server',
2157 b'zliblevel',
2160 b'zliblevel',
2158 default=-1,
2161 default=-1,
2159 )
2162 )
2160 coreconfigitem(
2163 coreconfigitem(
2161 b'server',
2164 b'server',
2162 b'zstdlevel',
2165 b'zstdlevel',
2163 default=3,
2166 default=3,
2164 )
2167 )
2165 coreconfigitem(
2168 coreconfigitem(
2166 b'share',
2169 b'share',
2167 b'pool',
2170 b'pool',
2168 default=None,
2171 default=None,
2169 )
2172 )
2170 coreconfigitem(
2173 coreconfigitem(
2171 b'share',
2174 b'share',
2172 b'poolnaming',
2175 b'poolnaming',
2173 default=b'identity',
2176 default=b'identity',
2174 )
2177 )
2175 coreconfigitem(
2178 coreconfigitem(
2176 b'share',
2179 b'share',
2177 b'safe-mismatch.source-not-safe',
2180 b'safe-mismatch.source-not-safe',
2178 default=b'abort',
2181 default=b'abort',
2179 )
2182 )
2180 coreconfigitem(
2183 coreconfigitem(
2181 b'share',
2184 b'share',
2182 b'safe-mismatch.source-safe',
2185 b'safe-mismatch.source-safe',
2183 default=b'abort',
2186 default=b'abort',
2184 )
2187 )
2185 coreconfigitem(
2188 coreconfigitem(
2186 b'share',
2189 b'share',
2187 b'safe-mismatch.source-not-safe.warn',
2190 b'safe-mismatch.source-not-safe.warn',
2188 default=True,
2191 default=True,
2189 )
2192 )
2190 coreconfigitem(
2193 coreconfigitem(
2191 b'share',
2194 b'share',
2192 b'safe-mismatch.source-safe.warn',
2195 b'safe-mismatch.source-safe.warn',
2193 default=True,
2196 default=True,
2194 )
2197 )
2195 coreconfigitem(
2198 coreconfigitem(
2196 b'share',
2199 b'share',
2197 b'safe-mismatch.source-not-safe:verbose-upgrade',
2200 b'safe-mismatch.source-not-safe:verbose-upgrade',
2198 default=True,
2201 default=True,
2199 )
2202 )
2200 coreconfigitem(
2203 coreconfigitem(
2201 b'share',
2204 b'share',
2202 b'safe-mismatch.source-safe:verbose-upgrade',
2205 b'safe-mismatch.source-safe:verbose-upgrade',
2203 default=True,
2206 default=True,
2204 )
2207 )
2205 coreconfigitem(
2208 coreconfigitem(
2206 b'shelve',
2209 b'shelve',
2207 b'maxbackups',
2210 b'maxbackups',
2208 default=10,
2211 default=10,
2209 )
2212 )
2210 coreconfigitem(
2213 coreconfigitem(
2211 b'smtp',
2214 b'smtp',
2212 b'host',
2215 b'host',
2213 default=None,
2216 default=None,
2214 )
2217 )
2215 coreconfigitem(
2218 coreconfigitem(
2216 b'smtp',
2219 b'smtp',
2217 b'local_hostname',
2220 b'local_hostname',
2218 default=None,
2221 default=None,
2219 )
2222 )
2220 coreconfigitem(
2223 coreconfigitem(
2221 b'smtp',
2224 b'smtp',
2222 b'password',
2225 b'password',
2223 default=None,
2226 default=None,
2224 )
2227 )
2225 coreconfigitem(
2228 coreconfigitem(
2226 b'smtp',
2229 b'smtp',
2227 b'port',
2230 b'port',
2228 default=dynamicdefault,
2231 default=dynamicdefault,
2229 )
2232 )
2230 coreconfigitem(
2233 coreconfigitem(
2231 b'smtp',
2234 b'smtp',
2232 b'tls',
2235 b'tls',
2233 default=b'none',
2236 default=b'none',
2234 )
2237 )
2235 coreconfigitem(
2238 coreconfigitem(
2236 b'smtp',
2239 b'smtp',
2237 b'username',
2240 b'username',
2238 default=None,
2241 default=None,
2239 )
2242 )
2240 coreconfigitem(
2243 coreconfigitem(
2241 b'sparse',
2244 b'sparse',
2242 b'missingwarning',
2245 b'missingwarning',
2243 default=True,
2246 default=True,
2244 experimental=True,
2247 experimental=True,
2245 )
2248 )
2246 coreconfigitem(
2249 coreconfigitem(
2247 b'subrepos',
2250 b'subrepos',
2248 b'allowed',
2251 b'allowed',
2249 default=dynamicdefault, # to make backporting simpler
2252 default=dynamicdefault, # to make backporting simpler
2250 )
2253 )
2251 coreconfigitem(
2254 coreconfigitem(
2252 b'subrepos',
2255 b'subrepos',
2253 b'hg:allowed',
2256 b'hg:allowed',
2254 default=dynamicdefault,
2257 default=dynamicdefault,
2255 )
2258 )
2256 coreconfigitem(
2259 coreconfigitem(
2257 b'subrepos',
2260 b'subrepos',
2258 b'git:allowed',
2261 b'git:allowed',
2259 default=dynamicdefault,
2262 default=dynamicdefault,
2260 )
2263 )
2261 coreconfigitem(
2264 coreconfigitem(
2262 b'subrepos',
2265 b'subrepos',
2263 b'svn:allowed',
2266 b'svn:allowed',
2264 default=dynamicdefault,
2267 default=dynamicdefault,
2265 )
2268 )
2266 coreconfigitem(
2269 coreconfigitem(
2267 b'templates',
2270 b'templates',
2268 b'.*',
2271 b'.*',
2269 default=None,
2272 default=None,
2270 generic=True,
2273 generic=True,
2271 )
2274 )
2272 coreconfigitem(
2275 coreconfigitem(
2273 b'templateconfig',
2276 b'templateconfig',
2274 b'.*',
2277 b'.*',
2275 default=dynamicdefault,
2278 default=dynamicdefault,
2276 generic=True,
2279 generic=True,
2277 )
2280 )
2278 coreconfigitem(
2281 coreconfigitem(
2279 b'trusted',
2282 b'trusted',
2280 b'groups',
2283 b'groups',
2281 default=list,
2284 default=list,
2282 )
2285 )
2283 coreconfigitem(
2286 coreconfigitem(
2284 b'trusted',
2287 b'trusted',
2285 b'users',
2288 b'users',
2286 default=list,
2289 default=list,
2287 )
2290 )
2288 coreconfigitem(
2291 coreconfigitem(
2289 b'ui',
2292 b'ui',
2290 b'_usedassubrepo',
2293 b'_usedassubrepo',
2291 default=False,
2294 default=False,
2292 )
2295 )
2293 coreconfigitem(
2296 coreconfigitem(
2294 b'ui',
2297 b'ui',
2295 b'allowemptycommit',
2298 b'allowemptycommit',
2296 default=False,
2299 default=False,
2297 )
2300 )
2298 coreconfigitem(
2301 coreconfigitem(
2299 b'ui',
2302 b'ui',
2300 b'archivemeta',
2303 b'archivemeta',
2301 default=True,
2304 default=True,
2302 )
2305 )
2303 coreconfigitem(
2306 coreconfigitem(
2304 b'ui',
2307 b'ui',
2305 b'askusername',
2308 b'askusername',
2306 default=False,
2309 default=False,
2307 )
2310 )
2308 coreconfigitem(
2311 coreconfigitem(
2309 b'ui',
2312 b'ui',
2310 b'available-memory',
2313 b'available-memory',
2311 default=None,
2314 default=None,
2312 )
2315 )
2313
2316
2314 coreconfigitem(
2317 coreconfigitem(
2315 b'ui',
2318 b'ui',
2316 b'clonebundlefallback',
2319 b'clonebundlefallback',
2317 default=False,
2320 default=False,
2318 )
2321 )
2319 coreconfigitem(
2322 coreconfigitem(
2320 b'ui',
2323 b'ui',
2321 b'clonebundleprefers',
2324 b'clonebundleprefers',
2322 default=list,
2325 default=list,
2323 )
2326 )
2324 coreconfigitem(
2327 coreconfigitem(
2325 b'ui',
2328 b'ui',
2326 b'clonebundles',
2329 b'clonebundles',
2327 default=True,
2330 default=True,
2328 )
2331 )
2329 coreconfigitem(
2332 coreconfigitem(
2330 b'ui',
2333 b'ui',
2331 b'color',
2334 b'color',
2332 default=b'auto',
2335 default=b'auto',
2333 )
2336 )
2334 coreconfigitem(
2337 coreconfigitem(
2335 b'ui',
2338 b'ui',
2336 b'commitsubrepos',
2339 b'commitsubrepos',
2337 default=False,
2340 default=False,
2338 )
2341 )
2339 coreconfigitem(
2342 coreconfigitem(
2340 b'ui',
2343 b'ui',
2341 b'debug',
2344 b'debug',
2342 default=False,
2345 default=False,
2343 )
2346 )
2344 coreconfigitem(
2347 coreconfigitem(
2345 b'ui',
2348 b'ui',
2346 b'debugger',
2349 b'debugger',
2347 default=None,
2350 default=None,
2348 )
2351 )
2349 coreconfigitem(
2352 coreconfigitem(
2350 b'ui',
2353 b'ui',
2351 b'editor',
2354 b'editor',
2352 default=dynamicdefault,
2355 default=dynamicdefault,
2353 )
2356 )
2354 coreconfigitem(
2357 coreconfigitem(
2355 b'ui',
2358 b'ui',
2356 b'detailed-exit-code',
2359 b'detailed-exit-code',
2357 default=False,
2360 default=False,
2358 experimental=True,
2361 experimental=True,
2359 )
2362 )
2360 coreconfigitem(
2363 coreconfigitem(
2361 b'ui',
2364 b'ui',
2362 b'fallbackencoding',
2365 b'fallbackencoding',
2363 default=None,
2366 default=None,
2364 )
2367 )
2365 coreconfigitem(
2368 coreconfigitem(
2366 b'ui',
2369 b'ui',
2367 b'forcecwd',
2370 b'forcecwd',
2368 default=None,
2371 default=None,
2369 )
2372 )
2370 coreconfigitem(
2373 coreconfigitem(
2371 b'ui',
2374 b'ui',
2372 b'forcemerge',
2375 b'forcemerge',
2373 default=None,
2376 default=None,
2374 )
2377 )
2375 coreconfigitem(
2378 coreconfigitem(
2376 b'ui',
2379 b'ui',
2377 b'formatdebug',
2380 b'formatdebug',
2378 default=False,
2381 default=False,
2379 )
2382 )
2380 coreconfigitem(
2383 coreconfigitem(
2381 b'ui',
2384 b'ui',
2382 b'formatjson',
2385 b'formatjson',
2383 default=False,
2386 default=False,
2384 )
2387 )
2385 coreconfigitem(
2388 coreconfigitem(
2386 b'ui',
2389 b'ui',
2387 b'formatted',
2390 b'formatted',
2388 default=None,
2391 default=None,
2389 )
2392 )
2390 coreconfigitem(
2393 coreconfigitem(
2391 b'ui',
2394 b'ui',
2392 b'interactive',
2395 b'interactive',
2393 default=None,
2396 default=None,
2394 )
2397 )
2395 coreconfigitem(
2398 coreconfigitem(
2396 b'ui',
2399 b'ui',
2397 b'interface',
2400 b'interface',
2398 default=None,
2401 default=None,
2399 )
2402 )
2400 coreconfigitem(
2403 coreconfigitem(
2401 b'ui',
2404 b'ui',
2402 b'interface.chunkselector',
2405 b'interface.chunkselector',
2403 default=None,
2406 default=None,
2404 )
2407 )
2405 coreconfigitem(
2408 coreconfigitem(
2406 b'ui',
2409 b'ui',
2407 b'large-file-limit',
2410 b'large-file-limit',
2408 default=10 * (2 ** 20),
2411 default=10 * (2 ** 20),
2409 )
2412 )
2410 coreconfigitem(
2413 coreconfigitem(
2411 b'ui',
2414 b'ui',
2412 b'logblockedtimes',
2415 b'logblockedtimes',
2413 default=False,
2416 default=False,
2414 )
2417 )
2415 coreconfigitem(
2418 coreconfigitem(
2416 b'ui',
2419 b'ui',
2417 b'merge',
2420 b'merge',
2418 default=None,
2421 default=None,
2419 )
2422 )
2420 coreconfigitem(
2423 coreconfigitem(
2421 b'ui',
2424 b'ui',
2422 b'mergemarkers',
2425 b'mergemarkers',
2423 default=b'basic',
2426 default=b'basic',
2424 )
2427 )
2425 coreconfigitem(
2428 coreconfigitem(
2426 b'ui',
2429 b'ui',
2427 b'message-output',
2430 b'message-output',
2428 default=b'stdio',
2431 default=b'stdio',
2429 )
2432 )
2430 coreconfigitem(
2433 coreconfigitem(
2431 b'ui',
2434 b'ui',
2432 b'nontty',
2435 b'nontty',
2433 default=False,
2436 default=False,
2434 )
2437 )
2435 coreconfigitem(
2438 coreconfigitem(
2436 b'ui',
2439 b'ui',
2437 b'origbackuppath',
2440 b'origbackuppath',
2438 default=None,
2441 default=None,
2439 )
2442 )
2440 coreconfigitem(
2443 coreconfigitem(
2441 b'ui',
2444 b'ui',
2442 b'paginate',
2445 b'paginate',
2443 default=True,
2446 default=True,
2444 )
2447 )
2445 coreconfigitem(
2448 coreconfigitem(
2446 b'ui',
2449 b'ui',
2447 b'patch',
2450 b'patch',
2448 default=None,
2451 default=None,
2449 )
2452 )
2450 coreconfigitem(
2453 coreconfigitem(
2451 b'ui',
2454 b'ui',
2452 b'portablefilenames',
2455 b'portablefilenames',
2453 default=b'warn',
2456 default=b'warn',
2454 )
2457 )
2455 coreconfigitem(
2458 coreconfigitem(
2456 b'ui',
2459 b'ui',
2457 b'promptecho',
2460 b'promptecho',
2458 default=False,
2461 default=False,
2459 )
2462 )
2460 coreconfigitem(
2463 coreconfigitem(
2461 b'ui',
2464 b'ui',
2462 b'quiet',
2465 b'quiet',
2463 default=False,
2466 default=False,
2464 )
2467 )
2465 coreconfigitem(
2468 coreconfigitem(
2466 b'ui',
2469 b'ui',
2467 b'quietbookmarkmove',
2470 b'quietbookmarkmove',
2468 default=False,
2471 default=False,
2469 )
2472 )
2470 coreconfigitem(
2473 coreconfigitem(
2471 b'ui',
2474 b'ui',
2472 b'relative-paths',
2475 b'relative-paths',
2473 default=b'legacy',
2476 default=b'legacy',
2474 )
2477 )
2475 coreconfigitem(
2478 coreconfigitem(
2476 b'ui',
2479 b'ui',
2477 b'remotecmd',
2480 b'remotecmd',
2478 default=b'hg',
2481 default=b'hg',
2479 )
2482 )
2480 coreconfigitem(
2483 coreconfigitem(
2481 b'ui',
2484 b'ui',
2482 b'report_untrusted',
2485 b'report_untrusted',
2483 default=True,
2486 default=True,
2484 )
2487 )
2485 coreconfigitem(
2488 coreconfigitem(
2486 b'ui',
2489 b'ui',
2487 b'rollback',
2490 b'rollback',
2488 default=True,
2491 default=True,
2489 )
2492 )
2490 coreconfigitem(
2493 coreconfigitem(
2491 b'ui',
2494 b'ui',
2492 b'signal-safe-lock',
2495 b'signal-safe-lock',
2493 default=True,
2496 default=True,
2494 )
2497 )
2495 coreconfigitem(
2498 coreconfigitem(
2496 b'ui',
2499 b'ui',
2497 b'slash',
2500 b'slash',
2498 default=False,
2501 default=False,
2499 )
2502 )
2500 coreconfigitem(
2503 coreconfigitem(
2501 b'ui',
2504 b'ui',
2502 b'ssh',
2505 b'ssh',
2503 default=b'ssh',
2506 default=b'ssh',
2504 )
2507 )
2505 coreconfigitem(
2508 coreconfigitem(
2506 b'ui',
2509 b'ui',
2507 b'ssherrorhint',
2510 b'ssherrorhint',
2508 default=None,
2511 default=None,
2509 )
2512 )
2510 coreconfigitem(
2513 coreconfigitem(
2511 b'ui',
2514 b'ui',
2512 b'statuscopies',
2515 b'statuscopies',
2513 default=False,
2516 default=False,
2514 )
2517 )
2515 coreconfigitem(
2518 coreconfigitem(
2516 b'ui',
2519 b'ui',
2517 b'strict',
2520 b'strict',
2518 default=False,
2521 default=False,
2519 )
2522 )
2520 coreconfigitem(
2523 coreconfigitem(
2521 b'ui',
2524 b'ui',
2522 b'style',
2525 b'style',
2523 default=b'',
2526 default=b'',
2524 )
2527 )
2525 coreconfigitem(
2528 coreconfigitem(
2526 b'ui',
2529 b'ui',
2527 b'supportcontact',
2530 b'supportcontact',
2528 default=None,
2531 default=None,
2529 )
2532 )
2530 coreconfigitem(
2533 coreconfigitem(
2531 b'ui',
2534 b'ui',
2532 b'textwidth',
2535 b'textwidth',
2533 default=78,
2536 default=78,
2534 )
2537 )
2535 coreconfigitem(
2538 coreconfigitem(
2536 b'ui',
2539 b'ui',
2537 b'timeout',
2540 b'timeout',
2538 default=b'600',
2541 default=b'600',
2539 )
2542 )
2540 coreconfigitem(
2543 coreconfigitem(
2541 b'ui',
2544 b'ui',
2542 b'timeout.warn',
2545 b'timeout.warn',
2543 default=0,
2546 default=0,
2544 )
2547 )
2545 coreconfigitem(
2548 coreconfigitem(
2546 b'ui',
2549 b'ui',
2547 b'timestamp-output',
2550 b'timestamp-output',
2548 default=False,
2551 default=False,
2549 )
2552 )
2550 coreconfigitem(
2553 coreconfigitem(
2551 b'ui',
2554 b'ui',
2552 b'traceback',
2555 b'traceback',
2553 default=False,
2556 default=False,
2554 )
2557 )
2555 coreconfigitem(
2558 coreconfigitem(
2556 b'ui',
2559 b'ui',
2557 b'tweakdefaults',
2560 b'tweakdefaults',
2558 default=False,
2561 default=False,
2559 )
2562 )
2560 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2563 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2561 coreconfigitem(
2564 coreconfigitem(
2562 b'ui',
2565 b'ui',
2563 b'verbose',
2566 b'verbose',
2564 default=False,
2567 default=False,
2565 )
2568 )
2566 coreconfigitem(
2569 coreconfigitem(
2567 b'verify',
2570 b'verify',
2568 b'skipflags',
2571 b'skipflags',
2569 default=None,
2572 default=None,
2570 )
2573 )
2571 coreconfigitem(
2574 coreconfigitem(
2572 b'web',
2575 b'web',
2573 b'allowbz2',
2576 b'allowbz2',
2574 default=False,
2577 default=False,
2575 )
2578 )
2576 coreconfigitem(
2579 coreconfigitem(
2577 b'web',
2580 b'web',
2578 b'allowgz',
2581 b'allowgz',
2579 default=False,
2582 default=False,
2580 )
2583 )
2581 coreconfigitem(
2584 coreconfigitem(
2582 b'web',
2585 b'web',
2583 b'allow-pull',
2586 b'allow-pull',
2584 alias=[(b'web', b'allowpull')],
2587 alias=[(b'web', b'allowpull')],
2585 default=True,
2588 default=True,
2586 )
2589 )
2587 coreconfigitem(
2590 coreconfigitem(
2588 b'web',
2591 b'web',
2589 b'allow-push',
2592 b'allow-push',
2590 alias=[(b'web', b'allow_push')],
2593 alias=[(b'web', b'allow_push')],
2591 default=list,
2594 default=list,
2592 )
2595 )
2593 coreconfigitem(
2596 coreconfigitem(
2594 b'web',
2597 b'web',
2595 b'allowzip',
2598 b'allowzip',
2596 default=False,
2599 default=False,
2597 )
2600 )
2598 coreconfigitem(
2601 coreconfigitem(
2599 b'web',
2602 b'web',
2600 b'archivesubrepos',
2603 b'archivesubrepos',
2601 default=False,
2604 default=False,
2602 )
2605 )
2603 coreconfigitem(
2606 coreconfigitem(
2604 b'web',
2607 b'web',
2605 b'cache',
2608 b'cache',
2606 default=True,
2609 default=True,
2607 )
2610 )
2608 coreconfigitem(
2611 coreconfigitem(
2609 b'web',
2612 b'web',
2610 b'comparisoncontext',
2613 b'comparisoncontext',
2611 default=5,
2614 default=5,
2612 )
2615 )
2613 coreconfigitem(
2616 coreconfigitem(
2614 b'web',
2617 b'web',
2615 b'contact',
2618 b'contact',
2616 default=None,
2619 default=None,
2617 )
2620 )
2618 coreconfigitem(
2621 coreconfigitem(
2619 b'web',
2622 b'web',
2620 b'deny_push',
2623 b'deny_push',
2621 default=list,
2624 default=list,
2622 )
2625 )
2623 coreconfigitem(
2626 coreconfigitem(
2624 b'web',
2627 b'web',
2625 b'guessmime',
2628 b'guessmime',
2626 default=False,
2629 default=False,
2627 )
2630 )
2628 coreconfigitem(
2631 coreconfigitem(
2629 b'web',
2632 b'web',
2630 b'hidden',
2633 b'hidden',
2631 default=False,
2634 default=False,
2632 )
2635 )
2633 coreconfigitem(
2636 coreconfigitem(
2634 b'web',
2637 b'web',
2635 b'labels',
2638 b'labels',
2636 default=list,
2639 default=list,
2637 )
2640 )
2638 coreconfigitem(
2641 coreconfigitem(
2639 b'web',
2642 b'web',
2640 b'logoimg',
2643 b'logoimg',
2641 default=b'hglogo.png',
2644 default=b'hglogo.png',
2642 )
2645 )
2643 coreconfigitem(
2646 coreconfigitem(
2644 b'web',
2647 b'web',
2645 b'logourl',
2648 b'logourl',
2646 default=b'https://mercurial-scm.org/',
2649 default=b'https://mercurial-scm.org/',
2647 )
2650 )
2648 coreconfigitem(
2651 coreconfigitem(
2649 b'web',
2652 b'web',
2650 b'accesslog',
2653 b'accesslog',
2651 default=b'-',
2654 default=b'-',
2652 )
2655 )
2653 coreconfigitem(
2656 coreconfigitem(
2654 b'web',
2657 b'web',
2655 b'address',
2658 b'address',
2656 default=b'',
2659 default=b'',
2657 )
2660 )
2658 coreconfigitem(
2661 coreconfigitem(
2659 b'web',
2662 b'web',
2660 b'allow-archive',
2663 b'allow-archive',
2661 alias=[(b'web', b'allow_archive')],
2664 alias=[(b'web', b'allow_archive')],
2662 default=list,
2665 default=list,
2663 )
2666 )
2664 coreconfigitem(
2667 coreconfigitem(
2665 b'web',
2668 b'web',
2666 b'allow_read',
2669 b'allow_read',
2667 default=list,
2670 default=list,
2668 )
2671 )
2669 coreconfigitem(
2672 coreconfigitem(
2670 b'web',
2673 b'web',
2671 b'baseurl',
2674 b'baseurl',
2672 default=None,
2675 default=None,
2673 )
2676 )
2674 coreconfigitem(
2677 coreconfigitem(
2675 b'web',
2678 b'web',
2676 b'cacerts',
2679 b'cacerts',
2677 default=None,
2680 default=None,
2678 )
2681 )
2679 coreconfigitem(
2682 coreconfigitem(
2680 b'web',
2683 b'web',
2681 b'certificate',
2684 b'certificate',
2682 default=None,
2685 default=None,
2683 )
2686 )
2684 coreconfigitem(
2687 coreconfigitem(
2685 b'web',
2688 b'web',
2686 b'collapse',
2689 b'collapse',
2687 default=False,
2690 default=False,
2688 )
2691 )
2689 coreconfigitem(
2692 coreconfigitem(
2690 b'web',
2693 b'web',
2691 b'csp',
2694 b'csp',
2692 default=None,
2695 default=None,
2693 )
2696 )
2694 coreconfigitem(
2697 coreconfigitem(
2695 b'web',
2698 b'web',
2696 b'deny_read',
2699 b'deny_read',
2697 default=list,
2700 default=list,
2698 )
2701 )
2699 coreconfigitem(
2702 coreconfigitem(
2700 b'web',
2703 b'web',
2701 b'descend',
2704 b'descend',
2702 default=True,
2705 default=True,
2703 )
2706 )
2704 coreconfigitem(
2707 coreconfigitem(
2705 b'web',
2708 b'web',
2706 b'description',
2709 b'description',
2707 default=b"",
2710 default=b"",
2708 )
2711 )
2709 coreconfigitem(
2712 coreconfigitem(
2710 b'web',
2713 b'web',
2711 b'encoding',
2714 b'encoding',
2712 default=lambda: encoding.encoding,
2715 default=lambda: encoding.encoding,
2713 )
2716 )
2714 coreconfigitem(
2717 coreconfigitem(
2715 b'web',
2718 b'web',
2716 b'errorlog',
2719 b'errorlog',
2717 default=b'-',
2720 default=b'-',
2718 )
2721 )
2719 coreconfigitem(
2722 coreconfigitem(
2720 b'web',
2723 b'web',
2721 b'ipv6',
2724 b'ipv6',
2722 default=False,
2725 default=False,
2723 )
2726 )
2724 coreconfigitem(
2727 coreconfigitem(
2725 b'web',
2728 b'web',
2726 b'maxchanges',
2729 b'maxchanges',
2727 default=10,
2730 default=10,
2728 )
2731 )
2729 coreconfigitem(
2732 coreconfigitem(
2730 b'web',
2733 b'web',
2731 b'maxfiles',
2734 b'maxfiles',
2732 default=10,
2735 default=10,
2733 )
2736 )
2734 coreconfigitem(
2737 coreconfigitem(
2735 b'web',
2738 b'web',
2736 b'maxshortchanges',
2739 b'maxshortchanges',
2737 default=60,
2740 default=60,
2738 )
2741 )
2739 coreconfigitem(
2742 coreconfigitem(
2740 b'web',
2743 b'web',
2741 b'motd',
2744 b'motd',
2742 default=b'',
2745 default=b'',
2743 )
2746 )
2744 coreconfigitem(
2747 coreconfigitem(
2745 b'web',
2748 b'web',
2746 b'name',
2749 b'name',
2747 default=dynamicdefault,
2750 default=dynamicdefault,
2748 )
2751 )
2749 coreconfigitem(
2752 coreconfigitem(
2750 b'web',
2753 b'web',
2751 b'port',
2754 b'port',
2752 default=8000,
2755 default=8000,
2753 )
2756 )
2754 coreconfigitem(
2757 coreconfigitem(
2755 b'web',
2758 b'web',
2756 b'prefix',
2759 b'prefix',
2757 default=b'',
2760 default=b'',
2758 )
2761 )
2759 coreconfigitem(
2762 coreconfigitem(
2760 b'web',
2763 b'web',
2761 b'push_ssl',
2764 b'push_ssl',
2762 default=True,
2765 default=True,
2763 )
2766 )
2764 coreconfigitem(
2767 coreconfigitem(
2765 b'web',
2768 b'web',
2766 b'refreshinterval',
2769 b'refreshinterval',
2767 default=20,
2770 default=20,
2768 )
2771 )
2769 coreconfigitem(
2772 coreconfigitem(
2770 b'web',
2773 b'web',
2771 b'server-header',
2774 b'server-header',
2772 default=None,
2775 default=None,
2773 )
2776 )
2774 coreconfigitem(
2777 coreconfigitem(
2775 b'web',
2778 b'web',
2776 b'static',
2779 b'static',
2777 default=None,
2780 default=None,
2778 )
2781 )
2779 coreconfigitem(
2782 coreconfigitem(
2780 b'web',
2783 b'web',
2781 b'staticurl',
2784 b'staticurl',
2782 default=None,
2785 default=None,
2783 )
2786 )
2784 coreconfigitem(
2787 coreconfigitem(
2785 b'web',
2788 b'web',
2786 b'stripes',
2789 b'stripes',
2787 default=1,
2790 default=1,
2788 )
2791 )
2789 coreconfigitem(
2792 coreconfigitem(
2790 b'web',
2793 b'web',
2791 b'style',
2794 b'style',
2792 default=b'paper',
2795 default=b'paper',
2793 )
2796 )
2794 coreconfigitem(
2797 coreconfigitem(
2795 b'web',
2798 b'web',
2796 b'templates',
2799 b'templates',
2797 default=None,
2800 default=None,
2798 )
2801 )
2799 coreconfigitem(
2802 coreconfigitem(
2800 b'web',
2803 b'web',
2801 b'view',
2804 b'view',
2802 default=b'served',
2805 default=b'served',
2803 experimental=True,
2806 experimental=True,
2804 )
2807 )
2805 coreconfigitem(
2808 coreconfigitem(
2806 b'worker',
2809 b'worker',
2807 b'backgroundclose',
2810 b'backgroundclose',
2808 default=dynamicdefault,
2811 default=dynamicdefault,
2809 )
2812 )
2810 # Windows defaults to a limit of 512 open files. A buffer of 128
2813 # Windows defaults to a limit of 512 open files. A buffer of 128
2811 # should give us enough headway.
2814 # should give us enough headway.
2812 coreconfigitem(
2815 coreconfigitem(
2813 b'worker',
2816 b'worker',
2814 b'backgroundclosemaxqueue',
2817 b'backgroundclosemaxqueue',
2815 default=384,
2818 default=384,
2816 )
2819 )
2817 coreconfigitem(
2820 coreconfigitem(
2818 b'worker',
2821 b'worker',
2819 b'backgroundcloseminfilecount',
2822 b'backgroundcloseminfilecount',
2820 default=2048,
2823 default=2048,
2821 )
2824 )
2822 coreconfigitem(
2825 coreconfigitem(
2823 b'worker',
2826 b'worker',
2824 b'backgroundclosethreadcount',
2827 b'backgroundclosethreadcount',
2825 default=4,
2828 default=4,
2826 )
2829 )
2827 coreconfigitem(
2830 coreconfigitem(
2828 b'worker',
2831 b'worker',
2829 b'enabled',
2832 b'enabled',
2830 default=True,
2833 default=True,
2831 )
2834 )
2832 coreconfigitem(
2835 coreconfigitem(
2833 b'worker',
2836 b'worker',
2834 b'numcpus',
2837 b'numcpus',
2835 default=None,
2838 default=None,
2836 )
2839 )
2837
2840
2838 # Rebase related configuration moved to core because other extension are doing
2841 # Rebase related configuration moved to core because other extension are doing
2839 # strange things. For example, shelve import the extensions to reuse some bit
2842 # strange things. For example, shelve import the extensions to reuse some bit
2840 # without formally loading it.
2843 # without formally loading it.
2841 coreconfigitem(
2844 coreconfigitem(
2842 b'commands',
2845 b'commands',
2843 b'rebase.requiredest',
2846 b'rebase.requiredest',
2844 default=False,
2847 default=False,
2845 )
2848 )
2846 coreconfigitem(
2849 coreconfigitem(
2847 b'experimental',
2850 b'experimental',
2848 b'rebaseskipobsolete',
2851 b'rebaseskipobsolete',
2849 default=True,
2852 default=True,
2850 )
2853 )
2851 coreconfigitem(
2854 coreconfigitem(
2852 b'rebase',
2855 b'rebase',
2853 b'singletransaction',
2856 b'singletransaction',
2854 default=False,
2857 default=False,
2855 )
2858 )
2856 coreconfigitem(
2859 coreconfigitem(
2857 b'rebase',
2860 b'rebase',
2858 b'experimental.inmemory',
2861 b'experimental.inmemory',
2859 default=False,
2862 default=False,
2860 )
2863 )
2861
2864
2862 # This setting controls creation of a rebase_source extra field
2865 # This setting controls creation of a rebase_source extra field
2863 # during rebase. When False, no such field is created. This is
2866 # during rebase. When False, no such field is created. This is
2864 # useful eg for incrementally converting changesets and then
2867 # useful eg for incrementally converting changesets and then
2865 # rebasing them onto an existing repo.
2868 # rebasing them onto an existing repo.
2866 # WARNING: this is an advanced setting reserved for people who know
2869 # WARNING: this is an advanced setting reserved for people who know
2867 # exactly what they are doing. Misuse of this setting can easily
2870 # exactly what they are doing. Misuse of this setting can easily
2868 # result in obsmarker cycles and a vivid headache.
2871 # result in obsmarker cycles and a vivid headache.
2869 coreconfigitem(
2872 coreconfigitem(
2870 b'rebase',
2873 b'rebase',
2871 b'store-source',
2874 b'store-source',
2872 default=True,
2875 default=True,
2873 experimental=True,
2876 experimental=True,
2874 )
2877 )
@@ -1,3951 +1,3951 b''
1 # localrepo.py - read/write repository class for mercurial
1 # localrepo.py - read/write repository class for mercurial
2 # coding: utf-8
2 # coding: utf-8
3 #
3 #
4 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
4 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9
9
10 import functools
10 import functools
11 import os
11 import os
12 import random
12 import random
13 import sys
13 import sys
14 import time
14 import time
15 import weakref
15 import weakref
16
16
17 from concurrent import futures
17 from concurrent import futures
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 nullrev,
22 nullrev,
23 sha1nodeconstants,
23 sha1nodeconstants,
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 wireprototypes,
74 wireprototypes,
75 )
75 )
76
76
77 from .interfaces import (
77 from .interfaces import (
78 repository,
78 repository,
79 util as interfaceutil,
79 util as interfaceutil,
80 )
80 )
81
81
82 from .utils import (
82 from .utils import (
83 hashutil,
83 hashutil,
84 procutil,
84 procutil,
85 stringutil,
85 stringutil,
86 urlutil,
86 urlutil,
87 )
87 )
88
88
89 from .revlogutils import (
89 from .revlogutils import (
90 concurrency_checker as revlogchecker,
90 concurrency_checker as revlogchecker,
91 constants as revlogconst,
91 constants as revlogconst,
92 sidedata as sidedatamod,
92 sidedata as sidedatamod,
93 )
93 )
94
94
95 release = lockmod.release
95 release = lockmod.release
96 urlerr = util.urlerr
96 urlerr = util.urlerr
97 urlreq = util.urlreq
97 urlreq = util.urlreq
98
98
99 # set of (path, vfs-location) tuples. vfs-location is:
99 # set of (path, vfs-location) tuples. vfs-location is:
100 # - 'plain for vfs relative paths
100 # - 'plain for vfs relative paths
101 # - '' for svfs relative paths
101 # - '' for svfs relative paths
102 _cachedfiles = set()
102 _cachedfiles = set()
103
103
104
104
105 class _basefilecache(scmutil.filecache):
105 class _basefilecache(scmutil.filecache):
106 """All filecache usage on repo are done for logic that should be unfiltered"""
106 """All filecache usage on repo are done for logic that should be unfiltered"""
107
107
108 def __get__(self, repo, type=None):
108 def __get__(self, repo, type=None):
109 if repo is None:
109 if repo is None:
110 return self
110 return self
111 # proxy to unfiltered __dict__ since filtered repo has no entry
111 # proxy to unfiltered __dict__ since filtered repo has no entry
112 unfi = repo.unfiltered()
112 unfi = repo.unfiltered()
113 try:
113 try:
114 return unfi.__dict__[self.sname]
114 return unfi.__dict__[self.sname]
115 except KeyError:
115 except KeyError:
116 pass
116 pass
117 return super(_basefilecache, self).__get__(unfi, type)
117 return super(_basefilecache, self).__get__(unfi, type)
118
118
119 def set(self, repo, value):
119 def set(self, repo, value):
120 return super(_basefilecache, self).set(repo.unfiltered(), value)
120 return super(_basefilecache, self).set(repo.unfiltered(), value)
121
121
122
122
123 class repofilecache(_basefilecache):
123 class repofilecache(_basefilecache):
124 """filecache for files in .hg but outside of .hg/store"""
124 """filecache for files in .hg but outside of .hg/store"""
125
125
126 def __init__(self, *paths):
126 def __init__(self, *paths):
127 super(repofilecache, self).__init__(*paths)
127 super(repofilecache, self).__init__(*paths)
128 for path in paths:
128 for path in paths:
129 _cachedfiles.add((path, b'plain'))
129 _cachedfiles.add((path, b'plain'))
130
130
131 def join(self, obj, fname):
131 def join(self, obj, fname):
132 return obj.vfs.join(fname)
132 return obj.vfs.join(fname)
133
133
134
134
135 class storecache(_basefilecache):
135 class storecache(_basefilecache):
136 """filecache for files in the store"""
136 """filecache for files in the store"""
137
137
138 def __init__(self, *paths):
138 def __init__(self, *paths):
139 super(storecache, self).__init__(*paths)
139 super(storecache, self).__init__(*paths)
140 for path in paths:
140 for path in paths:
141 _cachedfiles.add((path, b''))
141 _cachedfiles.add((path, b''))
142
142
143 def join(self, obj, fname):
143 def join(self, obj, fname):
144 return obj.sjoin(fname)
144 return obj.sjoin(fname)
145
145
146
146
147 class changelogcache(storecache):
147 class changelogcache(storecache):
148 """filecache for the changelog"""
148 """filecache for the changelog"""
149
149
150 def __init__(self):
150 def __init__(self):
151 super(changelogcache, self).__init__()
151 super(changelogcache, self).__init__()
152 _cachedfiles.add((b'00changelog.i', b''))
152 _cachedfiles.add((b'00changelog.i', b''))
153 _cachedfiles.add((b'00changelog.n', b''))
153 _cachedfiles.add((b'00changelog.n', b''))
154
154
155 def tracked_paths(self, obj):
155 def tracked_paths(self, obj):
156 paths = [self.join(obj, b'00changelog.i')]
156 paths = [self.join(obj, b'00changelog.i')]
157 if obj.store.opener.options.get(b'persistent-nodemap', False):
157 if obj.store.opener.options.get(b'persistent-nodemap', False):
158 paths.append(self.join(obj, b'00changelog.n'))
158 paths.append(self.join(obj, b'00changelog.n'))
159 return paths
159 return paths
160
160
161
161
162 class manifestlogcache(storecache):
162 class manifestlogcache(storecache):
163 """filecache for the manifestlog"""
163 """filecache for the manifestlog"""
164
164
165 def __init__(self):
165 def __init__(self):
166 super(manifestlogcache, self).__init__()
166 super(manifestlogcache, self).__init__()
167 _cachedfiles.add((b'00manifest.i', b''))
167 _cachedfiles.add((b'00manifest.i', b''))
168 _cachedfiles.add((b'00manifest.n', b''))
168 _cachedfiles.add((b'00manifest.n', b''))
169
169
170 def tracked_paths(self, obj):
170 def tracked_paths(self, obj):
171 paths = [self.join(obj, b'00manifest.i')]
171 paths = [self.join(obj, b'00manifest.i')]
172 if obj.store.opener.options.get(b'persistent-nodemap', False):
172 if obj.store.opener.options.get(b'persistent-nodemap', False):
173 paths.append(self.join(obj, b'00manifest.n'))
173 paths.append(self.join(obj, b'00manifest.n'))
174 return paths
174 return paths
175
175
176
176
177 class mixedrepostorecache(_basefilecache):
177 class mixedrepostorecache(_basefilecache):
178 """filecache for a mix files in .hg/store and outside"""
178 """filecache for a mix files in .hg/store and outside"""
179
179
180 def __init__(self, *pathsandlocations):
180 def __init__(self, *pathsandlocations):
181 # scmutil.filecache only uses the path for passing back into our
181 # scmutil.filecache only uses the path for passing back into our
182 # join(), so we can safely pass a list of paths and locations
182 # join(), so we can safely pass a list of paths and locations
183 super(mixedrepostorecache, self).__init__(*pathsandlocations)
183 super(mixedrepostorecache, self).__init__(*pathsandlocations)
184 _cachedfiles.update(pathsandlocations)
184 _cachedfiles.update(pathsandlocations)
185
185
186 def join(self, obj, fnameandlocation):
186 def join(self, obj, fnameandlocation):
187 fname, location = fnameandlocation
187 fname, location = fnameandlocation
188 if location == b'plain':
188 if location == b'plain':
189 return obj.vfs.join(fname)
189 return obj.vfs.join(fname)
190 else:
190 else:
191 if location != b'':
191 if location != b'':
192 raise error.ProgrammingError(
192 raise error.ProgrammingError(
193 b'unexpected location: %s' % location
193 b'unexpected location: %s' % location
194 )
194 )
195 return obj.sjoin(fname)
195 return obj.sjoin(fname)
196
196
197
197
198 def isfilecached(repo, name):
198 def isfilecached(repo, name):
199 """check if a repo has already cached "name" filecache-ed property
199 """check if a repo has already cached "name" filecache-ed property
200
200
201 This returns (cachedobj-or-None, iscached) tuple.
201 This returns (cachedobj-or-None, iscached) tuple.
202 """
202 """
203 cacheentry = repo.unfiltered()._filecache.get(name, None)
203 cacheentry = repo.unfiltered()._filecache.get(name, None)
204 if not cacheentry:
204 if not cacheentry:
205 return None, False
205 return None, False
206 return cacheentry.obj, True
206 return cacheentry.obj, True
207
207
208
208
209 class unfilteredpropertycache(util.propertycache):
209 class unfilteredpropertycache(util.propertycache):
210 """propertycache that apply to unfiltered repo only"""
210 """propertycache that apply to unfiltered repo only"""
211
211
212 def __get__(self, repo, type=None):
212 def __get__(self, repo, type=None):
213 unfi = repo.unfiltered()
213 unfi = repo.unfiltered()
214 if unfi is repo:
214 if unfi is repo:
215 return super(unfilteredpropertycache, self).__get__(unfi)
215 return super(unfilteredpropertycache, self).__get__(unfi)
216 return getattr(unfi, self.name)
216 return getattr(unfi, self.name)
217
217
218
218
219 class filteredpropertycache(util.propertycache):
219 class filteredpropertycache(util.propertycache):
220 """propertycache that must take filtering in account"""
220 """propertycache that must take filtering in account"""
221
221
222 def cachevalue(self, obj, value):
222 def cachevalue(self, obj, value):
223 object.__setattr__(obj, self.name, value)
223 object.__setattr__(obj, self.name, value)
224
224
225
225
226 def hasunfilteredcache(repo, name):
226 def hasunfilteredcache(repo, name):
227 """check if a repo has an unfilteredpropertycache value for <name>"""
227 """check if a repo has an unfilteredpropertycache value for <name>"""
228 return name in vars(repo.unfiltered())
228 return name in vars(repo.unfiltered())
229
229
230
230
231 def unfilteredmethod(orig):
231 def unfilteredmethod(orig):
232 """decorate method that always need to be run on unfiltered version"""
232 """decorate method that always need to be run on unfiltered version"""
233
233
234 @functools.wraps(orig)
234 @functools.wraps(orig)
235 def wrapper(repo, *args, **kwargs):
235 def wrapper(repo, *args, **kwargs):
236 return orig(repo.unfiltered(), *args, **kwargs)
236 return orig(repo.unfiltered(), *args, **kwargs)
237
237
238 return wrapper
238 return wrapper
239
239
240
240
241 moderncaps = {
241 moderncaps = {
242 b'lookup',
242 b'lookup',
243 b'branchmap',
243 b'branchmap',
244 b'pushkey',
244 b'pushkey',
245 b'known',
245 b'known',
246 b'getbundle',
246 b'getbundle',
247 b'unbundle',
247 b'unbundle',
248 }
248 }
249 legacycaps = moderncaps.union({b'changegroupsubset'})
249 legacycaps = moderncaps.union({b'changegroupsubset'})
250
250
251
251
252 @interfaceutil.implementer(repository.ipeercommandexecutor)
252 @interfaceutil.implementer(repository.ipeercommandexecutor)
253 class localcommandexecutor:
253 class localcommandexecutor:
254 def __init__(self, peer):
254 def __init__(self, peer):
255 self._peer = peer
255 self._peer = peer
256 self._sent = False
256 self._sent = False
257 self._closed = False
257 self._closed = False
258
258
259 def __enter__(self):
259 def __enter__(self):
260 return self
260 return self
261
261
262 def __exit__(self, exctype, excvalue, exctb):
262 def __exit__(self, exctype, excvalue, exctb):
263 self.close()
263 self.close()
264
264
265 def callcommand(self, command, args):
265 def callcommand(self, command, args):
266 if self._sent:
266 if self._sent:
267 raise error.ProgrammingError(
267 raise error.ProgrammingError(
268 b'callcommand() cannot be used after sendcommands()'
268 b'callcommand() cannot be used after sendcommands()'
269 )
269 )
270
270
271 if self._closed:
271 if self._closed:
272 raise error.ProgrammingError(
272 raise error.ProgrammingError(
273 b'callcommand() cannot be used after close()'
273 b'callcommand() cannot be used after close()'
274 )
274 )
275
275
276 # We don't need to support anything fancy. Just call the named
276 # We don't need to support anything fancy. Just call the named
277 # method on the peer and return a resolved future.
277 # method on the peer and return a resolved future.
278 fn = getattr(self._peer, pycompat.sysstr(command))
278 fn = getattr(self._peer, pycompat.sysstr(command))
279
279
280 f = futures.Future()
280 f = futures.Future()
281
281
282 try:
282 try:
283 result = fn(**pycompat.strkwargs(args))
283 result = fn(**pycompat.strkwargs(args))
284 except Exception:
284 except Exception:
285 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
285 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
286 else:
286 else:
287 f.set_result(result)
287 f.set_result(result)
288
288
289 return f
289 return f
290
290
291 def sendcommands(self):
291 def sendcommands(self):
292 self._sent = True
292 self._sent = True
293
293
294 def close(self):
294 def close(self):
295 self._closed = True
295 self._closed = True
296
296
297
297
298 @interfaceutil.implementer(repository.ipeercommands)
298 @interfaceutil.implementer(repository.ipeercommands)
299 class localpeer(repository.peer):
299 class localpeer(repository.peer):
300 '''peer for a local repo; reflects only the most recent API'''
300 '''peer for a local repo; reflects only the most recent API'''
301
301
302 def __init__(self, repo, caps=None):
302 def __init__(self, repo, caps=None):
303 super(localpeer, self).__init__()
303 super(localpeer, self).__init__()
304
304
305 if caps is None:
305 if caps is None:
306 caps = moderncaps.copy()
306 caps = moderncaps.copy()
307 self._repo = repo.filtered(b'served')
307 self._repo = repo.filtered(b'served')
308 self.ui = repo.ui
308 self.ui = repo.ui
309
309
310 if repo._wanted_sidedata:
310 if repo._wanted_sidedata:
311 formatted = bundle2.format_remote_wanted_sidedata(repo)
311 formatted = bundle2.format_remote_wanted_sidedata(repo)
312 caps.add(b'exp-wanted-sidedata=' + formatted)
312 caps.add(b'exp-wanted-sidedata=' + formatted)
313
313
314 self._caps = repo._restrictcapabilities(caps)
314 self._caps = repo._restrictcapabilities(caps)
315
315
316 # Begin of _basepeer interface.
316 # Begin of _basepeer interface.
317
317
318 def url(self):
318 def url(self):
319 return self._repo.url()
319 return self._repo.url()
320
320
321 def local(self):
321 def local(self):
322 return self._repo
322 return self._repo
323
323
324 def peer(self):
324 def peer(self):
325 return self
325 return self
326
326
327 def canpush(self):
327 def canpush(self):
328 return True
328 return True
329
329
330 def close(self):
330 def close(self):
331 self._repo.close()
331 self._repo.close()
332
332
333 # End of _basepeer interface.
333 # End of _basepeer interface.
334
334
335 # Begin of _basewirecommands interface.
335 # Begin of _basewirecommands interface.
336
336
337 def branchmap(self):
337 def branchmap(self):
338 return self._repo.branchmap()
338 return self._repo.branchmap()
339
339
340 def capabilities(self):
340 def capabilities(self):
341 return self._caps
341 return self._caps
342
342
343 def clonebundles(self):
343 def clonebundles(self):
344 return self._repo.tryread(bundlecaches.CB_MANIFEST_FILE)
344 return self._repo.tryread(bundlecaches.CB_MANIFEST_FILE)
345
345
346 def debugwireargs(self, one, two, three=None, four=None, five=None):
346 def debugwireargs(self, one, two, three=None, four=None, five=None):
347 """Used to test argument passing over the wire"""
347 """Used to test argument passing over the wire"""
348 return b"%s %s %s %s %s" % (
348 return b"%s %s %s %s %s" % (
349 one,
349 one,
350 two,
350 two,
351 pycompat.bytestr(three),
351 pycompat.bytestr(three),
352 pycompat.bytestr(four),
352 pycompat.bytestr(four),
353 pycompat.bytestr(five),
353 pycompat.bytestr(five),
354 )
354 )
355
355
356 def getbundle(
356 def getbundle(
357 self,
357 self,
358 source,
358 source,
359 heads=None,
359 heads=None,
360 common=None,
360 common=None,
361 bundlecaps=None,
361 bundlecaps=None,
362 remote_sidedata=None,
362 remote_sidedata=None,
363 **kwargs
363 **kwargs
364 ):
364 ):
365 chunks = exchange.getbundlechunks(
365 chunks = exchange.getbundlechunks(
366 self._repo,
366 self._repo,
367 source,
367 source,
368 heads=heads,
368 heads=heads,
369 common=common,
369 common=common,
370 bundlecaps=bundlecaps,
370 bundlecaps=bundlecaps,
371 remote_sidedata=remote_sidedata,
371 remote_sidedata=remote_sidedata,
372 **kwargs
372 **kwargs
373 )[1]
373 )[1]
374 cb = util.chunkbuffer(chunks)
374 cb = util.chunkbuffer(chunks)
375
375
376 if exchange.bundle2requested(bundlecaps):
376 if exchange.bundle2requested(bundlecaps):
377 # When requesting a bundle2, getbundle returns a stream to make the
377 # When requesting a bundle2, getbundle returns a stream to make the
378 # wire level function happier. We need to build a proper object
378 # wire level function happier. We need to build a proper object
379 # from it in local peer.
379 # from it in local peer.
380 return bundle2.getunbundler(self.ui, cb)
380 return bundle2.getunbundler(self.ui, cb)
381 else:
381 else:
382 return changegroup.getunbundler(b'01', cb, None)
382 return changegroup.getunbundler(b'01', cb, None)
383
383
384 def heads(self):
384 def heads(self):
385 return self._repo.heads()
385 return self._repo.heads()
386
386
387 def known(self, nodes):
387 def known(self, nodes):
388 return self._repo.known(nodes)
388 return self._repo.known(nodes)
389
389
390 def listkeys(self, namespace):
390 def listkeys(self, namespace):
391 return self._repo.listkeys(namespace)
391 return self._repo.listkeys(namespace)
392
392
393 def lookup(self, key):
393 def lookup(self, key):
394 return self._repo.lookup(key)
394 return self._repo.lookup(key)
395
395
396 def pushkey(self, namespace, key, old, new):
396 def pushkey(self, namespace, key, old, new):
397 return self._repo.pushkey(namespace, key, old, new)
397 return self._repo.pushkey(namespace, key, old, new)
398
398
399 def stream_out(self):
399 def stream_out(self):
400 raise error.Abort(_(b'cannot perform stream clone against local peer'))
400 raise error.Abort(_(b'cannot perform stream clone against local peer'))
401
401
402 def unbundle(self, bundle, heads, url):
402 def unbundle(self, bundle, heads, url):
403 """apply a bundle on a repo
403 """apply a bundle on a repo
404
404
405 This function handles the repo locking itself."""
405 This function handles the repo locking itself."""
406 try:
406 try:
407 try:
407 try:
408 bundle = exchange.readbundle(self.ui, bundle, None)
408 bundle = exchange.readbundle(self.ui, bundle, None)
409 ret = exchange.unbundle(self._repo, bundle, heads, b'push', url)
409 ret = exchange.unbundle(self._repo, bundle, heads, b'push', url)
410 if util.safehasattr(ret, b'getchunks'):
410 if util.safehasattr(ret, b'getchunks'):
411 # This is a bundle20 object, turn it into an unbundler.
411 # This is a bundle20 object, turn it into an unbundler.
412 # This little dance should be dropped eventually when the
412 # This little dance should be dropped eventually when the
413 # API is finally improved.
413 # API is finally improved.
414 stream = util.chunkbuffer(ret.getchunks())
414 stream = util.chunkbuffer(ret.getchunks())
415 ret = bundle2.getunbundler(self.ui, stream)
415 ret = bundle2.getunbundler(self.ui, stream)
416 return ret
416 return ret
417 except Exception as exc:
417 except Exception as exc:
418 # If the exception contains output salvaged from a bundle2
418 # If the exception contains output salvaged from a bundle2
419 # reply, we need to make sure it is printed before continuing
419 # reply, we need to make sure it is printed before continuing
420 # to fail. So we build a bundle2 with such output and consume
420 # to fail. So we build a bundle2 with such output and consume
421 # it directly.
421 # it directly.
422 #
422 #
423 # This is not very elegant but allows a "simple" solution for
423 # This is not very elegant but allows a "simple" solution for
424 # issue4594
424 # issue4594
425 output = getattr(exc, '_bundle2salvagedoutput', ())
425 output = getattr(exc, '_bundle2salvagedoutput', ())
426 if output:
426 if output:
427 bundler = bundle2.bundle20(self._repo.ui)
427 bundler = bundle2.bundle20(self._repo.ui)
428 for out in output:
428 for out in output:
429 bundler.addpart(out)
429 bundler.addpart(out)
430 stream = util.chunkbuffer(bundler.getchunks())
430 stream = util.chunkbuffer(bundler.getchunks())
431 b = bundle2.getunbundler(self.ui, stream)
431 b = bundle2.getunbundler(self.ui, stream)
432 bundle2.processbundle(self._repo, b)
432 bundle2.processbundle(self._repo, b)
433 raise
433 raise
434 except error.PushRaced as exc:
434 except error.PushRaced as exc:
435 raise error.ResponseError(
435 raise error.ResponseError(
436 _(b'push failed:'), stringutil.forcebytestr(exc)
436 _(b'push failed:'), stringutil.forcebytestr(exc)
437 )
437 )
438
438
439 # End of _basewirecommands interface.
439 # End of _basewirecommands interface.
440
440
441 # Begin of peer interface.
441 # Begin of peer interface.
442
442
443 def commandexecutor(self):
443 def commandexecutor(self):
444 return localcommandexecutor(self)
444 return localcommandexecutor(self)
445
445
446 # End of peer interface.
446 # End of peer interface.
447
447
448
448
449 @interfaceutil.implementer(repository.ipeerlegacycommands)
449 @interfaceutil.implementer(repository.ipeerlegacycommands)
450 class locallegacypeer(localpeer):
450 class locallegacypeer(localpeer):
451 """peer extension which implements legacy methods too; used for tests with
451 """peer extension which implements legacy methods too; used for tests with
452 restricted capabilities"""
452 restricted capabilities"""
453
453
454 def __init__(self, repo):
454 def __init__(self, repo):
455 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
455 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
456
456
457 # Begin of baselegacywirecommands interface.
457 # Begin of baselegacywirecommands interface.
458
458
459 def between(self, pairs):
459 def between(self, pairs):
460 return self._repo.between(pairs)
460 return self._repo.between(pairs)
461
461
462 def branches(self, nodes):
462 def branches(self, nodes):
463 return self._repo.branches(nodes)
463 return self._repo.branches(nodes)
464
464
465 def changegroup(self, nodes, source):
465 def changegroup(self, nodes, source):
466 outgoing = discovery.outgoing(
466 outgoing = discovery.outgoing(
467 self._repo, missingroots=nodes, ancestorsof=self._repo.heads()
467 self._repo, missingroots=nodes, ancestorsof=self._repo.heads()
468 )
468 )
469 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
469 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
470
470
471 def changegroupsubset(self, bases, heads, source):
471 def changegroupsubset(self, bases, heads, source):
472 outgoing = discovery.outgoing(
472 outgoing = discovery.outgoing(
473 self._repo, missingroots=bases, ancestorsof=heads
473 self._repo, missingroots=bases, ancestorsof=heads
474 )
474 )
475 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
475 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
476
476
477 # End of baselegacywirecommands interface.
477 # End of baselegacywirecommands interface.
478
478
479
479
480 # Functions receiving (ui, features) that extensions can register to impact
480 # Functions receiving (ui, features) that extensions can register to impact
481 # the ability to load repositories with custom requirements. Only
481 # the ability to load repositories with custom requirements. Only
482 # functions defined in loaded extensions are called.
482 # functions defined in loaded extensions are called.
483 #
483 #
484 # The function receives a set of requirement strings that the repository
484 # The function receives a set of requirement strings that the repository
485 # is capable of opening. Functions will typically add elements to the
485 # is capable of opening. Functions will typically add elements to the
486 # set to reflect that the extension knows how to handle that requirements.
486 # set to reflect that the extension knows how to handle that requirements.
487 featuresetupfuncs = set()
487 featuresetupfuncs = set()
488
488
489
489
490 def _getsharedvfs(hgvfs, requirements):
490 def _getsharedvfs(hgvfs, requirements):
491 """returns the vfs object pointing to root of shared source
491 """returns the vfs object pointing to root of shared source
492 repo for a shared repository
492 repo for a shared repository
493
493
494 hgvfs is vfs pointing at .hg/ of current repo (shared one)
494 hgvfs is vfs pointing at .hg/ of current repo (shared one)
495 requirements is a set of requirements of current repo (shared one)
495 requirements is a set of requirements of current repo (shared one)
496 """
496 """
497 # The ``shared`` or ``relshared`` requirements indicate the
497 # The ``shared`` or ``relshared`` requirements indicate the
498 # store lives in the path contained in the ``.hg/sharedpath`` file.
498 # store lives in the path contained in the ``.hg/sharedpath`` file.
499 # This is an absolute path for ``shared`` and relative to
499 # This is an absolute path for ``shared`` and relative to
500 # ``.hg/`` for ``relshared``.
500 # ``.hg/`` for ``relshared``.
501 sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
501 sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
502 if requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements:
502 if requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements:
503 sharedpath = util.normpath(hgvfs.join(sharedpath))
503 sharedpath = util.normpath(hgvfs.join(sharedpath))
504
504
505 sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
505 sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
506
506
507 if not sharedvfs.exists():
507 if not sharedvfs.exists():
508 raise error.RepoError(
508 raise error.RepoError(
509 _(b'.hg/sharedpath points to nonexistent directory %s')
509 _(b'.hg/sharedpath points to nonexistent directory %s')
510 % sharedvfs.base
510 % sharedvfs.base
511 )
511 )
512 return sharedvfs
512 return sharedvfs
513
513
514
514
515 def _readrequires(vfs, allowmissing):
515 def _readrequires(vfs, allowmissing):
516 """reads the require file present at root of this vfs
516 """reads the require file present at root of this vfs
517 and return a set of requirements
517 and return a set of requirements
518
518
519 If allowmissing is True, we suppress FileNotFoundError if raised"""
519 If allowmissing is True, we suppress FileNotFoundError if raised"""
520 # requires file contains a newline-delimited list of
520 # requires file contains a newline-delimited list of
521 # features/capabilities the opener (us) must have in order to use
521 # features/capabilities the opener (us) must have in order to use
522 # the repository. This file was introduced in Mercurial 0.9.2,
522 # the repository. This file was introduced in Mercurial 0.9.2,
523 # which means very old repositories may not have one. We assume
523 # which means very old repositories may not have one. We assume
524 # a missing file translates to no requirements.
524 # a missing file translates to no requirements.
525 try:
525 try:
526 return set(vfs.read(b'requires').splitlines())
526 return set(vfs.read(b'requires').splitlines())
527 except FileNotFoundError:
527 except FileNotFoundError:
528 if not allowmissing:
528 if not allowmissing:
529 raise
529 raise
530 return set()
530 return set()
531
531
532
532
533 def makelocalrepository(baseui, path, intents=None):
533 def makelocalrepository(baseui, path, intents=None):
534 """Create a local repository object.
534 """Create a local repository object.
535
535
536 Given arguments needed to construct a local repository, this function
536 Given arguments needed to construct a local repository, this function
537 performs various early repository loading functionality (such as
537 performs various early repository loading functionality (such as
538 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
538 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
539 the repository can be opened, derives a type suitable for representing
539 the repository can be opened, derives a type suitable for representing
540 that repository, and returns an instance of it.
540 that repository, and returns an instance of it.
541
541
542 The returned object conforms to the ``repository.completelocalrepository``
542 The returned object conforms to the ``repository.completelocalrepository``
543 interface.
543 interface.
544
544
545 The repository type is derived by calling a series of factory functions
545 The repository type is derived by calling a series of factory functions
546 for each aspect/interface of the final repository. These are defined by
546 for each aspect/interface of the final repository. These are defined by
547 ``REPO_INTERFACES``.
547 ``REPO_INTERFACES``.
548
548
549 Each factory function is called to produce a type implementing a specific
549 Each factory function is called to produce a type implementing a specific
550 interface. The cumulative list of returned types will be combined into a
550 interface. The cumulative list of returned types will be combined into a
551 new type and that type will be instantiated to represent the local
551 new type and that type will be instantiated to represent the local
552 repository.
552 repository.
553
553
554 The factory functions each receive various state that may be consulted
554 The factory functions each receive various state that may be consulted
555 as part of deriving a type.
555 as part of deriving a type.
556
556
557 Extensions should wrap these factory functions to customize repository type
557 Extensions should wrap these factory functions to customize repository type
558 creation. Note that an extension's wrapped function may be called even if
558 creation. Note that an extension's wrapped function may be called even if
559 that extension is not loaded for the repo being constructed. Extensions
559 that extension is not loaded for the repo being constructed. Extensions
560 should check if their ``__name__`` appears in the
560 should check if their ``__name__`` appears in the
561 ``extensionmodulenames`` set passed to the factory function and no-op if
561 ``extensionmodulenames`` set passed to the factory function and no-op if
562 not.
562 not.
563 """
563 """
564 ui = baseui.copy()
564 ui = baseui.copy()
565 # Prevent copying repo configuration.
565 # Prevent copying repo configuration.
566 ui.copy = baseui.copy
566 ui.copy = baseui.copy
567
567
568 # Working directory VFS rooted at repository root.
568 # Working directory VFS rooted at repository root.
569 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
569 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
570
570
571 # Main VFS for .hg/ directory.
571 # Main VFS for .hg/ directory.
572 hgpath = wdirvfs.join(b'.hg')
572 hgpath = wdirvfs.join(b'.hg')
573 hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
573 hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
574 # Whether this repository is shared one or not
574 # Whether this repository is shared one or not
575 shared = False
575 shared = False
576 # If this repository is shared, vfs pointing to shared repo
576 # If this repository is shared, vfs pointing to shared repo
577 sharedvfs = None
577 sharedvfs = None
578
578
579 # The .hg/ path should exist and should be a directory. All other
579 # The .hg/ path should exist and should be a directory. All other
580 # cases are errors.
580 # cases are errors.
581 if not hgvfs.isdir():
581 if not hgvfs.isdir():
582 try:
582 try:
583 hgvfs.stat()
583 hgvfs.stat()
584 except FileNotFoundError:
584 except FileNotFoundError:
585 pass
585 pass
586 except ValueError as e:
586 except ValueError as e:
587 # Can be raised on Python 3.8 when path is invalid.
587 # Can be raised on Python 3.8 when path is invalid.
588 raise error.Abort(
588 raise error.Abort(
589 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
589 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
590 )
590 )
591
591
592 raise error.RepoError(_(b'repository %s not found') % path)
592 raise error.RepoError(_(b'repository %s not found') % path)
593
593
594 requirements = _readrequires(hgvfs, True)
594 requirements = _readrequires(hgvfs, True)
595 shared = (
595 shared = (
596 requirementsmod.SHARED_REQUIREMENT in requirements
596 requirementsmod.SHARED_REQUIREMENT in requirements
597 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
597 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
598 )
598 )
599 storevfs = None
599 storevfs = None
600 if shared:
600 if shared:
601 # This is a shared repo
601 # This is a shared repo
602 sharedvfs = _getsharedvfs(hgvfs, requirements)
602 sharedvfs = _getsharedvfs(hgvfs, requirements)
603 storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
603 storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
604 else:
604 else:
605 storevfs = vfsmod.vfs(hgvfs.join(b'store'))
605 storevfs = vfsmod.vfs(hgvfs.join(b'store'))
606
606
607 # if .hg/requires contains the sharesafe requirement, it means
607 # if .hg/requires contains the sharesafe requirement, it means
608 # there exists a `.hg/store/requires` too and we should read it
608 # there exists a `.hg/store/requires` too and we should read it
609 # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
609 # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
610 # is present. We never write SHARESAFE_REQUIREMENT for a repo if store
610 # is present. We never write SHARESAFE_REQUIREMENT for a repo if store
611 # is not present, refer checkrequirementscompat() for that
611 # is not present, refer checkrequirementscompat() for that
612 #
612 #
613 # However, if SHARESAFE_REQUIREMENT is not present, it means that the
613 # However, if SHARESAFE_REQUIREMENT is not present, it means that the
614 # repository was shared the old way. We check the share source .hg/requires
614 # repository was shared the old way. We check the share source .hg/requires
615 # for SHARESAFE_REQUIREMENT to detect whether the current repository needs
615 # for SHARESAFE_REQUIREMENT to detect whether the current repository needs
616 # to be reshared
616 # to be reshared
617 hint = _(b"see `hg help config.format.use-share-safe` for more information")
617 hint = _(b"see `hg help config.format.use-share-safe` for more information")
618 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
618 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
619
619
620 if (
620 if (
621 shared
621 shared
622 and requirementsmod.SHARESAFE_REQUIREMENT
622 and requirementsmod.SHARESAFE_REQUIREMENT
623 not in _readrequires(sharedvfs, True)
623 not in _readrequires(sharedvfs, True)
624 ):
624 ):
625 mismatch_warn = ui.configbool(
625 mismatch_warn = ui.configbool(
626 b'share', b'safe-mismatch.source-not-safe.warn'
626 b'share', b'safe-mismatch.source-not-safe.warn'
627 )
627 )
628 mismatch_config = ui.config(
628 mismatch_config = ui.config(
629 b'share', b'safe-mismatch.source-not-safe'
629 b'share', b'safe-mismatch.source-not-safe'
630 )
630 )
631 mismatch_verbose_upgrade = ui.configbool(
631 mismatch_verbose_upgrade = ui.configbool(
632 b'share', b'safe-mismatch.source-not-safe:verbose-upgrade'
632 b'share', b'safe-mismatch.source-not-safe:verbose-upgrade'
633 )
633 )
634 if mismatch_config in (
634 if mismatch_config in (
635 b'downgrade-allow',
635 b'downgrade-allow',
636 b'allow',
636 b'allow',
637 b'downgrade-abort',
637 b'downgrade-abort',
638 ):
638 ):
639 # prevent cyclic import localrepo -> upgrade -> localrepo
639 # prevent cyclic import localrepo -> upgrade -> localrepo
640 from . import upgrade
640 from . import upgrade
641
641
642 upgrade.downgrade_share_to_non_safe(
642 upgrade.downgrade_share_to_non_safe(
643 ui,
643 ui,
644 hgvfs,
644 hgvfs,
645 sharedvfs,
645 sharedvfs,
646 requirements,
646 requirements,
647 mismatch_config,
647 mismatch_config,
648 mismatch_warn,
648 mismatch_warn,
649 mismatch_verbose_upgrade,
649 mismatch_verbose_upgrade,
650 )
650 )
651 elif mismatch_config == b'abort':
651 elif mismatch_config == b'abort':
652 raise error.Abort(
652 raise error.Abort(
653 _(b"share source does not support share-safe requirement"),
653 _(b"share source does not support share-safe requirement"),
654 hint=hint,
654 hint=hint,
655 )
655 )
656 else:
656 else:
657 raise error.Abort(
657 raise error.Abort(
658 _(
658 _(
659 b"share-safe mismatch with source.\nUnrecognized"
659 b"share-safe mismatch with source.\nUnrecognized"
660 b" value '%s' of `share.safe-mismatch.source-not-safe`"
660 b" value '%s' of `share.safe-mismatch.source-not-safe`"
661 b" set."
661 b" set."
662 )
662 )
663 % mismatch_config,
663 % mismatch_config,
664 hint=hint,
664 hint=hint,
665 )
665 )
666 else:
666 else:
667 requirements |= _readrequires(storevfs, False)
667 requirements |= _readrequires(storevfs, False)
668 elif shared:
668 elif shared:
669 sourcerequires = _readrequires(sharedvfs, False)
669 sourcerequires = _readrequires(sharedvfs, False)
670 if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires:
670 if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires:
671 mismatch_config = ui.config(b'share', b'safe-mismatch.source-safe')
671 mismatch_config = ui.config(b'share', b'safe-mismatch.source-safe')
672 mismatch_warn = ui.configbool(
672 mismatch_warn = ui.configbool(
673 b'share', b'safe-mismatch.source-safe.warn'
673 b'share', b'safe-mismatch.source-safe.warn'
674 )
674 )
675 mismatch_verbose_upgrade = ui.configbool(
675 mismatch_verbose_upgrade = ui.configbool(
676 b'share', b'safe-mismatch.source-safe:verbose-upgrade'
676 b'share', b'safe-mismatch.source-safe:verbose-upgrade'
677 )
677 )
678 if mismatch_config in (
678 if mismatch_config in (
679 b'upgrade-allow',
679 b'upgrade-allow',
680 b'allow',
680 b'allow',
681 b'upgrade-abort',
681 b'upgrade-abort',
682 ):
682 ):
683 # prevent cyclic import localrepo -> upgrade -> localrepo
683 # prevent cyclic import localrepo -> upgrade -> localrepo
684 from . import upgrade
684 from . import upgrade
685
685
686 upgrade.upgrade_share_to_safe(
686 upgrade.upgrade_share_to_safe(
687 ui,
687 ui,
688 hgvfs,
688 hgvfs,
689 storevfs,
689 storevfs,
690 requirements,
690 requirements,
691 mismatch_config,
691 mismatch_config,
692 mismatch_warn,
692 mismatch_warn,
693 mismatch_verbose_upgrade,
693 mismatch_verbose_upgrade,
694 )
694 )
695 elif mismatch_config == b'abort':
695 elif mismatch_config == b'abort':
696 raise error.Abort(
696 raise error.Abort(
697 _(
697 _(
698 b'version mismatch: source uses share-safe'
698 b'version mismatch: source uses share-safe'
699 b' functionality while the current share does not'
699 b' functionality while the current share does not'
700 ),
700 ),
701 hint=hint,
701 hint=hint,
702 )
702 )
703 else:
703 else:
704 raise error.Abort(
704 raise error.Abort(
705 _(
705 _(
706 b"share-safe mismatch with source.\nUnrecognized"
706 b"share-safe mismatch with source.\nUnrecognized"
707 b" value '%s' of `share.safe-mismatch.source-safe` set."
707 b" value '%s' of `share.safe-mismatch.source-safe` set."
708 )
708 )
709 % mismatch_config,
709 % mismatch_config,
710 hint=hint,
710 hint=hint,
711 )
711 )
712
712
713 # The .hg/hgrc file may load extensions or contain config options
713 # The .hg/hgrc file may load extensions or contain config options
714 # that influence repository construction. Attempt to load it and
714 # that influence repository construction. Attempt to load it and
715 # process any new extensions that it may have pulled in.
715 # process any new extensions that it may have pulled in.
716 if loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs):
716 if loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs):
717 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
717 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
718 extensions.loadall(ui)
718 extensions.loadall(ui)
719 extensions.populateui(ui)
719 extensions.populateui(ui)
720
720
721 # Set of module names of extensions loaded for this repository.
721 # Set of module names of extensions loaded for this repository.
722 extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
722 extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
723
723
724 supportedrequirements = gathersupportedrequirements(ui)
724 supportedrequirements = gathersupportedrequirements(ui)
725
725
726 # We first validate the requirements are known.
726 # We first validate the requirements are known.
727 ensurerequirementsrecognized(requirements, supportedrequirements)
727 ensurerequirementsrecognized(requirements, supportedrequirements)
728
728
729 # Then we validate that the known set is reasonable to use together.
729 # Then we validate that the known set is reasonable to use together.
730 ensurerequirementscompatible(ui, requirements)
730 ensurerequirementscompatible(ui, requirements)
731
731
732 # TODO there are unhandled edge cases related to opening repositories with
732 # TODO there are unhandled edge cases related to opening repositories with
733 # shared storage. If storage is shared, we should also test for requirements
733 # shared storage. If storage is shared, we should also test for requirements
734 # compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
734 # compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
735 # that repo, as that repo may load extensions needed to open it. This is a
735 # that repo, as that repo may load extensions needed to open it. This is a
736 # bit complicated because we don't want the other hgrc to overwrite settings
736 # bit complicated because we don't want the other hgrc to overwrite settings
737 # in this hgrc.
737 # in this hgrc.
738 #
738 #
739 # This bug is somewhat mitigated by the fact that we copy the .hg/requires
739 # This bug is somewhat mitigated by the fact that we copy the .hg/requires
740 # file when sharing repos. But if a requirement is added after the share is
740 # file when sharing repos. But if a requirement is added after the share is
741 # performed, thereby introducing a new requirement for the opener, we may
741 # performed, thereby introducing a new requirement for the opener, we may
742 # will not see that and could encounter a run-time error interacting with
742 # will not see that and could encounter a run-time error interacting with
743 # that shared store since it has an unknown-to-us requirement.
743 # that shared store since it has an unknown-to-us requirement.
744
744
745 # At this point, we know we should be capable of opening the repository.
745 # At this point, we know we should be capable of opening the repository.
746 # Now get on with doing that.
746 # Now get on with doing that.
747
747
748 features = set()
748 features = set()
749
749
750 # The "store" part of the repository holds versioned data. How it is
750 # The "store" part of the repository holds versioned data. How it is
751 # accessed is determined by various requirements. If `shared` or
751 # accessed is determined by various requirements. If `shared` or
752 # `relshared` requirements are present, this indicates current repository
752 # `relshared` requirements are present, this indicates current repository
753 # is a share and store exists in path mentioned in `.hg/sharedpath`
753 # is a share and store exists in path mentioned in `.hg/sharedpath`
754 if shared:
754 if shared:
755 storebasepath = sharedvfs.base
755 storebasepath = sharedvfs.base
756 cachepath = sharedvfs.join(b'cache')
756 cachepath = sharedvfs.join(b'cache')
757 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
757 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
758 else:
758 else:
759 storebasepath = hgvfs.base
759 storebasepath = hgvfs.base
760 cachepath = hgvfs.join(b'cache')
760 cachepath = hgvfs.join(b'cache')
761 wcachepath = hgvfs.join(b'wcache')
761 wcachepath = hgvfs.join(b'wcache')
762
762
763 # The store has changed over time and the exact layout is dictated by
763 # The store has changed over time and the exact layout is dictated by
764 # requirements. The store interface abstracts differences across all
764 # requirements. The store interface abstracts differences across all
765 # of them.
765 # of them.
766 store = makestore(
766 store = makestore(
767 requirements,
767 requirements,
768 storebasepath,
768 storebasepath,
769 lambda base: vfsmod.vfs(base, cacheaudited=True),
769 lambda base: vfsmod.vfs(base, cacheaudited=True),
770 )
770 )
771 hgvfs.createmode = store.createmode
771 hgvfs.createmode = store.createmode
772
772
773 storevfs = store.vfs
773 storevfs = store.vfs
774 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
774 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
775
775
776 if (
776 if (
777 requirementsmod.REVLOGV2_REQUIREMENT in requirements
777 requirementsmod.REVLOGV2_REQUIREMENT in requirements
778 or requirementsmod.CHANGELOGV2_REQUIREMENT in requirements
778 or requirementsmod.CHANGELOGV2_REQUIREMENT in requirements
779 ):
779 ):
780 features.add(repository.REPO_FEATURE_SIDE_DATA)
780 features.add(repository.REPO_FEATURE_SIDE_DATA)
781 # the revlogv2 docket introduced race condition that we need to fix
781 # the revlogv2 docket introduced race condition that we need to fix
782 features.discard(repository.REPO_FEATURE_STREAM_CLONE)
782 features.discard(repository.REPO_FEATURE_STREAM_CLONE)
783
783
784 # The cache vfs is used to manage cache files.
784 # The cache vfs is used to manage cache files.
785 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
785 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
786 cachevfs.createmode = store.createmode
786 cachevfs.createmode = store.createmode
787 # The cache vfs is used to manage cache files related to the working copy
787 # The cache vfs is used to manage cache files related to the working copy
788 wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
788 wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
789 wcachevfs.createmode = store.createmode
789 wcachevfs.createmode = store.createmode
790
790
791 # Now resolve the type for the repository object. We do this by repeatedly
791 # Now resolve the type for the repository object. We do this by repeatedly
792 # calling a factory function to produces types for specific aspects of the
792 # calling a factory function to produces types for specific aspects of the
793 # repo's operation. The aggregate returned types are used as base classes
793 # repo's operation. The aggregate returned types are used as base classes
794 # for a dynamically-derived type, which will represent our new repository.
794 # for a dynamically-derived type, which will represent our new repository.
795
795
796 bases = []
796 bases = []
797 extrastate = {}
797 extrastate = {}
798
798
799 for iface, fn in REPO_INTERFACES:
799 for iface, fn in REPO_INTERFACES:
800 # We pass all potentially useful state to give extensions tons of
800 # We pass all potentially useful state to give extensions tons of
801 # flexibility.
801 # flexibility.
802 typ = fn()(
802 typ = fn()(
803 ui=ui,
803 ui=ui,
804 intents=intents,
804 intents=intents,
805 requirements=requirements,
805 requirements=requirements,
806 features=features,
806 features=features,
807 wdirvfs=wdirvfs,
807 wdirvfs=wdirvfs,
808 hgvfs=hgvfs,
808 hgvfs=hgvfs,
809 store=store,
809 store=store,
810 storevfs=storevfs,
810 storevfs=storevfs,
811 storeoptions=storevfs.options,
811 storeoptions=storevfs.options,
812 cachevfs=cachevfs,
812 cachevfs=cachevfs,
813 wcachevfs=wcachevfs,
813 wcachevfs=wcachevfs,
814 extensionmodulenames=extensionmodulenames,
814 extensionmodulenames=extensionmodulenames,
815 extrastate=extrastate,
815 extrastate=extrastate,
816 baseclasses=bases,
816 baseclasses=bases,
817 )
817 )
818
818
819 if not isinstance(typ, type):
819 if not isinstance(typ, type):
820 raise error.ProgrammingError(
820 raise error.ProgrammingError(
821 b'unable to construct type for %s' % iface
821 b'unable to construct type for %s' % iface
822 )
822 )
823
823
824 bases.append(typ)
824 bases.append(typ)
825
825
826 # type() allows you to use characters in type names that wouldn't be
826 # type() allows you to use characters in type names that wouldn't be
827 # recognized as Python symbols in source code. We abuse that to add
827 # recognized as Python symbols in source code. We abuse that to add
828 # rich information about our constructed repo.
828 # rich information about our constructed repo.
829 name = pycompat.sysstr(
829 name = pycompat.sysstr(
830 b'derivedrepo:%s<%s>' % (wdirvfs.base, b','.join(sorted(requirements)))
830 b'derivedrepo:%s<%s>' % (wdirvfs.base, b','.join(sorted(requirements)))
831 )
831 )
832
832
833 cls = type(name, tuple(bases), {})
833 cls = type(name, tuple(bases), {})
834
834
835 return cls(
835 return cls(
836 baseui=baseui,
836 baseui=baseui,
837 ui=ui,
837 ui=ui,
838 origroot=path,
838 origroot=path,
839 wdirvfs=wdirvfs,
839 wdirvfs=wdirvfs,
840 hgvfs=hgvfs,
840 hgvfs=hgvfs,
841 requirements=requirements,
841 requirements=requirements,
842 supportedrequirements=supportedrequirements,
842 supportedrequirements=supportedrequirements,
843 sharedpath=storebasepath,
843 sharedpath=storebasepath,
844 store=store,
844 store=store,
845 cachevfs=cachevfs,
845 cachevfs=cachevfs,
846 wcachevfs=wcachevfs,
846 wcachevfs=wcachevfs,
847 features=features,
847 features=features,
848 intents=intents,
848 intents=intents,
849 )
849 )
850
850
851
851
852 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None):
852 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None):
853 """Load hgrc files/content into a ui instance.
853 """Load hgrc files/content into a ui instance.
854
854
855 This is called during repository opening to load any additional
855 This is called during repository opening to load any additional
856 config files or settings relevant to the current repository.
856 config files or settings relevant to the current repository.
857
857
858 Returns a bool indicating whether any additional configs were loaded.
858 Returns a bool indicating whether any additional configs were loaded.
859
859
860 Extensions should monkeypatch this function to modify how per-repo
860 Extensions should monkeypatch this function to modify how per-repo
861 configs are loaded. For example, an extension may wish to pull in
861 configs are loaded. For example, an extension may wish to pull in
862 configs from alternate files or sources.
862 configs from alternate files or sources.
863
863
864 sharedvfs is vfs object pointing to source repo if the current one is a
864 sharedvfs is vfs object pointing to source repo if the current one is a
865 shared one
865 shared one
866 """
866 """
867 if not rcutil.use_repo_hgrc():
867 if not rcutil.use_repo_hgrc():
868 return False
868 return False
869
869
870 ret = False
870 ret = False
871 # first load config from shared source if we has to
871 # first load config from shared source if we has to
872 if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs:
872 if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs:
873 try:
873 try:
874 ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base)
874 ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base)
875 ret = True
875 ret = True
876 except IOError:
876 except IOError:
877 pass
877 pass
878
878
879 try:
879 try:
880 ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
880 ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
881 ret = True
881 ret = True
882 except IOError:
882 except IOError:
883 pass
883 pass
884
884
885 try:
885 try:
886 ui.readconfig(hgvfs.join(b'hgrc-not-shared'), root=wdirvfs.base)
886 ui.readconfig(hgvfs.join(b'hgrc-not-shared'), root=wdirvfs.base)
887 ret = True
887 ret = True
888 except IOError:
888 except IOError:
889 pass
889 pass
890
890
891 return ret
891 return ret
892
892
893
893
894 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
894 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
895 """Perform additional actions after .hg/hgrc is loaded.
895 """Perform additional actions after .hg/hgrc is loaded.
896
896
897 This function is called during repository loading immediately after
897 This function is called during repository loading immediately after
898 the .hg/hgrc file is loaded and before per-repo extensions are loaded.
898 the .hg/hgrc file is loaded and before per-repo extensions are loaded.
899
899
900 The function can be used to validate configs, automatically add
900 The function can be used to validate configs, automatically add
901 options (including extensions) based on requirements, etc.
901 options (including extensions) based on requirements, etc.
902 """
902 """
903
903
904 # Map of requirements to list of extensions to load automatically when
904 # Map of requirements to list of extensions to load automatically when
905 # requirement is present.
905 # requirement is present.
906 autoextensions = {
906 autoextensions = {
907 b'git': [b'git'],
907 b'git': [b'git'],
908 b'largefiles': [b'largefiles'],
908 b'largefiles': [b'largefiles'],
909 b'lfs': [b'lfs'],
909 b'lfs': [b'lfs'],
910 }
910 }
911
911
912 for requirement, names in sorted(autoextensions.items()):
912 for requirement, names in sorted(autoextensions.items()):
913 if requirement not in requirements:
913 if requirement not in requirements:
914 continue
914 continue
915
915
916 for name in names:
916 for name in names:
917 if not ui.hasconfig(b'extensions', name):
917 if not ui.hasconfig(b'extensions', name):
918 ui.setconfig(b'extensions', name, b'', source=b'autoload')
918 ui.setconfig(b'extensions', name, b'', source=b'autoload')
919
919
920
920
921 def gathersupportedrequirements(ui):
921 def gathersupportedrequirements(ui):
922 """Determine the complete set of recognized requirements."""
922 """Determine the complete set of recognized requirements."""
923 # Start with all requirements supported by this file.
923 # Start with all requirements supported by this file.
924 supported = set(localrepository._basesupported)
924 supported = set(localrepository._basesupported)
925
925
926 # Execute ``featuresetupfuncs`` entries if they belong to an extension
926 # Execute ``featuresetupfuncs`` entries if they belong to an extension
927 # relevant to this ui instance.
927 # relevant to this ui instance.
928 modules = {m.__name__ for n, m in extensions.extensions(ui)}
928 modules = {m.__name__ for n, m in extensions.extensions(ui)}
929
929
930 for fn in featuresetupfuncs:
930 for fn in featuresetupfuncs:
931 if fn.__module__ in modules:
931 if fn.__module__ in modules:
932 fn(ui, supported)
932 fn(ui, supported)
933
933
934 # Add derived requirements from registered compression engines.
934 # Add derived requirements from registered compression engines.
935 for name in util.compengines:
935 for name in util.compengines:
936 engine = util.compengines[name]
936 engine = util.compengines[name]
937 if engine.available() and engine.revlogheader():
937 if engine.available() and engine.revlogheader():
938 supported.add(b'exp-compression-%s' % name)
938 supported.add(b'exp-compression-%s' % name)
939 if engine.name() == b'zstd':
939 if engine.name() == b'zstd':
940 supported.add(requirementsmod.REVLOG_COMPRESSION_ZSTD)
940 supported.add(requirementsmod.REVLOG_COMPRESSION_ZSTD)
941
941
942 return supported
942 return supported
943
943
944
944
945 def ensurerequirementsrecognized(requirements, supported):
945 def ensurerequirementsrecognized(requirements, supported):
946 """Validate that a set of local requirements is recognized.
946 """Validate that a set of local requirements is recognized.
947
947
948 Receives a set of requirements. Raises an ``error.RepoError`` if there
948 Receives a set of requirements. Raises an ``error.RepoError`` if there
949 exists any requirement in that set that currently loaded code doesn't
949 exists any requirement in that set that currently loaded code doesn't
950 recognize.
950 recognize.
951
951
952 Returns a set of supported requirements.
952 Returns a set of supported requirements.
953 """
953 """
954 missing = set()
954 missing = set()
955
955
956 for requirement in requirements:
956 for requirement in requirements:
957 if requirement in supported:
957 if requirement in supported:
958 continue
958 continue
959
959
960 if not requirement or not requirement[0:1].isalnum():
960 if not requirement or not requirement[0:1].isalnum():
961 raise error.RequirementError(_(b'.hg/requires file is corrupt'))
961 raise error.RequirementError(_(b'.hg/requires file is corrupt'))
962
962
963 missing.add(requirement)
963 missing.add(requirement)
964
964
965 if missing:
965 if missing:
966 raise error.RequirementError(
966 raise error.RequirementError(
967 _(b'repository requires features unknown to this Mercurial: %s')
967 _(b'repository requires features unknown to this Mercurial: %s')
968 % b' '.join(sorted(missing)),
968 % b' '.join(sorted(missing)),
969 hint=_(
969 hint=_(
970 b'see https://mercurial-scm.org/wiki/MissingRequirement '
970 b'see https://mercurial-scm.org/wiki/MissingRequirement '
971 b'for more information'
971 b'for more information'
972 ),
972 ),
973 )
973 )
974
974
975
975
976 def ensurerequirementscompatible(ui, requirements):
976 def ensurerequirementscompatible(ui, requirements):
977 """Validates that a set of recognized requirements is mutually compatible.
977 """Validates that a set of recognized requirements is mutually compatible.
978
978
979 Some requirements may not be compatible with others or require
979 Some requirements may not be compatible with others or require
980 config options that aren't enabled. This function is called during
980 config options that aren't enabled. This function is called during
981 repository opening to ensure that the set of requirements needed
981 repository opening to ensure that the set of requirements needed
982 to open a repository is sane and compatible with config options.
982 to open a repository is sane and compatible with config options.
983
983
984 Extensions can monkeypatch this function to perform additional
984 Extensions can monkeypatch this function to perform additional
985 checking.
985 checking.
986
986
987 ``error.RepoError`` should be raised on failure.
987 ``error.RepoError`` should be raised on failure.
988 """
988 """
989 if (
989 if (
990 requirementsmod.SPARSE_REQUIREMENT in requirements
990 requirementsmod.SPARSE_REQUIREMENT in requirements
991 and not sparse.enabled
991 and not sparse.enabled
992 ):
992 ):
993 raise error.RepoError(
993 raise error.RepoError(
994 _(
994 _(
995 b'repository is using sparse feature but '
995 b'repository is using sparse feature but '
996 b'sparse is not enabled; enable the '
996 b'sparse is not enabled; enable the '
997 b'"sparse" extensions to access'
997 b'"sparse" extensions to access'
998 )
998 )
999 )
999 )
1000
1000
1001
1001
1002 def makestore(requirements, path, vfstype):
1002 def makestore(requirements, path, vfstype):
1003 """Construct a storage object for a repository."""
1003 """Construct a storage object for a repository."""
1004 if requirementsmod.STORE_REQUIREMENT in requirements:
1004 if requirementsmod.STORE_REQUIREMENT in requirements:
1005 if requirementsmod.FNCACHE_REQUIREMENT in requirements:
1005 if requirementsmod.FNCACHE_REQUIREMENT in requirements:
1006 dotencode = requirementsmod.DOTENCODE_REQUIREMENT in requirements
1006 dotencode = requirementsmod.DOTENCODE_REQUIREMENT in requirements
1007 return storemod.fncachestore(path, vfstype, dotencode)
1007 return storemod.fncachestore(path, vfstype, dotencode)
1008
1008
1009 return storemod.encodedstore(path, vfstype)
1009 return storemod.encodedstore(path, vfstype)
1010
1010
1011 return storemod.basicstore(path, vfstype)
1011 return storemod.basicstore(path, vfstype)
1012
1012
1013
1013
1014 def resolvestorevfsoptions(ui, requirements, features):
1014 def resolvestorevfsoptions(ui, requirements, features):
1015 """Resolve the options to pass to the store vfs opener.
1015 """Resolve the options to pass to the store vfs opener.
1016
1016
1017 The returned dict is used to influence behavior of the storage layer.
1017 The returned dict is used to influence behavior of the storage layer.
1018 """
1018 """
1019 options = {}
1019 options = {}
1020
1020
1021 if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
1021 if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
1022 options[b'treemanifest'] = True
1022 options[b'treemanifest'] = True
1023
1023
1024 # experimental config: format.manifestcachesize
1024 # experimental config: format.manifestcachesize
1025 manifestcachesize = ui.configint(b'format', b'manifestcachesize')
1025 manifestcachesize = ui.configint(b'format', b'manifestcachesize')
1026 if manifestcachesize is not None:
1026 if manifestcachesize is not None:
1027 options[b'manifestcachesize'] = manifestcachesize
1027 options[b'manifestcachesize'] = manifestcachesize
1028
1028
1029 # In the absence of another requirement superseding a revlog-related
1029 # In the absence of another requirement superseding a revlog-related
1030 # requirement, we have to assume the repo is using revlog version 0.
1030 # requirement, we have to assume the repo is using revlog version 0.
1031 # This revlog format is super old and we don't bother trying to parse
1031 # This revlog format is super old and we don't bother trying to parse
1032 # opener options for it because those options wouldn't do anything
1032 # opener options for it because those options wouldn't do anything
1033 # meaningful on such old repos.
1033 # meaningful on such old repos.
1034 if (
1034 if (
1035 requirementsmod.REVLOGV1_REQUIREMENT in requirements
1035 requirementsmod.REVLOGV1_REQUIREMENT in requirements
1036 or requirementsmod.REVLOGV2_REQUIREMENT in requirements
1036 or requirementsmod.REVLOGV2_REQUIREMENT in requirements
1037 ):
1037 ):
1038 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
1038 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
1039 else: # explicitly mark repo as using revlogv0
1039 else: # explicitly mark repo as using revlogv0
1040 options[b'revlogv0'] = True
1040 options[b'revlogv0'] = True
1041
1041
1042 if requirementsmod.COPIESSDC_REQUIREMENT in requirements:
1042 if requirementsmod.COPIESSDC_REQUIREMENT in requirements:
1043 options[b'copies-storage'] = b'changeset-sidedata'
1043 options[b'copies-storage'] = b'changeset-sidedata'
1044 else:
1044 else:
1045 writecopiesto = ui.config(b'experimental', b'copies.write-to')
1045 writecopiesto = ui.config(b'experimental', b'copies.write-to')
1046 copiesextramode = (b'changeset-only', b'compatibility')
1046 copiesextramode = (b'changeset-only', b'compatibility')
1047 if writecopiesto in copiesextramode:
1047 if writecopiesto in copiesextramode:
1048 options[b'copies-storage'] = b'extra'
1048 options[b'copies-storage'] = b'extra'
1049
1049
1050 return options
1050 return options
1051
1051
1052
1052
1053 def resolverevlogstorevfsoptions(ui, requirements, features):
1053 def resolverevlogstorevfsoptions(ui, requirements, features):
1054 """Resolve opener options specific to revlogs."""
1054 """Resolve opener options specific to revlogs."""
1055
1055
1056 options = {}
1056 options = {}
1057 options[b'flagprocessors'] = {}
1057 options[b'flagprocessors'] = {}
1058
1058
1059 if requirementsmod.REVLOGV1_REQUIREMENT in requirements:
1059 if requirementsmod.REVLOGV1_REQUIREMENT in requirements:
1060 options[b'revlogv1'] = True
1060 options[b'revlogv1'] = True
1061 if requirementsmod.REVLOGV2_REQUIREMENT in requirements:
1061 if requirementsmod.REVLOGV2_REQUIREMENT in requirements:
1062 options[b'revlogv2'] = True
1062 options[b'revlogv2'] = True
1063 if requirementsmod.CHANGELOGV2_REQUIREMENT in requirements:
1063 if requirementsmod.CHANGELOGV2_REQUIREMENT in requirements:
1064 options[b'changelogv2'] = True
1064 options[b'changelogv2'] = True
1065
1065
1066 if requirementsmod.GENERALDELTA_REQUIREMENT in requirements:
1066 if requirementsmod.GENERALDELTA_REQUIREMENT in requirements:
1067 options[b'generaldelta'] = True
1067 options[b'generaldelta'] = True
1068
1068
1069 # experimental config: format.chunkcachesize
1069 # experimental config: format.chunkcachesize
1070 chunkcachesize = ui.configint(b'format', b'chunkcachesize')
1070 chunkcachesize = ui.configint(b'format', b'chunkcachesize')
1071 if chunkcachesize is not None:
1071 if chunkcachesize is not None:
1072 options[b'chunkcachesize'] = chunkcachesize
1072 options[b'chunkcachesize'] = chunkcachesize
1073
1073
1074 deltabothparents = ui.configbool(
1074 deltabothparents = ui.configbool(
1075 b'storage', b'revlog.optimize-delta-parent-choice'
1075 b'storage', b'revlog.optimize-delta-parent-choice'
1076 )
1076 )
1077 options[b'deltabothparents'] = deltabothparents
1077 options[b'deltabothparents'] = deltabothparents
1078 options[b'debug-delta'] = ui.configbool(b'debug', b'revlog.debug-delta')
1078 options[b'debug-delta'] = ui.configbool(b'debug', b'revlog.debug-delta')
1079
1079
1080 issue6528 = ui.configbool(b'storage', b'revlog.issue6528.fix-incoming')
1080 issue6528 = ui.configbool(b'storage', b'revlog.issue6528.fix-incoming')
1081 options[b'issue6528.fix-incoming'] = issue6528
1081 options[b'issue6528.fix-incoming'] = issue6528
1082
1082
1083 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
1083 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
1084 lazydeltabase = False
1084 lazydeltabase = False
1085 if lazydelta:
1085 if lazydelta:
1086 lazydeltabase = ui.configbool(
1086 lazydeltabase = ui.configbool(
1087 b'storage', b'revlog.reuse-external-delta-parent'
1087 b'storage', b'revlog.reuse-external-delta-parent'
1088 )
1088 )
1089 if lazydeltabase is None:
1089 if lazydeltabase is None:
1090 lazydeltabase = not scmutil.gddeltaconfig(ui)
1090 lazydeltabase = not scmutil.gddeltaconfig(ui)
1091 options[b'lazydelta'] = lazydelta
1091 options[b'lazydelta'] = lazydelta
1092 options[b'lazydeltabase'] = lazydeltabase
1092 options[b'lazydeltabase'] = lazydeltabase
1093
1093
1094 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
1094 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
1095 if 0 <= chainspan:
1095 if 0 <= chainspan:
1096 options[b'maxdeltachainspan'] = chainspan
1096 options[b'maxdeltachainspan'] = chainspan
1097
1097
1098 mmapindexthreshold = ui.configbytes(b'experimental', b'mmapindexthreshold')
1098 mmapindexthreshold = ui.configbytes(b'experimental', b'mmapindexthreshold')
1099 if mmapindexthreshold is not None:
1099 if mmapindexthreshold is not None:
1100 options[b'mmapindexthreshold'] = mmapindexthreshold
1100 options[b'mmapindexthreshold'] = mmapindexthreshold
1101
1101
1102 withsparseread = ui.configbool(b'experimental', b'sparse-read')
1102 withsparseread = ui.configbool(b'experimental', b'sparse-read')
1103 srdensitythres = float(
1103 srdensitythres = float(
1104 ui.config(b'experimental', b'sparse-read.density-threshold')
1104 ui.config(b'experimental', b'sparse-read.density-threshold')
1105 )
1105 )
1106 srmingapsize = ui.configbytes(b'experimental', b'sparse-read.min-gap-size')
1106 srmingapsize = ui.configbytes(b'experimental', b'sparse-read.min-gap-size')
1107 options[b'with-sparse-read'] = withsparseread
1107 options[b'with-sparse-read'] = withsparseread
1108 options[b'sparse-read-density-threshold'] = srdensitythres
1108 options[b'sparse-read-density-threshold'] = srdensitythres
1109 options[b'sparse-read-min-gap-size'] = srmingapsize
1109 options[b'sparse-read-min-gap-size'] = srmingapsize
1110
1110
1111 sparserevlog = requirementsmod.SPARSEREVLOG_REQUIREMENT in requirements
1111 sparserevlog = requirementsmod.SPARSEREVLOG_REQUIREMENT in requirements
1112 options[b'sparse-revlog'] = sparserevlog
1112 options[b'sparse-revlog'] = sparserevlog
1113 if sparserevlog:
1113 if sparserevlog:
1114 options[b'generaldelta'] = True
1114 options[b'generaldelta'] = True
1115
1115
1116 maxchainlen = None
1116 maxchainlen = None
1117 if sparserevlog:
1117 if sparserevlog:
1118 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
1118 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
1119 # experimental config: format.maxchainlen
1119 # experimental config: format.maxchainlen
1120 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
1120 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
1121 if maxchainlen is not None:
1121 if maxchainlen is not None:
1122 options[b'maxchainlen'] = maxchainlen
1122 options[b'maxchainlen'] = maxchainlen
1123
1123
1124 for r in requirements:
1124 for r in requirements:
1125 # we allow multiple compression engine requirement to co-exist because
1125 # we allow multiple compression engine requirement to co-exist because
1126 # strickly speaking, revlog seems to support mixed compression style.
1126 # strickly speaking, revlog seems to support mixed compression style.
1127 #
1127 #
1128 # The compression used for new entries will be "the last one"
1128 # The compression used for new entries will be "the last one"
1129 prefix = r.startswith
1129 prefix = r.startswith
1130 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
1130 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
1131 options[b'compengine'] = r.split(b'-', 2)[2]
1131 options[b'compengine'] = r.split(b'-', 2)[2]
1132
1132
1133 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
1133 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
1134 if options[b'zlib.level'] is not None:
1134 if options[b'zlib.level'] is not None:
1135 if not (0 <= options[b'zlib.level'] <= 9):
1135 if not (0 <= options[b'zlib.level'] <= 9):
1136 msg = _(b'invalid value for `storage.revlog.zlib.level` config: %d')
1136 msg = _(b'invalid value for `storage.revlog.zlib.level` config: %d')
1137 raise error.Abort(msg % options[b'zlib.level'])
1137 raise error.Abort(msg % options[b'zlib.level'])
1138 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
1138 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
1139 if options[b'zstd.level'] is not None:
1139 if options[b'zstd.level'] is not None:
1140 if not (0 <= options[b'zstd.level'] <= 22):
1140 if not (0 <= options[b'zstd.level'] <= 22):
1141 msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
1141 msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
1142 raise error.Abort(msg % options[b'zstd.level'])
1142 raise error.Abort(msg % options[b'zstd.level'])
1143
1143
1144 if requirementsmod.NARROW_REQUIREMENT in requirements:
1144 if requirementsmod.NARROW_REQUIREMENT in requirements:
1145 options[b'enableellipsis'] = True
1145 options[b'enableellipsis'] = True
1146
1146
1147 if ui.configbool(b'experimental', b'rust.index'):
1147 if ui.configbool(b'experimental', b'rust.index'):
1148 options[b'rust.index'] = True
1148 options[b'rust.index'] = True
1149 if requirementsmod.NODEMAP_REQUIREMENT in requirements:
1149 if requirementsmod.NODEMAP_REQUIREMENT in requirements:
1150 slow_path = ui.config(
1150 slow_path = ui.config(
1151 b'storage', b'revlog.persistent-nodemap.slow-path'
1151 b'storage', b'revlog.persistent-nodemap.slow-path'
1152 )
1152 )
1153 if slow_path not in (b'allow', b'warn', b'abort'):
1153 if slow_path not in (b'allow', b'warn', b'abort'):
1154 default = ui.config_default(
1154 default = ui.config_default(
1155 b'storage', b'revlog.persistent-nodemap.slow-path'
1155 b'storage', b'revlog.persistent-nodemap.slow-path'
1156 )
1156 )
1157 msg = _(
1157 msg = _(
1158 b'unknown value for config '
1158 b'unknown value for config '
1159 b'"storage.revlog.persistent-nodemap.slow-path": "%s"\n'
1159 b'"storage.revlog.persistent-nodemap.slow-path": "%s"\n'
1160 )
1160 )
1161 ui.warn(msg % slow_path)
1161 ui.warn(msg % slow_path)
1162 if not ui.quiet:
1162 if not ui.quiet:
1163 ui.warn(_(b'falling back to default value: %s\n') % default)
1163 ui.warn(_(b'falling back to default value: %s\n') % default)
1164 slow_path = default
1164 slow_path = default
1165
1165
1166 msg = _(
1166 msg = _(
1167 b"accessing `persistent-nodemap` repository without associated "
1167 b"accessing `persistent-nodemap` repository without associated "
1168 b"fast implementation."
1168 b"fast implementation."
1169 )
1169 )
1170 hint = _(
1170 hint = _(
1171 b"check `hg help config.format.use-persistent-nodemap` "
1171 b"check `hg help config.format.use-persistent-nodemap` "
1172 b"for details"
1172 b"for details"
1173 )
1173 )
1174 if not revlog.HAS_FAST_PERSISTENT_NODEMAP:
1174 if not revlog.HAS_FAST_PERSISTENT_NODEMAP:
1175 if slow_path == b'warn':
1175 if slow_path == b'warn':
1176 msg = b"warning: " + msg + b'\n'
1176 msg = b"warning: " + msg + b'\n'
1177 ui.warn(msg)
1177 ui.warn(msg)
1178 if not ui.quiet:
1178 if not ui.quiet:
1179 hint = b'(' + hint + b')\n'
1179 hint = b'(' + hint + b')\n'
1180 ui.warn(hint)
1180 ui.warn(hint)
1181 if slow_path == b'abort':
1181 if slow_path == b'abort':
1182 raise error.Abort(msg, hint=hint)
1182 raise error.Abort(msg, hint=hint)
1183 options[b'persistent-nodemap'] = True
1183 options[b'persistent-nodemap'] = True
1184 if requirementsmod.DIRSTATE_V2_REQUIREMENT in requirements:
1184 if requirementsmod.DIRSTATE_V2_REQUIREMENT in requirements:
1185 slow_path = ui.config(b'storage', b'dirstate-v2.slow-path')
1185 slow_path = ui.config(b'storage', b'dirstate-v2.slow-path')
1186 if slow_path not in (b'allow', b'warn', b'abort'):
1186 if slow_path not in (b'allow', b'warn', b'abort'):
1187 default = ui.config_default(b'storage', b'dirstate-v2.slow-path')
1187 default = ui.config_default(b'storage', b'dirstate-v2.slow-path')
1188 msg = _(b'unknown value for config "dirstate-v2.slow-path": "%s"\n')
1188 msg = _(b'unknown value for config "dirstate-v2.slow-path": "%s"\n')
1189 ui.warn(msg % slow_path)
1189 ui.warn(msg % slow_path)
1190 if not ui.quiet:
1190 if not ui.quiet:
1191 ui.warn(_(b'falling back to default value: %s\n') % default)
1191 ui.warn(_(b'falling back to default value: %s\n') % default)
1192 slow_path = default
1192 slow_path = default
1193
1193
1194 msg = _(
1194 msg = _(
1195 b"accessing `dirstate-v2` repository without associated "
1195 b"accessing `dirstate-v2` repository without associated "
1196 b"fast implementation."
1196 b"fast implementation."
1197 )
1197 )
1198 hint = _(
1198 hint = _(
1199 b"check `hg help config.format.use-dirstate-v2` " b"for details"
1199 b"check `hg help config.format.use-dirstate-v2` " b"for details"
1200 )
1200 )
1201 if not dirstate.HAS_FAST_DIRSTATE_V2:
1201 if not dirstate.HAS_FAST_DIRSTATE_V2:
1202 if slow_path == b'warn':
1202 if slow_path == b'warn':
1203 msg = b"warning: " + msg + b'\n'
1203 msg = b"warning: " + msg + b'\n'
1204 ui.warn(msg)
1204 ui.warn(msg)
1205 if not ui.quiet:
1205 if not ui.quiet:
1206 hint = b'(' + hint + b')\n'
1206 hint = b'(' + hint + b')\n'
1207 ui.warn(hint)
1207 ui.warn(hint)
1208 if slow_path == b'abort':
1208 if slow_path == b'abort':
1209 raise error.Abort(msg, hint=hint)
1209 raise error.Abort(msg, hint=hint)
1210 if ui.configbool(b'storage', b'revlog.persistent-nodemap.mmap'):
1210 if ui.configbool(b'storage', b'revlog.persistent-nodemap.mmap'):
1211 options[b'persistent-nodemap.mmap'] = True
1211 options[b'persistent-nodemap.mmap'] = True
1212 if ui.configbool(b'devel', b'persistent-nodemap'):
1212 if ui.configbool(b'devel', b'persistent-nodemap'):
1213 options[b'devel-force-nodemap'] = True
1213 options[b'devel-force-nodemap'] = True
1214
1214
1215 return options
1215 return options
1216
1216
1217
1217
1218 def makemain(**kwargs):
1218 def makemain(**kwargs):
1219 """Produce a type conforming to ``ilocalrepositorymain``."""
1219 """Produce a type conforming to ``ilocalrepositorymain``."""
1220 return localrepository
1220 return localrepository
1221
1221
1222
1222
1223 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1223 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1224 class revlogfilestorage:
1224 class revlogfilestorage:
1225 """File storage when using revlogs."""
1225 """File storage when using revlogs."""
1226
1226
1227 def file(self, path):
1227 def file(self, path):
1228 if path.startswith(b'/'):
1228 if path.startswith(b'/'):
1229 path = path[1:]
1229 path = path[1:]
1230
1230
1231 return filelog.filelog(self.svfs, path)
1231 return filelog.filelog(self.svfs, path)
1232
1232
1233
1233
1234 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1234 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1235 class revlognarrowfilestorage:
1235 class revlognarrowfilestorage:
1236 """File storage when using revlogs and narrow files."""
1236 """File storage when using revlogs and narrow files."""
1237
1237
1238 def file(self, path):
1238 def file(self, path):
1239 if path.startswith(b'/'):
1239 if path.startswith(b'/'):
1240 path = path[1:]
1240 path = path[1:]
1241
1241
1242 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
1242 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
1243
1243
1244
1244
1245 def makefilestorage(requirements, features, **kwargs):
1245 def makefilestorage(requirements, features, **kwargs):
1246 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
1246 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
1247 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
1247 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
1248 features.add(repository.REPO_FEATURE_STREAM_CLONE)
1248 features.add(repository.REPO_FEATURE_STREAM_CLONE)
1249
1249
1250 if requirementsmod.NARROW_REQUIREMENT in requirements:
1250 if requirementsmod.NARROW_REQUIREMENT in requirements:
1251 return revlognarrowfilestorage
1251 return revlognarrowfilestorage
1252 else:
1252 else:
1253 return revlogfilestorage
1253 return revlogfilestorage
1254
1254
1255
1255
1256 # List of repository interfaces and factory functions for them. Each
1256 # List of repository interfaces and factory functions for them. Each
1257 # will be called in order during ``makelocalrepository()`` to iteratively
1257 # will be called in order during ``makelocalrepository()`` to iteratively
1258 # derive the final type for a local repository instance. We capture the
1258 # derive the final type for a local repository instance. We capture the
1259 # function as a lambda so we don't hold a reference and the module-level
1259 # function as a lambda so we don't hold a reference and the module-level
1260 # functions can be wrapped.
1260 # functions can be wrapped.
1261 REPO_INTERFACES = [
1261 REPO_INTERFACES = [
1262 (repository.ilocalrepositorymain, lambda: makemain),
1262 (repository.ilocalrepositorymain, lambda: makemain),
1263 (repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
1263 (repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
1264 ]
1264 ]
1265
1265
1266
1266
1267 @interfaceutil.implementer(repository.ilocalrepositorymain)
1267 @interfaceutil.implementer(repository.ilocalrepositorymain)
1268 class localrepository:
1268 class localrepository:
1269 """Main class for representing local repositories.
1269 """Main class for representing local repositories.
1270
1270
1271 All local repositories are instances of this class.
1271 All local repositories are instances of this class.
1272
1272
1273 Constructed on its own, instances of this class are not usable as
1273 Constructed on its own, instances of this class are not usable as
1274 repository objects. To obtain a usable repository object, call
1274 repository objects. To obtain a usable repository object, call
1275 ``hg.repository()``, ``localrepo.instance()``, or
1275 ``hg.repository()``, ``localrepo.instance()``, or
1276 ``localrepo.makelocalrepository()``. The latter is the lowest-level.
1276 ``localrepo.makelocalrepository()``. The latter is the lowest-level.
1277 ``instance()`` adds support for creating new repositories.
1277 ``instance()`` adds support for creating new repositories.
1278 ``hg.repository()`` adds more extension integration, including calling
1278 ``hg.repository()`` adds more extension integration, including calling
1279 ``reposetup()``. Generally speaking, ``hg.repository()`` should be
1279 ``reposetup()``. Generally speaking, ``hg.repository()`` should be
1280 used.
1280 used.
1281 """
1281 """
1282
1282
1283 _basesupported = {
1283 _basesupported = {
1284 requirementsmod.ARCHIVED_PHASE_REQUIREMENT,
1284 requirementsmod.ARCHIVED_PHASE_REQUIREMENT,
1285 requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT,
1285 requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT,
1286 requirementsmod.CHANGELOGV2_REQUIREMENT,
1286 requirementsmod.CHANGELOGV2_REQUIREMENT,
1287 requirementsmod.COPIESSDC_REQUIREMENT,
1287 requirementsmod.COPIESSDC_REQUIREMENT,
1288 requirementsmod.DIRSTATE_TRACKED_HINT_V1,
1288 requirementsmod.DIRSTATE_TRACKED_HINT_V1,
1289 requirementsmod.DIRSTATE_V2_REQUIREMENT,
1289 requirementsmod.DIRSTATE_V2_REQUIREMENT,
1290 requirementsmod.DOTENCODE_REQUIREMENT,
1290 requirementsmod.DOTENCODE_REQUIREMENT,
1291 requirementsmod.FNCACHE_REQUIREMENT,
1291 requirementsmod.FNCACHE_REQUIREMENT,
1292 requirementsmod.GENERALDELTA_REQUIREMENT,
1292 requirementsmod.GENERALDELTA_REQUIREMENT,
1293 requirementsmod.INTERNAL_PHASE_REQUIREMENT,
1293 requirementsmod.INTERNAL_PHASE_REQUIREMENT,
1294 requirementsmod.NODEMAP_REQUIREMENT,
1294 requirementsmod.NODEMAP_REQUIREMENT,
1295 requirementsmod.RELATIVE_SHARED_REQUIREMENT,
1295 requirementsmod.RELATIVE_SHARED_REQUIREMENT,
1296 requirementsmod.REVLOGV1_REQUIREMENT,
1296 requirementsmod.REVLOGV1_REQUIREMENT,
1297 requirementsmod.REVLOGV2_REQUIREMENT,
1297 requirementsmod.REVLOGV2_REQUIREMENT,
1298 requirementsmod.SHARED_REQUIREMENT,
1298 requirementsmod.SHARED_REQUIREMENT,
1299 requirementsmod.SHARESAFE_REQUIREMENT,
1299 requirementsmod.SHARESAFE_REQUIREMENT,
1300 requirementsmod.SPARSE_REQUIREMENT,
1300 requirementsmod.SPARSE_REQUIREMENT,
1301 requirementsmod.SPARSEREVLOG_REQUIREMENT,
1301 requirementsmod.SPARSEREVLOG_REQUIREMENT,
1302 requirementsmod.STORE_REQUIREMENT,
1302 requirementsmod.STORE_REQUIREMENT,
1303 requirementsmod.TREEMANIFEST_REQUIREMENT,
1303 requirementsmod.TREEMANIFEST_REQUIREMENT,
1304 }
1304 }
1305
1305
1306 # list of prefix for file which can be written without 'wlock'
1306 # list of prefix for file which can be written without 'wlock'
1307 # Extensions should extend this list when needed
1307 # Extensions should extend this list when needed
1308 _wlockfreeprefix = {
1308 _wlockfreeprefix = {
1309 # We migh consider requiring 'wlock' for the next
1309 # We migh consider requiring 'wlock' for the next
1310 # two, but pretty much all the existing code assume
1310 # two, but pretty much all the existing code assume
1311 # wlock is not needed so we keep them excluded for
1311 # wlock is not needed so we keep them excluded for
1312 # now.
1312 # now.
1313 b'hgrc',
1313 b'hgrc',
1314 b'requires',
1314 b'requires',
1315 # XXX cache is a complicatged business someone
1315 # XXX cache is a complicatged business someone
1316 # should investigate this in depth at some point
1316 # should investigate this in depth at some point
1317 b'cache/',
1317 b'cache/',
1318 # XXX shouldn't be dirstate covered by the wlock?
1318 # XXX shouldn't be dirstate covered by the wlock?
1319 b'dirstate',
1319 b'dirstate',
1320 # XXX bisect was still a bit too messy at the time
1320 # XXX bisect was still a bit too messy at the time
1321 # this changeset was introduced. Someone should fix
1321 # this changeset was introduced. Someone should fix
1322 # the remainig bit and drop this line
1322 # the remainig bit and drop this line
1323 b'bisect.state',
1323 b'bisect.state',
1324 }
1324 }
1325
1325
1326 def __init__(
1326 def __init__(
1327 self,
1327 self,
1328 baseui,
1328 baseui,
1329 ui,
1329 ui,
1330 origroot,
1330 origroot,
1331 wdirvfs,
1331 wdirvfs,
1332 hgvfs,
1332 hgvfs,
1333 requirements,
1333 requirements,
1334 supportedrequirements,
1334 supportedrequirements,
1335 sharedpath,
1335 sharedpath,
1336 store,
1336 store,
1337 cachevfs,
1337 cachevfs,
1338 wcachevfs,
1338 wcachevfs,
1339 features,
1339 features,
1340 intents=None,
1340 intents=None,
1341 ):
1341 ):
1342 """Create a new local repository instance.
1342 """Create a new local repository instance.
1343
1343
1344 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
1344 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
1345 or ``localrepo.makelocalrepository()`` for obtaining a new repository
1345 or ``localrepo.makelocalrepository()`` for obtaining a new repository
1346 object.
1346 object.
1347
1347
1348 Arguments:
1348 Arguments:
1349
1349
1350 baseui
1350 baseui
1351 ``ui.ui`` instance that ``ui`` argument was based off of.
1351 ``ui.ui`` instance that ``ui`` argument was based off of.
1352
1352
1353 ui
1353 ui
1354 ``ui.ui`` instance for use by the repository.
1354 ``ui.ui`` instance for use by the repository.
1355
1355
1356 origroot
1356 origroot
1357 ``bytes`` path to working directory root of this repository.
1357 ``bytes`` path to working directory root of this repository.
1358
1358
1359 wdirvfs
1359 wdirvfs
1360 ``vfs.vfs`` rooted at the working directory.
1360 ``vfs.vfs`` rooted at the working directory.
1361
1361
1362 hgvfs
1362 hgvfs
1363 ``vfs.vfs`` rooted at .hg/
1363 ``vfs.vfs`` rooted at .hg/
1364
1364
1365 requirements
1365 requirements
1366 ``set`` of bytestrings representing repository opening requirements.
1366 ``set`` of bytestrings representing repository opening requirements.
1367
1367
1368 supportedrequirements
1368 supportedrequirements
1369 ``set`` of bytestrings representing repository requirements that we
1369 ``set`` of bytestrings representing repository requirements that we
1370 know how to open. May be a supetset of ``requirements``.
1370 know how to open. May be a supetset of ``requirements``.
1371
1371
1372 sharedpath
1372 sharedpath
1373 ``bytes`` Defining path to storage base directory. Points to a
1373 ``bytes`` Defining path to storage base directory. Points to a
1374 ``.hg/`` directory somewhere.
1374 ``.hg/`` directory somewhere.
1375
1375
1376 store
1376 store
1377 ``store.basicstore`` (or derived) instance providing access to
1377 ``store.basicstore`` (or derived) instance providing access to
1378 versioned storage.
1378 versioned storage.
1379
1379
1380 cachevfs
1380 cachevfs
1381 ``vfs.vfs`` used for cache files.
1381 ``vfs.vfs`` used for cache files.
1382
1382
1383 wcachevfs
1383 wcachevfs
1384 ``vfs.vfs`` used for cache files related to the working copy.
1384 ``vfs.vfs`` used for cache files related to the working copy.
1385
1385
1386 features
1386 features
1387 ``set`` of bytestrings defining features/capabilities of this
1387 ``set`` of bytestrings defining features/capabilities of this
1388 instance.
1388 instance.
1389
1389
1390 intents
1390 intents
1391 ``set`` of system strings indicating what this repo will be used
1391 ``set`` of system strings indicating what this repo will be used
1392 for.
1392 for.
1393 """
1393 """
1394 self.baseui = baseui
1394 self.baseui = baseui
1395 self.ui = ui
1395 self.ui = ui
1396 self.origroot = origroot
1396 self.origroot = origroot
1397 # vfs rooted at working directory.
1397 # vfs rooted at working directory.
1398 self.wvfs = wdirvfs
1398 self.wvfs = wdirvfs
1399 self.root = wdirvfs.base
1399 self.root = wdirvfs.base
1400 # vfs rooted at .hg/. Used to access most non-store paths.
1400 # vfs rooted at .hg/. Used to access most non-store paths.
1401 self.vfs = hgvfs
1401 self.vfs = hgvfs
1402 self.path = hgvfs.base
1402 self.path = hgvfs.base
1403 self.requirements = requirements
1403 self.requirements = requirements
1404 self.nodeconstants = sha1nodeconstants
1404 self.nodeconstants = sha1nodeconstants
1405 self.nullid = self.nodeconstants.nullid
1405 self.nullid = self.nodeconstants.nullid
1406 self.supported = supportedrequirements
1406 self.supported = supportedrequirements
1407 self.sharedpath = sharedpath
1407 self.sharedpath = sharedpath
1408 self.store = store
1408 self.store = store
1409 self.cachevfs = cachevfs
1409 self.cachevfs = cachevfs
1410 self.wcachevfs = wcachevfs
1410 self.wcachevfs = wcachevfs
1411 self.features = features
1411 self.features = features
1412
1412
1413 self.filtername = None
1413 self.filtername = None
1414
1414
1415 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1415 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1416 b'devel', b'check-locks'
1416 b'devel', b'check-locks'
1417 ):
1417 ):
1418 self.vfs.audit = self._getvfsward(self.vfs.audit)
1418 self.vfs.audit = self._getvfsward(self.vfs.audit)
1419 # A list of callback to shape the phase if no data were found.
1419 # A list of callback to shape the phase if no data were found.
1420 # Callback are in the form: func(repo, roots) --> processed root.
1420 # Callback are in the form: func(repo, roots) --> processed root.
1421 # This list it to be filled by extension during repo setup
1421 # This list it to be filled by extension during repo setup
1422 self._phasedefaults = []
1422 self._phasedefaults = []
1423
1423
1424 color.setup(self.ui)
1424 color.setup(self.ui)
1425
1425
1426 self.spath = self.store.path
1426 self.spath = self.store.path
1427 self.svfs = self.store.vfs
1427 self.svfs = self.store.vfs
1428 self.sjoin = self.store.join
1428 self.sjoin = self.store.join
1429 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1429 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1430 b'devel', b'check-locks'
1430 b'devel', b'check-locks'
1431 ):
1431 ):
1432 if util.safehasattr(self.svfs, b'vfs'): # this is filtervfs
1432 if util.safehasattr(self.svfs, b'vfs'): # this is filtervfs
1433 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
1433 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
1434 else: # standard vfs
1434 else: # standard vfs
1435 self.svfs.audit = self._getsvfsward(self.svfs.audit)
1435 self.svfs.audit = self._getsvfsward(self.svfs.audit)
1436
1436
1437 self._dirstatevalidatewarned = False
1437 self._dirstatevalidatewarned = False
1438
1438
1439 self._branchcaches = branchmap.BranchMapCache()
1439 self._branchcaches = branchmap.BranchMapCache()
1440 self._revbranchcache = None
1440 self._revbranchcache = None
1441 self._filterpats = {}
1441 self._filterpats = {}
1442 self._datafilters = {}
1442 self._datafilters = {}
1443 self._transref = self._lockref = self._wlockref = None
1443 self._transref = self._lockref = self._wlockref = None
1444
1444
1445 # A cache for various files under .hg/ that tracks file changes,
1445 # A cache for various files under .hg/ that tracks file changes,
1446 # (used by the filecache decorator)
1446 # (used by the filecache decorator)
1447 #
1447 #
1448 # Maps a property name to its util.filecacheentry
1448 # Maps a property name to its util.filecacheentry
1449 self._filecache = {}
1449 self._filecache = {}
1450
1450
1451 # hold sets of revision to be filtered
1451 # hold sets of revision to be filtered
1452 # should be cleared when something might have changed the filter value:
1452 # should be cleared when something might have changed the filter value:
1453 # - new changesets,
1453 # - new changesets,
1454 # - phase change,
1454 # - phase change,
1455 # - new obsolescence marker,
1455 # - new obsolescence marker,
1456 # - working directory parent change,
1456 # - working directory parent change,
1457 # - bookmark changes
1457 # - bookmark changes
1458 self.filteredrevcache = {}
1458 self.filteredrevcache = {}
1459
1459
1460 # post-dirstate-status hooks
1460 # post-dirstate-status hooks
1461 self._postdsstatus = []
1461 self._postdsstatus = []
1462
1462
1463 # generic mapping between names and nodes
1463 # generic mapping between names and nodes
1464 self.names = namespaces.namespaces()
1464 self.names = namespaces.namespaces()
1465
1465
1466 # Key to signature value.
1466 # Key to signature value.
1467 self._sparsesignaturecache = {}
1467 self._sparsesignaturecache = {}
1468 # Signature to cached matcher instance.
1468 # Signature to cached matcher instance.
1469 self._sparsematchercache = {}
1469 self._sparsematchercache = {}
1470
1470
1471 self._extrafilterid = repoview.extrafilter(ui)
1471 self._extrafilterid = repoview.extrafilter(ui)
1472
1472
1473 self.filecopiesmode = None
1473 self.filecopiesmode = None
1474 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
1474 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
1475 self.filecopiesmode = b'changeset-sidedata'
1475 self.filecopiesmode = b'changeset-sidedata'
1476
1476
1477 self._wanted_sidedata = set()
1477 self._wanted_sidedata = set()
1478 self._sidedata_computers = {}
1478 self._sidedata_computers = {}
1479 sidedatamod.set_sidedata_spec_for_repo(self)
1479 sidedatamod.set_sidedata_spec_for_repo(self)
1480
1480
1481 def _getvfsward(self, origfunc):
1481 def _getvfsward(self, origfunc):
1482 """build a ward for self.vfs"""
1482 """build a ward for self.vfs"""
1483 rref = weakref.ref(self)
1483 rref = weakref.ref(self)
1484
1484
1485 def checkvfs(path, mode=None):
1485 def checkvfs(path, mode=None):
1486 ret = origfunc(path, mode=mode)
1486 ret = origfunc(path, mode=mode)
1487 repo = rref()
1487 repo = rref()
1488 if (
1488 if (
1489 repo is None
1489 repo is None
1490 or not util.safehasattr(repo, b'_wlockref')
1490 or not util.safehasattr(repo, b'_wlockref')
1491 or not util.safehasattr(repo, b'_lockref')
1491 or not util.safehasattr(repo, b'_lockref')
1492 ):
1492 ):
1493 return
1493 return
1494 if mode in (None, b'r', b'rb'):
1494 if mode in (None, b'r', b'rb'):
1495 return
1495 return
1496 if path.startswith(repo.path):
1496 if path.startswith(repo.path):
1497 # truncate name relative to the repository (.hg)
1497 # truncate name relative to the repository (.hg)
1498 path = path[len(repo.path) + 1 :]
1498 path = path[len(repo.path) + 1 :]
1499 if path.startswith(b'cache/'):
1499 if path.startswith(b'cache/'):
1500 msg = b'accessing cache with vfs instead of cachevfs: "%s"'
1500 msg = b'accessing cache with vfs instead of cachevfs: "%s"'
1501 repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs")
1501 repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs")
1502 # path prefixes covered by 'lock'
1502 # path prefixes covered by 'lock'
1503 vfs_path_prefixes = (
1503 vfs_path_prefixes = (
1504 b'journal.',
1504 b'journal.',
1505 b'undo.',
1505 b'undo.',
1506 b'strip-backup/',
1506 b'strip-backup/',
1507 b'cache/',
1507 b'cache/',
1508 )
1508 )
1509 if any(path.startswith(prefix) for prefix in vfs_path_prefixes):
1509 if any(path.startswith(prefix) for prefix in vfs_path_prefixes):
1510 if repo._currentlock(repo._lockref) is None:
1510 if repo._currentlock(repo._lockref) is None:
1511 repo.ui.develwarn(
1511 repo.ui.develwarn(
1512 b'write with no lock: "%s"' % path,
1512 b'write with no lock: "%s"' % path,
1513 stacklevel=3,
1513 stacklevel=3,
1514 config=b'check-locks',
1514 config=b'check-locks',
1515 )
1515 )
1516 elif repo._currentlock(repo._wlockref) is None:
1516 elif repo._currentlock(repo._wlockref) is None:
1517 # rest of vfs files are covered by 'wlock'
1517 # rest of vfs files are covered by 'wlock'
1518 #
1518 #
1519 # exclude special files
1519 # exclude special files
1520 for prefix in self._wlockfreeprefix:
1520 for prefix in self._wlockfreeprefix:
1521 if path.startswith(prefix):
1521 if path.startswith(prefix):
1522 return
1522 return
1523 repo.ui.develwarn(
1523 repo.ui.develwarn(
1524 b'write with no wlock: "%s"' % path,
1524 b'write with no wlock: "%s"' % path,
1525 stacklevel=3,
1525 stacklevel=3,
1526 config=b'check-locks',
1526 config=b'check-locks',
1527 )
1527 )
1528 return ret
1528 return ret
1529
1529
1530 return checkvfs
1530 return checkvfs
1531
1531
1532 def _getsvfsward(self, origfunc):
1532 def _getsvfsward(self, origfunc):
1533 """build a ward for self.svfs"""
1533 """build a ward for self.svfs"""
1534 rref = weakref.ref(self)
1534 rref = weakref.ref(self)
1535
1535
1536 def checksvfs(path, mode=None):
1536 def checksvfs(path, mode=None):
1537 ret = origfunc(path, mode=mode)
1537 ret = origfunc(path, mode=mode)
1538 repo = rref()
1538 repo = rref()
1539 if repo is None or not util.safehasattr(repo, b'_lockref'):
1539 if repo is None or not util.safehasattr(repo, b'_lockref'):
1540 return
1540 return
1541 if mode in (None, b'r', b'rb'):
1541 if mode in (None, b'r', b'rb'):
1542 return
1542 return
1543 if path.startswith(repo.sharedpath):
1543 if path.startswith(repo.sharedpath):
1544 # truncate name relative to the repository (.hg)
1544 # truncate name relative to the repository (.hg)
1545 path = path[len(repo.sharedpath) + 1 :]
1545 path = path[len(repo.sharedpath) + 1 :]
1546 if repo._currentlock(repo._lockref) is None:
1546 if repo._currentlock(repo._lockref) is None:
1547 repo.ui.develwarn(
1547 repo.ui.develwarn(
1548 b'write with no lock: "%s"' % path, stacklevel=4
1548 b'write with no lock: "%s"' % path, stacklevel=4
1549 )
1549 )
1550 return ret
1550 return ret
1551
1551
1552 return checksvfs
1552 return checksvfs
1553
1553
1554 def close(self):
1554 def close(self):
1555 self._writecaches()
1555 self._writecaches()
1556
1556
1557 def _writecaches(self):
1557 def _writecaches(self):
1558 if self._revbranchcache:
1558 if self._revbranchcache:
1559 self._revbranchcache.write()
1559 self._revbranchcache.write()
1560
1560
1561 def _restrictcapabilities(self, caps):
1561 def _restrictcapabilities(self, caps):
1562 if self.ui.configbool(b'experimental', b'bundle2-advertise'):
1562 if self.ui.configbool(b'experimental', b'bundle2-advertise'):
1563 caps = set(caps)
1563 caps = set(caps)
1564 capsblob = bundle2.encodecaps(
1564 capsblob = bundle2.encodecaps(
1565 bundle2.getrepocaps(self, role=b'client')
1565 bundle2.getrepocaps(self, role=b'client')
1566 )
1566 )
1567 caps.add(b'bundle2=' + urlreq.quote(capsblob))
1567 caps.add(b'bundle2=' + urlreq.quote(capsblob))
1568 if self.ui.configbool(b'experimental', b'narrow'):
1568 if self.ui.configbool(b'experimental', b'narrow'):
1569 caps.add(wireprototypes.NARROWCAP)
1569 caps.add(wireprototypes.NARROWCAP)
1570 return caps
1570 return caps
1571
1571
1572 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
1572 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
1573 # self -> auditor -> self._checknested -> self
1573 # self -> auditor -> self._checknested -> self
1574
1574
1575 @property
1575 @property
1576 def auditor(self):
1576 def auditor(self):
1577 # This is only used by context.workingctx.match in order to
1577 # This is only used by context.workingctx.match in order to
1578 # detect files in subrepos.
1578 # detect files in subrepos.
1579 return pathutil.pathauditor(self.root, callback=self._checknested)
1579 return pathutil.pathauditor(self.root, callback=self._checknested)
1580
1580
1581 @property
1581 @property
1582 def nofsauditor(self):
1582 def nofsauditor(self):
1583 # This is only used by context.basectx.match in order to detect
1583 # This is only used by context.basectx.match in order to detect
1584 # files in subrepos.
1584 # files in subrepos.
1585 return pathutil.pathauditor(
1585 return pathutil.pathauditor(
1586 self.root, callback=self._checknested, realfs=False, cached=True
1586 self.root, callback=self._checknested, realfs=False, cached=True
1587 )
1587 )
1588
1588
1589 def _checknested(self, path):
1589 def _checknested(self, path):
1590 """Determine if path is a legal nested repository."""
1590 """Determine if path is a legal nested repository."""
1591 if not path.startswith(self.root):
1591 if not path.startswith(self.root):
1592 return False
1592 return False
1593 subpath = path[len(self.root) + 1 :]
1593 subpath = path[len(self.root) + 1 :]
1594 normsubpath = util.pconvert(subpath)
1594 normsubpath = util.pconvert(subpath)
1595
1595
1596 # XXX: Checking against the current working copy is wrong in
1596 # XXX: Checking against the current working copy is wrong in
1597 # the sense that it can reject things like
1597 # the sense that it can reject things like
1598 #
1598 #
1599 # $ hg cat -r 10 sub/x.txt
1599 # $ hg cat -r 10 sub/x.txt
1600 #
1600 #
1601 # if sub/ is no longer a subrepository in the working copy
1601 # if sub/ is no longer a subrepository in the working copy
1602 # parent revision.
1602 # parent revision.
1603 #
1603 #
1604 # However, it can of course also allow things that would have
1604 # However, it can of course also allow things that would have
1605 # been rejected before, such as the above cat command if sub/
1605 # been rejected before, such as the above cat command if sub/
1606 # is a subrepository now, but was a normal directory before.
1606 # is a subrepository now, but was a normal directory before.
1607 # The old path auditor would have rejected by mistake since it
1607 # The old path auditor would have rejected by mistake since it
1608 # panics when it sees sub/.hg/.
1608 # panics when it sees sub/.hg/.
1609 #
1609 #
1610 # All in all, checking against the working copy seems sensible
1610 # All in all, checking against the working copy seems sensible
1611 # since we want to prevent access to nested repositories on
1611 # since we want to prevent access to nested repositories on
1612 # the filesystem *now*.
1612 # the filesystem *now*.
1613 ctx = self[None]
1613 ctx = self[None]
1614 parts = util.splitpath(subpath)
1614 parts = util.splitpath(subpath)
1615 while parts:
1615 while parts:
1616 prefix = b'/'.join(parts)
1616 prefix = b'/'.join(parts)
1617 if prefix in ctx.substate:
1617 if prefix in ctx.substate:
1618 if prefix == normsubpath:
1618 if prefix == normsubpath:
1619 return True
1619 return True
1620 else:
1620 else:
1621 sub = ctx.sub(prefix)
1621 sub = ctx.sub(prefix)
1622 return sub.checknested(subpath[len(prefix) + 1 :])
1622 return sub.checknested(subpath[len(prefix) + 1 :])
1623 else:
1623 else:
1624 parts.pop()
1624 parts.pop()
1625 return False
1625 return False
1626
1626
1627 def peer(self):
1627 def peer(self):
1628 return localpeer(self) # not cached to avoid reference cycle
1628 return localpeer(self) # not cached to avoid reference cycle
1629
1629
1630 def unfiltered(self):
1630 def unfiltered(self):
1631 """Return unfiltered version of the repository
1631 """Return unfiltered version of the repository
1632
1632
1633 Intended to be overwritten by filtered repo."""
1633 Intended to be overwritten by filtered repo."""
1634 return self
1634 return self
1635
1635
1636 def filtered(self, name, visibilityexceptions=None):
1636 def filtered(self, name, visibilityexceptions=None):
1637 """Return a filtered version of a repository
1637 """Return a filtered version of a repository
1638
1638
1639 The `name` parameter is the identifier of the requested view. This
1639 The `name` parameter is the identifier of the requested view. This
1640 will return a repoview object set "exactly" to the specified view.
1640 will return a repoview object set "exactly" to the specified view.
1641
1641
1642 This function does not apply recursive filtering to a repository. For
1642 This function does not apply recursive filtering to a repository. For
1643 example calling `repo.filtered("served")` will return a repoview using
1643 example calling `repo.filtered("served")` will return a repoview using
1644 the "served" view, regardless of the initial view used by `repo`.
1644 the "served" view, regardless of the initial view used by `repo`.
1645
1645
1646 In other word, there is always only one level of `repoview` "filtering".
1646 In other word, there is always only one level of `repoview` "filtering".
1647 """
1647 """
1648 if self._extrafilterid is not None and b'%' not in name:
1648 if self._extrafilterid is not None and b'%' not in name:
1649 name = name + b'%' + self._extrafilterid
1649 name = name + b'%' + self._extrafilterid
1650
1650
1651 cls = repoview.newtype(self.unfiltered().__class__)
1651 cls = repoview.newtype(self.unfiltered().__class__)
1652 return cls(self, name, visibilityexceptions)
1652 return cls(self, name, visibilityexceptions)
1653
1653
1654 @mixedrepostorecache(
1654 @mixedrepostorecache(
1655 (b'bookmarks', b'plain'),
1655 (b'bookmarks', b'plain'),
1656 (b'bookmarks.current', b'plain'),
1656 (b'bookmarks.current', b'plain'),
1657 (b'bookmarks', b''),
1657 (b'bookmarks', b''),
1658 (b'00changelog.i', b''),
1658 (b'00changelog.i', b''),
1659 )
1659 )
1660 def _bookmarks(self):
1660 def _bookmarks(self):
1661 # Since the multiple files involved in the transaction cannot be
1661 # Since the multiple files involved in the transaction cannot be
1662 # written atomically (with current repository format), there is a race
1662 # written atomically (with current repository format), there is a race
1663 # condition here.
1663 # condition here.
1664 #
1664 #
1665 # 1) changelog content A is read
1665 # 1) changelog content A is read
1666 # 2) outside transaction update changelog to content B
1666 # 2) outside transaction update changelog to content B
1667 # 3) outside transaction update bookmark file referring to content B
1667 # 3) outside transaction update bookmark file referring to content B
1668 # 4) bookmarks file content is read and filtered against changelog-A
1668 # 4) bookmarks file content is read and filtered against changelog-A
1669 #
1669 #
1670 # When this happens, bookmarks against nodes missing from A are dropped.
1670 # When this happens, bookmarks against nodes missing from A are dropped.
1671 #
1671 #
1672 # Having this happening during read is not great, but it become worse
1672 # Having this happening during read is not great, but it become worse
1673 # when this happen during write because the bookmarks to the "unknown"
1673 # when this happen during write because the bookmarks to the "unknown"
1674 # nodes will be dropped for good. However, writes happen within locks.
1674 # nodes will be dropped for good. However, writes happen within locks.
1675 # This locking makes it possible to have a race free consistent read.
1675 # This locking makes it possible to have a race free consistent read.
1676 # For this purpose data read from disc before locking are
1676 # For this purpose data read from disc before locking are
1677 # "invalidated" right after the locks are taken. This invalidations are
1677 # "invalidated" right after the locks are taken. This invalidations are
1678 # "light", the `filecache` mechanism keep the data in memory and will
1678 # "light", the `filecache` mechanism keep the data in memory and will
1679 # reuse them if the underlying files did not changed. Not parsing the
1679 # reuse them if the underlying files did not changed. Not parsing the
1680 # same data multiple times helps performances.
1680 # same data multiple times helps performances.
1681 #
1681 #
1682 # Unfortunately in the case describe above, the files tracked by the
1682 # Unfortunately in the case describe above, the files tracked by the
1683 # bookmarks file cache might not have changed, but the in-memory
1683 # bookmarks file cache might not have changed, but the in-memory
1684 # content is still "wrong" because we used an older changelog content
1684 # content is still "wrong" because we used an older changelog content
1685 # to process the on-disk data. So after locking, the changelog would be
1685 # to process the on-disk data. So after locking, the changelog would be
1686 # refreshed but `_bookmarks` would be preserved.
1686 # refreshed but `_bookmarks` would be preserved.
1687 # Adding `00changelog.i` to the list of tracked file is not
1687 # Adding `00changelog.i` to the list of tracked file is not
1688 # enough, because at the time we build the content for `_bookmarks` in
1688 # enough, because at the time we build the content for `_bookmarks` in
1689 # (4), the changelog file has already diverged from the content used
1689 # (4), the changelog file has already diverged from the content used
1690 # for loading `changelog` in (1)
1690 # for loading `changelog` in (1)
1691 #
1691 #
1692 # To prevent the issue, we force the changelog to be explicitly
1692 # To prevent the issue, we force the changelog to be explicitly
1693 # reloaded while computing `_bookmarks`. The data race can still happen
1693 # reloaded while computing `_bookmarks`. The data race can still happen
1694 # without the lock (with a narrower window), but it would no longer go
1694 # without the lock (with a narrower window), but it would no longer go
1695 # undetected during the lock time refresh.
1695 # undetected during the lock time refresh.
1696 #
1696 #
1697 # The new schedule is as follow
1697 # The new schedule is as follow
1698 #
1698 #
1699 # 1) filecache logic detect that `_bookmarks` needs to be computed
1699 # 1) filecache logic detect that `_bookmarks` needs to be computed
1700 # 2) cachestat for `bookmarks` and `changelog` are captured (for book)
1700 # 2) cachestat for `bookmarks` and `changelog` are captured (for book)
1701 # 3) We force `changelog` filecache to be tested
1701 # 3) We force `changelog` filecache to be tested
1702 # 4) cachestat for `changelog` are captured (for changelog)
1702 # 4) cachestat for `changelog` are captured (for changelog)
1703 # 5) `_bookmarks` is computed and cached
1703 # 5) `_bookmarks` is computed and cached
1704 #
1704 #
1705 # The step in (3) ensure we have a changelog at least as recent as the
1705 # The step in (3) ensure we have a changelog at least as recent as the
1706 # cache stat computed in (1). As a result at locking time:
1706 # cache stat computed in (1). As a result at locking time:
1707 # * if the changelog did not changed since (1) -> we can reuse the data
1707 # * if the changelog did not changed since (1) -> we can reuse the data
1708 # * otherwise -> the bookmarks get refreshed.
1708 # * otherwise -> the bookmarks get refreshed.
1709 self._refreshchangelog()
1709 self._refreshchangelog()
1710 return bookmarks.bmstore(self)
1710 return bookmarks.bmstore(self)
1711
1711
1712 def _refreshchangelog(self):
1712 def _refreshchangelog(self):
1713 """make sure the in memory changelog match the on-disk one"""
1713 """make sure the in memory changelog match the on-disk one"""
1714 if 'changelog' in vars(self) and self.currenttransaction() is None:
1714 if 'changelog' in vars(self) and self.currenttransaction() is None:
1715 del self.changelog
1715 del self.changelog
1716
1716
1717 @property
1717 @property
1718 def _activebookmark(self):
1718 def _activebookmark(self):
1719 return self._bookmarks.active
1719 return self._bookmarks.active
1720
1720
1721 # _phasesets depend on changelog. what we need is to call
1721 # _phasesets depend on changelog. what we need is to call
1722 # _phasecache.invalidate() if '00changelog.i' was changed, but it
1722 # _phasecache.invalidate() if '00changelog.i' was changed, but it
1723 # can't be easily expressed in filecache mechanism.
1723 # can't be easily expressed in filecache mechanism.
1724 @storecache(b'phaseroots', b'00changelog.i')
1724 @storecache(b'phaseroots', b'00changelog.i')
1725 def _phasecache(self):
1725 def _phasecache(self):
1726 return phases.phasecache(self, self._phasedefaults)
1726 return phases.phasecache(self, self._phasedefaults)
1727
1727
1728 @storecache(b'obsstore')
1728 @storecache(b'obsstore')
1729 def obsstore(self):
1729 def obsstore(self):
1730 return obsolete.makestore(self.ui, self)
1730 return obsolete.makestore(self.ui, self)
1731
1731
1732 @changelogcache()
1732 @changelogcache()
1733 def changelog(repo):
1733 def changelog(repo):
1734 # load dirstate before changelog to avoid race see issue6303
1734 # load dirstate before changelog to avoid race see issue6303
1735 repo.dirstate.prefetch_parents()
1735 repo.dirstate.prefetch_parents()
1736 return repo.store.changelog(
1736 return repo.store.changelog(
1737 txnutil.mayhavepending(repo.root),
1737 txnutil.mayhavepending(repo.root),
1738 concurrencychecker=revlogchecker.get_checker(repo.ui, b'changelog'),
1738 concurrencychecker=revlogchecker.get_checker(repo.ui, b'changelog'),
1739 )
1739 )
1740
1740
1741 @manifestlogcache()
1741 @manifestlogcache()
1742 def manifestlog(self):
1742 def manifestlog(self):
1743 return self.store.manifestlog(self, self._storenarrowmatch)
1743 return self.store.manifestlog(self, self._storenarrowmatch)
1744
1744
1745 @repofilecache(b'dirstate')
1745 @repofilecache(b'dirstate')
1746 def dirstate(self):
1746 def dirstate(self):
1747 return self._makedirstate()
1747 return self._makedirstate()
1748
1748
1749 def _makedirstate(self):
1749 def _makedirstate(self):
1750 """Extension point for wrapping the dirstate per-repo."""
1750 """Extension point for wrapping the dirstate per-repo."""
1751 sparsematchfn = None
1751 sparsematchfn = None
1752 if sparse.use_sparse(self):
1752 if sparse.use_sparse(self):
1753 sparsematchfn = lambda: sparse.matcher(self)
1753 sparsematchfn = lambda: sparse.matcher(self)
1754 v2_req = requirementsmod.DIRSTATE_V2_REQUIREMENT
1754 v2_req = requirementsmod.DIRSTATE_V2_REQUIREMENT
1755 th = requirementsmod.DIRSTATE_TRACKED_HINT_V1
1755 th = requirementsmod.DIRSTATE_TRACKED_HINT_V1
1756 use_dirstate_v2 = v2_req in self.requirements
1756 use_dirstate_v2 = v2_req in self.requirements
1757 use_tracked_hint = th in self.requirements
1757 use_tracked_hint = th in self.requirements
1758
1758
1759 return dirstate.dirstate(
1759 return dirstate.dirstate(
1760 self.vfs,
1760 self.vfs,
1761 self.ui,
1761 self.ui,
1762 self.root,
1762 self.root,
1763 self._dirstatevalidate,
1763 self._dirstatevalidate,
1764 sparsematchfn,
1764 sparsematchfn,
1765 self.nodeconstants,
1765 self.nodeconstants,
1766 use_dirstate_v2,
1766 use_dirstate_v2,
1767 use_tracked_hint=use_tracked_hint,
1767 use_tracked_hint=use_tracked_hint,
1768 )
1768 )
1769
1769
1770 def _dirstatevalidate(self, node):
1770 def _dirstatevalidate(self, node):
1771 try:
1771 try:
1772 self.changelog.rev(node)
1772 self.changelog.rev(node)
1773 return node
1773 return node
1774 except error.LookupError:
1774 except error.LookupError:
1775 if not self._dirstatevalidatewarned:
1775 if not self._dirstatevalidatewarned:
1776 self._dirstatevalidatewarned = True
1776 self._dirstatevalidatewarned = True
1777 self.ui.warn(
1777 self.ui.warn(
1778 _(b"warning: ignoring unknown working parent %s!\n")
1778 _(b"warning: ignoring unknown working parent %s!\n")
1779 % short(node)
1779 % short(node)
1780 )
1780 )
1781 return self.nullid
1781 return self.nullid
1782
1782
1783 @storecache(narrowspec.FILENAME)
1783 @storecache(narrowspec.FILENAME)
1784 def narrowpats(self):
1784 def narrowpats(self):
1785 """matcher patterns for this repository's narrowspec
1785 """matcher patterns for this repository's narrowspec
1786
1786
1787 A tuple of (includes, excludes).
1787 A tuple of (includes, excludes).
1788 """
1788 """
1789 return narrowspec.load(self)
1789 return narrowspec.load(self)
1790
1790
1791 @storecache(narrowspec.FILENAME)
1791 @storecache(narrowspec.FILENAME)
1792 def _storenarrowmatch(self):
1792 def _storenarrowmatch(self):
1793 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1793 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1794 return matchmod.always()
1794 return matchmod.always()
1795 include, exclude = self.narrowpats
1795 include, exclude = self.narrowpats
1796 return narrowspec.match(self.root, include=include, exclude=exclude)
1796 return narrowspec.match(self.root, include=include, exclude=exclude)
1797
1797
1798 @storecache(narrowspec.FILENAME)
1798 @storecache(narrowspec.FILENAME)
1799 def _narrowmatch(self):
1799 def _narrowmatch(self):
1800 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1800 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1801 return matchmod.always()
1801 return matchmod.always()
1802 narrowspec.checkworkingcopynarrowspec(self)
1802 narrowspec.checkworkingcopynarrowspec(self)
1803 include, exclude = self.narrowpats
1803 include, exclude = self.narrowpats
1804 return narrowspec.match(self.root, include=include, exclude=exclude)
1804 return narrowspec.match(self.root, include=include, exclude=exclude)
1805
1805
1806 def narrowmatch(self, match=None, includeexact=False):
1806 def narrowmatch(self, match=None, includeexact=False):
1807 """matcher corresponding the the repo's narrowspec
1807 """matcher corresponding the the repo's narrowspec
1808
1808
1809 If `match` is given, then that will be intersected with the narrow
1809 If `match` is given, then that will be intersected with the narrow
1810 matcher.
1810 matcher.
1811
1811
1812 If `includeexact` is True, then any exact matches from `match` will
1812 If `includeexact` is True, then any exact matches from `match` will
1813 be included even if they're outside the narrowspec.
1813 be included even if they're outside the narrowspec.
1814 """
1814 """
1815 if match:
1815 if match:
1816 if includeexact and not self._narrowmatch.always():
1816 if includeexact and not self._narrowmatch.always():
1817 # do not exclude explicitly-specified paths so that they can
1817 # do not exclude explicitly-specified paths so that they can
1818 # be warned later on
1818 # be warned later on
1819 em = matchmod.exact(match.files())
1819 em = matchmod.exact(match.files())
1820 nm = matchmod.unionmatcher([self._narrowmatch, em])
1820 nm = matchmod.unionmatcher([self._narrowmatch, em])
1821 return matchmod.intersectmatchers(match, nm)
1821 return matchmod.intersectmatchers(match, nm)
1822 return matchmod.intersectmatchers(match, self._narrowmatch)
1822 return matchmod.intersectmatchers(match, self._narrowmatch)
1823 return self._narrowmatch
1823 return self._narrowmatch
1824
1824
1825 def setnarrowpats(self, newincludes, newexcludes):
1825 def setnarrowpats(self, newincludes, newexcludes):
1826 narrowspec.save(self, newincludes, newexcludes)
1826 narrowspec.save(self, newincludes, newexcludes)
1827 self.invalidate(clearfilecache=True)
1827 self.invalidate(clearfilecache=True)
1828
1828
1829 @unfilteredpropertycache
1829 @unfilteredpropertycache
1830 def _quick_access_changeid_null(self):
1830 def _quick_access_changeid_null(self):
1831 return {
1831 return {
1832 b'null': (nullrev, self.nodeconstants.nullid),
1832 b'null': (nullrev, self.nodeconstants.nullid),
1833 nullrev: (nullrev, self.nodeconstants.nullid),
1833 nullrev: (nullrev, self.nodeconstants.nullid),
1834 self.nullid: (nullrev, self.nullid),
1834 self.nullid: (nullrev, self.nullid),
1835 }
1835 }
1836
1836
1837 @unfilteredpropertycache
1837 @unfilteredpropertycache
1838 def _quick_access_changeid_wc(self):
1838 def _quick_access_changeid_wc(self):
1839 # also fast path access to the working copy parents
1839 # also fast path access to the working copy parents
1840 # however, only do it for filter that ensure wc is visible.
1840 # however, only do it for filter that ensure wc is visible.
1841 quick = self._quick_access_changeid_null.copy()
1841 quick = self._quick_access_changeid_null.copy()
1842 cl = self.unfiltered().changelog
1842 cl = self.unfiltered().changelog
1843 for node in self.dirstate.parents():
1843 for node in self.dirstate.parents():
1844 if node == self.nullid:
1844 if node == self.nullid:
1845 continue
1845 continue
1846 rev = cl.index.get_rev(node)
1846 rev = cl.index.get_rev(node)
1847 if rev is None:
1847 if rev is None:
1848 # unknown working copy parent case:
1848 # unknown working copy parent case:
1849 #
1849 #
1850 # skip the fast path and let higher code deal with it
1850 # skip the fast path and let higher code deal with it
1851 continue
1851 continue
1852 pair = (rev, node)
1852 pair = (rev, node)
1853 quick[rev] = pair
1853 quick[rev] = pair
1854 quick[node] = pair
1854 quick[node] = pair
1855 # also add the parents of the parents
1855 # also add the parents of the parents
1856 for r in cl.parentrevs(rev):
1856 for r in cl.parentrevs(rev):
1857 if r == nullrev:
1857 if r == nullrev:
1858 continue
1858 continue
1859 n = cl.node(r)
1859 n = cl.node(r)
1860 pair = (r, n)
1860 pair = (r, n)
1861 quick[r] = pair
1861 quick[r] = pair
1862 quick[n] = pair
1862 quick[n] = pair
1863 p1node = self.dirstate.p1()
1863 p1node = self.dirstate.p1()
1864 if p1node != self.nullid:
1864 if p1node != self.nullid:
1865 quick[b'.'] = quick[p1node]
1865 quick[b'.'] = quick[p1node]
1866 return quick
1866 return quick
1867
1867
1868 @unfilteredmethod
1868 @unfilteredmethod
1869 def _quick_access_changeid_invalidate(self):
1869 def _quick_access_changeid_invalidate(self):
1870 if '_quick_access_changeid_wc' in vars(self):
1870 if '_quick_access_changeid_wc' in vars(self):
1871 del self.__dict__['_quick_access_changeid_wc']
1871 del self.__dict__['_quick_access_changeid_wc']
1872
1872
1873 @property
1873 @property
1874 def _quick_access_changeid(self):
1874 def _quick_access_changeid(self):
1875 """an helper dictionnary for __getitem__ calls
1875 """an helper dictionnary for __getitem__ calls
1876
1876
1877 This contains a list of symbol we can recognise right away without
1877 This contains a list of symbol we can recognise right away without
1878 further processing.
1878 further processing.
1879 """
1879 """
1880 if self.filtername in repoview.filter_has_wc:
1880 if self.filtername in repoview.filter_has_wc:
1881 return self._quick_access_changeid_wc
1881 return self._quick_access_changeid_wc
1882 return self._quick_access_changeid_null
1882 return self._quick_access_changeid_null
1883
1883
1884 def __getitem__(self, changeid):
1884 def __getitem__(self, changeid):
1885 # dealing with special cases
1885 # dealing with special cases
1886 if changeid is None:
1886 if changeid is None:
1887 return context.workingctx(self)
1887 return context.workingctx(self)
1888 if isinstance(changeid, context.basectx):
1888 if isinstance(changeid, context.basectx):
1889 return changeid
1889 return changeid
1890
1890
1891 # dealing with multiple revisions
1891 # dealing with multiple revisions
1892 if isinstance(changeid, slice):
1892 if isinstance(changeid, slice):
1893 # wdirrev isn't contiguous so the slice shouldn't include it
1893 # wdirrev isn't contiguous so the slice shouldn't include it
1894 return [
1894 return [
1895 self[i]
1895 self[i]
1896 for i in range(*changeid.indices(len(self)))
1896 for i in range(*changeid.indices(len(self)))
1897 if i not in self.changelog.filteredrevs
1897 if i not in self.changelog.filteredrevs
1898 ]
1898 ]
1899
1899
1900 # dealing with some special values
1900 # dealing with some special values
1901 quick_access = self._quick_access_changeid.get(changeid)
1901 quick_access = self._quick_access_changeid.get(changeid)
1902 if quick_access is not None:
1902 if quick_access is not None:
1903 rev, node = quick_access
1903 rev, node = quick_access
1904 return context.changectx(self, rev, node, maybe_filtered=False)
1904 return context.changectx(self, rev, node, maybe_filtered=False)
1905 if changeid == b'tip':
1905 if changeid == b'tip':
1906 node = self.changelog.tip()
1906 node = self.changelog.tip()
1907 rev = self.changelog.rev(node)
1907 rev = self.changelog.rev(node)
1908 return context.changectx(self, rev, node)
1908 return context.changectx(self, rev, node)
1909
1909
1910 # dealing with arbitrary values
1910 # dealing with arbitrary values
1911 try:
1911 try:
1912 if isinstance(changeid, int):
1912 if isinstance(changeid, int):
1913 node = self.changelog.node(changeid)
1913 node = self.changelog.node(changeid)
1914 rev = changeid
1914 rev = changeid
1915 elif changeid == b'.':
1915 elif changeid == b'.':
1916 # this is a hack to delay/avoid loading obsmarkers
1916 # this is a hack to delay/avoid loading obsmarkers
1917 # when we know that '.' won't be hidden
1917 # when we know that '.' won't be hidden
1918 node = self.dirstate.p1()
1918 node = self.dirstate.p1()
1919 rev = self.unfiltered().changelog.rev(node)
1919 rev = self.unfiltered().changelog.rev(node)
1920 elif len(changeid) == self.nodeconstants.nodelen:
1920 elif len(changeid) == self.nodeconstants.nodelen:
1921 try:
1921 try:
1922 node = changeid
1922 node = changeid
1923 rev = self.changelog.rev(changeid)
1923 rev = self.changelog.rev(changeid)
1924 except error.FilteredLookupError:
1924 except error.FilteredLookupError:
1925 changeid = hex(changeid) # for the error message
1925 changeid = hex(changeid) # for the error message
1926 raise
1926 raise
1927 except LookupError:
1927 except LookupError:
1928 # check if it might have come from damaged dirstate
1928 # check if it might have come from damaged dirstate
1929 #
1929 #
1930 # XXX we could avoid the unfiltered if we had a recognizable
1930 # XXX we could avoid the unfiltered if we had a recognizable
1931 # exception for filtered changeset access
1931 # exception for filtered changeset access
1932 if (
1932 if (
1933 self.local()
1933 self.local()
1934 and changeid in self.unfiltered().dirstate.parents()
1934 and changeid in self.unfiltered().dirstate.parents()
1935 ):
1935 ):
1936 msg = _(b"working directory has unknown parent '%s'!")
1936 msg = _(b"working directory has unknown parent '%s'!")
1937 raise error.Abort(msg % short(changeid))
1937 raise error.Abort(msg % short(changeid))
1938 changeid = hex(changeid) # for the error message
1938 changeid = hex(changeid) # for the error message
1939 raise
1939 raise
1940
1940
1941 elif len(changeid) == 2 * self.nodeconstants.nodelen:
1941 elif len(changeid) == 2 * self.nodeconstants.nodelen:
1942 node = bin(changeid)
1942 node = bin(changeid)
1943 rev = self.changelog.rev(node)
1943 rev = self.changelog.rev(node)
1944 else:
1944 else:
1945 raise error.ProgrammingError(
1945 raise error.ProgrammingError(
1946 b"unsupported changeid '%s' of type %s"
1946 b"unsupported changeid '%s' of type %s"
1947 % (changeid, pycompat.bytestr(type(changeid)))
1947 % (changeid, pycompat.bytestr(type(changeid)))
1948 )
1948 )
1949
1949
1950 return context.changectx(self, rev, node)
1950 return context.changectx(self, rev, node)
1951
1951
1952 except (error.FilteredIndexError, error.FilteredLookupError):
1952 except (error.FilteredIndexError, error.FilteredLookupError):
1953 raise error.FilteredRepoLookupError(
1953 raise error.FilteredRepoLookupError(
1954 _(b"filtered revision '%s'") % pycompat.bytestr(changeid)
1954 _(b"filtered revision '%s'") % pycompat.bytestr(changeid)
1955 )
1955 )
1956 except (IndexError, LookupError):
1956 except (IndexError, LookupError):
1957 raise error.RepoLookupError(
1957 raise error.RepoLookupError(
1958 _(b"unknown revision '%s'") % pycompat.bytestr(changeid)
1958 _(b"unknown revision '%s'") % pycompat.bytestr(changeid)
1959 )
1959 )
1960 except error.WdirUnsupported:
1960 except error.WdirUnsupported:
1961 return context.workingctx(self)
1961 return context.workingctx(self)
1962
1962
1963 def __contains__(self, changeid):
1963 def __contains__(self, changeid):
1964 """True if the given changeid exists"""
1964 """True if the given changeid exists"""
1965 try:
1965 try:
1966 self[changeid]
1966 self[changeid]
1967 return True
1967 return True
1968 except error.RepoLookupError:
1968 except error.RepoLookupError:
1969 return False
1969 return False
1970
1970
1971 def __nonzero__(self):
1971 def __nonzero__(self):
1972 return True
1972 return True
1973
1973
1974 __bool__ = __nonzero__
1974 __bool__ = __nonzero__
1975
1975
1976 def __len__(self):
1976 def __len__(self):
1977 # no need to pay the cost of repoview.changelog
1977 # no need to pay the cost of repoview.changelog
1978 unfi = self.unfiltered()
1978 unfi = self.unfiltered()
1979 return len(unfi.changelog)
1979 return len(unfi.changelog)
1980
1980
1981 def __iter__(self):
1981 def __iter__(self):
1982 return iter(self.changelog)
1982 return iter(self.changelog)
1983
1983
1984 def revs(self, expr, *args):
1984 def revs(self, expr, *args):
1985 """Find revisions matching a revset.
1985 """Find revisions matching a revset.
1986
1986
1987 The revset is specified as a string ``expr`` that may contain
1987 The revset is specified as a string ``expr`` that may contain
1988 %-formatting to escape certain types. See ``revsetlang.formatspec``.
1988 %-formatting to escape certain types. See ``revsetlang.formatspec``.
1989
1989
1990 Revset aliases from the configuration are not expanded. To expand
1990 Revset aliases from the configuration are not expanded. To expand
1991 user aliases, consider calling ``scmutil.revrange()`` or
1991 user aliases, consider calling ``scmutil.revrange()`` or
1992 ``repo.anyrevs([expr], user=True)``.
1992 ``repo.anyrevs([expr], user=True)``.
1993
1993
1994 Returns a smartset.abstractsmartset, which is a list-like interface
1994 Returns a smartset.abstractsmartset, which is a list-like interface
1995 that contains integer revisions.
1995 that contains integer revisions.
1996 """
1996 """
1997 tree = revsetlang.spectree(expr, *args)
1997 tree = revsetlang.spectree(expr, *args)
1998 return revset.makematcher(tree)(self)
1998 return revset.makematcher(tree)(self)
1999
1999
2000 def set(self, expr, *args):
2000 def set(self, expr, *args):
2001 """Find revisions matching a revset and emit changectx instances.
2001 """Find revisions matching a revset and emit changectx instances.
2002
2002
2003 This is a convenience wrapper around ``revs()`` that iterates the
2003 This is a convenience wrapper around ``revs()`` that iterates the
2004 result and is a generator of changectx instances.
2004 result and is a generator of changectx instances.
2005
2005
2006 Revset aliases from the configuration are not expanded. To expand
2006 Revset aliases from the configuration are not expanded. To expand
2007 user aliases, consider calling ``scmutil.revrange()``.
2007 user aliases, consider calling ``scmutil.revrange()``.
2008 """
2008 """
2009 for r in self.revs(expr, *args):
2009 for r in self.revs(expr, *args):
2010 yield self[r]
2010 yield self[r]
2011
2011
2012 def anyrevs(self, specs, user=False, localalias=None):
2012 def anyrevs(self, specs, user=False, localalias=None):
2013 """Find revisions matching one of the given revsets.
2013 """Find revisions matching one of the given revsets.
2014
2014
2015 Revset aliases from the configuration are not expanded by default. To
2015 Revset aliases from the configuration are not expanded by default. To
2016 expand user aliases, specify ``user=True``. To provide some local
2016 expand user aliases, specify ``user=True``. To provide some local
2017 definitions overriding user aliases, set ``localalias`` to
2017 definitions overriding user aliases, set ``localalias`` to
2018 ``{name: definitionstring}``.
2018 ``{name: definitionstring}``.
2019 """
2019 """
2020 if specs == [b'null']:
2020 if specs == [b'null']:
2021 return revset.baseset([nullrev])
2021 return revset.baseset([nullrev])
2022 if specs == [b'.']:
2022 if specs == [b'.']:
2023 quick_data = self._quick_access_changeid.get(b'.')
2023 quick_data = self._quick_access_changeid.get(b'.')
2024 if quick_data is not None:
2024 if quick_data is not None:
2025 return revset.baseset([quick_data[0]])
2025 return revset.baseset([quick_data[0]])
2026 if user:
2026 if user:
2027 m = revset.matchany(
2027 m = revset.matchany(
2028 self.ui,
2028 self.ui,
2029 specs,
2029 specs,
2030 lookup=revset.lookupfn(self),
2030 lookup=revset.lookupfn(self),
2031 localalias=localalias,
2031 localalias=localalias,
2032 )
2032 )
2033 else:
2033 else:
2034 m = revset.matchany(None, specs, localalias=localalias)
2034 m = revset.matchany(None, specs, localalias=localalias)
2035 return m(self)
2035 return m(self)
2036
2036
2037 def url(self):
2037 def url(self):
2038 return b'file:' + self.root
2038 return b'file:' + self.root
2039
2039
2040 def hook(self, name, throw=False, **args):
2040 def hook(self, name, throw=False, **args):
2041 """Call a hook, passing this repo instance.
2041 """Call a hook, passing this repo instance.
2042
2042
2043 This a convenience method to aid invoking hooks. Extensions likely
2043 This a convenience method to aid invoking hooks. Extensions likely
2044 won't call this unless they have registered a custom hook or are
2044 won't call this unless they have registered a custom hook or are
2045 replacing code that is expected to call a hook.
2045 replacing code that is expected to call a hook.
2046 """
2046 """
2047 return hook.hook(self.ui, self, name, throw, **args)
2047 return hook.hook(self.ui, self, name, throw, **args)
2048
2048
2049 @filteredpropertycache
2049 @filteredpropertycache
2050 def _tagscache(self):
2050 def _tagscache(self):
2051 """Returns a tagscache object that contains various tags related
2051 """Returns a tagscache object that contains various tags related
2052 caches."""
2052 caches."""
2053
2053
2054 # This simplifies its cache management by having one decorated
2054 # This simplifies its cache management by having one decorated
2055 # function (this one) and the rest simply fetch things from it.
2055 # function (this one) and the rest simply fetch things from it.
2056 class tagscache:
2056 class tagscache:
2057 def __init__(self):
2057 def __init__(self):
2058 # These two define the set of tags for this repository. tags
2058 # These two define the set of tags for this repository. tags
2059 # maps tag name to node; tagtypes maps tag name to 'global' or
2059 # maps tag name to node; tagtypes maps tag name to 'global' or
2060 # 'local'. (Global tags are defined by .hgtags across all
2060 # 'local'. (Global tags are defined by .hgtags across all
2061 # heads, and local tags are defined in .hg/localtags.)
2061 # heads, and local tags are defined in .hg/localtags.)
2062 # They constitute the in-memory cache of tags.
2062 # They constitute the in-memory cache of tags.
2063 self.tags = self.tagtypes = None
2063 self.tags = self.tagtypes = None
2064
2064
2065 self.nodetagscache = self.tagslist = None
2065 self.nodetagscache = self.tagslist = None
2066
2066
2067 cache = tagscache()
2067 cache = tagscache()
2068 cache.tags, cache.tagtypes = self._findtags()
2068 cache.tags, cache.tagtypes = self._findtags()
2069
2069
2070 return cache
2070 return cache
2071
2071
2072 def tags(self):
2072 def tags(self):
2073 '''return a mapping of tag to node'''
2073 '''return a mapping of tag to node'''
2074 t = {}
2074 t = {}
2075 if self.changelog.filteredrevs:
2075 if self.changelog.filteredrevs:
2076 tags, tt = self._findtags()
2076 tags, tt = self._findtags()
2077 else:
2077 else:
2078 tags = self._tagscache.tags
2078 tags = self._tagscache.tags
2079 rev = self.changelog.rev
2079 rev = self.changelog.rev
2080 for k, v in tags.items():
2080 for k, v in tags.items():
2081 try:
2081 try:
2082 # ignore tags to unknown nodes
2082 # ignore tags to unknown nodes
2083 rev(v)
2083 rev(v)
2084 t[k] = v
2084 t[k] = v
2085 except (error.LookupError, ValueError):
2085 except (error.LookupError, ValueError):
2086 pass
2086 pass
2087 return t
2087 return t
2088
2088
2089 def _findtags(self):
2089 def _findtags(self):
2090 """Do the hard work of finding tags. Return a pair of dicts
2090 """Do the hard work of finding tags. Return a pair of dicts
2091 (tags, tagtypes) where tags maps tag name to node, and tagtypes
2091 (tags, tagtypes) where tags maps tag name to node, and tagtypes
2092 maps tag name to a string like \'global\' or \'local\'.
2092 maps tag name to a string like \'global\' or \'local\'.
2093 Subclasses or extensions are free to add their own tags, but
2093 Subclasses or extensions are free to add their own tags, but
2094 should be aware that the returned dicts will be retained for the
2094 should be aware that the returned dicts will be retained for the
2095 duration of the localrepo object."""
2095 duration of the localrepo object."""
2096
2096
2097 # XXX what tagtype should subclasses/extensions use? Currently
2097 # XXX what tagtype should subclasses/extensions use? Currently
2098 # mq and bookmarks add tags, but do not set the tagtype at all.
2098 # mq and bookmarks add tags, but do not set the tagtype at all.
2099 # Should each extension invent its own tag type? Should there
2099 # Should each extension invent its own tag type? Should there
2100 # be one tagtype for all such "virtual" tags? Or is the status
2100 # be one tagtype for all such "virtual" tags? Or is the status
2101 # quo fine?
2101 # quo fine?
2102
2102
2103 # map tag name to (node, hist)
2103 # map tag name to (node, hist)
2104 alltags = tagsmod.findglobaltags(self.ui, self)
2104 alltags = tagsmod.findglobaltags(self.ui, self)
2105 # map tag name to tag type
2105 # map tag name to tag type
2106 tagtypes = {tag: b'global' for tag in alltags}
2106 tagtypes = {tag: b'global' for tag in alltags}
2107
2107
2108 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
2108 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
2109
2109
2110 # Build the return dicts. Have to re-encode tag names because
2110 # Build the return dicts. Have to re-encode tag names because
2111 # the tags module always uses UTF-8 (in order not to lose info
2111 # the tags module always uses UTF-8 (in order not to lose info
2112 # writing to the cache), but the rest of Mercurial wants them in
2112 # writing to the cache), but the rest of Mercurial wants them in
2113 # local encoding.
2113 # local encoding.
2114 tags = {}
2114 tags = {}
2115 for (name, (node, hist)) in alltags.items():
2115 for (name, (node, hist)) in alltags.items():
2116 if node != self.nullid:
2116 if node != self.nullid:
2117 tags[encoding.tolocal(name)] = node
2117 tags[encoding.tolocal(name)] = node
2118 tags[b'tip'] = self.changelog.tip()
2118 tags[b'tip'] = self.changelog.tip()
2119 tagtypes = {
2119 tagtypes = {
2120 encoding.tolocal(name): value for (name, value) in tagtypes.items()
2120 encoding.tolocal(name): value for (name, value) in tagtypes.items()
2121 }
2121 }
2122 return (tags, tagtypes)
2122 return (tags, tagtypes)
2123
2123
2124 def tagtype(self, tagname):
2124 def tagtype(self, tagname):
2125 """
2125 """
2126 return the type of the given tag. result can be:
2126 return the type of the given tag. result can be:
2127
2127
2128 'local' : a local tag
2128 'local' : a local tag
2129 'global' : a global tag
2129 'global' : a global tag
2130 None : tag does not exist
2130 None : tag does not exist
2131 """
2131 """
2132
2132
2133 return self._tagscache.tagtypes.get(tagname)
2133 return self._tagscache.tagtypes.get(tagname)
2134
2134
2135 def tagslist(self):
2135 def tagslist(self):
2136 '''return a list of tags ordered by revision'''
2136 '''return a list of tags ordered by revision'''
2137 if not self._tagscache.tagslist:
2137 if not self._tagscache.tagslist:
2138 l = []
2138 l = []
2139 for t, n in self.tags().items():
2139 for t, n in self.tags().items():
2140 l.append((self.changelog.rev(n), t, n))
2140 l.append((self.changelog.rev(n), t, n))
2141 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
2141 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
2142
2142
2143 return self._tagscache.tagslist
2143 return self._tagscache.tagslist
2144
2144
2145 def nodetags(self, node):
2145 def nodetags(self, node):
2146 '''return the tags associated with a node'''
2146 '''return the tags associated with a node'''
2147 if not self._tagscache.nodetagscache:
2147 if not self._tagscache.nodetagscache:
2148 nodetagscache = {}
2148 nodetagscache = {}
2149 for t, n in self._tagscache.tags.items():
2149 for t, n in self._tagscache.tags.items():
2150 nodetagscache.setdefault(n, []).append(t)
2150 nodetagscache.setdefault(n, []).append(t)
2151 for tags in nodetagscache.values():
2151 for tags in nodetagscache.values():
2152 tags.sort()
2152 tags.sort()
2153 self._tagscache.nodetagscache = nodetagscache
2153 self._tagscache.nodetagscache = nodetagscache
2154 return self._tagscache.nodetagscache.get(node, [])
2154 return self._tagscache.nodetagscache.get(node, [])
2155
2155
2156 def nodebookmarks(self, node):
2156 def nodebookmarks(self, node):
2157 """return the list of bookmarks pointing to the specified node"""
2157 """return the list of bookmarks pointing to the specified node"""
2158 return self._bookmarks.names(node)
2158 return self._bookmarks.names(node)
2159
2159
2160 def branchmap(self):
2160 def branchmap(self):
2161 """returns a dictionary {branch: [branchheads]} with branchheads
2161 """returns a dictionary {branch: [branchheads]} with branchheads
2162 ordered by increasing revision number"""
2162 ordered by increasing revision number"""
2163 return self._branchcaches[self]
2163 return self._branchcaches[self]
2164
2164
2165 @unfilteredmethod
2165 @unfilteredmethod
2166 def revbranchcache(self):
2166 def revbranchcache(self):
2167 if not self._revbranchcache:
2167 if not self._revbranchcache:
2168 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
2168 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
2169 return self._revbranchcache
2169 return self._revbranchcache
2170
2170
2171 def register_changeset(self, rev, changelogrevision):
2171 def register_changeset(self, rev, changelogrevision):
2172 self.revbranchcache().setdata(rev, changelogrevision)
2172 self.revbranchcache().setdata(rev, changelogrevision)
2173
2173
2174 def branchtip(self, branch, ignoremissing=False):
2174 def branchtip(self, branch, ignoremissing=False):
2175 """return the tip node for a given branch
2175 """return the tip node for a given branch
2176
2176
2177 If ignoremissing is True, then this method will not raise an error.
2177 If ignoremissing is True, then this method will not raise an error.
2178 This is helpful for callers that only expect None for a missing branch
2178 This is helpful for callers that only expect None for a missing branch
2179 (e.g. namespace).
2179 (e.g. namespace).
2180
2180
2181 """
2181 """
2182 try:
2182 try:
2183 return self.branchmap().branchtip(branch)
2183 return self.branchmap().branchtip(branch)
2184 except KeyError:
2184 except KeyError:
2185 if not ignoremissing:
2185 if not ignoremissing:
2186 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
2186 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
2187 else:
2187 else:
2188 pass
2188 pass
2189
2189
2190 def lookup(self, key):
2190 def lookup(self, key):
2191 node = scmutil.revsymbol(self, key).node()
2191 node = scmutil.revsymbol(self, key).node()
2192 if node is None:
2192 if node is None:
2193 raise error.RepoLookupError(_(b"unknown revision '%s'") % key)
2193 raise error.RepoLookupError(_(b"unknown revision '%s'") % key)
2194 return node
2194 return node
2195
2195
2196 def lookupbranch(self, key):
2196 def lookupbranch(self, key):
2197 if self.branchmap().hasbranch(key):
2197 if self.branchmap().hasbranch(key):
2198 return key
2198 return key
2199
2199
2200 return scmutil.revsymbol(self, key).branch()
2200 return scmutil.revsymbol(self, key).branch()
2201
2201
2202 def known(self, nodes):
2202 def known(self, nodes):
2203 cl = self.changelog
2203 cl = self.changelog
2204 get_rev = cl.index.get_rev
2204 get_rev = cl.index.get_rev
2205 filtered = cl.filteredrevs
2205 filtered = cl.filteredrevs
2206 result = []
2206 result = []
2207 for n in nodes:
2207 for n in nodes:
2208 r = get_rev(n)
2208 r = get_rev(n)
2209 resp = not (r is None or r in filtered)
2209 resp = not (r is None or r in filtered)
2210 result.append(resp)
2210 result.append(resp)
2211 return result
2211 return result
2212
2212
2213 def local(self):
2213 def local(self):
2214 return self
2214 return self
2215
2215
2216 def publishing(self):
2216 def publishing(self):
2217 # it's safe (and desirable) to trust the publish flag unconditionally
2217 # it's safe (and desirable) to trust the publish flag unconditionally
2218 # so that we don't finalize changes shared between users via ssh or nfs
2218 # so that we don't finalize changes shared between users via ssh or nfs
2219 return self.ui.configbool(b'phases', b'publish', untrusted=True)
2219 return self.ui.configbool(b'phases', b'publish', untrusted=True)
2220
2220
2221 def cancopy(self):
2221 def cancopy(self):
2222 # so statichttprepo's override of local() works
2222 # so statichttprepo's override of local() works
2223 if not self.local():
2223 if not self.local():
2224 return False
2224 return False
2225 if not self.publishing():
2225 if not self.publishing():
2226 return True
2226 return True
2227 # if publishing we can't copy if there is filtered content
2227 # if publishing we can't copy if there is filtered content
2228 return not self.filtered(b'visible').changelog.filteredrevs
2228 return not self.filtered(b'visible').changelog.filteredrevs
2229
2229
2230 def shared(self):
2230 def shared(self):
2231 '''the type of shared repository (None if not shared)'''
2231 '''the type of shared repository (None if not shared)'''
2232 if self.sharedpath != self.path:
2232 if self.sharedpath != self.path:
2233 return b'store'
2233 return b'store'
2234 return None
2234 return None
2235
2235
2236 def wjoin(self, f, *insidef):
2236 def wjoin(self, f, *insidef):
2237 return self.vfs.reljoin(self.root, f, *insidef)
2237 return self.vfs.reljoin(self.root, f, *insidef)
2238
2238
2239 def setparents(self, p1, p2=None):
2239 def setparents(self, p1, p2=None):
2240 if p2 is None:
2240 if p2 is None:
2241 p2 = self.nullid
2241 p2 = self.nullid
2242 self[None].setparents(p1, p2)
2242 self[None].setparents(p1, p2)
2243 self._quick_access_changeid_invalidate()
2243 self._quick_access_changeid_invalidate()
2244
2244
2245 def filectx(self, path, changeid=None, fileid=None, changectx=None):
2245 def filectx(self, path, changeid=None, fileid=None, changectx=None):
2246 """changeid must be a changeset revision, if specified.
2246 """changeid must be a changeset revision, if specified.
2247 fileid can be a file revision or node."""
2247 fileid can be a file revision or node."""
2248 return context.filectx(
2248 return context.filectx(
2249 self, path, changeid, fileid, changectx=changectx
2249 self, path, changeid, fileid, changectx=changectx
2250 )
2250 )
2251
2251
2252 def getcwd(self):
2252 def getcwd(self):
2253 return self.dirstate.getcwd()
2253 return self.dirstate.getcwd()
2254
2254
2255 def pathto(self, f, cwd=None):
2255 def pathto(self, f, cwd=None):
2256 return self.dirstate.pathto(f, cwd)
2256 return self.dirstate.pathto(f, cwd)
2257
2257
2258 def _loadfilter(self, filter):
2258 def _loadfilter(self, filter):
2259 if filter not in self._filterpats:
2259 if filter not in self._filterpats:
2260 l = []
2260 l = []
2261 for pat, cmd in self.ui.configitems(filter):
2261 for pat, cmd in self.ui.configitems(filter):
2262 if cmd == b'!':
2262 if cmd == b'!':
2263 continue
2263 continue
2264 mf = matchmod.match(self.root, b'', [pat])
2264 mf = matchmod.match(self.root, b'', [pat])
2265 fn = None
2265 fn = None
2266 params = cmd
2266 params = cmd
2267 for name, filterfn in self._datafilters.items():
2267 for name, filterfn in self._datafilters.items():
2268 if cmd.startswith(name):
2268 if cmd.startswith(name):
2269 fn = filterfn
2269 fn = filterfn
2270 params = cmd[len(name) :].lstrip()
2270 params = cmd[len(name) :].lstrip()
2271 break
2271 break
2272 if not fn:
2272 if not fn:
2273 fn = lambda s, c, **kwargs: procutil.filter(s, c)
2273 fn = lambda s, c, **kwargs: procutil.filter(s, c)
2274 fn.__name__ = 'commandfilter'
2274 fn.__name__ = 'commandfilter'
2275 # Wrap old filters not supporting keyword arguments
2275 # Wrap old filters not supporting keyword arguments
2276 if not pycompat.getargspec(fn)[2]:
2276 if not pycompat.getargspec(fn)[2]:
2277 oldfn = fn
2277 oldfn = fn
2278 fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c)
2278 fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c)
2279 fn.__name__ = 'compat-' + oldfn.__name__
2279 fn.__name__ = 'compat-' + oldfn.__name__
2280 l.append((mf, fn, params))
2280 l.append((mf, fn, params))
2281 self._filterpats[filter] = l
2281 self._filterpats[filter] = l
2282 return self._filterpats[filter]
2282 return self._filterpats[filter]
2283
2283
2284 def _filter(self, filterpats, filename, data):
2284 def _filter(self, filterpats, filename, data):
2285 for mf, fn, cmd in filterpats:
2285 for mf, fn, cmd in filterpats:
2286 if mf(filename):
2286 if mf(filename):
2287 self.ui.debug(
2287 self.ui.debug(
2288 b"filtering %s through %s\n"
2288 b"filtering %s through %s\n"
2289 % (filename, cmd or pycompat.sysbytes(fn.__name__))
2289 % (filename, cmd or pycompat.sysbytes(fn.__name__))
2290 )
2290 )
2291 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
2291 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
2292 break
2292 break
2293
2293
2294 return data
2294 return data
2295
2295
2296 @unfilteredpropertycache
2296 @unfilteredpropertycache
2297 def _encodefilterpats(self):
2297 def _encodefilterpats(self):
2298 return self._loadfilter(b'encode')
2298 return self._loadfilter(b'encode')
2299
2299
2300 @unfilteredpropertycache
2300 @unfilteredpropertycache
2301 def _decodefilterpats(self):
2301 def _decodefilterpats(self):
2302 return self._loadfilter(b'decode')
2302 return self._loadfilter(b'decode')
2303
2303
2304 def adddatafilter(self, name, filter):
2304 def adddatafilter(self, name, filter):
2305 self._datafilters[name] = filter
2305 self._datafilters[name] = filter
2306
2306
2307 def wread(self, filename):
2307 def wread(self, filename):
2308 if self.wvfs.islink(filename):
2308 if self.wvfs.islink(filename):
2309 data = self.wvfs.readlink(filename)
2309 data = self.wvfs.readlink(filename)
2310 else:
2310 else:
2311 data = self.wvfs.read(filename)
2311 data = self.wvfs.read(filename)
2312 return self._filter(self._encodefilterpats, filename, data)
2312 return self._filter(self._encodefilterpats, filename, data)
2313
2313
2314 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
2314 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
2315 """write ``data`` into ``filename`` in the working directory
2315 """write ``data`` into ``filename`` in the working directory
2316
2316
2317 This returns length of written (maybe decoded) data.
2317 This returns length of written (maybe decoded) data.
2318 """
2318 """
2319 data = self._filter(self._decodefilterpats, filename, data)
2319 data = self._filter(self._decodefilterpats, filename, data)
2320 if b'l' in flags:
2320 if b'l' in flags:
2321 self.wvfs.symlink(data, filename)
2321 self.wvfs.symlink(data, filename)
2322 else:
2322 else:
2323 self.wvfs.write(
2323 self.wvfs.write(
2324 filename, data, backgroundclose=backgroundclose, **kwargs
2324 filename, data, backgroundclose=backgroundclose, **kwargs
2325 )
2325 )
2326 if b'x' in flags:
2326 if b'x' in flags:
2327 self.wvfs.setflags(filename, False, True)
2327 self.wvfs.setflags(filename, False, True)
2328 else:
2328 else:
2329 self.wvfs.setflags(filename, False, False)
2329 self.wvfs.setflags(filename, False, False)
2330 return len(data)
2330 return len(data)
2331
2331
2332 def wwritedata(self, filename, data):
2332 def wwritedata(self, filename, data):
2333 return self._filter(self._decodefilterpats, filename, data)
2333 return self._filter(self._decodefilterpats, filename, data)
2334
2334
2335 def currenttransaction(self):
2335 def currenttransaction(self):
2336 """return the current transaction or None if non exists"""
2336 """return the current transaction or None if non exists"""
2337 if self._transref:
2337 if self._transref:
2338 tr = self._transref()
2338 tr = self._transref()
2339 else:
2339 else:
2340 tr = None
2340 tr = None
2341
2341
2342 if tr and tr.running():
2342 if tr and tr.running():
2343 return tr
2343 return tr
2344 return None
2344 return None
2345
2345
2346 def transaction(self, desc, report=None):
2346 def transaction(self, desc, report=None):
2347 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
2347 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
2348 b'devel', b'check-locks'
2348 b'devel', b'check-locks'
2349 ):
2349 ):
2350 if self._currentlock(self._lockref) is None:
2350 if self._currentlock(self._lockref) is None:
2351 raise error.ProgrammingError(b'transaction requires locking')
2351 raise error.ProgrammingError(b'transaction requires locking')
2352 tr = self.currenttransaction()
2352 tr = self.currenttransaction()
2353 if tr is not None:
2353 if tr is not None:
2354 return tr.nest(name=desc)
2354 return tr.nest(name=desc)
2355
2355
2356 # abort here if the journal already exists
2356 # abort here if the journal already exists
2357 if self.svfs.exists(b"journal"):
2357 if self.svfs.exists(b"journal"):
2358 raise error.RepoError(
2358 raise error.RepoError(
2359 _(b"abandoned transaction found"),
2359 _(b"abandoned transaction found"),
2360 hint=_(b"run 'hg recover' to clean up transaction"),
2360 hint=_(b"run 'hg recover' to clean up transaction"),
2361 )
2361 )
2362
2362
2363 idbase = b"%.40f#%f" % (random.random(), time.time())
2363 idbase = b"%.40f#%f" % (random.random(), time.time())
2364 ha = hex(hashutil.sha1(idbase).digest())
2364 ha = hex(hashutil.sha1(idbase).digest())
2365 txnid = b'TXN:' + ha
2365 txnid = b'TXN:' + ha
2366 self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
2366 self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
2367
2367
2368 self._writejournal(desc)
2368 self._writejournal(desc)
2369 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
2369 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
2370 if report:
2370 if report:
2371 rp = report
2371 rp = report
2372 else:
2372 else:
2373 rp = self.ui.warn
2373 rp = self.ui.warn
2374 vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
2374 vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
2375 # we must avoid cyclic reference between repo and transaction.
2375 # we must avoid cyclic reference between repo and transaction.
2376 reporef = weakref.ref(self)
2376 reporef = weakref.ref(self)
2377 # Code to track tag movement
2377 # Code to track tag movement
2378 #
2378 #
2379 # Since tags are all handled as file content, it is actually quite hard
2379 # Since tags are all handled as file content, it is actually quite hard
2380 # to track these movement from a code perspective. So we fallback to a
2380 # to track these movement from a code perspective. So we fallback to a
2381 # tracking at the repository level. One could envision to track changes
2381 # tracking at the repository level. One could envision to track changes
2382 # to the '.hgtags' file through changegroup apply but that fails to
2382 # to the '.hgtags' file through changegroup apply but that fails to
2383 # cope with case where transaction expose new heads without changegroup
2383 # cope with case where transaction expose new heads without changegroup
2384 # being involved (eg: phase movement).
2384 # being involved (eg: phase movement).
2385 #
2385 #
2386 # For now, We gate the feature behind a flag since this likely comes
2386 # For now, We gate the feature behind a flag since this likely comes
2387 # with performance impacts. The current code run more often than needed
2387 # with performance impacts. The current code run more often than needed
2388 # and do not use caches as much as it could. The current focus is on
2388 # and do not use caches as much as it could. The current focus is on
2389 # the behavior of the feature so we disable it by default. The flag
2389 # the behavior of the feature so we disable it by default. The flag
2390 # will be removed when we are happy with the performance impact.
2390 # will be removed when we are happy with the performance impact.
2391 #
2391 #
2392 # Once this feature is no longer experimental move the following
2392 # Once this feature is no longer experimental move the following
2393 # documentation to the appropriate help section:
2393 # documentation to the appropriate help section:
2394 #
2394 #
2395 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
2395 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
2396 # tags (new or changed or deleted tags). In addition the details of
2396 # tags (new or changed or deleted tags). In addition the details of
2397 # these changes are made available in a file at:
2397 # these changes are made available in a file at:
2398 # ``REPOROOT/.hg/changes/tags.changes``.
2398 # ``REPOROOT/.hg/changes/tags.changes``.
2399 # Make sure you check for HG_TAG_MOVED before reading that file as it
2399 # Make sure you check for HG_TAG_MOVED before reading that file as it
2400 # might exist from a previous transaction even if no tag were touched
2400 # might exist from a previous transaction even if no tag were touched
2401 # in this one. Changes are recorded in a line base format::
2401 # in this one. Changes are recorded in a line base format::
2402 #
2402 #
2403 # <action> <hex-node> <tag-name>\n
2403 # <action> <hex-node> <tag-name>\n
2404 #
2404 #
2405 # Actions are defined as follow:
2405 # Actions are defined as follow:
2406 # "-R": tag is removed,
2406 # "-R": tag is removed,
2407 # "+A": tag is added,
2407 # "+A": tag is added,
2408 # "-M": tag is moved (old value),
2408 # "-M": tag is moved (old value),
2409 # "+M": tag is moved (new value),
2409 # "+M": tag is moved (new value),
2410 tracktags = lambda x: None
2410 tracktags = lambda x: None
2411 # experimental config: experimental.hook-track-tags
2411 # experimental config: experimental.hook-track-tags
2412 shouldtracktags = self.ui.configbool(
2412 shouldtracktags = self.ui.configbool(
2413 b'experimental', b'hook-track-tags'
2413 b'experimental', b'hook-track-tags'
2414 )
2414 )
2415 if desc != b'strip' and shouldtracktags:
2415 if desc != b'strip' and shouldtracktags:
2416 oldheads = self.changelog.headrevs()
2416 oldheads = self.changelog.headrevs()
2417
2417
2418 def tracktags(tr2):
2418 def tracktags(tr2):
2419 repo = reporef()
2419 repo = reporef()
2420 assert repo is not None # help pytype
2420 assert repo is not None # help pytype
2421 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
2421 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
2422 newheads = repo.changelog.headrevs()
2422 newheads = repo.changelog.headrevs()
2423 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
2423 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
2424 # notes: we compare lists here.
2424 # notes: we compare lists here.
2425 # As we do it only once buiding set would not be cheaper
2425 # As we do it only once buiding set would not be cheaper
2426 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
2426 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
2427 if changes:
2427 if changes:
2428 tr2.hookargs[b'tag_moved'] = b'1'
2428 tr2.hookargs[b'tag_moved'] = b'1'
2429 with repo.vfs(
2429 with repo.vfs(
2430 b'changes/tags.changes', b'w', atomictemp=True
2430 b'changes/tags.changes', b'w', atomictemp=True
2431 ) as changesfile:
2431 ) as changesfile:
2432 # note: we do not register the file to the transaction
2432 # note: we do not register the file to the transaction
2433 # because we needs it to still exist on the transaction
2433 # because we needs it to still exist on the transaction
2434 # is close (for txnclose hooks)
2434 # is close (for txnclose hooks)
2435 tagsmod.writediff(changesfile, changes)
2435 tagsmod.writediff(changesfile, changes)
2436
2436
2437 def validate(tr2):
2437 def validate(tr2):
2438 """will run pre-closing hooks"""
2438 """will run pre-closing hooks"""
2439 # XXX the transaction API is a bit lacking here so we take a hacky
2439 # XXX the transaction API is a bit lacking here so we take a hacky
2440 # path for now
2440 # path for now
2441 #
2441 #
2442 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
2442 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
2443 # dict is copied before these run. In addition we needs the data
2443 # dict is copied before these run. In addition we needs the data
2444 # available to in memory hooks too.
2444 # available to in memory hooks too.
2445 #
2445 #
2446 # Moreover, we also need to make sure this runs before txnclose
2446 # Moreover, we also need to make sure this runs before txnclose
2447 # hooks and there is no "pending" mechanism that would execute
2447 # hooks and there is no "pending" mechanism that would execute
2448 # logic only if hooks are about to run.
2448 # logic only if hooks are about to run.
2449 #
2449 #
2450 # Fixing this limitation of the transaction is also needed to track
2450 # Fixing this limitation of the transaction is also needed to track
2451 # other families of changes (bookmarks, phases, obsolescence).
2451 # other families of changes (bookmarks, phases, obsolescence).
2452 #
2452 #
2453 # This will have to be fixed before we remove the experimental
2453 # This will have to be fixed before we remove the experimental
2454 # gating.
2454 # gating.
2455 tracktags(tr2)
2455 tracktags(tr2)
2456 repo = reporef()
2456 repo = reporef()
2457 assert repo is not None # help pytype
2457 assert repo is not None # help pytype
2458
2458
2459 singleheadopt = (b'experimental', b'single-head-per-branch')
2459 singleheadopt = (b'experimental', b'single-head-per-branch')
2460 singlehead = repo.ui.configbool(*singleheadopt)
2460 singlehead = repo.ui.configbool(*singleheadopt)
2461 if singlehead:
2461 if singlehead:
2462 singleheadsub = repo.ui.configsuboptions(*singleheadopt)[1]
2462 singleheadsub = repo.ui.configsuboptions(*singleheadopt)[1]
2463 accountclosed = singleheadsub.get(
2463 accountclosed = singleheadsub.get(
2464 b"account-closed-heads", False
2464 b"account-closed-heads", False
2465 )
2465 )
2466 if singleheadsub.get(b"public-changes-only", False):
2466 if singleheadsub.get(b"public-changes-only", False):
2467 filtername = b"immutable"
2467 filtername = b"immutable"
2468 else:
2468 else:
2469 filtername = b"visible"
2469 filtername = b"visible"
2470 scmutil.enforcesinglehead(
2470 scmutil.enforcesinglehead(
2471 repo, tr2, desc, accountclosed, filtername
2471 repo, tr2, desc, accountclosed, filtername
2472 )
2472 )
2473 if hook.hashook(repo.ui, b'pretxnclose-bookmark'):
2473 if hook.hashook(repo.ui, b'pretxnclose-bookmark'):
2474 for name, (old, new) in sorted(
2474 for name, (old, new) in sorted(
2475 tr.changes[b'bookmarks'].items()
2475 tr.changes[b'bookmarks'].items()
2476 ):
2476 ):
2477 args = tr.hookargs.copy()
2477 args = tr.hookargs.copy()
2478 args.update(bookmarks.preparehookargs(name, old, new))
2478 args.update(bookmarks.preparehookargs(name, old, new))
2479 repo.hook(
2479 repo.hook(
2480 b'pretxnclose-bookmark',
2480 b'pretxnclose-bookmark',
2481 throw=True,
2481 throw=True,
2482 **pycompat.strkwargs(args)
2482 **pycompat.strkwargs(args)
2483 )
2483 )
2484 if hook.hashook(repo.ui, b'pretxnclose-phase'):
2484 if hook.hashook(repo.ui, b'pretxnclose-phase'):
2485 cl = repo.unfiltered().changelog
2485 cl = repo.unfiltered().changelog
2486 for revs, (old, new) in tr.changes[b'phases']:
2486 for revs, (old, new) in tr.changes[b'phases']:
2487 for rev in revs:
2487 for rev in revs:
2488 args = tr.hookargs.copy()
2488 args = tr.hookargs.copy()
2489 node = hex(cl.node(rev))
2489 node = hex(cl.node(rev))
2490 args.update(phases.preparehookargs(node, old, new))
2490 args.update(phases.preparehookargs(node, old, new))
2491 repo.hook(
2491 repo.hook(
2492 b'pretxnclose-phase',
2492 b'pretxnclose-phase',
2493 throw=True,
2493 throw=True,
2494 **pycompat.strkwargs(args)
2494 **pycompat.strkwargs(args)
2495 )
2495 )
2496
2496
2497 repo.hook(
2497 repo.hook(
2498 b'pretxnclose', throw=True, **pycompat.strkwargs(tr.hookargs)
2498 b'pretxnclose', throw=True, **pycompat.strkwargs(tr.hookargs)
2499 )
2499 )
2500
2500
2501 def releasefn(tr, success):
2501 def releasefn(tr, success):
2502 repo = reporef()
2502 repo = reporef()
2503 if repo is None:
2503 if repo is None:
2504 # If the repo has been GC'd (and this release function is being
2504 # If the repo has been GC'd (and this release function is being
2505 # called from transaction.__del__), there's not much we can do,
2505 # called from transaction.__del__), there's not much we can do,
2506 # so just leave the unfinished transaction there and let the
2506 # so just leave the unfinished transaction there and let the
2507 # user run `hg recover`.
2507 # user run `hg recover`.
2508 return
2508 return
2509 if success:
2509 if success:
2510 # this should be explicitly invoked here, because
2510 # this should be explicitly invoked here, because
2511 # in-memory changes aren't written out at closing
2511 # in-memory changes aren't written out at closing
2512 # transaction, if tr.addfilegenerator (via
2512 # transaction, if tr.addfilegenerator (via
2513 # dirstate.write or so) isn't invoked while
2513 # dirstate.write or so) isn't invoked while
2514 # transaction running
2514 # transaction running
2515 repo.dirstate.write(None)
2515 repo.dirstate.write(None)
2516 else:
2516 else:
2517 # discard all changes (including ones already written
2517 # discard all changes (including ones already written
2518 # out) in this transaction
2518 # out) in this transaction
2519 narrowspec.restorebackup(self, b'journal.narrowspec')
2519 narrowspec.restorebackup(self, b'journal.narrowspec')
2520 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
2520 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
2521 repo.dirstate.restorebackup(None, b'journal.dirstate')
2521 repo.dirstate.restorebackup(None, b'journal.dirstate')
2522
2522
2523 repo.invalidate(clearfilecache=True)
2523 repo.invalidate(clearfilecache=True)
2524
2524
2525 tr = transaction.transaction(
2525 tr = transaction.transaction(
2526 rp,
2526 rp,
2527 self.svfs,
2527 self.svfs,
2528 vfsmap,
2528 vfsmap,
2529 b"journal",
2529 b"journal",
2530 b"undo",
2530 b"undo",
2531 aftertrans(renames),
2531 aftertrans(renames),
2532 self.store.createmode,
2532 self.store.createmode,
2533 validator=validate,
2533 validator=validate,
2534 releasefn=releasefn,
2534 releasefn=releasefn,
2535 checkambigfiles=_cachedfiles,
2535 checkambigfiles=_cachedfiles,
2536 name=desc,
2536 name=desc,
2537 )
2537 )
2538 tr.changes[b'origrepolen'] = len(self)
2538 tr.changes[b'origrepolen'] = len(self)
2539 tr.changes[b'obsmarkers'] = set()
2539 tr.changes[b'obsmarkers'] = set()
2540 tr.changes[b'phases'] = []
2540 tr.changes[b'phases'] = []
2541 tr.changes[b'bookmarks'] = {}
2541 tr.changes[b'bookmarks'] = {}
2542
2542
2543 tr.hookargs[b'txnid'] = txnid
2543 tr.hookargs[b'txnid'] = txnid
2544 tr.hookargs[b'txnname'] = desc
2544 tr.hookargs[b'txnname'] = desc
2545 tr.hookargs[b'changes'] = tr.changes
2545 tr.hookargs[b'changes'] = tr.changes
2546 # note: writing the fncache only during finalize mean that the file is
2546 # note: writing the fncache only during finalize mean that the file is
2547 # outdated when running hooks. As fncache is used for streaming clone,
2547 # outdated when running hooks. As fncache is used for streaming clone,
2548 # this is not expected to break anything that happen during the hooks.
2548 # this is not expected to break anything that happen during the hooks.
2549 tr.addfinalize(b'flush-fncache', self.store.write)
2549 tr.addfinalize(b'flush-fncache', self.store.write)
2550
2550
2551 def txnclosehook(tr2):
2551 def txnclosehook(tr2):
2552 """To be run if transaction is successful, will schedule a hook run"""
2552 """To be run if transaction is successful, will schedule a hook run"""
2553 # Don't reference tr2 in hook() so we don't hold a reference.
2553 # Don't reference tr2 in hook() so we don't hold a reference.
2554 # This reduces memory consumption when there are multiple
2554 # This reduces memory consumption when there are multiple
2555 # transactions per lock. This can likely go away if issue5045
2555 # transactions per lock. This can likely go away if issue5045
2556 # fixes the function accumulation.
2556 # fixes the function accumulation.
2557 hookargs = tr2.hookargs
2557 hookargs = tr2.hookargs
2558
2558
2559 def hookfunc(unused_success):
2559 def hookfunc(unused_success):
2560 repo = reporef()
2560 repo = reporef()
2561 assert repo is not None # help pytype
2561 assert repo is not None # help pytype
2562
2562
2563 if hook.hashook(repo.ui, b'txnclose-bookmark'):
2563 if hook.hashook(repo.ui, b'txnclose-bookmark'):
2564 bmchanges = sorted(tr.changes[b'bookmarks'].items())
2564 bmchanges = sorted(tr.changes[b'bookmarks'].items())
2565 for name, (old, new) in bmchanges:
2565 for name, (old, new) in bmchanges:
2566 args = tr.hookargs.copy()
2566 args = tr.hookargs.copy()
2567 args.update(bookmarks.preparehookargs(name, old, new))
2567 args.update(bookmarks.preparehookargs(name, old, new))
2568 repo.hook(
2568 repo.hook(
2569 b'txnclose-bookmark',
2569 b'txnclose-bookmark',
2570 throw=False,
2570 throw=False,
2571 **pycompat.strkwargs(args)
2571 **pycompat.strkwargs(args)
2572 )
2572 )
2573
2573
2574 if hook.hashook(repo.ui, b'txnclose-phase'):
2574 if hook.hashook(repo.ui, b'txnclose-phase'):
2575 cl = repo.unfiltered().changelog
2575 cl = repo.unfiltered().changelog
2576 phasemv = sorted(
2576 phasemv = sorted(
2577 tr.changes[b'phases'], key=lambda r: r[0][0]
2577 tr.changes[b'phases'], key=lambda r: r[0][0]
2578 )
2578 )
2579 for revs, (old, new) in phasemv:
2579 for revs, (old, new) in phasemv:
2580 for rev in revs:
2580 for rev in revs:
2581 args = tr.hookargs.copy()
2581 args = tr.hookargs.copy()
2582 node = hex(cl.node(rev))
2582 node = hex(cl.node(rev))
2583 args.update(phases.preparehookargs(node, old, new))
2583 args.update(phases.preparehookargs(node, old, new))
2584 repo.hook(
2584 repo.hook(
2585 b'txnclose-phase',
2585 b'txnclose-phase',
2586 throw=False,
2586 throw=False,
2587 **pycompat.strkwargs(args)
2587 **pycompat.strkwargs(args)
2588 )
2588 )
2589
2589
2590 repo.hook(
2590 repo.hook(
2591 b'txnclose', throw=False, **pycompat.strkwargs(hookargs)
2591 b'txnclose', throw=False, **pycompat.strkwargs(hookargs)
2592 )
2592 )
2593
2593
2594 repo = reporef()
2594 repo = reporef()
2595 assert repo is not None # help pytype
2595 assert repo is not None # help pytype
2596 repo._afterlock(hookfunc)
2596 repo._afterlock(hookfunc)
2597
2597
2598 tr.addfinalize(b'txnclose-hook', txnclosehook)
2598 tr.addfinalize(b'txnclose-hook', txnclosehook)
2599 # Include a leading "-" to make it happen before the transaction summary
2599 # Include a leading "-" to make it happen before the transaction summary
2600 # reports registered via scmutil.registersummarycallback() whose names
2600 # reports registered via scmutil.registersummarycallback() whose names
2601 # are 00-txnreport etc. That way, the caches will be warm when the
2601 # are 00-txnreport etc. That way, the caches will be warm when the
2602 # callbacks run.
2602 # callbacks run.
2603 tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr))
2603 tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr))
2604
2604
2605 def txnaborthook(tr2):
2605 def txnaborthook(tr2):
2606 """To be run if transaction is aborted"""
2606 """To be run if transaction is aborted"""
2607 repo = reporef()
2607 repo = reporef()
2608 assert repo is not None # help pytype
2608 assert repo is not None # help pytype
2609 repo.hook(
2609 repo.hook(
2610 b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs)
2610 b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs)
2611 )
2611 )
2612
2612
2613 tr.addabort(b'txnabort-hook', txnaborthook)
2613 tr.addabort(b'txnabort-hook', txnaborthook)
2614 # avoid eager cache invalidation. in-memory data should be identical
2614 # avoid eager cache invalidation. in-memory data should be identical
2615 # to stored data if transaction has no error.
2615 # to stored data if transaction has no error.
2616 tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats)
2616 tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats)
2617 self._transref = weakref.ref(tr)
2617 self._transref = weakref.ref(tr)
2618 scmutil.registersummarycallback(self, tr, desc)
2618 scmutil.registersummarycallback(self, tr, desc)
2619 return tr
2619 return tr
2620
2620
2621 def _journalfiles(self):
2621 def _journalfiles(self):
2622 return (
2622 return (
2623 (self.svfs, b'journal'),
2623 (self.svfs, b'journal'),
2624 (self.svfs, b'journal.narrowspec'),
2624 (self.svfs, b'journal.narrowspec'),
2625 (self.vfs, b'journal.narrowspec.dirstate'),
2625 (self.vfs, b'journal.narrowspec.dirstate'),
2626 (self.vfs, b'journal.dirstate'),
2626 (self.vfs, b'journal.dirstate'),
2627 (self.vfs, b'journal.branch'),
2627 (self.vfs, b'journal.branch'),
2628 (self.vfs, b'journal.desc'),
2628 (self.vfs, b'journal.desc'),
2629 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
2629 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
2630 (self.svfs, b'journal.phaseroots'),
2630 (self.svfs, b'journal.phaseroots'),
2631 )
2631 )
2632
2632
2633 def undofiles(self):
2633 def undofiles(self):
2634 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
2634 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
2635
2635
2636 @unfilteredmethod
2636 @unfilteredmethod
2637 def _writejournal(self, desc):
2637 def _writejournal(self, desc):
2638 self.dirstate.savebackup(None, b'journal.dirstate')
2638 self.dirstate.savebackup(None, b'journal.dirstate')
2639 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
2639 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
2640 narrowspec.savebackup(self, b'journal.narrowspec')
2640 narrowspec.savebackup(self, b'journal.narrowspec')
2641 self.vfs.write(
2641 self.vfs.write(
2642 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
2642 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
2643 )
2643 )
2644 self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
2644 self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
2645 bookmarksvfs = bookmarks.bookmarksvfs(self)
2645 bookmarksvfs = bookmarks.bookmarksvfs(self)
2646 bookmarksvfs.write(
2646 bookmarksvfs.write(
2647 b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks")
2647 b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks")
2648 )
2648 )
2649 self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots"))
2649 self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots"))
2650
2650
2651 def recover(self):
2651 def recover(self):
2652 with self.lock():
2652 with self.lock():
2653 if self.svfs.exists(b"journal"):
2653 if self.svfs.exists(b"journal"):
2654 self.ui.status(_(b"rolling back interrupted transaction\n"))
2654 self.ui.status(_(b"rolling back interrupted transaction\n"))
2655 vfsmap = {
2655 vfsmap = {
2656 b'': self.svfs,
2656 b'': self.svfs,
2657 b'plain': self.vfs,
2657 b'plain': self.vfs,
2658 }
2658 }
2659 transaction.rollback(
2659 transaction.rollback(
2660 self.svfs,
2660 self.svfs,
2661 vfsmap,
2661 vfsmap,
2662 b"journal",
2662 b"journal",
2663 self.ui.warn,
2663 self.ui.warn,
2664 checkambigfiles=_cachedfiles,
2664 checkambigfiles=_cachedfiles,
2665 )
2665 )
2666 self.invalidate()
2666 self.invalidate()
2667 return True
2667 return True
2668 else:
2668 else:
2669 self.ui.warn(_(b"no interrupted transaction available\n"))
2669 self.ui.warn(_(b"no interrupted transaction available\n"))
2670 return False
2670 return False
2671
2671
2672 def rollback(self, dryrun=False, force=False):
2672 def rollback(self, dryrun=False, force=False):
2673 wlock = lock = dsguard = None
2673 wlock = lock = dsguard = None
2674 try:
2674 try:
2675 wlock = self.wlock()
2675 wlock = self.wlock()
2676 lock = self.lock()
2676 lock = self.lock()
2677 if self.svfs.exists(b"undo"):
2677 if self.svfs.exists(b"undo"):
2678 dsguard = dirstateguard.dirstateguard(self, b'rollback')
2678 dsguard = dirstateguard.dirstateguard(self, b'rollback')
2679
2679
2680 return self._rollback(dryrun, force, dsguard)
2680 return self._rollback(dryrun, force, dsguard)
2681 else:
2681 else:
2682 self.ui.warn(_(b"no rollback information available\n"))
2682 self.ui.warn(_(b"no rollback information available\n"))
2683 return 1
2683 return 1
2684 finally:
2684 finally:
2685 release(dsguard, lock, wlock)
2685 release(dsguard, lock, wlock)
2686
2686
2687 @unfilteredmethod # Until we get smarter cache management
2687 @unfilteredmethod # Until we get smarter cache management
2688 def _rollback(self, dryrun, force, dsguard):
2688 def _rollback(self, dryrun, force, dsguard):
2689 ui = self.ui
2689 ui = self.ui
2690 try:
2690 try:
2691 args = self.vfs.read(b'undo.desc').splitlines()
2691 args = self.vfs.read(b'undo.desc').splitlines()
2692 (oldlen, desc, detail) = (int(args[0]), args[1], None)
2692 (oldlen, desc, detail) = (int(args[0]), args[1], None)
2693 if len(args) >= 3:
2693 if len(args) >= 3:
2694 detail = args[2]
2694 detail = args[2]
2695 oldtip = oldlen - 1
2695 oldtip = oldlen - 1
2696
2696
2697 if detail and ui.verbose:
2697 if detail and ui.verbose:
2698 msg = _(
2698 msg = _(
2699 b'repository tip rolled back to revision %d'
2699 b'repository tip rolled back to revision %d'
2700 b' (undo %s: %s)\n'
2700 b' (undo %s: %s)\n'
2701 ) % (oldtip, desc, detail)
2701 ) % (oldtip, desc, detail)
2702 else:
2702 else:
2703 msg = _(
2703 msg = _(
2704 b'repository tip rolled back to revision %d (undo %s)\n'
2704 b'repository tip rolled back to revision %d (undo %s)\n'
2705 ) % (oldtip, desc)
2705 ) % (oldtip, desc)
2706 except IOError:
2706 except IOError:
2707 msg = _(b'rolling back unknown transaction\n')
2707 msg = _(b'rolling back unknown transaction\n')
2708 desc = None
2708 desc = None
2709
2709
2710 if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
2710 if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
2711 raise error.Abort(
2711 raise error.Abort(
2712 _(
2712 _(
2713 b'rollback of last commit while not checked out '
2713 b'rollback of last commit while not checked out '
2714 b'may lose data'
2714 b'may lose data'
2715 ),
2715 ),
2716 hint=_(b'use -f to force'),
2716 hint=_(b'use -f to force'),
2717 )
2717 )
2718
2718
2719 ui.status(msg)
2719 ui.status(msg)
2720 if dryrun:
2720 if dryrun:
2721 return 0
2721 return 0
2722
2722
2723 parents = self.dirstate.parents()
2723 parents = self.dirstate.parents()
2724 self.destroying()
2724 self.destroying()
2725 vfsmap = {b'plain': self.vfs, b'': self.svfs}
2725 vfsmap = {b'plain': self.vfs, b'': self.svfs}
2726 transaction.rollback(
2726 transaction.rollback(
2727 self.svfs, vfsmap, b'undo', ui.warn, checkambigfiles=_cachedfiles
2727 self.svfs, vfsmap, b'undo', ui.warn, checkambigfiles=_cachedfiles
2728 )
2728 )
2729 bookmarksvfs = bookmarks.bookmarksvfs(self)
2729 bookmarksvfs = bookmarks.bookmarksvfs(self)
2730 if bookmarksvfs.exists(b'undo.bookmarks'):
2730 if bookmarksvfs.exists(b'undo.bookmarks'):
2731 bookmarksvfs.rename(
2731 bookmarksvfs.rename(
2732 b'undo.bookmarks', b'bookmarks', checkambig=True
2732 b'undo.bookmarks', b'bookmarks', checkambig=True
2733 )
2733 )
2734 if self.svfs.exists(b'undo.phaseroots'):
2734 if self.svfs.exists(b'undo.phaseroots'):
2735 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
2735 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
2736 self.invalidate()
2736 self.invalidate()
2737
2737
2738 has_node = self.changelog.index.has_node
2738 has_node = self.changelog.index.has_node
2739 parentgone = any(not has_node(p) for p in parents)
2739 parentgone = any(not has_node(p) for p in parents)
2740 if parentgone:
2740 if parentgone:
2741 # prevent dirstateguard from overwriting already restored one
2741 # prevent dirstateguard from overwriting already restored one
2742 dsguard.close()
2742 dsguard.close()
2743
2743
2744 narrowspec.restorebackup(self, b'undo.narrowspec')
2744 narrowspec.restorebackup(self, b'undo.narrowspec')
2745 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
2745 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
2746 self.dirstate.restorebackup(None, b'undo.dirstate')
2746 self.dirstate.restorebackup(None, b'undo.dirstate')
2747 try:
2747 try:
2748 branch = self.vfs.read(b'undo.branch')
2748 branch = self.vfs.read(b'undo.branch')
2749 self.dirstate.setbranch(encoding.tolocal(branch))
2749 self.dirstate.setbranch(encoding.tolocal(branch))
2750 except IOError:
2750 except IOError:
2751 ui.warn(
2751 ui.warn(
2752 _(
2752 _(
2753 b'named branch could not be reset: '
2753 b'named branch could not be reset: '
2754 b'current branch is still \'%s\'\n'
2754 b'current branch is still \'%s\'\n'
2755 )
2755 )
2756 % self.dirstate.branch()
2756 % self.dirstate.branch()
2757 )
2757 )
2758
2758
2759 parents = tuple([p.rev() for p in self[None].parents()])
2759 parents = tuple([p.rev() for p in self[None].parents()])
2760 if len(parents) > 1:
2760 if len(parents) > 1:
2761 ui.status(
2761 ui.status(
2762 _(
2762 _(
2763 b'working directory now based on '
2763 b'working directory now based on '
2764 b'revisions %d and %d\n'
2764 b'revisions %d and %d\n'
2765 )
2765 )
2766 % parents
2766 % parents
2767 )
2767 )
2768 else:
2768 else:
2769 ui.status(
2769 ui.status(
2770 _(b'working directory now based on revision %d\n') % parents
2770 _(b'working directory now based on revision %d\n') % parents
2771 )
2771 )
2772 mergestatemod.mergestate.clean(self)
2772 mergestatemod.mergestate.clean(self)
2773
2773
2774 # TODO: if we know which new heads may result from this rollback, pass
2774 # TODO: if we know which new heads may result from this rollback, pass
2775 # them to destroy(), which will prevent the branchhead cache from being
2775 # them to destroy(), which will prevent the branchhead cache from being
2776 # invalidated.
2776 # invalidated.
2777 self.destroyed()
2777 self.destroyed()
2778 return 0
2778 return 0
2779
2779
2780 def _buildcacheupdater(self, newtransaction):
2780 def _buildcacheupdater(self, newtransaction):
2781 """called during transaction to build the callback updating cache
2781 """called during transaction to build the callback updating cache
2782
2782
2783 Lives on the repository to help extension who might want to augment
2783 Lives on the repository to help extension who might want to augment
2784 this logic. For this purpose, the created transaction is passed to the
2784 this logic. For this purpose, the created transaction is passed to the
2785 method.
2785 method.
2786 """
2786 """
2787 # we must avoid cyclic reference between repo and transaction.
2787 # we must avoid cyclic reference between repo and transaction.
2788 reporef = weakref.ref(self)
2788 reporef = weakref.ref(self)
2789
2789
2790 def updater(tr):
2790 def updater(tr):
2791 repo = reporef()
2791 repo = reporef()
2792 assert repo is not None # help pytype
2792 assert repo is not None # help pytype
2793 repo.updatecaches(tr)
2793 repo.updatecaches(tr)
2794
2794
2795 return updater
2795 return updater
2796
2796
2797 @unfilteredmethod
2797 @unfilteredmethod
2798 def updatecaches(self, tr=None, full=False, caches=None):
2798 def updatecaches(self, tr=None, full=False, caches=None):
2799 """warm appropriate caches
2799 """warm appropriate caches
2800
2800
2801 If this function is called after a transaction closed. The transaction
2801 If this function is called after a transaction closed. The transaction
2802 will be available in the 'tr' argument. This can be used to selectively
2802 will be available in the 'tr' argument. This can be used to selectively
2803 update caches relevant to the changes in that transaction.
2803 update caches relevant to the changes in that transaction.
2804
2804
2805 If 'full' is set, make sure all caches the function knows about have
2805 If 'full' is set, make sure all caches the function knows about have
2806 up-to-date data. Even the ones usually loaded more lazily.
2806 up-to-date data. Even the ones usually loaded more lazily.
2807
2807
2808 The `full` argument can take a special "post-clone" value. In this case
2808 The `full` argument can take a special "post-clone" value. In this case
2809 the cache warming is made after a clone and of the slower cache might
2809 the cache warming is made after a clone and of the slower cache might
2810 be skipped, namely the `.fnodetags` one. This argument is 5.8 specific
2810 be skipped, namely the `.fnodetags` one. This argument is 5.8 specific
2811 as we plan for a cleaner way to deal with this for 5.9.
2811 as we plan for a cleaner way to deal with this for 5.9.
2812 """
2812 """
2813 if tr is not None and tr.hookargs.get(b'source') == b'strip':
2813 if tr is not None and tr.hookargs.get(b'source') == b'strip':
2814 # During strip, many caches are invalid but
2814 # During strip, many caches are invalid but
2815 # later call to `destroyed` will refresh them.
2815 # later call to `destroyed` will refresh them.
2816 return
2816 return
2817
2817
2818 unfi = self.unfiltered()
2818 unfi = self.unfiltered()
2819
2819
2820 if full:
2820 if full:
2821 msg = (
2821 msg = (
2822 "`full` argument for `repo.updatecaches` is deprecated\n"
2822 "`full` argument for `repo.updatecaches` is deprecated\n"
2823 "(use `caches=repository.CACHE_ALL` instead)"
2823 "(use `caches=repository.CACHE_ALL` instead)"
2824 )
2824 )
2825 self.ui.deprecwarn(msg, b"5.9")
2825 self.ui.deprecwarn(msg, b"5.9")
2826 caches = repository.CACHES_ALL
2826 caches = repository.CACHES_ALL
2827 if full == b"post-clone":
2827 if full == b"post-clone":
2828 caches = repository.CACHES_POST_CLONE
2828 caches = repository.CACHES_POST_CLONE
2829 caches = repository.CACHES_ALL
2829 caches = repository.CACHES_ALL
2830 elif caches is None:
2830 elif caches is None:
2831 caches = repository.CACHES_DEFAULT
2831 caches = repository.CACHES_DEFAULT
2832
2832
2833 if repository.CACHE_BRANCHMAP_SERVED in caches:
2833 if repository.CACHE_BRANCHMAP_SERVED in caches:
2834 if tr is None or tr.changes[b'origrepolen'] < len(self):
2834 if tr is None or tr.changes[b'origrepolen'] < len(self):
2835 # accessing the 'served' branchmap should refresh all the others,
2835 # accessing the 'served' branchmap should refresh all the others,
2836 self.ui.debug(b'updating the branch cache\n')
2836 self.ui.debug(b'updating the branch cache\n')
2837 self.filtered(b'served').branchmap()
2837 self.filtered(b'served').branchmap()
2838 self.filtered(b'served.hidden').branchmap()
2838 self.filtered(b'served.hidden').branchmap()
2839 # flush all possibly delayed write.
2839 # flush all possibly delayed write.
2840 self._branchcaches.write_delayed(self)
2840 self._branchcaches.write_delayed(self)
2841
2841
2842 if repository.CACHE_CHANGELOG_CACHE in caches:
2842 if repository.CACHE_CHANGELOG_CACHE in caches:
2843 self.changelog.update_caches(transaction=tr)
2843 self.changelog.update_caches(transaction=tr)
2844
2844
2845 if repository.CACHE_MANIFESTLOG_CACHE in caches:
2845 if repository.CACHE_MANIFESTLOG_CACHE in caches:
2846 self.manifestlog.update_caches(transaction=tr)
2846 self.manifestlog.update_caches(transaction=tr)
2847
2847
2848 if repository.CACHE_REV_BRANCH in caches:
2848 if repository.CACHE_REV_BRANCH in caches:
2849 rbc = unfi.revbranchcache()
2849 rbc = unfi.revbranchcache()
2850 for r in unfi.changelog:
2850 for r in unfi.changelog:
2851 rbc.branchinfo(r)
2851 rbc.branchinfo(r)
2852 rbc.write()
2852 rbc.write()
2853
2853
2854 if repository.CACHE_FULL_MANIFEST in caches:
2854 if repository.CACHE_FULL_MANIFEST in caches:
2855 # ensure the working copy parents are in the manifestfulltextcache
2855 # ensure the working copy parents are in the manifestfulltextcache
2856 for ctx in self[b'.'].parents():
2856 for ctx in self[b'.'].parents():
2857 ctx.manifest() # accessing the manifest is enough
2857 ctx.manifest() # accessing the manifest is enough
2858
2858
2859 if repository.CACHE_FILE_NODE_TAGS in caches:
2859 if repository.CACHE_FILE_NODE_TAGS in caches:
2860 # accessing fnode cache warms the cache
2860 # accessing fnode cache warms the cache
2861 tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
2861 tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
2862
2862
2863 if repository.CACHE_TAGS_DEFAULT in caches:
2863 if repository.CACHE_TAGS_DEFAULT in caches:
2864 # accessing tags warm the cache
2864 # accessing tags warm the cache
2865 self.tags()
2865 self.tags()
2866 if repository.CACHE_TAGS_SERVED in caches:
2866 if repository.CACHE_TAGS_SERVED in caches:
2867 self.filtered(b'served').tags()
2867 self.filtered(b'served').tags()
2868
2868
2869 if repository.CACHE_BRANCHMAP_ALL in caches:
2869 if repository.CACHE_BRANCHMAP_ALL in caches:
2870 # The CACHE_BRANCHMAP_ALL updates lazily-loaded caches immediately,
2870 # The CACHE_BRANCHMAP_ALL updates lazily-loaded caches immediately,
2871 # so we're forcing a write to cause these caches to be warmed up
2871 # so we're forcing a write to cause these caches to be warmed up
2872 # even if they haven't explicitly been requested yet (if they've
2872 # even if they haven't explicitly been requested yet (if they've
2873 # never been used by hg, they won't ever have been written, even if
2873 # never been used by hg, they won't ever have been written, even if
2874 # they're a subset of another kind of cache that *has* been used).
2874 # they're a subset of another kind of cache that *has* been used).
2875 for filt in repoview.filtertable.keys():
2875 for filt in repoview.filtertable.keys():
2876 filtered = self.filtered(filt)
2876 filtered = self.filtered(filt)
2877 filtered.branchmap().write(filtered)
2877 filtered.branchmap().write(filtered)
2878
2878
2879 def invalidatecaches(self):
2879 def invalidatecaches(self):
2880
2880
2881 if '_tagscache' in vars(self):
2881 if '_tagscache' in vars(self):
2882 # can't use delattr on proxy
2882 # can't use delattr on proxy
2883 del self.__dict__['_tagscache']
2883 del self.__dict__['_tagscache']
2884
2884
2885 self._branchcaches.clear()
2885 self._branchcaches.clear()
2886 self.invalidatevolatilesets()
2886 self.invalidatevolatilesets()
2887 self._sparsesignaturecache.clear()
2887 self._sparsesignaturecache.clear()
2888
2888
2889 def invalidatevolatilesets(self):
2889 def invalidatevolatilesets(self):
2890 self.filteredrevcache.clear()
2890 self.filteredrevcache.clear()
2891 obsolete.clearobscaches(self)
2891 obsolete.clearobscaches(self)
2892 self._quick_access_changeid_invalidate()
2892 self._quick_access_changeid_invalidate()
2893
2893
2894 def invalidatedirstate(self):
2894 def invalidatedirstate(self):
2895 """Invalidates the dirstate, causing the next call to dirstate
2895 """Invalidates the dirstate, causing the next call to dirstate
2896 to check if it was modified since the last time it was read,
2896 to check if it was modified since the last time it was read,
2897 rereading it if it has.
2897 rereading it if it has.
2898
2898
2899 This is different to dirstate.invalidate() that it doesn't always
2899 This is different to dirstate.invalidate() that it doesn't always
2900 rereads the dirstate. Use dirstate.invalidate() if you want to
2900 rereads the dirstate. Use dirstate.invalidate() if you want to
2901 explicitly read the dirstate again (i.e. restoring it to a previous
2901 explicitly read the dirstate again (i.e. restoring it to a previous
2902 known good state)."""
2902 known good state)."""
2903 if hasunfilteredcache(self, 'dirstate'):
2903 if hasunfilteredcache(self, 'dirstate'):
2904 for k in self.dirstate._filecache:
2904 for k in self.dirstate._filecache:
2905 try:
2905 try:
2906 delattr(self.dirstate, k)
2906 delattr(self.dirstate, k)
2907 except AttributeError:
2907 except AttributeError:
2908 pass
2908 pass
2909 delattr(self.unfiltered(), 'dirstate')
2909 delattr(self.unfiltered(), 'dirstate')
2910
2910
2911 def invalidate(self, clearfilecache=False):
2911 def invalidate(self, clearfilecache=False):
2912 """Invalidates both store and non-store parts other than dirstate
2912 """Invalidates both store and non-store parts other than dirstate
2913
2913
2914 If a transaction is running, invalidation of store is omitted,
2914 If a transaction is running, invalidation of store is omitted,
2915 because discarding in-memory changes might cause inconsistency
2915 because discarding in-memory changes might cause inconsistency
2916 (e.g. incomplete fncache causes unintentional failure, but
2916 (e.g. incomplete fncache causes unintentional failure, but
2917 redundant one doesn't).
2917 redundant one doesn't).
2918 """
2918 """
2919 unfiltered = self.unfiltered() # all file caches are stored unfiltered
2919 unfiltered = self.unfiltered() # all file caches are stored unfiltered
2920 for k in list(self._filecache.keys()):
2920 for k in list(self._filecache.keys()):
2921 # dirstate is invalidated separately in invalidatedirstate()
2921 # dirstate is invalidated separately in invalidatedirstate()
2922 if k == b'dirstate':
2922 if k == b'dirstate':
2923 continue
2923 continue
2924 if (
2924 if (
2925 k == b'changelog'
2925 k == b'changelog'
2926 and self.currenttransaction()
2926 and self.currenttransaction()
2927 and self.changelog._delayed
2927 and self.changelog._delayed
2928 ):
2928 ):
2929 # The changelog object may store unwritten revisions. We don't
2929 # The changelog object may store unwritten revisions. We don't
2930 # want to lose them.
2930 # want to lose them.
2931 # TODO: Solve the problem instead of working around it.
2931 # TODO: Solve the problem instead of working around it.
2932 continue
2932 continue
2933
2933
2934 if clearfilecache:
2934 if clearfilecache:
2935 del self._filecache[k]
2935 del self._filecache[k]
2936 try:
2936 try:
2937 delattr(unfiltered, k)
2937 delattr(unfiltered, k)
2938 except AttributeError:
2938 except AttributeError:
2939 pass
2939 pass
2940 self.invalidatecaches()
2940 self.invalidatecaches()
2941 if not self.currenttransaction():
2941 if not self.currenttransaction():
2942 # TODO: Changing contents of store outside transaction
2942 # TODO: Changing contents of store outside transaction
2943 # causes inconsistency. We should make in-memory store
2943 # causes inconsistency. We should make in-memory store
2944 # changes detectable, and abort if changed.
2944 # changes detectable, and abort if changed.
2945 self.store.invalidatecaches()
2945 self.store.invalidatecaches()
2946
2946
2947 def invalidateall(self):
2947 def invalidateall(self):
2948 """Fully invalidates both store and non-store parts, causing the
2948 """Fully invalidates both store and non-store parts, causing the
2949 subsequent operation to reread any outside changes."""
2949 subsequent operation to reread any outside changes."""
2950 # extension should hook this to invalidate its caches
2950 # extension should hook this to invalidate its caches
2951 self.invalidate()
2951 self.invalidate()
2952 self.invalidatedirstate()
2952 self.invalidatedirstate()
2953
2953
2954 @unfilteredmethod
2954 @unfilteredmethod
2955 def _refreshfilecachestats(self, tr):
2955 def _refreshfilecachestats(self, tr):
2956 """Reload stats of cached files so that they are flagged as valid"""
2956 """Reload stats of cached files so that they are flagged as valid"""
2957 for k, ce in self._filecache.items():
2957 for k, ce in self._filecache.items():
2958 k = pycompat.sysstr(k)
2958 k = pycompat.sysstr(k)
2959 if k == 'dirstate' or k not in self.__dict__:
2959 if k == 'dirstate' or k not in self.__dict__:
2960 continue
2960 continue
2961 ce.refresh()
2961 ce.refresh()
2962
2962
2963 def _lock(
2963 def _lock(
2964 self,
2964 self,
2965 vfs,
2965 vfs,
2966 lockname,
2966 lockname,
2967 wait,
2967 wait,
2968 releasefn,
2968 releasefn,
2969 acquirefn,
2969 acquirefn,
2970 desc,
2970 desc,
2971 ):
2971 ):
2972 timeout = 0
2972 timeout = 0
2973 warntimeout = 0
2973 warntimeout = 0
2974 if wait:
2974 if wait:
2975 timeout = self.ui.configint(b"ui", b"timeout")
2975 timeout = self.ui.configint(b"ui", b"timeout")
2976 warntimeout = self.ui.configint(b"ui", b"timeout.warn")
2976 warntimeout = self.ui.configint(b"ui", b"timeout.warn")
2977 # internal config: ui.signal-safe-lock
2977 # internal config: ui.signal-safe-lock
2978 signalsafe = self.ui.configbool(b'ui', b'signal-safe-lock')
2978 signalsafe = self.ui.configbool(b'ui', b'signal-safe-lock')
2979
2979
2980 l = lockmod.trylock(
2980 l = lockmod.trylock(
2981 self.ui,
2981 self.ui,
2982 vfs,
2982 vfs,
2983 lockname,
2983 lockname,
2984 timeout,
2984 timeout,
2985 warntimeout,
2985 warntimeout,
2986 releasefn=releasefn,
2986 releasefn=releasefn,
2987 acquirefn=acquirefn,
2987 acquirefn=acquirefn,
2988 desc=desc,
2988 desc=desc,
2989 signalsafe=signalsafe,
2989 signalsafe=signalsafe,
2990 )
2990 )
2991 return l
2991 return l
2992
2992
2993 def _afterlock(self, callback):
2993 def _afterlock(self, callback):
2994 """add a callback to be run when the repository is fully unlocked
2994 """add a callback to be run when the repository is fully unlocked
2995
2995
2996 The callback will be executed when the outermost lock is released
2996 The callback will be executed when the outermost lock is released
2997 (with wlock being higher level than 'lock')."""
2997 (with wlock being higher level than 'lock')."""
2998 for ref in (self._wlockref, self._lockref):
2998 for ref in (self._wlockref, self._lockref):
2999 l = ref and ref()
2999 l = ref and ref()
3000 if l and l.held:
3000 if l and l.held:
3001 l.postrelease.append(callback)
3001 l.postrelease.append(callback)
3002 break
3002 break
3003 else: # no lock have been found.
3003 else: # no lock have been found.
3004 callback(True)
3004 callback(True)
3005
3005
3006 def lock(self, wait=True):
3006 def lock(self, wait=True):
3007 """Lock the repository store (.hg/store) and return a weak reference
3007 """Lock the repository store (.hg/store) and return a weak reference
3008 to the lock. Use this before modifying the store (e.g. committing or
3008 to the lock. Use this before modifying the store (e.g. committing or
3009 stripping). If you are opening a transaction, get a lock as well.)
3009 stripping). If you are opening a transaction, get a lock as well.)
3010
3010
3011 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
3011 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
3012 'wlock' first to avoid a dead-lock hazard."""
3012 'wlock' first to avoid a dead-lock hazard."""
3013 l = self._currentlock(self._lockref)
3013 l = self._currentlock(self._lockref)
3014 if l is not None:
3014 if l is not None:
3015 l.lock()
3015 l.lock()
3016 return l
3016 return l
3017
3017
3018 l = self._lock(
3018 l = self._lock(
3019 vfs=self.svfs,
3019 vfs=self.svfs,
3020 lockname=b"lock",
3020 lockname=b"lock",
3021 wait=wait,
3021 wait=wait,
3022 releasefn=None,
3022 releasefn=None,
3023 acquirefn=self.invalidate,
3023 acquirefn=self.invalidate,
3024 desc=_(b'repository %s') % self.origroot,
3024 desc=_(b'repository %s') % self.origroot,
3025 )
3025 )
3026 self._lockref = weakref.ref(l)
3026 self._lockref = weakref.ref(l)
3027 return l
3027 return l
3028
3028
3029 def wlock(self, wait=True):
3029 def wlock(self, wait=True):
3030 """Lock the non-store parts of the repository (everything under
3030 """Lock the non-store parts of the repository (everything under
3031 .hg except .hg/store) and return a weak reference to the lock.
3031 .hg except .hg/store) and return a weak reference to the lock.
3032
3032
3033 Use this before modifying files in .hg.
3033 Use this before modifying files in .hg.
3034
3034
3035 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
3035 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
3036 'wlock' first to avoid a dead-lock hazard."""
3036 'wlock' first to avoid a dead-lock hazard."""
3037 l = self._wlockref() if self._wlockref else None
3037 l = self._wlockref() if self._wlockref else None
3038 if l is not None and l.held:
3038 if l is not None and l.held:
3039 l.lock()
3039 l.lock()
3040 return l
3040 return l
3041
3041
3042 # We do not need to check for non-waiting lock acquisition. Such
3042 # We do not need to check for non-waiting lock acquisition. Such
3043 # acquisition would not cause dead-lock as they would just fail.
3043 # acquisition would not cause dead-lock as they would just fail.
3044 if wait and (
3044 if wait and (
3045 self.ui.configbool(b'devel', b'all-warnings')
3045 self.ui.configbool(b'devel', b'all-warnings')
3046 or self.ui.configbool(b'devel', b'check-locks')
3046 or self.ui.configbool(b'devel', b'check-locks')
3047 ):
3047 ):
3048 if self._currentlock(self._lockref) is not None:
3048 if self._currentlock(self._lockref) is not None:
3049 self.ui.develwarn(b'"wlock" acquired after "lock"')
3049 self.ui.develwarn(b'"wlock" acquired after "lock"')
3050
3050
3051 def unlock():
3051 def unlock():
3052 if self.dirstate.pendingparentchange():
3052 if self.dirstate.pendingparentchange():
3053 self.dirstate.invalidate()
3053 self.dirstate.invalidate()
3054 else:
3054 else:
3055 self.dirstate.write(None)
3055 self.dirstate.write(None)
3056
3056
3057 self._filecache[b'dirstate'].refresh()
3057 self._filecache[b'dirstate'].refresh()
3058
3058
3059 l = self._lock(
3059 l = self._lock(
3060 self.vfs,
3060 self.vfs,
3061 b"wlock",
3061 b"wlock",
3062 wait,
3062 wait,
3063 unlock,
3063 unlock,
3064 self.invalidatedirstate,
3064 self.invalidatedirstate,
3065 _(b'working directory of %s') % self.origroot,
3065 _(b'working directory of %s') % self.origroot,
3066 )
3066 )
3067 self._wlockref = weakref.ref(l)
3067 self._wlockref = weakref.ref(l)
3068 return l
3068 return l
3069
3069
3070 def _currentlock(self, lockref):
3070 def _currentlock(self, lockref):
3071 """Returns the lock if it's held, or None if it's not."""
3071 """Returns the lock if it's held, or None if it's not."""
3072 if lockref is None:
3072 if lockref is None:
3073 return None
3073 return None
3074 l = lockref()
3074 l = lockref()
3075 if l is None or not l.held:
3075 if l is None or not l.held:
3076 return None
3076 return None
3077 return l
3077 return l
3078
3078
3079 def currentwlock(self):
3079 def currentwlock(self):
3080 """Returns the wlock if it's held, or None if it's not."""
3080 """Returns the wlock if it's held, or None if it's not."""
3081 return self._currentlock(self._wlockref)
3081 return self._currentlock(self._wlockref)
3082
3082
3083 def checkcommitpatterns(self, wctx, match, status, fail):
3083 def checkcommitpatterns(self, wctx, match, status, fail):
3084 """check for commit arguments that aren't committable"""
3084 """check for commit arguments that aren't committable"""
3085 if match.isexact() or match.prefix():
3085 if match.isexact() or match.prefix():
3086 matched = set(status.modified + status.added + status.removed)
3086 matched = set(status.modified + status.added + status.removed)
3087
3087
3088 for f in match.files():
3088 for f in match.files():
3089 f = self.dirstate.normalize(f)
3089 f = self.dirstate.normalize(f)
3090 if f == b'.' or f in matched or f in wctx.substate:
3090 if f == b'.' or f in matched or f in wctx.substate:
3091 continue
3091 continue
3092 if f in status.deleted:
3092 if f in status.deleted:
3093 fail(f, _(b'file not found!'))
3093 fail(f, _(b'file not found!'))
3094 # Is it a directory that exists or used to exist?
3094 # Is it a directory that exists or used to exist?
3095 if self.wvfs.isdir(f) or wctx.p1().hasdir(f):
3095 if self.wvfs.isdir(f) or wctx.p1().hasdir(f):
3096 d = f + b'/'
3096 d = f + b'/'
3097 for mf in matched:
3097 for mf in matched:
3098 if mf.startswith(d):
3098 if mf.startswith(d):
3099 break
3099 break
3100 else:
3100 else:
3101 fail(f, _(b"no match under directory!"))
3101 fail(f, _(b"no match under directory!"))
3102 elif f not in self.dirstate:
3102 elif f not in self.dirstate:
3103 fail(f, _(b"file not tracked!"))
3103 fail(f, _(b"file not tracked!"))
3104
3104
3105 @unfilteredmethod
3105 @unfilteredmethod
3106 def commit(
3106 def commit(
3107 self,
3107 self,
3108 text=b"",
3108 text=b"",
3109 user=None,
3109 user=None,
3110 date=None,
3110 date=None,
3111 match=None,
3111 match=None,
3112 force=False,
3112 force=False,
3113 editor=None,
3113 editor=None,
3114 extra=None,
3114 extra=None,
3115 ):
3115 ):
3116 """Add a new revision to current repository.
3116 """Add a new revision to current repository.
3117
3117
3118 Revision information is gathered from the working directory,
3118 Revision information is gathered from the working directory,
3119 match can be used to filter the committed files. If editor is
3119 match can be used to filter the committed files. If editor is
3120 supplied, it is called to get a commit message.
3120 supplied, it is called to get a commit message.
3121 """
3121 """
3122 if extra is None:
3122 if extra is None:
3123 extra = {}
3123 extra = {}
3124
3124
3125 def fail(f, msg):
3125 def fail(f, msg):
3126 raise error.InputError(b'%s: %s' % (f, msg))
3126 raise error.InputError(b'%s: %s' % (f, msg))
3127
3127
3128 if not match:
3128 if not match:
3129 match = matchmod.always()
3129 match = matchmod.always()
3130
3130
3131 if not force:
3131 if not force:
3132 match.bad = fail
3132 match.bad = fail
3133
3133
3134 # lock() for recent changelog (see issue4368)
3134 # lock() for recent changelog (see issue4368)
3135 with self.wlock(), self.lock():
3135 with self.wlock(), self.lock():
3136 wctx = self[None]
3136 wctx = self[None]
3137 merge = len(wctx.parents()) > 1
3137 merge = len(wctx.parents()) > 1
3138
3138
3139 if not force and merge and not match.always():
3139 if not force and merge and not match.always():
3140 raise error.Abort(
3140 raise error.Abort(
3141 _(
3141 _(
3142 b'cannot partially commit a merge '
3142 b'cannot partially commit a merge '
3143 b'(do not specify files or patterns)'
3143 b'(do not specify files or patterns)'
3144 )
3144 )
3145 )
3145 )
3146
3146
3147 status = self.status(match=match, clean=force)
3147 status = self.status(match=match, clean=force)
3148 if force:
3148 if force:
3149 status.modified.extend(
3149 status.modified.extend(
3150 status.clean
3150 status.clean
3151 ) # mq may commit clean files
3151 ) # mq may commit clean files
3152
3152
3153 # check subrepos
3153 # check subrepos
3154 subs, commitsubs, newstate = subrepoutil.precommit(
3154 subs, commitsubs, newstate = subrepoutil.precommit(
3155 self.ui, wctx, status, match, force=force
3155 self.ui, wctx, status, match, force=force
3156 )
3156 )
3157
3157
3158 # make sure all explicit patterns are matched
3158 # make sure all explicit patterns are matched
3159 if not force:
3159 if not force:
3160 self.checkcommitpatterns(wctx, match, status, fail)
3160 self.checkcommitpatterns(wctx, match, status, fail)
3161
3161
3162 cctx = context.workingcommitctx(
3162 cctx = context.workingcommitctx(
3163 self, status, text, user, date, extra
3163 self, status, text, user, date, extra
3164 )
3164 )
3165
3165
3166 ms = mergestatemod.mergestate.read(self)
3166 ms = mergestatemod.mergestate.read(self)
3167 mergeutil.checkunresolved(ms)
3167 mergeutil.checkunresolved(ms)
3168
3168
3169 # internal config: ui.allowemptycommit
3169 # internal config: ui.allowemptycommit
3170 if cctx.isempty() and not self.ui.configbool(
3170 if cctx.isempty() and not self.ui.configbool(
3171 b'ui', b'allowemptycommit'
3171 b'ui', b'allowemptycommit'
3172 ):
3172 ):
3173 self.ui.debug(b'nothing to commit, clearing merge state\n')
3173 self.ui.debug(b'nothing to commit, clearing merge state\n')
3174 ms.reset()
3174 ms.reset()
3175 return None
3175 return None
3176
3176
3177 if merge and cctx.deleted():
3177 if merge and cctx.deleted():
3178 raise error.Abort(_(b"cannot commit merge with missing files"))
3178 raise error.Abort(_(b"cannot commit merge with missing files"))
3179
3179
3180 if editor:
3180 if editor:
3181 cctx._text = editor(self, cctx, subs)
3181 cctx._text = editor(self, cctx, subs)
3182 edited = text != cctx._text
3182 edited = text != cctx._text
3183
3183
3184 # Save commit message in case this transaction gets rolled back
3184 # Save commit message in case this transaction gets rolled back
3185 # (e.g. by a pretxncommit hook). Leave the content alone on
3185 # (e.g. by a pretxncommit hook). Leave the content alone on
3186 # the assumption that the user will use the same editor again.
3186 # the assumption that the user will use the same editor again.
3187 msg_path = self.savecommitmessage(cctx._text)
3187 msg_path = self.savecommitmessage(cctx._text)
3188
3188
3189 # commit subs and write new state
3189 # commit subs and write new state
3190 if subs:
3190 if subs:
3191 uipathfn = scmutil.getuipathfn(self)
3191 uipathfn = scmutil.getuipathfn(self)
3192 for s in sorted(commitsubs):
3192 for s in sorted(commitsubs):
3193 sub = wctx.sub(s)
3193 sub = wctx.sub(s)
3194 self.ui.status(
3194 self.ui.status(
3195 _(b'committing subrepository %s\n')
3195 _(b'committing subrepository %s\n')
3196 % uipathfn(subrepoutil.subrelpath(sub))
3196 % uipathfn(subrepoutil.subrelpath(sub))
3197 )
3197 )
3198 sr = sub.commit(cctx._text, user, date)
3198 sr = sub.commit(cctx._text, user, date)
3199 newstate[s] = (newstate[s][0], sr)
3199 newstate[s] = (newstate[s][0], sr)
3200 subrepoutil.writestate(self, newstate)
3200 subrepoutil.writestate(self, newstate)
3201
3201
3202 p1, p2 = self.dirstate.parents()
3202 p1, p2 = self.dirstate.parents()
3203 hookp1, hookp2 = hex(p1), (p2 != self.nullid and hex(p2) or b'')
3203 hookp1, hookp2 = hex(p1), (p2 != self.nullid and hex(p2) or b'')
3204 try:
3204 try:
3205 self.hook(
3205 self.hook(
3206 b"precommit", throw=True, parent1=hookp1, parent2=hookp2
3206 b"precommit", throw=True, parent1=hookp1, parent2=hookp2
3207 )
3207 )
3208 with self.transaction(b'commit'):
3208 with self.transaction(b'commit'):
3209 ret = self.commitctx(cctx, True)
3209 ret = self.commitctx(cctx, True)
3210 # update bookmarks, dirstate and mergestate
3210 # update bookmarks, dirstate and mergestate
3211 bookmarks.update(self, [p1, p2], ret)
3211 bookmarks.update(self, [p1, p2], ret)
3212 cctx.markcommitted(ret)
3212 cctx.markcommitted(ret)
3213 ms.reset()
3213 ms.reset()
3214 except: # re-raises
3214 except: # re-raises
3215 if edited:
3215 if edited:
3216 self.ui.write(
3216 self.ui.write(
3217 _(b'note: commit message saved in %s\n') % msg_path
3217 _(b'note: commit message saved in %s\n') % msg_path
3218 )
3218 )
3219 self.ui.write(
3219 self.ui.write(
3220 _(
3220 _(
3221 b"note: use 'hg commit --logfile "
3221 b"note: use 'hg commit --logfile "
3222 b"%s --edit' to reuse it\n"
3222 b"%s --edit' to reuse it\n"
3223 )
3223 )
3224 % msg_path
3224 % msg_path
3225 )
3225 )
3226 raise
3226 raise
3227
3227
3228 def commithook(unused_success):
3228 def commithook(unused_success):
3229 # hack for command that use a temporary commit (eg: histedit)
3229 # hack for command that use a temporary commit (eg: histedit)
3230 # temporary commit got stripped before hook release
3230 # temporary commit got stripped before hook release
3231 if self.changelog.hasnode(ret):
3231 if self.changelog.hasnode(ret):
3232 self.hook(
3232 self.hook(
3233 b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2
3233 b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2
3234 )
3234 )
3235
3235
3236 self._afterlock(commithook)
3236 self._afterlock(commithook)
3237 return ret
3237 return ret
3238
3238
3239 @unfilteredmethod
3239 @unfilteredmethod
3240 def commitctx(self, ctx, error=False, origctx=None):
3240 def commitctx(self, ctx, error=False, origctx=None):
3241 return commit.commitctx(self, ctx, error=error, origctx=origctx)
3241 return commit.commitctx(self, ctx, error=error, origctx=origctx)
3242
3242
3243 @unfilteredmethod
3243 @unfilteredmethod
3244 def destroying(self):
3244 def destroying(self):
3245 """Inform the repository that nodes are about to be destroyed.
3245 """Inform the repository that nodes are about to be destroyed.
3246 Intended for use by strip and rollback, so there's a common
3246 Intended for use by strip and rollback, so there's a common
3247 place for anything that has to be done before destroying history.
3247 place for anything that has to be done before destroying history.
3248
3248
3249 This is mostly useful for saving state that is in memory and waiting
3249 This is mostly useful for saving state that is in memory and waiting
3250 to be flushed when the current lock is released. Because a call to
3250 to be flushed when the current lock is released. Because a call to
3251 destroyed is imminent, the repo will be invalidated causing those
3251 destroyed is imminent, the repo will be invalidated causing those
3252 changes to stay in memory (waiting for the next unlock), or vanish
3252 changes to stay in memory (waiting for the next unlock), or vanish
3253 completely.
3253 completely.
3254 """
3254 """
3255 # When using the same lock to commit and strip, the phasecache is left
3255 # When using the same lock to commit and strip, the phasecache is left
3256 # dirty after committing. Then when we strip, the repo is invalidated,
3256 # dirty after committing. Then when we strip, the repo is invalidated,
3257 # causing those changes to disappear.
3257 # causing those changes to disappear.
3258 if '_phasecache' in vars(self):
3258 if '_phasecache' in vars(self):
3259 self._phasecache.write()
3259 self._phasecache.write()
3260
3260
3261 @unfilteredmethod
3261 @unfilteredmethod
3262 def destroyed(self):
3262 def destroyed(self):
3263 """Inform the repository that nodes have been destroyed.
3263 """Inform the repository that nodes have been destroyed.
3264 Intended for use by strip and rollback, so there's a common
3264 Intended for use by strip and rollback, so there's a common
3265 place for anything that has to be done after destroying history.
3265 place for anything that has to be done after destroying history.
3266 """
3266 """
3267 # When one tries to:
3267 # When one tries to:
3268 # 1) destroy nodes thus calling this method (e.g. strip)
3268 # 1) destroy nodes thus calling this method (e.g. strip)
3269 # 2) use phasecache somewhere (e.g. commit)
3269 # 2) use phasecache somewhere (e.g. commit)
3270 #
3270 #
3271 # then 2) will fail because the phasecache contains nodes that were
3271 # then 2) will fail because the phasecache contains nodes that were
3272 # removed. We can either remove phasecache from the filecache,
3272 # removed. We can either remove phasecache from the filecache,
3273 # causing it to reload next time it is accessed, or simply filter
3273 # causing it to reload next time it is accessed, or simply filter
3274 # the removed nodes now and write the updated cache.
3274 # the removed nodes now and write the updated cache.
3275 self._phasecache.filterunknown(self)
3275 self._phasecache.filterunknown(self)
3276 self._phasecache.write()
3276 self._phasecache.write()
3277
3277
3278 # refresh all repository caches
3278 # refresh all repository caches
3279 self.updatecaches()
3279 self.updatecaches()
3280
3280
3281 # Ensure the persistent tag cache is updated. Doing it now
3281 # Ensure the persistent tag cache is updated. Doing it now
3282 # means that the tag cache only has to worry about destroyed
3282 # means that the tag cache only has to worry about destroyed
3283 # heads immediately after a strip/rollback. That in turn
3283 # heads immediately after a strip/rollback. That in turn
3284 # guarantees that "cachetip == currenttip" (comparing both rev
3284 # guarantees that "cachetip == currenttip" (comparing both rev
3285 # and node) always means no nodes have been added or destroyed.
3285 # and node) always means no nodes have been added or destroyed.
3286
3286
3287 # XXX this is suboptimal when qrefresh'ing: we strip the current
3287 # XXX this is suboptimal when qrefresh'ing: we strip the current
3288 # head, refresh the tag cache, then immediately add a new head.
3288 # head, refresh the tag cache, then immediately add a new head.
3289 # But I think doing it this way is necessary for the "instant
3289 # But I think doing it this way is necessary for the "instant
3290 # tag cache retrieval" case to work.
3290 # tag cache retrieval" case to work.
3291 self.invalidate()
3291 self.invalidate()
3292
3292
3293 def status(
3293 def status(
3294 self,
3294 self,
3295 node1=b'.',
3295 node1=b'.',
3296 node2=None,
3296 node2=None,
3297 match=None,
3297 match=None,
3298 ignored=False,
3298 ignored=False,
3299 clean=False,
3299 clean=False,
3300 unknown=False,
3300 unknown=False,
3301 listsubrepos=False,
3301 listsubrepos=False,
3302 ):
3302 ):
3303 '''a convenience method that calls node1.status(node2)'''
3303 '''a convenience method that calls node1.status(node2)'''
3304 return self[node1].status(
3304 return self[node1].status(
3305 node2, match, ignored, clean, unknown, listsubrepos
3305 node2, match, ignored, clean, unknown, listsubrepos
3306 )
3306 )
3307
3307
3308 def addpostdsstatus(self, ps):
3308 def addpostdsstatus(self, ps):
3309 """Add a callback to run within the wlock, at the point at which status
3309 """Add a callback to run within the wlock, at the point at which status
3310 fixups happen.
3310 fixups happen.
3311
3311
3312 On status completion, callback(wctx, status) will be called with the
3312 On status completion, callback(wctx, status) will be called with the
3313 wlock held, unless the dirstate has changed from underneath or the wlock
3313 wlock held, unless the dirstate has changed from underneath or the wlock
3314 couldn't be grabbed.
3314 couldn't be grabbed.
3315
3315
3316 Callbacks should not capture and use a cached copy of the dirstate --
3316 Callbacks should not capture and use a cached copy of the dirstate --
3317 it might change in the meanwhile. Instead, they should access the
3317 it might change in the meanwhile. Instead, they should access the
3318 dirstate via wctx.repo().dirstate.
3318 dirstate via wctx.repo().dirstate.
3319
3319
3320 This list is emptied out after each status run -- extensions should
3320 This list is emptied out after each status run -- extensions should
3321 make sure it adds to this list each time dirstate.status is called.
3321 make sure it adds to this list each time dirstate.status is called.
3322 Extensions should also make sure they don't call this for statuses
3322 Extensions should also make sure they don't call this for statuses
3323 that don't involve the dirstate.
3323 that don't involve the dirstate.
3324 """
3324 """
3325
3325
3326 # The list is located here for uniqueness reasons -- it is actually
3326 # The list is located here for uniqueness reasons -- it is actually
3327 # managed by the workingctx, but that isn't unique per-repo.
3327 # managed by the workingctx, but that isn't unique per-repo.
3328 self._postdsstatus.append(ps)
3328 self._postdsstatus.append(ps)
3329
3329
3330 def postdsstatus(self):
3330 def postdsstatus(self):
3331 """Used by workingctx to get the list of post-dirstate-status hooks."""
3331 """Used by workingctx to get the list of post-dirstate-status hooks."""
3332 return self._postdsstatus
3332 return self._postdsstatus
3333
3333
3334 def clearpostdsstatus(self):
3334 def clearpostdsstatus(self):
3335 """Used by workingctx to clear post-dirstate-status hooks."""
3335 """Used by workingctx to clear post-dirstate-status hooks."""
3336 del self._postdsstatus[:]
3336 del self._postdsstatus[:]
3337
3337
3338 def heads(self, start=None):
3338 def heads(self, start=None):
3339 if start is None:
3339 if start is None:
3340 cl = self.changelog
3340 cl = self.changelog
3341 headrevs = reversed(cl.headrevs())
3341 headrevs = reversed(cl.headrevs())
3342 return [cl.node(rev) for rev in headrevs]
3342 return [cl.node(rev) for rev in headrevs]
3343
3343
3344 heads = self.changelog.heads(start)
3344 heads = self.changelog.heads(start)
3345 # sort the output in rev descending order
3345 # sort the output in rev descending order
3346 return sorted(heads, key=self.changelog.rev, reverse=True)
3346 return sorted(heads, key=self.changelog.rev, reverse=True)
3347
3347
3348 def branchheads(self, branch=None, start=None, closed=False):
3348 def branchheads(self, branch=None, start=None, closed=False):
3349 """return a (possibly filtered) list of heads for the given branch
3349 """return a (possibly filtered) list of heads for the given branch
3350
3350
3351 Heads are returned in topological order, from newest to oldest.
3351 Heads are returned in topological order, from newest to oldest.
3352 If branch is None, use the dirstate branch.
3352 If branch is None, use the dirstate branch.
3353 If start is not None, return only heads reachable from start.
3353 If start is not None, return only heads reachable from start.
3354 If closed is True, return heads that are marked as closed as well.
3354 If closed is True, return heads that are marked as closed as well.
3355 """
3355 """
3356 if branch is None:
3356 if branch is None:
3357 branch = self[None].branch()
3357 branch = self[None].branch()
3358 branches = self.branchmap()
3358 branches = self.branchmap()
3359 if not branches.hasbranch(branch):
3359 if not branches.hasbranch(branch):
3360 return []
3360 return []
3361 # the cache returns heads ordered lowest to highest
3361 # the cache returns heads ordered lowest to highest
3362 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
3362 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
3363 if start is not None:
3363 if start is not None:
3364 # filter out the heads that cannot be reached from startrev
3364 # filter out the heads that cannot be reached from startrev
3365 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
3365 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
3366 bheads = [h for h in bheads if h in fbheads]
3366 bheads = [h for h in bheads if h in fbheads]
3367 return bheads
3367 return bheads
3368
3368
3369 def branches(self, nodes):
3369 def branches(self, nodes):
3370 if not nodes:
3370 if not nodes:
3371 nodes = [self.changelog.tip()]
3371 nodes = [self.changelog.tip()]
3372 b = []
3372 b = []
3373 for n in nodes:
3373 for n in nodes:
3374 t = n
3374 t = n
3375 while True:
3375 while True:
3376 p = self.changelog.parents(n)
3376 p = self.changelog.parents(n)
3377 if p[1] != self.nullid or p[0] == self.nullid:
3377 if p[1] != self.nullid or p[0] == self.nullid:
3378 b.append((t, n, p[0], p[1]))
3378 b.append((t, n, p[0], p[1]))
3379 break
3379 break
3380 n = p[0]
3380 n = p[0]
3381 return b
3381 return b
3382
3382
3383 def between(self, pairs):
3383 def between(self, pairs):
3384 r = []
3384 r = []
3385
3385
3386 for top, bottom in pairs:
3386 for top, bottom in pairs:
3387 n, l, i = top, [], 0
3387 n, l, i = top, [], 0
3388 f = 1
3388 f = 1
3389
3389
3390 while n != bottom and n != self.nullid:
3390 while n != bottom and n != self.nullid:
3391 p = self.changelog.parents(n)[0]
3391 p = self.changelog.parents(n)[0]
3392 if i == f:
3392 if i == f:
3393 l.append(n)
3393 l.append(n)
3394 f = f * 2
3394 f = f * 2
3395 n = p
3395 n = p
3396 i += 1
3396 i += 1
3397
3397
3398 r.append(l)
3398 r.append(l)
3399
3399
3400 return r
3400 return r
3401
3401
3402 def checkpush(self, pushop):
3402 def checkpush(self, pushop):
3403 """Extensions can override this function if additional checks have
3403 """Extensions can override this function if additional checks have
3404 to be performed before pushing, or call it if they override push
3404 to be performed before pushing, or call it if they override push
3405 command.
3405 command.
3406 """
3406 """
3407
3407
3408 @unfilteredpropertycache
3408 @unfilteredpropertycache
3409 def prepushoutgoinghooks(self):
3409 def prepushoutgoinghooks(self):
3410 """Return util.hooks consists of a pushop with repo, remote, outgoing
3410 """Return util.hooks consists of a pushop with repo, remote, outgoing
3411 methods, which are called before pushing changesets.
3411 methods, which are called before pushing changesets.
3412 """
3412 """
3413 return util.hooks()
3413 return util.hooks()
3414
3414
3415 def pushkey(self, namespace, key, old, new):
3415 def pushkey(self, namespace, key, old, new):
3416 try:
3416 try:
3417 tr = self.currenttransaction()
3417 tr = self.currenttransaction()
3418 hookargs = {}
3418 hookargs = {}
3419 if tr is not None:
3419 if tr is not None:
3420 hookargs.update(tr.hookargs)
3420 hookargs.update(tr.hookargs)
3421 hookargs = pycompat.strkwargs(hookargs)
3421 hookargs = pycompat.strkwargs(hookargs)
3422 hookargs['namespace'] = namespace
3422 hookargs['namespace'] = namespace
3423 hookargs['key'] = key
3423 hookargs['key'] = key
3424 hookargs['old'] = old
3424 hookargs['old'] = old
3425 hookargs['new'] = new
3425 hookargs['new'] = new
3426 self.hook(b'prepushkey', throw=True, **hookargs)
3426 self.hook(b'prepushkey', throw=True, **hookargs)
3427 except error.HookAbort as exc:
3427 except error.HookAbort as exc:
3428 self.ui.write_err(_(b"pushkey-abort: %s\n") % exc)
3428 self.ui.write_err(_(b"pushkey-abort: %s\n") % exc)
3429 if exc.hint:
3429 if exc.hint:
3430 self.ui.write_err(_(b"(%s)\n") % exc.hint)
3430 self.ui.write_err(_(b"(%s)\n") % exc.hint)
3431 return False
3431 return False
3432 self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key))
3432 self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key))
3433 ret = pushkey.push(self, namespace, key, old, new)
3433 ret = pushkey.push(self, namespace, key, old, new)
3434
3434
3435 def runhook(unused_success):
3435 def runhook(unused_success):
3436 self.hook(
3436 self.hook(
3437 b'pushkey',
3437 b'pushkey',
3438 namespace=namespace,
3438 namespace=namespace,
3439 key=key,
3439 key=key,
3440 old=old,
3440 old=old,
3441 new=new,
3441 new=new,
3442 ret=ret,
3442 ret=ret,
3443 )
3443 )
3444
3444
3445 self._afterlock(runhook)
3445 self._afterlock(runhook)
3446 return ret
3446 return ret
3447
3447
3448 def listkeys(self, namespace):
3448 def listkeys(self, namespace):
3449 self.hook(b'prelistkeys', throw=True, namespace=namespace)
3449 self.hook(b'prelistkeys', throw=True, namespace=namespace)
3450 self.ui.debug(b'listing keys for "%s"\n' % namespace)
3450 self.ui.debug(b'listing keys for "%s"\n' % namespace)
3451 values = pushkey.list(self, namespace)
3451 values = pushkey.list(self, namespace)
3452 self.hook(b'listkeys', namespace=namespace, values=values)
3452 self.hook(b'listkeys', namespace=namespace, values=values)
3453 return values
3453 return values
3454
3454
3455 def debugwireargs(self, one, two, three=None, four=None, five=None):
3455 def debugwireargs(self, one, two, three=None, four=None, five=None):
3456 '''used to test argument passing over the wire'''
3456 '''used to test argument passing over the wire'''
3457 return b"%s %s %s %s %s" % (
3457 return b"%s %s %s %s %s" % (
3458 one,
3458 one,
3459 two,
3459 two,
3460 pycompat.bytestr(three),
3460 pycompat.bytestr(three),
3461 pycompat.bytestr(four),
3461 pycompat.bytestr(four),
3462 pycompat.bytestr(five),
3462 pycompat.bytestr(five),
3463 )
3463 )
3464
3464
3465 def savecommitmessage(self, text):
3465 def savecommitmessage(self, text):
3466 fp = self.vfs(b'last-message.txt', b'wb')
3466 fp = self.vfs(b'last-message.txt', b'wb')
3467 try:
3467 try:
3468 fp.write(text)
3468 fp.write(text)
3469 finally:
3469 finally:
3470 fp.close()
3470 fp.close()
3471 return self.pathto(fp.name[len(self.root) + 1 :])
3471 return self.pathto(fp.name[len(self.root) + 1 :])
3472
3472
3473 def register_wanted_sidedata(self, category):
3473 def register_wanted_sidedata(self, category):
3474 if repository.REPO_FEATURE_SIDE_DATA not in self.features:
3474 if repository.REPO_FEATURE_SIDE_DATA not in self.features:
3475 # Only revlogv2 repos can want sidedata.
3475 # Only revlogv2 repos can want sidedata.
3476 return
3476 return
3477 self._wanted_sidedata.add(pycompat.bytestr(category))
3477 self._wanted_sidedata.add(pycompat.bytestr(category))
3478
3478
3479 def register_sidedata_computer(
3479 def register_sidedata_computer(
3480 self, kind, category, keys, computer, flags, replace=False
3480 self, kind, category, keys, computer, flags, replace=False
3481 ):
3481 ):
3482 if kind not in revlogconst.ALL_KINDS:
3482 if kind not in revlogconst.ALL_KINDS:
3483 msg = _(b"unexpected revlog kind '%s'.")
3483 msg = _(b"unexpected revlog kind '%s'.")
3484 raise error.ProgrammingError(msg % kind)
3484 raise error.ProgrammingError(msg % kind)
3485 category = pycompat.bytestr(category)
3485 category = pycompat.bytestr(category)
3486 already_registered = category in self._sidedata_computers.get(kind, [])
3486 already_registered = category in self._sidedata_computers.get(kind, [])
3487 if already_registered and not replace:
3487 if already_registered and not replace:
3488 msg = _(
3488 msg = _(
3489 b"cannot register a sidedata computer twice for category '%s'."
3489 b"cannot register a sidedata computer twice for category '%s'."
3490 )
3490 )
3491 raise error.ProgrammingError(msg % category)
3491 raise error.ProgrammingError(msg % category)
3492 if replace and not already_registered:
3492 if replace and not already_registered:
3493 msg = _(
3493 msg = _(
3494 b"cannot replace a sidedata computer that isn't registered "
3494 b"cannot replace a sidedata computer that isn't registered "
3495 b"for category '%s'."
3495 b"for category '%s'."
3496 )
3496 )
3497 raise error.ProgrammingError(msg % category)
3497 raise error.ProgrammingError(msg % category)
3498 self._sidedata_computers.setdefault(kind, {})
3498 self._sidedata_computers.setdefault(kind, {})
3499 self._sidedata_computers[kind][category] = (keys, computer, flags)
3499 self._sidedata_computers[kind][category] = (keys, computer, flags)
3500
3500
3501
3501
3502 # used to avoid circular references so destructors work
3502 # used to avoid circular references so destructors work
3503 def aftertrans(files):
3503 def aftertrans(files):
3504 renamefiles = [tuple(t) for t in files]
3504 renamefiles = [tuple(t) for t in files]
3505
3505
3506 def a():
3506 def a():
3507 for vfs, src, dest in renamefiles:
3507 for vfs, src, dest in renamefiles:
3508 # if src and dest refer to a same file, vfs.rename is a no-op,
3508 # if src and dest refer to a same file, vfs.rename is a no-op,
3509 # leaving both src and dest on disk. delete dest to make sure
3509 # leaving both src and dest on disk. delete dest to make sure
3510 # the rename couldn't be such a no-op.
3510 # the rename couldn't be such a no-op.
3511 vfs.tryunlink(dest)
3511 vfs.tryunlink(dest)
3512 try:
3512 try:
3513 vfs.rename(src, dest)
3513 vfs.rename(src, dest)
3514 except FileNotFoundError: # journal file does not yet exist
3514 except FileNotFoundError: # journal file does not yet exist
3515 pass
3515 pass
3516
3516
3517 return a
3517 return a
3518
3518
3519
3519
3520 def undoname(fn):
3520 def undoname(fn):
3521 base, name = os.path.split(fn)
3521 base, name = os.path.split(fn)
3522 assert name.startswith(b'journal')
3522 assert name.startswith(b'journal')
3523 return os.path.join(base, name.replace(b'journal', b'undo', 1))
3523 return os.path.join(base, name.replace(b'journal', b'undo', 1))
3524
3524
3525
3525
3526 def instance(ui, path, create, intents=None, createopts=None):
3526 def instance(ui, path, create, intents=None, createopts=None):
3527
3527
3528 # prevent cyclic import localrepo -> upgrade -> localrepo
3528 # prevent cyclic import localrepo -> upgrade -> localrepo
3529 from . import upgrade
3529 from . import upgrade
3530
3530
3531 localpath = urlutil.urllocalpath(path)
3531 localpath = urlutil.urllocalpath(path)
3532 if create:
3532 if create:
3533 createrepository(ui, localpath, createopts=createopts)
3533 createrepository(ui, localpath, createopts=createopts)
3534
3534
3535 def repo_maker():
3535 def repo_maker():
3536 return makelocalrepository(ui, localpath, intents=intents)
3536 return makelocalrepository(ui, localpath, intents=intents)
3537
3537
3538 repo = repo_maker()
3538 repo = repo_maker()
3539 repo = upgrade.may_auto_upgrade(repo, repo_maker)
3539 repo = upgrade.may_auto_upgrade(repo, repo_maker)
3540 return repo
3540 return repo
3541
3541
3542
3542
3543 def islocal(path):
3543 def islocal(path):
3544 return True
3544 return True
3545
3545
3546
3546
3547 def defaultcreateopts(ui, createopts=None):
3547 def defaultcreateopts(ui, createopts=None):
3548 """Populate the default creation options for a repository.
3548 """Populate the default creation options for a repository.
3549
3549
3550 A dictionary of explicitly requested creation options can be passed
3550 A dictionary of explicitly requested creation options can be passed
3551 in. Missing keys will be populated.
3551 in. Missing keys will be populated.
3552 """
3552 """
3553 createopts = dict(createopts or {})
3553 createopts = dict(createopts or {})
3554
3554
3555 if b'backend' not in createopts:
3555 if b'backend' not in createopts:
3556 # experimental config: storage.new-repo-backend
3556 # experimental config: storage.new-repo-backend
3557 createopts[b'backend'] = ui.config(b'storage', b'new-repo-backend')
3557 createopts[b'backend'] = ui.config(b'storage', b'new-repo-backend')
3558
3558
3559 return createopts
3559 return createopts
3560
3560
3561
3561
3562 def clone_requirements(ui, createopts, srcrepo):
3562 def clone_requirements(ui, createopts, srcrepo):
3563 """clone the requirements of a local repo for a local clone
3563 """clone the requirements of a local repo for a local clone
3564
3564
3565 The store requirements are unchanged while the working copy requirements
3565 The store requirements are unchanged while the working copy requirements
3566 depends on the configuration
3566 depends on the configuration
3567 """
3567 """
3568 target_requirements = set()
3568 target_requirements = set()
3569 if not srcrepo.requirements:
3569 if not srcrepo.requirements:
3570 # this is a legacy revlog "v0" repository, we cannot do anything fancy
3570 # this is a legacy revlog "v0" repository, we cannot do anything fancy
3571 # with it.
3571 # with it.
3572 return target_requirements
3572 return target_requirements
3573 createopts = defaultcreateopts(ui, createopts=createopts)
3573 createopts = defaultcreateopts(ui, createopts=createopts)
3574 for r in newreporequirements(ui, createopts):
3574 for r in newreporequirements(ui, createopts):
3575 if r in requirementsmod.WORKING_DIR_REQUIREMENTS:
3575 if r in requirementsmod.WORKING_DIR_REQUIREMENTS:
3576 target_requirements.add(r)
3576 target_requirements.add(r)
3577
3577
3578 for r in srcrepo.requirements:
3578 for r in srcrepo.requirements:
3579 if r not in requirementsmod.WORKING_DIR_REQUIREMENTS:
3579 if r not in requirementsmod.WORKING_DIR_REQUIREMENTS:
3580 target_requirements.add(r)
3580 target_requirements.add(r)
3581 return target_requirements
3581 return target_requirements
3582
3582
3583
3583
3584 def newreporequirements(ui, createopts):
3584 def newreporequirements(ui, createopts):
3585 """Determine the set of requirements for a new local repository.
3585 """Determine the set of requirements for a new local repository.
3586
3586
3587 Extensions can wrap this function to specify custom requirements for
3587 Extensions can wrap this function to specify custom requirements for
3588 new repositories.
3588 new repositories.
3589 """
3589 """
3590
3590
3591 if b'backend' not in createopts:
3591 if b'backend' not in createopts:
3592 raise error.ProgrammingError(
3592 raise error.ProgrammingError(
3593 b'backend key not present in createopts; '
3593 b'backend key not present in createopts; '
3594 b'was defaultcreateopts() called?'
3594 b'was defaultcreateopts() called?'
3595 )
3595 )
3596
3596
3597 if createopts[b'backend'] != b'revlogv1':
3597 if createopts[b'backend'] != b'revlogv1':
3598 raise error.Abort(
3598 raise error.Abort(
3599 _(
3599 _(
3600 b'unable to determine repository requirements for '
3600 b'unable to determine repository requirements for '
3601 b'storage backend: %s'
3601 b'storage backend: %s'
3602 )
3602 )
3603 % createopts[b'backend']
3603 % createopts[b'backend']
3604 )
3604 )
3605
3605
3606 requirements = {requirementsmod.REVLOGV1_REQUIREMENT}
3606 requirements = {requirementsmod.REVLOGV1_REQUIREMENT}
3607 if ui.configbool(b'format', b'usestore'):
3607 if ui.configbool(b'format', b'usestore'):
3608 requirements.add(requirementsmod.STORE_REQUIREMENT)
3608 requirements.add(requirementsmod.STORE_REQUIREMENT)
3609 if ui.configbool(b'format', b'usefncache'):
3609 if ui.configbool(b'format', b'usefncache'):
3610 requirements.add(requirementsmod.FNCACHE_REQUIREMENT)
3610 requirements.add(requirementsmod.FNCACHE_REQUIREMENT)
3611 if ui.configbool(b'format', b'dotencode'):
3611 if ui.configbool(b'format', b'dotencode'):
3612 requirements.add(requirementsmod.DOTENCODE_REQUIREMENT)
3612 requirements.add(requirementsmod.DOTENCODE_REQUIREMENT)
3613
3613
3614 compengines = ui.configlist(b'format', b'revlog-compression')
3614 compengines = ui.configlist(b'format', b'revlog-compression')
3615 for compengine in compengines:
3615 for compengine in compengines:
3616 if compengine in util.compengines:
3616 if compengine in util.compengines:
3617 engine = util.compengines[compengine]
3617 engine = util.compengines[compengine]
3618 if engine.available() and engine.revlogheader():
3618 if engine.available() and engine.revlogheader():
3619 break
3619 break
3620 else:
3620 else:
3621 raise error.Abort(
3621 raise error.Abort(
3622 _(
3622 _(
3623 b'compression engines %s defined by '
3623 b'compression engines %s defined by '
3624 b'format.revlog-compression not available'
3624 b'format.revlog-compression not available'
3625 )
3625 )
3626 % b', '.join(b'"%s"' % e for e in compengines),
3626 % b', '.join(b'"%s"' % e for e in compengines),
3627 hint=_(
3627 hint=_(
3628 b'run "hg debuginstall" to list available '
3628 b'run "hg debuginstall" to list available '
3629 b'compression engines'
3629 b'compression engines'
3630 ),
3630 ),
3631 )
3631 )
3632
3632
3633 # zlib is the historical default and doesn't need an explicit requirement.
3633 # zlib is the historical default and doesn't need an explicit requirement.
3634 if compengine == b'zstd':
3634 if compengine == b'zstd':
3635 requirements.add(b'revlog-compression-zstd')
3635 requirements.add(b'revlog-compression-zstd')
3636 elif compengine != b'zlib':
3636 elif compengine != b'zlib':
3637 requirements.add(b'exp-compression-%s' % compengine)
3637 requirements.add(b'exp-compression-%s' % compengine)
3638
3638
3639 if scmutil.gdinitconfig(ui):
3639 if scmutil.gdinitconfig(ui):
3640 requirements.add(requirementsmod.GENERALDELTA_REQUIREMENT)
3640 requirements.add(requirementsmod.GENERALDELTA_REQUIREMENT)
3641 if ui.configbool(b'format', b'sparse-revlog'):
3641 if ui.configbool(b'format', b'sparse-revlog'):
3642 requirements.add(requirementsmod.SPARSEREVLOG_REQUIREMENT)
3642 requirements.add(requirementsmod.SPARSEREVLOG_REQUIREMENT)
3643
3643
3644 # experimental config: format.use-dirstate-v2
3644 # experimental config: format.use-dirstate-v2
3645 # Keep this logic in sync with `has_dirstate_v2()` in `tests/hghave.py`
3645 # Keep this logic in sync with `has_dirstate_v2()` in `tests/hghave.py`
3646 if ui.configbool(b'format', b'use-dirstate-v2'):
3646 if ui.configbool(b'format', b'use-dirstate-v2'):
3647 requirements.add(requirementsmod.DIRSTATE_V2_REQUIREMENT)
3647 requirements.add(requirementsmod.DIRSTATE_V2_REQUIREMENT)
3648
3648
3649 # experimental config: format.exp-use-copies-side-data-changeset
3649 # experimental config: format.exp-use-copies-side-data-changeset
3650 if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'):
3650 if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'):
3651 requirements.add(requirementsmod.CHANGELOGV2_REQUIREMENT)
3651 requirements.add(requirementsmod.CHANGELOGV2_REQUIREMENT)
3652 requirements.add(requirementsmod.COPIESSDC_REQUIREMENT)
3652 requirements.add(requirementsmod.COPIESSDC_REQUIREMENT)
3653 if ui.configbool(b'experimental', b'treemanifest'):
3653 if ui.configbool(b'experimental', b'treemanifest'):
3654 requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
3654 requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
3655
3655
3656 changelogv2 = ui.config(b'format', b'exp-use-changelog-v2')
3656 changelogv2 = ui.config(b'format', b'exp-use-changelog-v2')
3657 if changelogv2 == b'enable-unstable-format-and-corrupt-my-data':
3657 if changelogv2 == b'enable-unstable-format-and-corrupt-my-data':
3658 requirements.add(requirementsmod.CHANGELOGV2_REQUIREMENT)
3658 requirements.add(requirementsmod.CHANGELOGV2_REQUIREMENT)
3659
3659
3660 revlogv2 = ui.config(b'experimental', b'revlogv2')
3660 revlogv2 = ui.config(b'experimental', b'revlogv2')
3661 if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
3661 if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
3662 requirements.discard(requirementsmod.REVLOGV1_REQUIREMENT)
3662 requirements.discard(requirementsmod.REVLOGV1_REQUIREMENT)
3663 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3663 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3664 # experimental config: format.internal-phase
3664 # experimental config: format.internal-phase
3665 if ui.configbool(b'format', b'internal-phase'):
3665 if ui.configbool(b'format', b'use-internal-phase'):
3666 requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
3666 requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
3667
3667
3668 # experimental config: format.exp-archived-phase
3668 # experimental config: format.exp-archived-phase
3669 if ui.configbool(b'format', b'exp-archived-phase'):
3669 if ui.configbool(b'format', b'exp-archived-phase'):
3670 requirements.add(requirementsmod.ARCHIVED_PHASE_REQUIREMENT)
3670 requirements.add(requirementsmod.ARCHIVED_PHASE_REQUIREMENT)
3671
3671
3672 if createopts.get(b'narrowfiles'):
3672 if createopts.get(b'narrowfiles'):
3673 requirements.add(requirementsmod.NARROW_REQUIREMENT)
3673 requirements.add(requirementsmod.NARROW_REQUIREMENT)
3674
3674
3675 if createopts.get(b'lfs'):
3675 if createopts.get(b'lfs'):
3676 requirements.add(b'lfs')
3676 requirements.add(b'lfs')
3677
3677
3678 if ui.configbool(b'format', b'bookmarks-in-store'):
3678 if ui.configbool(b'format', b'bookmarks-in-store'):
3679 requirements.add(requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT)
3679 requirements.add(requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT)
3680
3680
3681 if ui.configbool(b'format', b'use-persistent-nodemap'):
3681 if ui.configbool(b'format', b'use-persistent-nodemap'):
3682 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
3682 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
3683
3683
3684 # if share-safe is enabled, let's create the new repository with the new
3684 # if share-safe is enabled, let's create the new repository with the new
3685 # requirement
3685 # requirement
3686 if ui.configbool(b'format', b'use-share-safe'):
3686 if ui.configbool(b'format', b'use-share-safe'):
3687 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
3687 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
3688
3688
3689 # if we are creating a share-repoΒΉ we have to handle requirement
3689 # if we are creating a share-repoΒΉ we have to handle requirement
3690 # differently.
3690 # differently.
3691 #
3691 #
3692 # [1] (i.e. reusing the store from another repository, just having a
3692 # [1] (i.e. reusing the store from another repository, just having a
3693 # working copy)
3693 # working copy)
3694 if b'sharedrepo' in createopts:
3694 if b'sharedrepo' in createopts:
3695 source_requirements = set(createopts[b'sharedrepo'].requirements)
3695 source_requirements = set(createopts[b'sharedrepo'].requirements)
3696
3696
3697 if requirementsmod.SHARESAFE_REQUIREMENT not in source_requirements:
3697 if requirementsmod.SHARESAFE_REQUIREMENT not in source_requirements:
3698 # share to an old school repository, we have to copy the
3698 # share to an old school repository, we have to copy the
3699 # requirements and hope for the best.
3699 # requirements and hope for the best.
3700 requirements = source_requirements
3700 requirements = source_requirements
3701 else:
3701 else:
3702 # We have control on the working copy only, so "copy" the non
3702 # We have control on the working copy only, so "copy" the non
3703 # working copy part over, ignoring previous logic.
3703 # working copy part over, ignoring previous logic.
3704 to_drop = set()
3704 to_drop = set()
3705 for req in requirements:
3705 for req in requirements:
3706 if req in requirementsmod.WORKING_DIR_REQUIREMENTS:
3706 if req in requirementsmod.WORKING_DIR_REQUIREMENTS:
3707 continue
3707 continue
3708 if req in source_requirements:
3708 if req in source_requirements:
3709 continue
3709 continue
3710 to_drop.add(req)
3710 to_drop.add(req)
3711 requirements -= to_drop
3711 requirements -= to_drop
3712 requirements |= source_requirements
3712 requirements |= source_requirements
3713
3713
3714 if createopts.get(b'sharedrelative'):
3714 if createopts.get(b'sharedrelative'):
3715 requirements.add(requirementsmod.RELATIVE_SHARED_REQUIREMENT)
3715 requirements.add(requirementsmod.RELATIVE_SHARED_REQUIREMENT)
3716 else:
3716 else:
3717 requirements.add(requirementsmod.SHARED_REQUIREMENT)
3717 requirements.add(requirementsmod.SHARED_REQUIREMENT)
3718
3718
3719 if ui.configbool(b'format', b'use-dirstate-tracked-hint'):
3719 if ui.configbool(b'format', b'use-dirstate-tracked-hint'):
3720 version = ui.configint(b'format', b'use-dirstate-tracked-hint.version')
3720 version = ui.configint(b'format', b'use-dirstate-tracked-hint.version')
3721 msg = _("ignoring unknown tracked key version: %d\n")
3721 msg = _("ignoring unknown tracked key version: %d\n")
3722 hint = _("see `hg help config.format.use-dirstate-tracked-hint-version")
3722 hint = _("see `hg help config.format.use-dirstate-tracked-hint-version")
3723 if version != 1:
3723 if version != 1:
3724 ui.warn(msg % version, hint=hint)
3724 ui.warn(msg % version, hint=hint)
3725 else:
3725 else:
3726 requirements.add(requirementsmod.DIRSTATE_TRACKED_HINT_V1)
3726 requirements.add(requirementsmod.DIRSTATE_TRACKED_HINT_V1)
3727
3727
3728 return requirements
3728 return requirements
3729
3729
3730
3730
3731 def checkrequirementscompat(ui, requirements):
3731 def checkrequirementscompat(ui, requirements):
3732 """Checks compatibility of repository requirements enabled and disabled.
3732 """Checks compatibility of repository requirements enabled and disabled.
3733
3733
3734 Returns a set of requirements which needs to be dropped because dependend
3734 Returns a set of requirements which needs to be dropped because dependend
3735 requirements are not enabled. Also warns users about it"""
3735 requirements are not enabled. Also warns users about it"""
3736
3736
3737 dropped = set()
3737 dropped = set()
3738
3738
3739 if requirementsmod.STORE_REQUIREMENT not in requirements:
3739 if requirementsmod.STORE_REQUIREMENT not in requirements:
3740 if requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT in requirements:
3740 if requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT in requirements:
3741 ui.warn(
3741 ui.warn(
3742 _(
3742 _(
3743 b'ignoring enabled \'format.bookmarks-in-store\' config '
3743 b'ignoring enabled \'format.bookmarks-in-store\' config '
3744 b'beacuse it is incompatible with disabled '
3744 b'beacuse it is incompatible with disabled '
3745 b'\'format.usestore\' config\n'
3745 b'\'format.usestore\' config\n'
3746 )
3746 )
3747 )
3747 )
3748 dropped.add(requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT)
3748 dropped.add(requirementsmod.BOOKMARKS_IN_STORE_REQUIREMENT)
3749
3749
3750 if (
3750 if (
3751 requirementsmod.SHARED_REQUIREMENT in requirements
3751 requirementsmod.SHARED_REQUIREMENT in requirements
3752 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
3752 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
3753 ):
3753 ):
3754 raise error.Abort(
3754 raise error.Abort(
3755 _(
3755 _(
3756 b"cannot create shared repository as source was created"
3756 b"cannot create shared repository as source was created"
3757 b" with 'format.usestore' config disabled"
3757 b" with 'format.usestore' config disabled"
3758 )
3758 )
3759 )
3759 )
3760
3760
3761 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
3761 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
3762 if ui.hasconfig(b'format', b'use-share-safe'):
3762 if ui.hasconfig(b'format', b'use-share-safe'):
3763 msg = _(
3763 msg = _(
3764 b"ignoring enabled 'format.use-share-safe' config because "
3764 b"ignoring enabled 'format.use-share-safe' config because "
3765 b"it is incompatible with disabled 'format.usestore'"
3765 b"it is incompatible with disabled 'format.usestore'"
3766 b" config\n"
3766 b" config\n"
3767 )
3767 )
3768 ui.warn(msg)
3768 ui.warn(msg)
3769 dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
3769 dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
3770
3770
3771 return dropped
3771 return dropped
3772
3772
3773
3773
3774 def filterknowncreateopts(ui, createopts):
3774 def filterknowncreateopts(ui, createopts):
3775 """Filters a dict of repo creation options against options that are known.
3775 """Filters a dict of repo creation options against options that are known.
3776
3776
3777 Receives a dict of repo creation options and returns a dict of those
3777 Receives a dict of repo creation options and returns a dict of those
3778 options that we don't know how to handle.
3778 options that we don't know how to handle.
3779
3779
3780 This function is called as part of repository creation. If the
3780 This function is called as part of repository creation. If the
3781 returned dict contains any items, repository creation will not
3781 returned dict contains any items, repository creation will not
3782 be allowed, as it means there was a request to create a repository
3782 be allowed, as it means there was a request to create a repository
3783 with options not recognized by loaded code.
3783 with options not recognized by loaded code.
3784
3784
3785 Extensions can wrap this function to filter out creation options
3785 Extensions can wrap this function to filter out creation options
3786 they know how to handle.
3786 they know how to handle.
3787 """
3787 """
3788 known = {
3788 known = {
3789 b'backend',
3789 b'backend',
3790 b'lfs',
3790 b'lfs',
3791 b'narrowfiles',
3791 b'narrowfiles',
3792 b'sharedrepo',
3792 b'sharedrepo',
3793 b'sharedrelative',
3793 b'sharedrelative',
3794 b'shareditems',
3794 b'shareditems',
3795 b'shallowfilestore',
3795 b'shallowfilestore',
3796 }
3796 }
3797
3797
3798 return {k: v for k, v in createopts.items() if k not in known}
3798 return {k: v for k, v in createopts.items() if k not in known}
3799
3799
3800
3800
3801 def createrepository(ui, path, createopts=None, requirements=None):
3801 def createrepository(ui, path, createopts=None, requirements=None):
3802 """Create a new repository in a vfs.
3802 """Create a new repository in a vfs.
3803
3803
3804 ``path`` path to the new repo's working directory.
3804 ``path`` path to the new repo's working directory.
3805 ``createopts`` options for the new repository.
3805 ``createopts`` options for the new repository.
3806 ``requirement`` predefined set of requirements.
3806 ``requirement`` predefined set of requirements.
3807 (incompatible with ``createopts``)
3807 (incompatible with ``createopts``)
3808
3808
3809 The following keys for ``createopts`` are recognized:
3809 The following keys for ``createopts`` are recognized:
3810
3810
3811 backend
3811 backend
3812 The storage backend to use.
3812 The storage backend to use.
3813 lfs
3813 lfs
3814 Repository will be created with ``lfs`` requirement. The lfs extension
3814 Repository will be created with ``lfs`` requirement. The lfs extension
3815 will automatically be loaded when the repository is accessed.
3815 will automatically be loaded when the repository is accessed.
3816 narrowfiles
3816 narrowfiles
3817 Set up repository to support narrow file storage.
3817 Set up repository to support narrow file storage.
3818 sharedrepo
3818 sharedrepo
3819 Repository object from which storage should be shared.
3819 Repository object from which storage should be shared.
3820 sharedrelative
3820 sharedrelative
3821 Boolean indicating if the path to the shared repo should be
3821 Boolean indicating if the path to the shared repo should be
3822 stored as relative. By default, the pointer to the "parent" repo
3822 stored as relative. By default, the pointer to the "parent" repo
3823 is stored as an absolute path.
3823 is stored as an absolute path.
3824 shareditems
3824 shareditems
3825 Set of items to share to the new repository (in addition to storage).
3825 Set of items to share to the new repository (in addition to storage).
3826 shallowfilestore
3826 shallowfilestore
3827 Indicates that storage for files should be shallow (not all ancestor
3827 Indicates that storage for files should be shallow (not all ancestor
3828 revisions are known).
3828 revisions are known).
3829 """
3829 """
3830
3830
3831 if requirements is not None:
3831 if requirements is not None:
3832 if createopts is not None:
3832 if createopts is not None:
3833 msg = b'cannot specify both createopts and requirements'
3833 msg = b'cannot specify both createopts and requirements'
3834 raise error.ProgrammingError(msg)
3834 raise error.ProgrammingError(msg)
3835 createopts = {}
3835 createopts = {}
3836 else:
3836 else:
3837 createopts = defaultcreateopts(ui, createopts=createopts)
3837 createopts = defaultcreateopts(ui, createopts=createopts)
3838
3838
3839 unknownopts = filterknowncreateopts(ui, createopts)
3839 unknownopts = filterknowncreateopts(ui, createopts)
3840
3840
3841 if not isinstance(unknownopts, dict):
3841 if not isinstance(unknownopts, dict):
3842 raise error.ProgrammingError(
3842 raise error.ProgrammingError(
3843 b'filterknowncreateopts() did not return a dict'
3843 b'filterknowncreateopts() did not return a dict'
3844 )
3844 )
3845
3845
3846 if unknownopts:
3846 if unknownopts:
3847 raise error.Abort(
3847 raise error.Abort(
3848 _(
3848 _(
3849 b'unable to create repository because of unknown '
3849 b'unable to create repository because of unknown '
3850 b'creation option: %s'
3850 b'creation option: %s'
3851 )
3851 )
3852 % b', '.join(sorted(unknownopts)),
3852 % b', '.join(sorted(unknownopts)),
3853 hint=_(b'is a required extension not loaded?'),
3853 hint=_(b'is a required extension not loaded?'),
3854 )
3854 )
3855
3855
3856 requirements = newreporequirements(ui, createopts=createopts)
3856 requirements = newreporequirements(ui, createopts=createopts)
3857 requirements -= checkrequirementscompat(ui, requirements)
3857 requirements -= checkrequirementscompat(ui, requirements)
3858
3858
3859 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
3859 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
3860
3860
3861 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
3861 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
3862 if hgvfs.exists():
3862 if hgvfs.exists():
3863 raise error.RepoError(_(b'repository %s already exists') % path)
3863 raise error.RepoError(_(b'repository %s already exists') % path)
3864
3864
3865 if b'sharedrepo' in createopts:
3865 if b'sharedrepo' in createopts:
3866 sharedpath = createopts[b'sharedrepo'].sharedpath
3866 sharedpath = createopts[b'sharedrepo'].sharedpath
3867
3867
3868 if createopts.get(b'sharedrelative'):
3868 if createopts.get(b'sharedrelative'):
3869 try:
3869 try:
3870 sharedpath = os.path.relpath(sharedpath, hgvfs.base)
3870 sharedpath = os.path.relpath(sharedpath, hgvfs.base)
3871 sharedpath = util.pconvert(sharedpath)
3871 sharedpath = util.pconvert(sharedpath)
3872 except (IOError, ValueError) as e:
3872 except (IOError, ValueError) as e:
3873 # ValueError is raised on Windows if the drive letters differ
3873 # ValueError is raised on Windows if the drive letters differ
3874 # on each path.
3874 # on each path.
3875 raise error.Abort(
3875 raise error.Abort(
3876 _(b'cannot calculate relative path'),
3876 _(b'cannot calculate relative path'),
3877 hint=stringutil.forcebytestr(e),
3877 hint=stringutil.forcebytestr(e),
3878 )
3878 )
3879
3879
3880 if not wdirvfs.exists():
3880 if not wdirvfs.exists():
3881 wdirvfs.makedirs()
3881 wdirvfs.makedirs()
3882
3882
3883 hgvfs.makedir(notindexed=True)
3883 hgvfs.makedir(notindexed=True)
3884 if b'sharedrepo' not in createopts:
3884 if b'sharedrepo' not in createopts:
3885 hgvfs.mkdir(b'cache')
3885 hgvfs.mkdir(b'cache')
3886 hgvfs.mkdir(b'wcache')
3886 hgvfs.mkdir(b'wcache')
3887
3887
3888 has_store = requirementsmod.STORE_REQUIREMENT in requirements
3888 has_store = requirementsmod.STORE_REQUIREMENT in requirements
3889 if has_store and b'sharedrepo' not in createopts:
3889 if has_store and b'sharedrepo' not in createopts:
3890 hgvfs.mkdir(b'store')
3890 hgvfs.mkdir(b'store')
3891
3891
3892 # We create an invalid changelog outside the store so very old
3892 # We create an invalid changelog outside the store so very old
3893 # Mercurial versions (which didn't know about the requirements
3893 # Mercurial versions (which didn't know about the requirements
3894 # file) encounter an error on reading the changelog. This
3894 # file) encounter an error on reading the changelog. This
3895 # effectively locks out old clients and prevents them from
3895 # effectively locks out old clients and prevents them from
3896 # mucking with a repo in an unknown format.
3896 # mucking with a repo in an unknown format.
3897 #
3897 #
3898 # The revlog header has version 65535, which won't be recognized by
3898 # The revlog header has version 65535, which won't be recognized by
3899 # such old clients.
3899 # such old clients.
3900 hgvfs.append(
3900 hgvfs.append(
3901 b'00changelog.i',
3901 b'00changelog.i',
3902 b'\0\0\xFF\xFF dummy changelog to prevent using the old repo '
3902 b'\0\0\xFF\xFF dummy changelog to prevent using the old repo '
3903 b'layout',
3903 b'layout',
3904 )
3904 )
3905
3905
3906 # Filter the requirements into working copy and store ones
3906 # Filter the requirements into working copy and store ones
3907 wcreq, storereq = scmutil.filterrequirements(requirements)
3907 wcreq, storereq = scmutil.filterrequirements(requirements)
3908 # write working copy ones
3908 # write working copy ones
3909 scmutil.writerequires(hgvfs, wcreq)
3909 scmutil.writerequires(hgvfs, wcreq)
3910 # If there are store requirements and the current repository
3910 # If there are store requirements and the current repository
3911 # is not a shared one, write stored requirements
3911 # is not a shared one, write stored requirements
3912 # For new shared repository, we don't need to write the store
3912 # For new shared repository, we don't need to write the store
3913 # requirements as they are already present in store requires
3913 # requirements as they are already present in store requires
3914 if storereq and b'sharedrepo' not in createopts:
3914 if storereq and b'sharedrepo' not in createopts:
3915 storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
3915 storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
3916 scmutil.writerequires(storevfs, storereq)
3916 scmutil.writerequires(storevfs, storereq)
3917
3917
3918 # Write out file telling readers where to find the shared store.
3918 # Write out file telling readers where to find the shared store.
3919 if b'sharedrepo' in createopts:
3919 if b'sharedrepo' in createopts:
3920 hgvfs.write(b'sharedpath', sharedpath)
3920 hgvfs.write(b'sharedpath', sharedpath)
3921
3921
3922 if createopts.get(b'shareditems'):
3922 if createopts.get(b'shareditems'):
3923 shared = b'\n'.join(sorted(createopts[b'shareditems'])) + b'\n'
3923 shared = b'\n'.join(sorted(createopts[b'shareditems'])) + b'\n'
3924 hgvfs.write(b'shared', shared)
3924 hgvfs.write(b'shared', shared)
3925
3925
3926
3926
3927 def poisonrepository(repo):
3927 def poisonrepository(repo):
3928 """Poison a repository instance so it can no longer be used."""
3928 """Poison a repository instance so it can no longer be used."""
3929 # Perform any cleanup on the instance.
3929 # Perform any cleanup on the instance.
3930 repo.close()
3930 repo.close()
3931
3931
3932 # Our strategy is to replace the type of the object with one that
3932 # Our strategy is to replace the type of the object with one that
3933 # has all attribute lookups result in error.
3933 # has all attribute lookups result in error.
3934 #
3934 #
3935 # But we have to allow the close() method because some constructors
3935 # But we have to allow the close() method because some constructors
3936 # of repos call close() on repo references.
3936 # of repos call close() on repo references.
3937 class poisonedrepository:
3937 class poisonedrepository:
3938 def __getattribute__(self, item):
3938 def __getattribute__(self, item):
3939 if item == 'close':
3939 if item == 'close':
3940 return object.__getattribute__(self, item)
3940 return object.__getattribute__(self, item)
3941
3941
3942 raise error.ProgrammingError(
3942 raise error.ProgrammingError(
3943 b'repo instances should not be used after unshare'
3943 b'repo instances should not be used after unshare'
3944 )
3944 )
3945
3945
3946 def close(self):
3946 def close(self):
3947 pass
3947 pass
3948
3948
3949 # We may have a repoview, which intercepts __setattr__. So be sure
3949 # We may have a repoview, which intercepts __setattr__. So be sure
3950 # we operate at the lowest level possible.
3950 # we operate at the lowest level possible.
3951 object.__setattr__(repo, '__class__', poisonedrepository)
3951 object.__setattr__(repo, '__class__', poisonedrepository)
@@ -1,125 +1,125 b''
1 # requirements.py - objects and functions related to repository requirements
1 # requirements.py - objects and functions related to repository requirements
2 #
2 #
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2007 Olivia Mackall <olivia@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
8
9 # obsolete experimental requirements:
9 # obsolete experimental requirements:
10 # - manifestv2: An experimental new manifest format that allowed
10 # - manifestv2: An experimental new manifest format that allowed
11 # for stem compression of long paths. Experiment ended up not
11 # for stem compression of long paths. Experiment ended up not
12 # being successful (repository sizes went up due to worse delta
12 # being successful (repository sizes went up due to worse delta
13 # chains), and the code was deleted in 4.6.
13 # chains), and the code was deleted in 4.6.
14
14
15 GENERALDELTA_REQUIREMENT = b'generaldelta'
15 GENERALDELTA_REQUIREMENT = b'generaldelta'
16 DOTENCODE_REQUIREMENT = b'dotencode'
16 DOTENCODE_REQUIREMENT = b'dotencode'
17 STORE_REQUIREMENT = b'store'
17 STORE_REQUIREMENT = b'store'
18 FNCACHE_REQUIREMENT = b'fncache'
18 FNCACHE_REQUIREMENT = b'fncache'
19
19
20 DIRSTATE_TRACKED_HINT_V1 = b'dirstate-tracked-key-v1'
20 DIRSTATE_TRACKED_HINT_V1 = b'dirstate-tracked-key-v1'
21 DIRSTATE_V2_REQUIREMENT = b'dirstate-v2'
21 DIRSTATE_V2_REQUIREMENT = b'dirstate-v2'
22
22
23 # When narrowing is finalized and no longer subject to format changes,
23 # When narrowing is finalized and no longer subject to format changes,
24 # we should move this to just "narrow" or similar.
24 # we should move this to just "narrow" or similar.
25 NARROW_REQUIREMENT = b'narrowhg-experimental'
25 NARROW_REQUIREMENT = b'narrowhg-experimental'
26
26
27 # Enables sparse working directory usage
27 # Enables sparse working directory usage
28 SPARSE_REQUIREMENT = b'exp-sparse'
28 SPARSE_REQUIREMENT = b'exp-sparse'
29
29
30 # Enables the internal phase which is used to hide changesets instead
30 # Enables the internal phase which is used to hide changesets instead
31 # of stripping them
31 # of stripping them
32 INTERNAL_PHASE_REQUIREMENT = b'internal-phase'
32 INTERNAL_PHASE_REQUIREMENT = b'internal-phase-2'
33
33
34 # Enables the internal phase which is used to hide changesets instead
34 # Enables the internal phase which is used to hide changesets instead
35 # of stripping them
35 # of stripping them
36 ARCHIVED_PHASE_REQUIREMENT = b'exp-archived-phase'
36 ARCHIVED_PHASE_REQUIREMENT = b'exp-archived-phase'
37
37
38 # Stores manifest in Tree structure
38 # Stores manifest in Tree structure
39 TREEMANIFEST_REQUIREMENT = b'treemanifest'
39 TREEMANIFEST_REQUIREMENT = b'treemanifest'
40
40
41 REVLOGV1_REQUIREMENT = b'revlogv1'
41 REVLOGV1_REQUIREMENT = b'revlogv1'
42
42
43 # allow using ZSTD as compression engine for revlog content
43 # allow using ZSTD as compression engine for revlog content
44 REVLOG_COMPRESSION_ZSTD = b'revlog-compression-zstd'
44 REVLOG_COMPRESSION_ZSTD = b'revlog-compression-zstd'
45
45
46 # Increment the sub-version when the revlog v2 format changes to lock out old
46 # Increment the sub-version when the revlog v2 format changes to lock out old
47 # clients.
47 # clients.
48 CHANGELOGV2_REQUIREMENT = b'exp-changelog-v2'
48 CHANGELOGV2_REQUIREMENT = b'exp-changelog-v2'
49
49
50 # Increment the sub-version when the revlog v2 format changes to lock out old
50 # Increment the sub-version when the revlog v2 format changes to lock out old
51 # clients.
51 # clients.
52 REVLOGV2_REQUIREMENT = b'exp-revlogv2.2'
52 REVLOGV2_REQUIREMENT = b'exp-revlogv2.2'
53
53
54 # A repository with the sparserevlog feature will have delta chains that
54 # A repository with the sparserevlog feature will have delta chains that
55 # can spread over a larger span. Sparse reading cuts these large spans into
55 # can spread over a larger span. Sparse reading cuts these large spans into
56 # pieces, so that each piece isn't too big.
56 # pieces, so that each piece isn't too big.
57 # Without the sparserevlog capability, reading from the repository could use
57 # Without the sparserevlog capability, reading from the repository could use
58 # huge amounts of memory, because the whole span would be read at once,
58 # huge amounts of memory, because the whole span would be read at once,
59 # including all the intermediate revisions that aren't pertinent for the chain.
59 # including all the intermediate revisions that aren't pertinent for the chain.
60 # This is why once a repository has enabled sparse-read, it becomes required.
60 # This is why once a repository has enabled sparse-read, it becomes required.
61 SPARSEREVLOG_REQUIREMENT = b'sparserevlog'
61 SPARSEREVLOG_REQUIREMENT = b'sparserevlog'
62
62
63 # A repository with the the copies-sidedata-changeset requirement will store
63 # A repository with the the copies-sidedata-changeset requirement will store
64 # copies related information in changeset's sidedata.
64 # copies related information in changeset's sidedata.
65 COPIESSDC_REQUIREMENT = b'exp-copies-sidedata-changeset'
65 COPIESSDC_REQUIREMENT = b'exp-copies-sidedata-changeset'
66
66
67 # The repository use persistent nodemap for the changelog and the manifest.
67 # The repository use persistent nodemap for the changelog and the manifest.
68 NODEMAP_REQUIREMENT = b'persistent-nodemap'
68 NODEMAP_REQUIREMENT = b'persistent-nodemap'
69
69
70 # Denotes that the current repository is a share
70 # Denotes that the current repository is a share
71 SHARED_REQUIREMENT = b'shared'
71 SHARED_REQUIREMENT = b'shared'
72
72
73 # Denotes that current repository is a share and the shared source path is
73 # Denotes that current repository is a share and the shared source path is
74 # relative to the current repository root path
74 # relative to the current repository root path
75 RELATIVE_SHARED_REQUIREMENT = b'relshared'
75 RELATIVE_SHARED_REQUIREMENT = b'relshared'
76
76
77 # A repository with share implemented safely. The repository has different
77 # A repository with share implemented safely. The repository has different
78 # store and working copy requirements i.e. both `.hg/requires` and
78 # store and working copy requirements i.e. both `.hg/requires` and
79 # `.hg/store/requires` are present.
79 # `.hg/store/requires` are present.
80 SHARESAFE_REQUIREMENT = b'share-safe'
80 SHARESAFE_REQUIREMENT = b'share-safe'
81
81
82 # Bookmarks must be stored in the `store` part of the repository and will be
82 # Bookmarks must be stored in the `store` part of the repository and will be
83 # share accross shares
83 # share accross shares
84 BOOKMARKS_IN_STORE_REQUIREMENT = b'bookmarksinstore'
84 BOOKMARKS_IN_STORE_REQUIREMENT = b'bookmarksinstore'
85
85
86 # List of requirements which are working directory specific
86 # List of requirements which are working directory specific
87 # These requirements cannot be shared between repositories if they
87 # These requirements cannot be shared between repositories if they
88 # share the same store
88 # share the same store
89 # * sparse is a working directory specific functionality and hence working
89 # * sparse is a working directory specific functionality and hence working
90 # directory specific requirement
90 # directory specific requirement
91 # * SHARED_REQUIREMENT and RELATIVE_SHARED_REQUIREMENT are requirements which
91 # * SHARED_REQUIREMENT and RELATIVE_SHARED_REQUIREMENT are requirements which
92 # represents that the current working copy/repository shares store of another
92 # represents that the current working copy/repository shares store of another
93 # repo. Hence both of them should be stored in working copy
93 # repo. Hence both of them should be stored in working copy
94 # * SHARESAFE_REQUIREMENT needs to be stored in working dir to mark that rest of
94 # * SHARESAFE_REQUIREMENT needs to be stored in working dir to mark that rest of
95 # the requirements are stored in store's requires
95 # the requirements are stored in store's requires
96 # * DIRSTATE_V2_REQUIREMENT affects .hg/dirstate, of which there is one per
96 # * DIRSTATE_V2_REQUIREMENT affects .hg/dirstate, of which there is one per
97 # working directory.
97 # working directory.
98 WORKING_DIR_REQUIREMENTS = {
98 WORKING_DIR_REQUIREMENTS = {
99 SPARSE_REQUIREMENT,
99 SPARSE_REQUIREMENT,
100 SHARED_REQUIREMENT,
100 SHARED_REQUIREMENT,
101 RELATIVE_SHARED_REQUIREMENT,
101 RELATIVE_SHARED_REQUIREMENT,
102 SHARESAFE_REQUIREMENT,
102 SHARESAFE_REQUIREMENT,
103 DIRSTATE_TRACKED_HINT_V1,
103 DIRSTATE_TRACKED_HINT_V1,
104 DIRSTATE_V2_REQUIREMENT,
104 DIRSTATE_V2_REQUIREMENT,
105 }
105 }
106
106
107 # List of requirement that impact "stream-clone" (and hardlink clone) and
107 # List of requirement that impact "stream-clone" (and hardlink clone) and
108 # cannot be changed in such cases.
108 # cannot be changed in such cases.
109 #
109 #
110 # requirements not in this list are safe to be altered during stream-clone.
110 # requirements not in this list are safe to be altered during stream-clone.
111 #
111 #
112 # note: the list is currently inherited from previous code and miss some relevant requirement while containing some irrelevant ones.
112 # note: the list is currently inherited from previous code and miss some relevant requirement while containing some irrelevant ones.
113 STREAM_FIXED_REQUIREMENTS = {
113 STREAM_FIXED_REQUIREMENTS = {
114 ARCHIVED_PHASE_REQUIREMENT,
114 ARCHIVED_PHASE_REQUIREMENT,
115 BOOKMARKS_IN_STORE_REQUIREMENT,
115 BOOKMARKS_IN_STORE_REQUIREMENT,
116 CHANGELOGV2_REQUIREMENT,
116 CHANGELOGV2_REQUIREMENT,
117 COPIESSDC_REQUIREMENT,
117 COPIESSDC_REQUIREMENT,
118 GENERALDELTA_REQUIREMENT,
118 GENERALDELTA_REQUIREMENT,
119 INTERNAL_PHASE_REQUIREMENT,
119 INTERNAL_PHASE_REQUIREMENT,
120 REVLOG_COMPRESSION_ZSTD,
120 REVLOG_COMPRESSION_ZSTD,
121 REVLOGV1_REQUIREMENT,
121 REVLOGV1_REQUIREMENT,
122 REVLOGV2_REQUIREMENT,
122 REVLOGV2_REQUIREMENT,
123 SPARSEREVLOG_REQUIREMENT,
123 SPARSEREVLOG_REQUIREMENT,
124 TREEMANIFEST_REQUIREMENT,
124 TREEMANIFEST_REQUIREMENT,
125 }
125 }
@@ -1,1049 +1,1049 b''
1 $ cat > $TESTTMP/hook.sh << 'EOF'
1 $ cat > $TESTTMP/hook.sh << 'EOF'
2 > echo "test-hook-close-phase: $HG_NODE: $HG_OLDPHASE -> $HG_PHASE"
2 > echo "test-hook-close-phase: $HG_NODE: $HG_OLDPHASE -> $HG_PHASE"
3 > EOF
3 > EOF
4
4
5 $ cat >> $HGRCPATH << EOF
5 $ cat >> $HGRCPATH << EOF
6 > [extensions]
6 > [extensions]
7 > phasereport=$TESTDIR/testlib/ext-phase-report.py
7 > phasereport=$TESTDIR/testlib/ext-phase-report.py
8 > [hooks]
8 > [hooks]
9 > txnclose-phase.test = sh $TESTTMP/hook.sh
9 > txnclose-phase.test = sh $TESTTMP/hook.sh
10 > EOF
10 > EOF
11
11
12 $ hglog() { hg log --template "{rev} {phaseidx} {desc}\n" $*; }
12 $ hglog() { hg log --template "{rev} {phaseidx} {desc}\n" $*; }
13 $ mkcommit() {
13 $ mkcommit() {
14 > echo "$1" > "$1"
14 > echo "$1" > "$1"
15 > hg add "$1"
15 > hg add "$1"
16 > message="$1"
16 > message="$1"
17 > shift
17 > shift
18 > hg ci -m "$message" $*
18 > hg ci -m "$message" $*
19 > }
19 > }
20
20
21 $ hg init initialrepo
21 $ hg init initialrepo
22 $ cd initialrepo
22 $ cd initialrepo
23
23
24 Cannot change null revision phase
24 Cannot change null revision phase
25
25
26 $ hg phase --force --secret null
26 $ hg phase --force --secret null
27 abort: cannot change null revision phase
27 abort: cannot change null revision phase
28 [255]
28 [255]
29 $ hg phase null
29 $ hg phase null
30 -1: public
30 -1: public
31
31
32 $ mkcommit A
32 $ mkcommit A
33 test-debug-phase: new rev 0: x -> 1
33 test-debug-phase: new rev 0: x -> 1
34 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> draft
34 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> draft
35
35
36 New commit are draft by default
36 New commit are draft by default
37
37
38 $ hglog
38 $ hglog
39 0 1 A
39 0 1 A
40
40
41 Following commit are draft too
41 Following commit are draft too
42
42
43 $ mkcommit B
43 $ mkcommit B
44 test-debug-phase: new rev 1: x -> 1
44 test-debug-phase: new rev 1: x -> 1
45 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> draft
45 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> draft
46
46
47 $ hglog
47 $ hglog
48 1 1 B
48 1 1 B
49 0 1 A
49 0 1 A
50
50
51 Working directory phase is secret when its parent is secret.
51 Working directory phase is secret when its parent is secret.
52
52
53 $ hg phase --force --secret .
53 $ hg phase --force --secret .
54 test-debug-phase: move rev 0: 1 -> 2
54 test-debug-phase: move rev 0: 1 -> 2
55 test-debug-phase: move rev 1: 1 -> 2
55 test-debug-phase: move rev 1: 1 -> 2
56 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: draft -> secret
56 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: draft -> secret
57 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> secret
57 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> secret
58 $ hg log -r 'wdir()' -T '{phase}\n'
58 $ hg log -r 'wdir()' -T '{phase}\n'
59 secret
59 secret
60 $ hg log -r 'wdir() and public()' -T '{phase}\n'
60 $ hg log -r 'wdir() and public()' -T '{phase}\n'
61 $ hg log -r 'wdir() and draft()' -T '{phase}\n'
61 $ hg log -r 'wdir() and draft()' -T '{phase}\n'
62 $ hg log -r 'wdir() and secret()' -T '{phase}\n'
62 $ hg log -r 'wdir() and secret()' -T '{phase}\n'
63 secret
63 secret
64
64
65 Working directory phase is draft when its parent is draft.
65 Working directory phase is draft when its parent is draft.
66
66
67 $ hg phase --draft .
67 $ hg phase --draft .
68 test-debug-phase: move rev 1: 2 -> 1
68 test-debug-phase: move rev 1: 2 -> 1
69 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: secret -> draft
69 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: secret -> draft
70 $ hg log -r 'wdir()' -T '{phase}\n'
70 $ hg log -r 'wdir()' -T '{phase}\n'
71 draft
71 draft
72 $ hg log -r 'wdir() and public()' -T '{phase}\n'
72 $ hg log -r 'wdir() and public()' -T '{phase}\n'
73 $ hg log -r 'wdir() and draft()' -T '{phase}\n'
73 $ hg log -r 'wdir() and draft()' -T '{phase}\n'
74 draft
74 draft
75 $ hg log -r 'wdir() and secret()' -T '{phase}\n'
75 $ hg log -r 'wdir() and secret()' -T '{phase}\n'
76
76
77 Working directory phase is secret when a new commit will be created as secret,
77 Working directory phase is secret when a new commit will be created as secret,
78 even if the parent is draft.
78 even if the parent is draft.
79
79
80 $ hg log -r 'wdir() and secret()' -T '{phase}\n' \
80 $ hg log -r 'wdir() and secret()' -T '{phase}\n' \
81 > --config phases.new-commit='secret'
81 > --config phases.new-commit='secret'
82 secret
82 secret
83
83
84 Working directory phase is draft when its parent is public.
84 Working directory phase is draft when its parent is public.
85
85
86 $ hg phase --public .
86 $ hg phase --public .
87 test-debug-phase: move rev 0: 1 -> 0
87 test-debug-phase: move rev 0: 1 -> 0
88 test-debug-phase: move rev 1: 1 -> 0
88 test-debug-phase: move rev 1: 1 -> 0
89 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: draft -> public
89 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: draft -> public
90 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> public
90 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> public
91 $ hg log -r 'wdir()' -T '{phase}\n'
91 $ hg log -r 'wdir()' -T '{phase}\n'
92 draft
92 draft
93 $ hg log -r 'wdir() and public()' -T '{phase}\n'
93 $ hg log -r 'wdir() and public()' -T '{phase}\n'
94 $ hg log -r 'wdir() and draft()' -T '{phase}\n'
94 $ hg log -r 'wdir() and draft()' -T '{phase}\n'
95 draft
95 draft
96 $ hg log -r 'wdir() and secret()' -T '{phase}\n'
96 $ hg log -r 'wdir() and secret()' -T '{phase}\n'
97 $ hg log -r 'wdir() and secret()' -T '{phase}\n' \
97 $ hg log -r 'wdir() and secret()' -T '{phase}\n' \
98 > --config phases.new-commit='secret'
98 > --config phases.new-commit='secret'
99 secret
99 secret
100
100
101 Draft commit are properly created over public one:
101 Draft commit are properly created over public one:
102
102
103 $ hg phase
103 $ hg phase
104 1: public
104 1: public
105 $ hglog
105 $ hglog
106 1 0 B
106 1 0 B
107 0 0 A
107 0 0 A
108
108
109 $ mkcommit C
109 $ mkcommit C
110 test-debug-phase: new rev 2: x -> 1
110 test-debug-phase: new rev 2: x -> 1
111 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> draft
111 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> draft
112 $ mkcommit D
112 $ mkcommit D
113 test-debug-phase: new rev 3: x -> 1
113 test-debug-phase: new rev 3: x -> 1
114 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> draft
114 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> draft
115
115
116 $ hglog
116 $ hglog
117 3 1 D
117 3 1 D
118 2 1 C
118 2 1 C
119 1 0 B
119 1 0 B
120 0 0 A
120 0 0 A
121
121
122 Test creating changeset as secret
122 Test creating changeset as secret
123
123
124 $ mkcommit E --config phases.new-commit='secret'
124 $ mkcommit E --config phases.new-commit='secret'
125 test-debug-phase: new rev 4: x -> 2
125 test-debug-phase: new rev 4: x -> 2
126 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: -> secret
126 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: -> secret
127 $ hglog
127 $ hglog
128 4 2 E
128 4 2 E
129 3 1 D
129 3 1 D
130 2 1 C
130 2 1 C
131 1 0 B
131 1 0 B
132 0 0 A
132 0 0 A
133
133
134 Test the secret property is inherited
134 Test the secret property is inherited
135
135
136 $ mkcommit H
136 $ mkcommit H
137 test-debug-phase: new rev 5: x -> 2
137 test-debug-phase: new rev 5: x -> 2
138 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: -> secret
138 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: -> secret
139 $ hglog
139 $ hglog
140 5 2 H
140 5 2 H
141 4 2 E
141 4 2 E
142 3 1 D
142 3 1 D
143 2 1 C
143 2 1 C
144 1 0 B
144 1 0 B
145 0 0 A
145 0 0 A
146
146
147 Even on merge
147 Even on merge
148
148
149 $ hg up -q 1
149 $ hg up -q 1
150 $ mkcommit "B'"
150 $ mkcommit "B'"
151 test-debug-phase: new rev 6: x -> 1
151 test-debug-phase: new rev 6: x -> 1
152 created new head
152 created new head
153 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> draft
153 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> draft
154 $ hglog
154 $ hglog
155 6 1 B'
155 6 1 B'
156 5 2 H
156 5 2 H
157 4 2 E
157 4 2 E
158 3 1 D
158 3 1 D
159 2 1 C
159 2 1 C
160 1 0 B
160 1 0 B
161 0 0 A
161 0 0 A
162 $ hg merge 4 # E
162 $ hg merge 4 # E
163 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
164 (branch merge, don't forget to commit)
164 (branch merge, don't forget to commit)
165 $ hg phase
165 $ hg phase
166 6: draft
166 6: draft
167 4: secret
167 4: secret
168 $ hg ci -m "merge B' and E"
168 $ hg ci -m "merge B' and E"
169 test-debug-phase: new rev 7: x -> 2
169 test-debug-phase: new rev 7: x -> 2
170 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: -> secret
170 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: -> secret
171
171
172 $ hglog
172 $ hglog
173 7 2 merge B' and E
173 7 2 merge B' and E
174 6 1 B'
174 6 1 B'
175 5 2 H
175 5 2 H
176 4 2 E
176 4 2 E
177 3 1 D
177 3 1 D
178 2 1 C
178 2 1 C
179 1 0 B
179 1 0 B
180 0 0 A
180 0 0 A
181
181
182 Test secret changeset are not pushed
182 Test secret changeset are not pushed
183
183
184 $ hg init ../push-dest
184 $ hg init ../push-dest
185 $ cat > ../push-dest/.hg/hgrc << EOF
185 $ cat > ../push-dest/.hg/hgrc << EOF
186 > [phases]
186 > [phases]
187 > publish=False
187 > publish=False
188 > EOF
188 > EOF
189 $ hg outgoing ../push-dest --template='{rev} {phase} {desc|firstline}\n'
189 $ hg outgoing ../push-dest --template='{rev} {phase} {desc|firstline}\n'
190 comparing with ../push-dest
190 comparing with ../push-dest
191 searching for changes
191 searching for changes
192 0 public A
192 0 public A
193 1 public B
193 1 public B
194 2 draft C
194 2 draft C
195 3 draft D
195 3 draft D
196 6 draft B'
196 6 draft B'
197 $ hg outgoing -r 'branch(default)' ../push-dest --template='{rev} {phase} {desc|firstline}\n'
197 $ hg outgoing -r 'branch(default)' ../push-dest --template='{rev} {phase} {desc|firstline}\n'
198 comparing with ../push-dest
198 comparing with ../push-dest
199 searching for changes
199 searching for changes
200 0 public A
200 0 public A
201 1 public B
201 1 public B
202 2 draft C
202 2 draft C
203 3 draft D
203 3 draft D
204 6 draft B'
204 6 draft B'
205
205
206 $ hg push ../push-dest -f # force because we push multiple heads
206 $ hg push ../push-dest -f # force because we push multiple heads
207 pushing to ../push-dest
207 pushing to ../push-dest
208 searching for changes
208 searching for changes
209 adding changesets
209 adding changesets
210 adding manifests
210 adding manifests
211 adding file changes
211 adding file changes
212 added 5 changesets with 5 changes to 5 files (+1 heads)
212 added 5 changesets with 5 changes to 5 files (+1 heads)
213 test-debug-phase: new rev 0: x -> 0
213 test-debug-phase: new rev 0: x -> 0
214 test-debug-phase: new rev 1: x -> 0
214 test-debug-phase: new rev 1: x -> 0
215 test-debug-phase: new rev 2: x -> 1
215 test-debug-phase: new rev 2: x -> 1
216 test-debug-phase: new rev 3: x -> 1
216 test-debug-phase: new rev 3: x -> 1
217 test-debug-phase: new rev 4: x -> 1
217 test-debug-phase: new rev 4: x -> 1
218 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
218 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
219 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
219 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
220 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> draft
220 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> draft
221 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> draft
221 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> draft
222 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> draft
222 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> draft
223 $ hglog
223 $ hglog
224 7 2 merge B' and E
224 7 2 merge B' and E
225 6 1 B'
225 6 1 B'
226 5 2 H
226 5 2 H
227 4 2 E
227 4 2 E
228 3 1 D
228 3 1 D
229 2 1 C
229 2 1 C
230 1 0 B
230 1 0 B
231 0 0 A
231 0 0 A
232 $ cd ../push-dest
232 $ cd ../push-dest
233 $ hglog
233 $ hglog
234 4 1 B'
234 4 1 B'
235 3 1 D
235 3 1 D
236 2 1 C
236 2 1 C
237 1 0 B
237 1 0 B
238 0 0 A
238 0 0 A
239
239
240 (Issue3303)
240 (Issue3303)
241 Check that remote secret changeset are ignore when checking creation of remote heads
241 Check that remote secret changeset are ignore when checking creation of remote heads
242
242
243 We add a secret head into the push destination. This secret head shadows a
243 We add a secret head into the push destination. This secret head shadows a
244 visible shared between the initial repo and the push destination.
244 visible shared between the initial repo and the push destination.
245
245
246 $ hg up -q 4 # B'
246 $ hg up -q 4 # B'
247 $ mkcommit Z --config phases.new-commit=secret
247 $ mkcommit Z --config phases.new-commit=secret
248 test-debug-phase: new rev 5: x -> 2
248 test-debug-phase: new rev 5: x -> 2
249 test-hook-close-phase: 2713879da13d6eea1ff22b442a5a87cb31a7ce6a: -> secret
249 test-hook-close-phase: 2713879da13d6eea1ff22b442a5a87cb31a7ce6a: -> secret
250 $ hg phase .
250 $ hg phase .
251 5: secret
251 5: secret
252
252
253 We now try to push a new public changeset that descend from the common public
253 We now try to push a new public changeset that descend from the common public
254 head shadowed by the remote secret head.
254 head shadowed by the remote secret head.
255
255
256 $ cd ../initialrepo
256 $ cd ../initialrepo
257 $ hg up -q 6 #B'
257 $ hg up -q 6 #B'
258 $ mkcommit I
258 $ mkcommit I
259 test-debug-phase: new rev 8: x -> 1
259 test-debug-phase: new rev 8: x -> 1
260 created new head
260 created new head
261 test-hook-close-phase: 6d6770faffce199f1fddd1cf87f6f026138cf061: -> draft
261 test-hook-close-phase: 6d6770faffce199f1fddd1cf87f6f026138cf061: -> draft
262 $ hg push ../push-dest
262 $ hg push ../push-dest
263 pushing to ../push-dest
263 pushing to ../push-dest
264 searching for changes
264 searching for changes
265 adding changesets
265 adding changesets
266 adding manifests
266 adding manifests
267 adding file changes
267 adding file changes
268 added 1 changesets with 1 changes to 1 files (+1 heads)
268 added 1 changesets with 1 changes to 1 files (+1 heads)
269 test-debug-phase: new rev 6: x -> 1
269 test-debug-phase: new rev 6: x -> 1
270 test-hook-close-phase: 6d6770faffce199f1fddd1cf87f6f026138cf061: -> draft
270 test-hook-close-phase: 6d6770faffce199f1fddd1cf87f6f026138cf061: -> draft
271
271
272 :note: The "(+1 heads)" is wrong as we do not had any visible head
272 :note: The "(+1 heads)" is wrong as we do not had any visible head
273
273
274 check that branch cache with "served" filter are properly computed and stored
274 check that branch cache with "served" filter are properly computed and stored
275
275
276 $ ls ../push-dest/.hg/cache/branch2*
276 $ ls ../push-dest/.hg/cache/branch2*
277 ../push-dest/.hg/cache/branch2-base
277 ../push-dest/.hg/cache/branch2-base
278 ../push-dest/.hg/cache/branch2-served
278 ../push-dest/.hg/cache/branch2-served
279 $ cat ../push-dest/.hg/cache/branch2-served
279 $ cat ../push-dest/.hg/cache/branch2-served
280 6d6770faffce199f1fddd1cf87f6f026138cf061 6 465891ffab3c47a3c23792f7dc84156e19a90722
280 6d6770faffce199f1fddd1cf87f6f026138cf061 6 465891ffab3c47a3c23792f7dc84156e19a90722
281 b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
281 b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
282 6d6770faffce199f1fddd1cf87f6f026138cf061 o default
282 6d6770faffce199f1fddd1cf87f6f026138cf061 o default
283 $ hg heads -R ../push-dest --template '{rev}:{node} {phase}\n' #update visible cache too
283 $ hg heads -R ../push-dest --template '{rev}:{node} {phase}\n' #update visible cache too
284 6:6d6770faffce199f1fddd1cf87f6f026138cf061 draft
284 6:6d6770faffce199f1fddd1cf87f6f026138cf061 draft
285 5:2713879da13d6eea1ff22b442a5a87cb31a7ce6a secret
285 5:2713879da13d6eea1ff22b442a5a87cb31a7ce6a secret
286 3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e draft
286 3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e draft
287 $ ls ../push-dest/.hg/cache/branch2*
287 $ ls ../push-dest/.hg/cache/branch2*
288 ../push-dest/.hg/cache/branch2-base
288 ../push-dest/.hg/cache/branch2-base
289 ../push-dest/.hg/cache/branch2-served
289 ../push-dest/.hg/cache/branch2-served
290 ../push-dest/.hg/cache/branch2-visible
290 ../push-dest/.hg/cache/branch2-visible
291 $ cat ../push-dest/.hg/cache/branch2-served
291 $ cat ../push-dest/.hg/cache/branch2-served
292 6d6770faffce199f1fddd1cf87f6f026138cf061 6 465891ffab3c47a3c23792f7dc84156e19a90722
292 6d6770faffce199f1fddd1cf87f6f026138cf061 6 465891ffab3c47a3c23792f7dc84156e19a90722
293 b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
293 b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
294 6d6770faffce199f1fddd1cf87f6f026138cf061 o default
294 6d6770faffce199f1fddd1cf87f6f026138cf061 o default
295 $ cat ../push-dest/.hg/cache/branch2-visible
295 $ cat ../push-dest/.hg/cache/branch2-visible
296 6d6770faffce199f1fddd1cf87f6f026138cf061 6
296 6d6770faffce199f1fddd1cf87f6f026138cf061 6
297 b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
297 b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
298 2713879da13d6eea1ff22b442a5a87cb31a7ce6a o default
298 2713879da13d6eea1ff22b442a5a87cb31a7ce6a o default
299 6d6770faffce199f1fddd1cf87f6f026138cf061 o default
299 6d6770faffce199f1fddd1cf87f6f026138cf061 o default
300
300
301
301
302 Restore condition prior extra insertion.
302 Restore condition prior extra insertion.
303 $ hg -q --config extensions.mq= strip .
303 $ hg -q --config extensions.mq= strip .
304 $ hg up -q 7
304 $ hg up -q 7
305 $ cd ..
305 $ cd ..
306
306
307 Test secret changeset are not pull
307 Test secret changeset are not pull
308
308
309 $ hg init pull-dest
309 $ hg init pull-dest
310 $ cd pull-dest
310 $ cd pull-dest
311 $ hg pull ../initialrepo
311 $ hg pull ../initialrepo
312 pulling from ../initialrepo
312 pulling from ../initialrepo
313 requesting all changes
313 requesting all changes
314 adding changesets
314 adding changesets
315 adding manifests
315 adding manifests
316 adding file changes
316 adding file changes
317 added 5 changesets with 5 changes to 5 files (+1 heads)
317 added 5 changesets with 5 changes to 5 files (+1 heads)
318 new changesets 4a2df7238c3b:cf9fe039dfd6
318 new changesets 4a2df7238c3b:cf9fe039dfd6
319 test-debug-phase: new rev 0: x -> 0
319 test-debug-phase: new rev 0: x -> 0
320 test-debug-phase: new rev 1: x -> 0
320 test-debug-phase: new rev 1: x -> 0
321 test-debug-phase: new rev 2: x -> 0
321 test-debug-phase: new rev 2: x -> 0
322 test-debug-phase: new rev 3: x -> 0
322 test-debug-phase: new rev 3: x -> 0
323 test-debug-phase: new rev 4: x -> 0
323 test-debug-phase: new rev 4: x -> 0
324 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
324 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
325 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
325 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
326 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> public
326 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> public
327 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> public
327 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> public
328 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> public
328 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> public
329 (run 'hg heads' to see heads, 'hg merge' to merge)
329 (run 'hg heads' to see heads, 'hg merge' to merge)
330 $ hglog
330 $ hglog
331 4 0 B'
331 4 0 B'
332 3 0 D
332 3 0 D
333 2 0 C
333 2 0 C
334 1 0 B
334 1 0 B
335 0 0 A
335 0 0 A
336 $ cd ..
336 $ cd ..
337
337
338 But secret can still be bundled explicitly
338 But secret can still be bundled explicitly
339
339
340 $ cd initialrepo
340 $ cd initialrepo
341 $ hg bundle --base '4^' -r 'children(4)' ../secret-bundle.hg
341 $ hg bundle --base '4^' -r 'children(4)' ../secret-bundle.hg
342 4 changesets found
342 4 changesets found
343 $ cd ..
343 $ cd ..
344
344
345 Test secret changeset are not cloned
345 Test secret changeset are not cloned
346 (during local clone)
346 (during local clone)
347
347
348 $ hg clone -qU initialrepo clone-dest
348 $ hg clone -qU initialrepo clone-dest
349 test-debug-phase: new rev 0: x -> 0
349 test-debug-phase: new rev 0: x -> 0
350 test-debug-phase: new rev 1: x -> 0
350 test-debug-phase: new rev 1: x -> 0
351 test-debug-phase: new rev 2: x -> 0
351 test-debug-phase: new rev 2: x -> 0
352 test-debug-phase: new rev 3: x -> 0
352 test-debug-phase: new rev 3: x -> 0
353 test-debug-phase: new rev 4: x -> 0
353 test-debug-phase: new rev 4: x -> 0
354 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
354 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
355 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
355 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
356 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> public
356 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> public
357 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> public
357 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> public
358 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> public
358 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> public
359 $ hglog -R clone-dest
359 $ hglog -R clone-dest
360 4 0 B'
360 4 0 B'
361 3 0 D
361 3 0 D
362 2 0 C
362 2 0 C
363 1 0 B
363 1 0 B
364 0 0 A
364 0 0 A
365
365
366 Test summary
366 Test summary
367
367
368 $ hg summary -R clone-dest --verbose
368 $ hg summary -R clone-dest --verbose
369 parent: -1:000000000000 (no revision checked out)
369 parent: -1:000000000000 (no revision checked out)
370 branch: default
370 branch: default
371 commit: (clean)
371 commit: (clean)
372 update: 5 new changesets (update)
372 update: 5 new changesets (update)
373 $ hg summary -R initialrepo
373 $ hg summary -R initialrepo
374 parent: 7:17a481b3bccb tip
374 parent: 7:17a481b3bccb tip
375 merge B' and E
375 merge B' and E
376 branch: default
376 branch: default
377 commit: (clean) (secret)
377 commit: (clean) (secret)
378 update: 1 new changesets, 2 branch heads (merge)
378 update: 1 new changesets, 2 branch heads (merge)
379 phases: 3 draft, 3 secret
379 phases: 3 draft, 3 secret
380 $ hg summary -R initialrepo --quiet
380 $ hg summary -R initialrepo --quiet
381 parent: 7:17a481b3bccb tip
381 parent: 7:17a481b3bccb tip
382 update: 1 new changesets, 2 branch heads (merge)
382 update: 1 new changesets, 2 branch heads (merge)
383
383
384 Test revset
384 Test revset
385
385
386 $ cd initialrepo
386 $ cd initialrepo
387 $ hglog -r 'public()'
387 $ hglog -r 'public()'
388 0 0 A
388 0 0 A
389 1 0 B
389 1 0 B
390 $ hglog -r 'draft()'
390 $ hglog -r 'draft()'
391 2 1 C
391 2 1 C
392 3 1 D
392 3 1 D
393 6 1 B'
393 6 1 B'
394 $ hglog -r 'secret()'
394 $ hglog -r 'secret()'
395 4 2 E
395 4 2 E
396 5 2 H
396 5 2 H
397 7 2 merge B' and E
397 7 2 merge B' and E
398
398
399 test that phase are displayed in log at debug level
399 test that phase are displayed in log at debug level
400
400
401 $ hg log --debug
401 $ hg log --debug
402 changeset: 7:17a481b3bccb796c0521ae97903d81c52bfee4af
402 changeset: 7:17a481b3bccb796c0521ae97903d81c52bfee4af
403 tag: tip
403 tag: tip
404 phase: secret
404 phase: secret
405 parent: 6:cf9fe039dfd67e829edf6522a45de057b5c86519
405 parent: 6:cf9fe039dfd67e829edf6522a45de057b5c86519
406 parent: 4:a603bfb5a83e312131cebcd05353c217d4d21dde
406 parent: 4:a603bfb5a83e312131cebcd05353c217d4d21dde
407 manifest: 7:5e724ffacba267b2ab726c91fc8b650710deaaa8
407 manifest: 7:5e724ffacba267b2ab726c91fc8b650710deaaa8
408 user: test
408 user: test
409 date: Thu Jan 01 00:00:00 1970 +0000
409 date: Thu Jan 01 00:00:00 1970 +0000
410 extra: branch=default
410 extra: branch=default
411 description:
411 description:
412 merge B' and E
412 merge B' and E
413
413
414
414
415 changeset: 6:cf9fe039dfd67e829edf6522a45de057b5c86519
415 changeset: 6:cf9fe039dfd67e829edf6522a45de057b5c86519
416 phase: draft
416 phase: draft
417 parent: 1:27547f69f25460a52fff66ad004e58da7ad3fb56
417 parent: 1:27547f69f25460a52fff66ad004e58da7ad3fb56
418 parent: -1:0000000000000000000000000000000000000000
418 parent: -1:0000000000000000000000000000000000000000
419 manifest: 6:ab8bfef2392903058bf4ebb9e7746e8d7026b27a
419 manifest: 6:ab8bfef2392903058bf4ebb9e7746e8d7026b27a
420 user: test
420 user: test
421 date: Thu Jan 01 00:00:00 1970 +0000
421 date: Thu Jan 01 00:00:00 1970 +0000
422 files+: B'
422 files+: B'
423 extra: branch=default
423 extra: branch=default
424 description:
424 description:
425 B'
425 B'
426
426
427
427
428 changeset: 5:a030c6be5127abc010fcbff1851536552e6951a8
428 changeset: 5:a030c6be5127abc010fcbff1851536552e6951a8
429 phase: secret
429 phase: secret
430 parent: 4:a603bfb5a83e312131cebcd05353c217d4d21dde
430 parent: 4:a603bfb5a83e312131cebcd05353c217d4d21dde
431 parent: -1:0000000000000000000000000000000000000000
431 parent: -1:0000000000000000000000000000000000000000
432 manifest: 5:5c710aa854874fe3d5fa7192e77bdb314cc08b5a
432 manifest: 5:5c710aa854874fe3d5fa7192e77bdb314cc08b5a
433 user: test
433 user: test
434 date: Thu Jan 01 00:00:00 1970 +0000
434 date: Thu Jan 01 00:00:00 1970 +0000
435 files+: H
435 files+: H
436 extra: branch=default
436 extra: branch=default
437 description:
437 description:
438 H
438 H
439
439
440
440
441 changeset: 4:a603bfb5a83e312131cebcd05353c217d4d21dde
441 changeset: 4:a603bfb5a83e312131cebcd05353c217d4d21dde
442 phase: secret
442 phase: secret
443 parent: 3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e
443 parent: 3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e
444 parent: -1:0000000000000000000000000000000000000000
444 parent: -1:0000000000000000000000000000000000000000
445 manifest: 4:7173fd1c27119750b959e3a0f47ed78abe75d6dc
445 manifest: 4:7173fd1c27119750b959e3a0f47ed78abe75d6dc
446 user: test
446 user: test
447 date: Thu Jan 01 00:00:00 1970 +0000
447 date: Thu Jan 01 00:00:00 1970 +0000
448 files+: E
448 files+: E
449 extra: branch=default
449 extra: branch=default
450 description:
450 description:
451 E
451 E
452
452
453
453
454 changeset: 3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e
454 changeset: 3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e
455 phase: draft
455 phase: draft
456 parent: 2:f838bfaca5c7226600ebcfd84f3c3c13a28d3757
456 parent: 2:f838bfaca5c7226600ebcfd84f3c3c13a28d3757
457 parent: -1:0000000000000000000000000000000000000000
457 parent: -1:0000000000000000000000000000000000000000
458 manifest: 3:6e1f4c47ecb533ffd0c8e52cdc88afb6cd39e20c
458 manifest: 3:6e1f4c47ecb533ffd0c8e52cdc88afb6cd39e20c
459 user: test
459 user: test
460 date: Thu Jan 01 00:00:00 1970 +0000
460 date: Thu Jan 01 00:00:00 1970 +0000
461 files+: D
461 files+: D
462 extra: branch=default
462 extra: branch=default
463 description:
463 description:
464 D
464 D
465
465
466
466
467 changeset: 2:f838bfaca5c7226600ebcfd84f3c3c13a28d3757
467 changeset: 2:f838bfaca5c7226600ebcfd84f3c3c13a28d3757
468 phase: draft
468 phase: draft
469 parent: 1:27547f69f25460a52fff66ad004e58da7ad3fb56
469 parent: 1:27547f69f25460a52fff66ad004e58da7ad3fb56
470 parent: -1:0000000000000000000000000000000000000000
470 parent: -1:0000000000000000000000000000000000000000
471 manifest: 2:66a5a01817fdf5239c273802b5b7618d051c89e4
471 manifest: 2:66a5a01817fdf5239c273802b5b7618d051c89e4
472 user: test
472 user: test
473 date: Thu Jan 01 00:00:00 1970 +0000
473 date: Thu Jan 01 00:00:00 1970 +0000
474 files+: C
474 files+: C
475 extra: branch=default
475 extra: branch=default
476 description:
476 description:
477 C
477 C
478
478
479
479
480 changeset: 1:27547f69f25460a52fff66ad004e58da7ad3fb56
480 changeset: 1:27547f69f25460a52fff66ad004e58da7ad3fb56
481 phase: public
481 phase: public
482 parent: 0:4a2df7238c3b48766b5e22fafbb8a2f506ec8256
482 parent: 0:4a2df7238c3b48766b5e22fafbb8a2f506ec8256
483 parent: -1:0000000000000000000000000000000000000000
483 parent: -1:0000000000000000000000000000000000000000
484 manifest: 1:cb5cbbc1bfbf24cc34b9e8c16914e9caa2d2a7fd
484 manifest: 1:cb5cbbc1bfbf24cc34b9e8c16914e9caa2d2a7fd
485 user: test
485 user: test
486 date: Thu Jan 01 00:00:00 1970 +0000
486 date: Thu Jan 01 00:00:00 1970 +0000
487 files+: B
487 files+: B
488 extra: branch=default
488 extra: branch=default
489 description:
489 description:
490 B
490 B
491
491
492
492
493 changeset: 0:4a2df7238c3b48766b5e22fafbb8a2f506ec8256
493 changeset: 0:4a2df7238c3b48766b5e22fafbb8a2f506ec8256
494 phase: public
494 phase: public
495 parent: -1:0000000000000000000000000000000000000000
495 parent: -1:0000000000000000000000000000000000000000
496 parent: -1:0000000000000000000000000000000000000000
496 parent: -1:0000000000000000000000000000000000000000
497 manifest: 0:007d8c9d88841325f5c6b06371b35b4e8a2b1a83
497 manifest: 0:007d8c9d88841325f5c6b06371b35b4e8a2b1a83
498 user: test
498 user: test
499 date: Thu Jan 01 00:00:00 1970 +0000
499 date: Thu Jan 01 00:00:00 1970 +0000
500 files+: A
500 files+: A
501 extra: branch=default
501 extra: branch=default
502 description:
502 description:
503 A
503 A
504
504
505
505
506
506
507
507
508 (Issue3707)
508 (Issue3707)
509 test invalid phase name
509 test invalid phase name
510
510
511 $ mkcommit I --config phases.new-commit='babar'
511 $ mkcommit I --config phases.new-commit='babar'
512 transaction abort!
512 transaction abort!
513 rollback completed
513 rollback completed
514 config error: phases.new-commit: not a valid phase name ('babar')
514 config error: phases.new-commit: not a valid phase name ('babar')
515 [30]
515 [30]
516 Test phase command
516 Test phase command
517 ===================
517 ===================
518
518
519 initial picture
519 initial picture
520
520
521 $ hg log -G --template "{rev} {phase} {desc}\n"
521 $ hg log -G --template "{rev} {phase} {desc}\n"
522 @ 7 secret merge B' and E
522 @ 7 secret merge B' and E
523 |\
523 |\
524 | o 6 draft B'
524 | o 6 draft B'
525 | |
525 | |
526 +---o 5 secret H
526 +---o 5 secret H
527 | |
527 | |
528 o | 4 secret E
528 o | 4 secret E
529 | |
529 | |
530 o | 3 draft D
530 o | 3 draft D
531 | |
531 | |
532 o | 2 draft C
532 o | 2 draft C
533 |/
533 |/
534 o 1 public B
534 o 1 public B
535 |
535 |
536 o 0 public A
536 o 0 public A
537
537
538
538
539 display changesets phase
539 display changesets phase
540
540
541 (mixing -r and plain rev specification)
541 (mixing -r and plain rev specification)
542
542
543 $ hg phase 1::4 -r 7
543 $ hg phase 1::4 -r 7
544 1: public
544 1: public
545 2: draft
545 2: draft
546 3: draft
546 3: draft
547 4: secret
547 4: secret
548 7: secret
548 7: secret
549
549
550
550
551 move changeset forward
551 move changeset forward
552
552
553 (with -r option)
553 (with -r option)
554
554
555 $ hg phase --public -r 2
555 $ hg phase --public -r 2
556 test-debug-phase: move rev 2: 1 -> 0
556 test-debug-phase: move rev 2: 1 -> 0
557 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: draft -> public
557 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: draft -> public
558 $ hg log -G --template "{rev} {phase} {desc}\n"
558 $ hg log -G --template "{rev} {phase} {desc}\n"
559 @ 7 secret merge B' and E
559 @ 7 secret merge B' and E
560 |\
560 |\
561 | o 6 draft B'
561 | o 6 draft B'
562 | |
562 | |
563 +---o 5 secret H
563 +---o 5 secret H
564 | |
564 | |
565 o | 4 secret E
565 o | 4 secret E
566 | |
566 | |
567 o | 3 draft D
567 o | 3 draft D
568 | |
568 | |
569 o | 2 public C
569 o | 2 public C
570 |/
570 |/
571 o 1 public B
571 o 1 public B
572 |
572 |
573 o 0 public A
573 o 0 public A
574
574
575
575
576 move changeset backward
576 move changeset backward
577
577
578 (without -r option)
578 (without -r option)
579
579
580 $ hg phase --draft --force 2
580 $ hg phase --draft --force 2
581 test-debug-phase: move rev 2: 0 -> 1
581 test-debug-phase: move rev 2: 0 -> 1
582 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: public -> draft
582 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: public -> draft
583 $ hg log -G --template "{rev} {phase} {desc}\n"
583 $ hg log -G --template "{rev} {phase} {desc}\n"
584 @ 7 secret merge B' and E
584 @ 7 secret merge B' and E
585 |\
585 |\
586 | o 6 draft B'
586 | o 6 draft B'
587 | |
587 | |
588 +---o 5 secret H
588 +---o 5 secret H
589 | |
589 | |
590 o | 4 secret E
590 o | 4 secret E
591 | |
591 | |
592 o | 3 draft D
592 o | 3 draft D
593 | |
593 | |
594 o | 2 draft C
594 o | 2 draft C
595 |/
595 |/
596 o 1 public B
596 o 1 public B
597 |
597 |
598 o 0 public A
598 o 0 public A
599
599
600
600
601 move changeset forward and backward
601 move changeset forward and backward
602
602
603 $ hg phase --draft --force 1::4
603 $ hg phase --draft --force 1::4
604 test-debug-phase: move rev 1: 0 -> 1
604 test-debug-phase: move rev 1: 0 -> 1
605 test-debug-phase: move rev 4: 2 -> 1
605 test-debug-phase: move rev 4: 2 -> 1
606 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: public -> draft
606 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: public -> draft
607 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: secret -> draft
607 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: secret -> draft
608 $ hg log -G --template "{rev} {phase} {desc}\n"
608 $ hg log -G --template "{rev} {phase} {desc}\n"
609 @ 7 secret merge B' and E
609 @ 7 secret merge B' and E
610 |\
610 |\
611 | o 6 draft B'
611 | o 6 draft B'
612 | |
612 | |
613 +---o 5 secret H
613 +---o 5 secret H
614 | |
614 | |
615 o | 4 draft E
615 o | 4 draft E
616 | |
616 | |
617 o | 3 draft D
617 o | 3 draft D
618 | |
618 | |
619 o | 2 draft C
619 o | 2 draft C
620 |/
620 |/
621 o 1 draft B
621 o 1 draft B
622 |
622 |
623 o 0 public A
623 o 0 public A
624
624
625 test partial failure
625 test partial failure
626
626
627 $ hg phase --public 7
627 $ hg phase --public 7
628 test-debug-phase: move rev 1: 1 -> 0
628 test-debug-phase: move rev 1: 1 -> 0
629 test-debug-phase: move rev 2: 1 -> 0
629 test-debug-phase: move rev 2: 1 -> 0
630 test-debug-phase: move rev 3: 1 -> 0
630 test-debug-phase: move rev 3: 1 -> 0
631 test-debug-phase: move rev 4: 1 -> 0
631 test-debug-phase: move rev 4: 1 -> 0
632 test-debug-phase: move rev 6: 1 -> 0
632 test-debug-phase: move rev 6: 1 -> 0
633 test-debug-phase: move rev 7: 2 -> 0
633 test-debug-phase: move rev 7: 2 -> 0
634 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> public
634 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> public
635 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: draft -> public
635 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: draft -> public
636 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: draft -> public
636 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: draft -> public
637 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: draft -> public
637 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: draft -> public
638 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: draft -> public
638 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: draft -> public
639 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: secret -> public
639 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: secret -> public
640 $ hg phase --draft '5 or 7'
640 $ hg phase --draft '5 or 7'
641 test-debug-phase: move rev 5: 2 -> 1
641 test-debug-phase: move rev 5: 2 -> 1
642 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: secret -> draft
642 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: secret -> draft
643 cannot move 1 changesets to a higher phase, use --force
643 cannot move 1 changesets to a higher phase, use --force
644 phase changed for 1 changesets
644 phase changed for 1 changesets
645 [1]
645 [1]
646 $ hg log -G --template "{rev} {phase} {desc}\n"
646 $ hg log -G --template "{rev} {phase} {desc}\n"
647 @ 7 public merge B' and E
647 @ 7 public merge B' and E
648 |\
648 |\
649 | o 6 public B'
649 | o 6 public B'
650 | |
650 | |
651 +---o 5 draft H
651 +---o 5 draft H
652 | |
652 | |
653 o | 4 public E
653 o | 4 public E
654 | |
654 | |
655 o | 3 public D
655 o | 3 public D
656 | |
656 | |
657 o | 2 public C
657 o | 2 public C
658 |/
658 |/
659 o 1 public B
659 o 1 public B
660 |
660 |
661 o 0 public A
661 o 0 public A
662
662
663
663
664 test complete failure
664 test complete failure
665
665
666 $ hg phase --draft 7
666 $ hg phase --draft 7
667 cannot move 1 changesets to a higher phase, use --force
667 cannot move 1 changesets to a higher phase, use --force
668 no phases changed
668 no phases changed
669 [1]
669 [1]
670
670
671 $ cd ..
671 $ cd ..
672
672
673 test hidden changeset are not cloned as public (issue3935)
673 test hidden changeset are not cloned as public (issue3935)
674
674
675 $ cd initialrepo
675 $ cd initialrepo
676
676
677 (enabling evolution)
677 (enabling evolution)
678 $ cat >> $HGRCPATH << EOF
678 $ cat >> $HGRCPATH << EOF
679 > [experimental]
679 > [experimental]
680 > evolution.createmarkers=True
680 > evolution.createmarkers=True
681 > EOF
681 > EOF
682
682
683 (making a changeset hidden; H in that case)
683 (making a changeset hidden; H in that case)
684 $ hg debugobsolete `hg id --debug -r 5`
684 $ hg debugobsolete `hg id --debug -r 5`
685 1 new obsolescence markers
685 1 new obsolescence markers
686 obsoleted 1 changesets
686 obsoleted 1 changesets
687
687
688 $ cd ..
688 $ cd ..
689 $ hg clone initialrepo clonewithobs
689 $ hg clone initialrepo clonewithobs
690 requesting all changes
690 requesting all changes
691 adding changesets
691 adding changesets
692 adding manifests
692 adding manifests
693 adding file changes
693 adding file changes
694 added 7 changesets with 6 changes to 6 files
694 added 7 changesets with 6 changes to 6 files
695 new changesets 4a2df7238c3b:17a481b3bccb
695 new changesets 4a2df7238c3b:17a481b3bccb
696 test-debug-phase: new rev 0: x -> 0
696 test-debug-phase: new rev 0: x -> 0
697 test-debug-phase: new rev 1: x -> 0
697 test-debug-phase: new rev 1: x -> 0
698 test-debug-phase: new rev 2: x -> 0
698 test-debug-phase: new rev 2: x -> 0
699 test-debug-phase: new rev 3: x -> 0
699 test-debug-phase: new rev 3: x -> 0
700 test-debug-phase: new rev 4: x -> 0
700 test-debug-phase: new rev 4: x -> 0
701 test-debug-phase: new rev 5: x -> 0
701 test-debug-phase: new rev 5: x -> 0
702 test-debug-phase: new rev 6: x -> 0
702 test-debug-phase: new rev 6: x -> 0
703 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
703 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> public
704 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
704 test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: -> public
705 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> public
705 test-hook-close-phase: f838bfaca5c7226600ebcfd84f3c3c13a28d3757: -> public
706 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> public
706 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: -> public
707 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: -> public
707 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: -> public
708 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> public
708 test-hook-close-phase: cf9fe039dfd67e829edf6522a45de057b5c86519: -> public
709 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: -> public
709 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: -> public
710 updating to branch default
710 updating to branch default
711 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
711 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
712 $ cd clonewithobs
712 $ cd clonewithobs
713 $ hg log -G --template "{rev} {phase} {desc}\n"
713 $ hg log -G --template "{rev} {phase} {desc}\n"
714 @ 6 public merge B' and E
714 @ 6 public merge B' and E
715 |\
715 |\
716 | o 5 public B'
716 | o 5 public B'
717 | |
717 | |
718 o | 4 public E
718 o | 4 public E
719 | |
719 | |
720 o | 3 public D
720 o | 3 public D
721 | |
721 | |
722 o | 2 public C
722 o | 2 public C
723 |/
723 |/
724 o 1 public B
724 o 1 public B
725 |
725 |
726 o 0 public A
726 o 0 public A
727
727
728
728
729 test verify repo containing hidden changesets, which should not abort just
729 test verify repo containing hidden changesets, which should not abort just
730 because repo.cancopy() is False
730 because repo.cancopy() is False
731
731
732 $ cd ../initialrepo
732 $ cd ../initialrepo
733 $ hg verify
733 $ hg verify
734 checking changesets
734 checking changesets
735 checking manifests
735 checking manifests
736 crosschecking files in changesets and manifests
736 crosschecking files in changesets and manifests
737 checking files
737 checking files
738 checked 8 changesets with 7 changes to 7 files
738 checked 8 changesets with 7 changes to 7 files
739
739
740 $ cd ..
740 $ cd ..
741
741
742 check whether HG_PENDING makes pending changes only in related
742 check whether HG_PENDING makes pending changes only in related
743 repositories visible to an external hook.
743 repositories visible to an external hook.
744
744
745 (emulate a transaction running concurrently by copied
745 (emulate a transaction running concurrently by copied
746 .hg/phaseroots.pending in subsequent test)
746 .hg/phaseroots.pending in subsequent test)
747
747
748 $ cat > $TESTTMP/savepending.sh <<EOF
748 $ cat > $TESTTMP/savepending.sh <<EOF
749 > cp .hg/store/phaseroots.pending .hg/store/phaseroots.pending.saved
749 > cp .hg/store/phaseroots.pending .hg/store/phaseroots.pending.saved
750 > exit 1 # to avoid changing phase for subsequent tests
750 > exit 1 # to avoid changing phase for subsequent tests
751 > EOF
751 > EOF
752 $ cd push-dest
752 $ cd push-dest
753 $ hg phase 6
753 $ hg phase 6
754 6: draft
754 6: draft
755 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" phase -f -s 6
755 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" phase -f -s 6
756 transaction abort!
756 transaction abort!
757 rollback completed
757 rollback completed
758 abort: pretxnclose hook exited with status 1
758 abort: pretxnclose hook exited with status 1
759 [40]
759 [40]
760 $ cp .hg/store/phaseroots.pending.saved .hg/store/phaseroots.pending
760 $ cp .hg/store/phaseroots.pending.saved .hg/store/phaseroots.pending
761
761
762 (check (in)visibility of phaseroot while transaction running in repo)
762 (check (in)visibility of phaseroot while transaction running in repo)
763
763
764 $ cat > $TESTTMP/checkpending.sh <<EOF
764 $ cat > $TESTTMP/checkpending.sh <<EOF
765 > echo '@initialrepo'
765 > echo '@initialrepo'
766 > hg -R "$TESTTMP/initialrepo" phase 7
766 > hg -R "$TESTTMP/initialrepo" phase 7
767 > echo '@push-dest'
767 > echo '@push-dest'
768 > hg -R "$TESTTMP/push-dest" phase 6
768 > hg -R "$TESTTMP/push-dest" phase 6
769 > exit 1 # to avoid changing phase for subsequent tests
769 > exit 1 # to avoid changing phase for subsequent tests
770 > EOF
770 > EOF
771 $ cd ../initialrepo
771 $ cd ../initialrepo
772 $ hg phase 7
772 $ hg phase 7
773 7: public
773 7: public
774 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" phase -f -s 7
774 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" phase -f -s 7
775 @initialrepo
775 @initialrepo
776 7: secret
776 7: secret
777 @push-dest
777 @push-dest
778 6: draft
778 6: draft
779 transaction abort!
779 transaction abort!
780 rollback completed
780 rollback completed
781 abort: pretxnclose hook exited with status 1
781 abort: pretxnclose hook exited with status 1
782 [40]
782 [40]
783
783
784 Check that pretxnclose-phase hook can control phase movement
784 Check that pretxnclose-phase hook can control phase movement
785
785
786 $ hg phase --force b3325c91a4d9 --secret
786 $ hg phase --force b3325c91a4d9 --secret
787 test-debug-phase: move rev 3: 0 -> 2
787 test-debug-phase: move rev 3: 0 -> 2
788 test-debug-phase: move rev 4: 0 -> 2
788 test-debug-phase: move rev 4: 0 -> 2
789 test-debug-phase: move rev 5: 1 -> 2
789 test-debug-phase: move rev 5: 1 -> 2
790 test-debug-phase: move rev 7: 0 -> 2
790 test-debug-phase: move rev 7: 0 -> 2
791 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: public -> secret
791 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: public -> secret
792 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: public -> secret
792 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: public -> secret
793 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: draft -> secret
793 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: draft -> secret
794 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: public -> secret
794 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: public -> secret
795 $ hg log -G -T phases
795 $ hg log -G -T phases
796 @ changeset: 7:17a481b3bccb
796 @ changeset: 7:17a481b3bccb
797 |\ tag: tip
797 |\ tag: tip
798 | | phase: secret
798 | | phase: secret
799 | | parent: 6:cf9fe039dfd6
799 | | parent: 6:cf9fe039dfd6
800 | | parent: 4:a603bfb5a83e
800 | | parent: 4:a603bfb5a83e
801 | | user: test
801 | | user: test
802 | | date: Thu Jan 01 00:00:00 1970 +0000
802 | | date: Thu Jan 01 00:00:00 1970 +0000
803 | | summary: merge B' and E
803 | | summary: merge B' and E
804 | |
804 | |
805 | o changeset: 6:cf9fe039dfd6
805 | o changeset: 6:cf9fe039dfd6
806 | | phase: public
806 | | phase: public
807 | | parent: 1:27547f69f254
807 | | parent: 1:27547f69f254
808 | | user: test
808 | | user: test
809 | | date: Thu Jan 01 00:00:00 1970 +0000
809 | | date: Thu Jan 01 00:00:00 1970 +0000
810 | | summary: B'
810 | | summary: B'
811 | |
811 | |
812 o | changeset: 4:a603bfb5a83e
812 o | changeset: 4:a603bfb5a83e
813 | | phase: secret
813 | | phase: secret
814 | | user: test
814 | | user: test
815 | | date: Thu Jan 01 00:00:00 1970 +0000
815 | | date: Thu Jan 01 00:00:00 1970 +0000
816 | | summary: E
816 | | summary: E
817 | |
817 | |
818 o | changeset: 3:b3325c91a4d9
818 o | changeset: 3:b3325c91a4d9
819 | | phase: secret
819 | | phase: secret
820 | | user: test
820 | | user: test
821 | | date: Thu Jan 01 00:00:00 1970 +0000
821 | | date: Thu Jan 01 00:00:00 1970 +0000
822 | | summary: D
822 | | summary: D
823 | |
823 | |
824 o | changeset: 2:f838bfaca5c7
824 o | changeset: 2:f838bfaca5c7
825 |/ phase: public
825 |/ phase: public
826 | user: test
826 | user: test
827 | date: Thu Jan 01 00:00:00 1970 +0000
827 | date: Thu Jan 01 00:00:00 1970 +0000
828 | summary: C
828 | summary: C
829 |
829 |
830 o changeset: 1:27547f69f254
830 o changeset: 1:27547f69f254
831 | phase: public
831 | phase: public
832 | user: test
832 | user: test
833 | date: Thu Jan 01 00:00:00 1970 +0000
833 | date: Thu Jan 01 00:00:00 1970 +0000
834 | summary: B
834 | summary: B
835 |
835 |
836 o changeset: 0:4a2df7238c3b
836 o changeset: 0:4a2df7238c3b
837 phase: public
837 phase: public
838 user: test
838 user: test
839 date: Thu Jan 01 00:00:00 1970 +0000
839 date: Thu Jan 01 00:00:00 1970 +0000
840 summary: A
840 summary: A
841
841
842
842
843 Install a hook that prevent b3325c91a4d9 to become public
843 Install a hook that prevent b3325c91a4d9 to become public
844
844
845 $ cat >> .hg/hgrc << EOF
845 $ cat >> .hg/hgrc << EOF
846 > [hooks]
846 > [hooks]
847 > pretxnclose-phase.nopublish_D = sh -c "(echo \$HG_NODE| grep -v b3325c91a4d9>/dev/null) || [ 'public' != \$HG_PHASE ]"
847 > pretxnclose-phase.nopublish_D = sh -c "(echo \$HG_NODE| grep -v b3325c91a4d9>/dev/null) || [ 'public' != \$HG_PHASE ]"
848 > EOF
848 > EOF
849
849
850 Try various actions. only the draft move should succeed
850 Try various actions. only the draft move should succeed
851
851
852 $ hg phase --public b3325c91a4d9
852 $ hg phase --public b3325c91a4d9
853 transaction abort!
853 transaction abort!
854 rollback completed
854 rollback completed
855 abort: pretxnclose-phase.nopublish_D hook exited with status 1
855 abort: pretxnclose-phase.nopublish_D hook exited with status 1
856 [40]
856 [40]
857 $ hg phase --public a603bfb5a83e
857 $ hg phase --public a603bfb5a83e
858 transaction abort!
858 transaction abort!
859 rollback completed
859 rollback completed
860 abort: pretxnclose-phase.nopublish_D hook exited with status 1
860 abort: pretxnclose-phase.nopublish_D hook exited with status 1
861 [40]
861 [40]
862 $ hg phase --draft 17a481b3bccb
862 $ hg phase --draft 17a481b3bccb
863 test-debug-phase: move rev 3: 2 -> 1
863 test-debug-phase: move rev 3: 2 -> 1
864 test-debug-phase: move rev 4: 2 -> 1
864 test-debug-phase: move rev 4: 2 -> 1
865 test-debug-phase: move rev 7: 2 -> 1
865 test-debug-phase: move rev 7: 2 -> 1
866 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: secret -> draft
866 test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: secret -> draft
867 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: secret -> draft
867 test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: secret -> draft
868 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: secret -> draft
868 test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: secret -> draft
869 $ hg phase --public 17a481b3bccb
869 $ hg phase --public 17a481b3bccb
870 transaction abort!
870 transaction abort!
871 rollback completed
871 rollback completed
872 abort: pretxnclose-phase.nopublish_D hook exited with status 1
872 abort: pretxnclose-phase.nopublish_D hook exited with status 1
873 [40]
873 [40]
874
874
875 $ cd ..
875 $ cd ..
876
876
877 Test for the "internal" phase
877 Test for the "internal" phase
878 =============================
878 =============================
879
879
880 Check we deny its usage on older repository
880 Check we deny its usage on older repository
881
881
882 $ hg init no-internal-phase --config format.internal-phase=no
882 $ hg init no-internal-phase --config format.use-internal-phase=no
883 $ cd no-internal-phase
883 $ cd no-internal-phase
884 $ hg debugrequires | grep internal-phase
884 $ hg debugrequires | grep internal-phase
885 [1]
885 [1]
886 $ echo X > X
886 $ echo X > X
887 $ hg add X
887 $ hg add X
888 $ hg status
888 $ hg status
889 A X
889 A X
890 $ hg --config "phases.new-commit=internal" commit -m "my test internal commit" 2>&1 | grep ProgrammingError
890 $ hg --config "phases.new-commit=internal" commit -m "my test internal commit" 2>&1 | grep ProgrammingError
891 ** ProgrammingError: this repository does not support the internal phase
891 ** ProgrammingError: this repository does not support the internal phase
892 raise error.ProgrammingError(msg) (no-pyoxidizer !)
892 raise error.ProgrammingError(msg) (no-pyoxidizer !)
893 *ProgrammingError: this repository does not support the internal phase (glob)
893 *ProgrammingError: this repository does not support the internal phase (glob)
894 $ hg --config "phases.new-commit=archived" commit -m "my test archived commit" 2>&1 | grep ProgrammingError
894 $ hg --config "phases.new-commit=archived" commit -m "my test archived commit" 2>&1 | grep ProgrammingError
895 ** ProgrammingError: this repository does not support the archived phase
895 ** ProgrammingError: this repository does not support the archived phase
896 raise error.ProgrammingError(msg) (no-pyoxidizer !)
896 raise error.ProgrammingError(msg) (no-pyoxidizer !)
897 *ProgrammingError: this repository does not support the archived phase (glob)
897 *ProgrammingError: this repository does not support the archived phase (glob)
898
898
899 $ cd ..
899 $ cd ..
900
900
901 Check it works fine with repository that supports it.
901 Check it works fine with repository that supports it.
902
902
903 $ hg init internal-phase --config format.internal-phase=yes
903 $ hg init internal-phase --config format.use-internal-phase=yes
904 $ cd internal-phase
904 $ cd internal-phase
905 $ hg debugrequires | grep internal-phase
905 $ hg debugrequires | grep internal-phase
906 internal-phase
906 internal-phase-2
907 $ mkcommit A
907 $ mkcommit A
908 test-debug-phase: new rev 0: x -> 1
908 test-debug-phase: new rev 0: x -> 1
909 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> draft
909 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: -> draft
910
910
911 Commit an internal changesets
911 Commit an internal changesets
912
912
913 $ echo B > B
913 $ echo B > B
914 $ hg add B
914 $ hg add B
915 $ hg status
915 $ hg status
916 A B
916 A B
917 $ hg --config "phases.new-commit=internal" commit -m "my test internal commit"
917 $ hg --config "phases.new-commit=internal" commit -m "my test internal commit"
918 test-debug-phase: new rev 1: x -> 96
918 test-debug-phase: new rev 1: x -> 96
919 test-hook-close-phase: c01c42dffc7f81223397e99652a0703f83e1c5ea: -> internal
919 test-hook-close-phase: c01c42dffc7f81223397e99652a0703f83e1c5ea: -> internal
920
920
921 The changeset is a working parent descendant.
921 The changeset is a working parent descendant.
922 Per the usual visibility rules, it is made visible.
922 Per the usual visibility rules, it is made visible.
923
923
924 $ hg log -G -l 3
924 $ hg log -G -l 3
925 @ changeset: 1:c01c42dffc7f
925 @ changeset: 1:c01c42dffc7f
926 | tag: tip
926 | tag: tip
927 | user: test
927 | user: test
928 | date: Thu Jan 01 00:00:00 1970 +0000
928 | date: Thu Jan 01 00:00:00 1970 +0000
929 | summary: my test internal commit
929 | summary: my test internal commit
930 |
930 |
931 o changeset: 0:4a2df7238c3b
931 o changeset: 0:4a2df7238c3b
932 user: test
932 user: test
933 date: Thu Jan 01 00:00:00 1970 +0000
933 date: Thu Jan 01 00:00:00 1970 +0000
934 summary: A
934 summary: A
935
935
936
936
937 Commit is hidden as expected
937 Commit is hidden as expected
938
938
939 $ hg up 0
939 $ hg up 0
940 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
940 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
941 $ hg log -G
941 $ hg log -G
942 @ changeset: 0:4a2df7238c3b
942 @ changeset: 0:4a2df7238c3b
943 tag: tip
943 tag: tip
944 user: test
944 user: test
945 date: Thu Jan 01 00:00:00 1970 +0000
945 date: Thu Jan 01 00:00:00 1970 +0000
946 summary: A
946 summary: A
947
947
948
948
949 Test for archived phase
949 Test for archived phase
950 -----------------------
950 -----------------------
951
951
952 Commit an archived changesets
952 Commit an archived changesets
953
953
954 $ cd ..
954 $ cd ..
955 $ hg clone --quiet --pull internal-phase archived-phase \
955 $ hg clone --quiet --pull internal-phase archived-phase \
956 > --config format.exp-archived-phase=yes \
956 > --config format.exp-archived-phase=yes \
957 > --config extensions.phasereport='!' \
957 > --config extensions.phasereport='!' \
958 > --config hooks.txnclose-phase.test=
958 > --config hooks.txnclose-phase.test=
959
959
960 $ cd archived-phase
960 $ cd archived-phase
961
961
962 $ echo B > B
962 $ echo B > B
963 $ hg add B
963 $ hg add B
964 $ hg status
964 $ hg status
965 A B
965 A B
966 $ hg --config "phases.new-commit=archived" commit -m "my test archived commit"
966 $ hg --config "phases.new-commit=archived" commit -m "my test archived commit"
967 test-debug-phase: new rev 1: x -> 32
967 test-debug-phase: new rev 1: x -> 32
968 test-hook-close-phase: 8df5997c3361518f733d1ae67cd3adb9b0eaf125: -> archived
968 test-hook-close-phase: 8df5997c3361518f733d1ae67cd3adb9b0eaf125: -> archived
969
969
970 The changeset is a working parent descendant.
970 The changeset is a working parent descendant.
971 Per the usual visibility rules, it is made visible.
971 Per the usual visibility rules, it is made visible.
972
972
973 $ hg log -G -l 3
973 $ hg log -G -l 3
974 @ changeset: 1:8df5997c3361
974 @ changeset: 1:8df5997c3361
975 | tag: tip
975 | tag: tip
976 | user: test
976 | user: test
977 | date: Thu Jan 01 00:00:00 1970 +0000
977 | date: Thu Jan 01 00:00:00 1970 +0000
978 | summary: my test archived commit
978 | summary: my test archived commit
979 |
979 |
980 o changeset: 0:4a2df7238c3b
980 o changeset: 0:4a2df7238c3b
981 user: test
981 user: test
982 date: Thu Jan 01 00:00:00 1970 +0000
982 date: Thu Jan 01 00:00:00 1970 +0000
983 summary: A
983 summary: A
984
984
985
985
986 Commit is hidden as expected
986 Commit is hidden as expected
987
987
988 $ hg up 0
988 $ hg up 0
989 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
989 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
990 $ hg log -G
990 $ hg log -G
991 @ changeset: 0:4a2df7238c3b
991 @ changeset: 0:4a2df7238c3b
992 tag: tip
992 tag: tip
993 user: test
993 user: test
994 date: Thu Jan 01 00:00:00 1970 +0000
994 date: Thu Jan 01 00:00:00 1970 +0000
995 summary: A
995 summary: A
996
996
997 $ cd ..
997 $ cd ..
998
998
999 Recommitting an exact match of a public commit shouldn't change it to
999 Recommitting an exact match of a public commit shouldn't change it to
1000 draft:
1000 draft:
1001
1001
1002 $ cd initialrepo
1002 $ cd initialrepo
1003 $ hg phase -r 2
1003 $ hg phase -r 2
1004 2: public
1004 2: public
1005 $ hg up -C 1
1005 $ hg up -C 1
1006 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
1006 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
1007 $ mkcommit C
1007 $ mkcommit C
1008 warning: commit already existed in the repository!
1008 warning: commit already existed in the repository!
1009 $ hg phase -r 2
1009 $ hg phase -r 2
1010 2: public
1010 2: public
1011
1011
1012 Same, but for secret:
1012 Same, but for secret:
1013
1013
1014 $ hg up 7
1014 $ hg up 7
1015 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1015 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1016 $ mkcommit F -s
1016 $ mkcommit F -s
1017 test-debug-phase: new rev 8: x -> 2
1017 test-debug-phase: new rev 8: x -> 2
1018 test-hook-close-phase: de414268ec5ce2330c590b942fbb5ff0b0ca1a0a: -> secret
1018 test-hook-close-phase: de414268ec5ce2330c590b942fbb5ff0b0ca1a0a: -> secret
1019 $ hg up 7
1019 $ hg up 7
1020 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1020 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1021 $ hg phase
1021 $ hg phase
1022 7: draft
1022 7: draft
1023 $ mkcommit F
1023 $ mkcommit F
1024 test-debug-phase: new rev 8: x -> 2
1024 test-debug-phase: new rev 8: x -> 2
1025 warning: commit already existed in the repository!
1025 warning: commit already existed in the repository!
1026 test-hook-close-phase: de414268ec5ce2330c590b942fbb5ff0b0ca1a0a: -> secret
1026 test-hook-close-phase: de414268ec5ce2330c590b942fbb5ff0b0ca1a0a: -> secret
1027 $ hg phase -r tip
1027 $ hg phase -r tip
1028 8: secret
1028 8: secret
1029
1029
1030 But what about obsoleted changesets?
1030 But what about obsoleted changesets?
1031
1031
1032 $ hg up 4
1032 $ hg up 4
1033 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1033 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1034 $ mkcommit H
1034 $ mkcommit H
1035 test-debug-phase: new rev 5: x -> 2
1035 test-debug-phase: new rev 5: x -> 2
1036 warning: commit already existed in the repository!
1036 warning: commit already existed in the repository!
1037 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: -> secret
1037 test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: -> secret
1038 $ hg phase -r 5
1038 $ hg phase -r 5
1039 5: secret
1039 5: secret
1040 $ hg par
1040 $ hg par
1041 changeset: 5:a030c6be5127
1041 changeset: 5:a030c6be5127
1042 user: test
1042 user: test
1043 date: Thu Jan 01 00:00:00 1970 +0000
1043 date: Thu Jan 01 00:00:00 1970 +0000
1044 obsolete: pruned
1044 obsolete: pruned
1045 summary: H
1045 summary: H
1046
1046
1047 $ hg up tip
1047 $ hg up tip
1048 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1048 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1049 $ cd ..
1049 $ cd ..
@@ -1,1601 +1,1601 b''
1 #testcases stripbased phasebased
1 #testcases stripbased phasebased
2
2
3 $ cat <<EOF >> $HGRCPATH
3 $ cat <<EOF >> $HGRCPATH
4 > [extensions]
4 > [extensions]
5 > mq =
5 > mq =
6 > [defaults]
6 > [defaults]
7 > diff = --nodates --git
7 > diff = --nodates --git
8 > qnew = --date '0 0'
8 > qnew = --date '0 0'
9 > [shelve]
9 > [shelve]
10 > maxbackups = 2
10 > maxbackups = 2
11 > EOF
11 > EOF
12
12
13 #if phasebased
13 #if phasebased
14
14
15 $ cat <<EOF >> $HGRCPATH
15 $ cat <<EOF >> $HGRCPATH
16 > [format]
16 > [format]
17 > internal-phase = yes
17 > use-internal-phase = yes
18 > EOF
18 > EOF
19
19
20 #endif
20 #endif
21
21
22 $ hg init repo
22 $ hg init repo
23 $ cd repo
23 $ cd repo
24 $ mkdir a b
24 $ mkdir a b
25 $ echo a > a/a
25 $ echo a > a/a
26 $ echo b > b/b
26 $ echo b > b/b
27 $ echo c > c
27 $ echo c > c
28 $ echo d > d
28 $ echo d > d
29 $ echo x > x
29 $ echo x > x
30 $ hg addremove -q
30 $ hg addremove -q
31
31
32 shelve has a help message
32 shelve has a help message
33 $ hg shelve -h
33 $ hg shelve -h
34 hg shelve [OPTION]... [FILE]...
34 hg shelve [OPTION]... [FILE]...
35
35
36 save and set aside changes from the working directory
36 save and set aside changes from the working directory
37
37
38 Shelving takes files that "hg status" reports as not clean, saves the
38 Shelving takes files that "hg status" reports as not clean, saves the
39 modifications to a bundle (a shelved change), and reverts the files so
39 modifications to a bundle (a shelved change), and reverts the files so
40 that their state in the working directory becomes clean.
40 that their state in the working directory becomes clean.
41
41
42 To restore these changes to the working directory, using "hg unshelve";
42 To restore these changes to the working directory, using "hg unshelve";
43 this will work even if you switch to a different commit.
43 this will work even if you switch to a different commit.
44
44
45 When no files are specified, "hg shelve" saves all not-clean files. If
45 When no files are specified, "hg shelve" saves all not-clean files. If
46 specific files or directories are named, only changes to those files are
46 specific files or directories are named, only changes to those files are
47 shelved.
47 shelved.
48
48
49 In bare shelve (when no files are specified, without interactive, include
49 In bare shelve (when no files are specified, without interactive, include
50 and exclude option), shelving remembers information if the working
50 and exclude option), shelving remembers information if the working
51 directory was on newly created branch, in other words working directory
51 directory was on newly created branch, in other words working directory
52 was on different branch than its first parent. In this situation
52 was on different branch than its first parent. In this situation
53 unshelving restores branch information to the working directory.
53 unshelving restores branch information to the working directory.
54
54
55 Each shelved change has a name that makes it easier to find later. The
55 Each shelved change has a name that makes it easier to find later. The
56 name of a shelved change defaults to being based on the active bookmark,
56 name of a shelved change defaults to being based on the active bookmark,
57 or if there is no active bookmark, the current named branch. To specify a
57 or if there is no active bookmark, the current named branch. To specify a
58 different name, use "--name".
58 different name, use "--name".
59
59
60 To see a list of existing shelved changes, use the "--list" option. For
60 To see a list of existing shelved changes, use the "--list" option. For
61 each shelved change, this will print its name, age, and description; use "
61 each shelved change, this will print its name, age, and description; use "
62 --patch" or "--stat" for more details.
62 --patch" or "--stat" for more details.
63
63
64 To delete specific shelved changes, use "--delete". To delete all shelved
64 To delete specific shelved changes, use "--delete". To delete all shelved
65 changes, use "--cleanup".
65 changes, use "--cleanup".
66
66
67 options ([+] can be repeated):
67 options ([+] can be repeated):
68
68
69 -A --addremove mark new/missing files as added/removed before
69 -A --addremove mark new/missing files as added/removed before
70 shelving
70 shelving
71 -u --unknown store unknown files in the shelve
71 -u --unknown store unknown files in the shelve
72 --cleanup delete all shelved changes
72 --cleanup delete all shelved changes
73 --date DATE shelve with the specified commit date
73 --date DATE shelve with the specified commit date
74 -d --delete delete the named shelved change(s)
74 -d --delete delete the named shelved change(s)
75 -e --edit invoke editor on commit messages
75 -e --edit invoke editor on commit messages
76 -k --keep shelve, but keep changes in the working directory
76 -k --keep shelve, but keep changes in the working directory
77 -l --list list current shelves
77 -l --list list current shelves
78 -m --message TEXT use text as shelve message
78 -m --message TEXT use text as shelve message
79 -n --name NAME use the given name for the shelved commit
79 -n --name NAME use the given name for the shelved commit
80 -p --patch output patches for changes (provide the names of the
80 -p --patch output patches for changes (provide the names of the
81 shelved changes as positional arguments)
81 shelved changes as positional arguments)
82 -i --interactive interactive mode
82 -i --interactive interactive mode
83 --stat output diffstat-style summary of changes (provide
83 --stat output diffstat-style summary of changes (provide
84 the names of the shelved changes as positional
84 the names of the shelved changes as positional
85 arguments)
85 arguments)
86 -I --include PATTERN [+] include names matching the given patterns
86 -I --include PATTERN [+] include names matching the given patterns
87 -X --exclude PATTERN [+] exclude names matching the given patterns
87 -X --exclude PATTERN [+] exclude names matching the given patterns
88 --mq operate on patch repository
88 --mq operate on patch repository
89
89
90 (some details hidden, use --verbose to show complete help)
90 (some details hidden, use --verbose to show complete help)
91
91
92 shelving in an empty repo should be possible
92 shelving in an empty repo should be possible
93 (this tests also that editor is not invoked, if '--edit' is not
93 (this tests also that editor is not invoked, if '--edit' is not
94 specified)
94 specified)
95
95
96 $ HGEDITOR=cat hg shelve
96 $ HGEDITOR=cat hg shelve
97 shelved as default
97 shelved as default
98 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
98 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
99
99
100 $ hg unshelve
100 $ hg unshelve
101 unshelving change 'default'
101 unshelving change 'default'
102
102
103 $ hg commit -q -m 'initial commit'
103 $ hg commit -q -m 'initial commit'
104
104
105 $ hg shelve
105 $ hg shelve
106 nothing changed
106 nothing changed
107 [1]
107 [1]
108
108
109 make sure shelve files were backed up
109 make sure shelve files were backed up
110
110
111 $ ls .hg/shelve-backup
111 $ ls .hg/shelve-backup
112 default.hg
112 default.hg
113 default.patch
113 default.patch
114 default.shelve
114 default.shelve
115
115
116 checks to make sure we dont create a directory or
116 checks to make sure we dont create a directory or
117 hidden file while choosing a new shelve name
117 hidden file while choosing a new shelve name
118
118
119 when we are given a name
119 when we are given a name
120
120
121 $ hg shelve -n foo/bar
121 $ hg shelve -n foo/bar
122 abort: shelved change names can not contain slashes
122 abort: shelved change names can not contain slashes
123 [255]
123 [255]
124 $ hg shelve -n .baz
124 $ hg shelve -n .baz
125 abort: shelved change names can not start with '.'
125 abort: shelved change names can not start with '.'
126 [255]
126 [255]
127 $ hg shelve -n foo\\bar
127 $ hg shelve -n foo\\bar
128 abort: shelved change names can not contain slashes
128 abort: shelved change names can not contain slashes
129 [255]
129 [255]
130
130
131 when shelve has to choose itself
131 when shelve has to choose itself
132
132
133 $ hg branch x/y -q
133 $ hg branch x/y -q
134 $ hg commit -q -m "Branch commit 0"
134 $ hg commit -q -m "Branch commit 0"
135 $ hg shelve
135 $ hg shelve
136 nothing changed
136 nothing changed
137 [1]
137 [1]
138 $ hg branch .x -q
138 $ hg branch .x -q
139 $ hg commit -q -m "Branch commit 1"
139 $ hg commit -q -m "Branch commit 1"
140 $ hg shelve
140 $ hg shelve
141 nothing changed
141 nothing changed
142 [1]
142 [1]
143 $ hg branch x\\y -q
143 $ hg branch x\\y -q
144 $ hg commit -q -m "Branch commit 2"
144 $ hg commit -q -m "Branch commit 2"
145 $ hg shelve
145 $ hg shelve
146 nothing changed
146 nothing changed
147 [1]
147 [1]
148
148
149 cleaning the branches made for name checking tests
149 cleaning the branches made for name checking tests
150
150
151 $ hg up default -q
151 $ hg up default -q
152 $ hg strip e9177275307e+6a6d231f43d+882bae7c62c2 -q
152 $ hg strip e9177275307e+6a6d231f43d+882bae7c62c2 -q
153
153
154 create an mq patch - shelving should work fine with a patch applied
154 create an mq patch - shelving should work fine with a patch applied
155
155
156 $ echo n > n
156 $ echo n > n
157 $ hg add n
157 $ hg add n
158 $ hg commit n -m second
158 $ hg commit n -m second
159 $ hg qnew second.patch
159 $ hg qnew second.patch
160
160
161 shelve a change that we will delete later
161 shelve a change that we will delete later
162
162
163 $ echo a >> a/a
163 $ echo a >> a/a
164 $ hg shelve
164 $ hg shelve
165 shelved as default
165 shelved as default
166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
167
167
168 set up some more complex changes to shelve
168 set up some more complex changes to shelve
169
169
170 $ echo a >> a/a
170 $ echo a >> a/a
171 $ hg mv b b.rename
171 $ hg mv b b.rename
172 moving b/b to b.rename/b
172 moving b/b to b.rename/b
173 $ hg cp c c.copy
173 $ hg cp c c.copy
174 $ hg mv d ghost
174 $ hg mv d ghost
175 $ rm ghost
175 $ rm ghost
176 $ hg status -C
176 $ hg status -C
177 M a/a
177 M a/a
178 A b.rename/b
178 A b.rename/b
179 b/b
179 b/b
180 A c.copy
180 A c.copy
181 c
181 c
182 R b/b
182 R b/b
183 R d
183 R d
184 ! ghost
184 ! ghost
185 d
185 d
186
186
187 the common case - no options or filenames
187 the common case - no options or filenames
188
188
189 $ hg shelve
189 $ hg shelve
190 shelved as default-01
190 shelved as default-01
191 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
191 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
192 $ hg status -C
192 $ hg status -C
193
193
194 ensure that our shelved changes exist
194 ensure that our shelved changes exist
195
195
196 $ hg shelve -l
196 $ hg shelve -l
197 default-01 (*)* changes to: [mq]: second.patch (glob)
197 default-01 (*)* changes to: [mq]: second.patch (glob)
198 default (*)* changes to: [mq]: second.patch (glob)
198 default (*)* changes to: [mq]: second.patch (glob)
199
199
200 $ hg shelve -l -p default
200 $ hg shelve -l -p default
201 default (*)* changes to: [mq]: second.patch (glob)
201 default (*)* changes to: [mq]: second.patch (glob)
202
202
203 diff --git a/a/a b/a/a
203 diff --git a/a/a b/a/a
204 --- a/a/a
204 --- a/a/a
205 +++ b/a/a
205 +++ b/a/a
206 @@ -1,1 +1,2 @@
206 @@ -1,1 +1,2 @@
207 a
207 a
208 +a
208 +a
209
209
210 $ hg shelve --list --addremove
210 $ hg shelve --list --addremove
211 abort: options '--list' and '--addremove' may not be used together
211 abort: options '--list' and '--addremove' may not be used together
212 [10]
212 [10]
213
213
214 delete our older shelved change
214 delete our older shelved change
215
215
216 $ hg shelve -d default
216 $ hg shelve -d default
217 $ hg qfinish -a -q
217 $ hg qfinish -a -q
218
218
219 ensure shelve backups aren't overwritten
219 ensure shelve backups aren't overwritten
220
220
221 $ ls .hg/shelve-backup/
221 $ ls .hg/shelve-backup/
222 default-1.hg
222 default-1.hg
223 default-1.patch
223 default-1.patch
224 default-1.shelve
224 default-1.shelve
225 default.hg
225 default.hg
226 default.patch
226 default.patch
227 default.shelve
227 default.shelve
228
228
229 local edits should not prevent a shelved change from applying
229 local edits should not prevent a shelved change from applying
230
230
231 $ printf "z\na\n" > a/a
231 $ printf "z\na\n" > a/a
232 $ hg unshelve --keep
232 $ hg unshelve --keep
233 unshelving change 'default-01'
233 unshelving change 'default-01'
234 temporarily committing pending changes (restore with 'hg unshelve --abort')
234 temporarily committing pending changes (restore with 'hg unshelve --abort')
235 rebasing shelved changes
235 rebasing shelved changes
236 merging a/a
236 merging a/a
237
237
238 $ hg revert --all -q
238 $ hg revert --all -q
239 $ rm a/a.orig b.rename/b c.copy
239 $ rm a/a.orig b.rename/b c.copy
240
240
241 apply it and make sure our state is as expected
241 apply it and make sure our state is as expected
242
242
243 (this also tests that same timestamp prevents backups from being
243 (this also tests that same timestamp prevents backups from being
244 removed, even though there are more than 'maxbackups' backups)
244 removed, even though there are more than 'maxbackups' backups)
245
245
246 $ f -t .hg/shelve-backup/default.shelve
246 $ f -t .hg/shelve-backup/default.shelve
247 .hg/shelve-backup/default.shelve: file
247 .hg/shelve-backup/default.shelve: file
248 $ touch -t 200001010000 .hg/shelve-backup/default.shelve
248 $ touch -t 200001010000 .hg/shelve-backup/default.shelve
249 $ f -t .hg/shelve-backup/default-1.shelve
249 $ f -t .hg/shelve-backup/default-1.shelve
250 .hg/shelve-backup/default-1.shelve: file
250 .hg/shelve-backup/default-1.shelve: file
251 $ touch -t 200001010000 .hg/shelve-backup/default-1.shelve
251 $ touch -t 200001010000 .hg/shelve-backup/default-1.shelve
252
252
253 $ hg unshelve
253 $ hg unshelve
254 unshelving change 'default-01'
254 unshelving change 'default-01'
255 $ hg status -C
255 $ hg status -C
256 M a/a
256 M a/a
257 A b.rename/b
257 A b.rename/b
258 b/b
258 b/b
259 A c.copy
259 A c.copy
260 c
260 c
261 R b/b
261 R b/b
262 R d
262 R d
263 $ hg shelve -l
263 $ hg shelve -l
264
264
265 (both of default.hg and default-1.hg should be still kept, because it
265 (both of default.hg and default-1.hg should be still kept, because it
266 is difficult to decide actual order of them from same timestamp)
266 is difficult to decide actual order of them from same timestamp)
267
267
268 $ ls .hg/shelve-backup/
268 $ ls .hg/shelve-backup/
269 default-01.hg
269 default-01.hg
270 default-01.patch
270 default-01.patch
271 default-01.shelve
271 default-01.shelve
272 default-1.hg
272 default-1.hg
273 default-1.patch
273 default-1.patch
274 default-1.shelve
274 default-1.shelve
275 default.hg
275 default.hg
276 default.patch
276 default.patch
277 default.shelve
277 default.shelve
278
278
279 $ hg unshelve
279 $ hg unshelve
280 abort: no shelved changes to apply!
280 abort: no shelved changes to apply!
281 [20]
281 [20]
282 $ hg unshelve foo
282 $ hg unshelve foo
283 abort: shelved change 'foo' not found
283 abort: shelved change 'foo' not found
284 [10]
284 [10]
285
285
286 named shelves, specific filenames, and "commit messages" should all work
286 named shelves, specific filenames, and "commit messages" should all work
287 (this tests also that editor is invoked, if '--edit' is specified)
287 (this tests also that editor is invoked, if '--edit' is specified)
288
288
289 $ hg status -C
289 $ hg status -C
290 M a/a
290 M a/a
291 A b.rename/b
291 A b.rename/b
292 b/b
292 b/b
293 A c.copy
293 A c.copy
294 c
294 c
295 R b/b
295 R b/b
296 R d
296 R d
297 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
297 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
298 wat
298 wat
299
299
300
300
301 HG: Enter commit message. Lines beginning with 'HG:' are removed.
301 HG: Enter commit message. Lines beginning with 'HG:' are removed.
302 HG: Leave message empty to abort commit.
302 HG: Leave message empty to abort commit.
303 HG: --
303 HG: --
304 HG: user: shelve@localhost
304 HG: user: shelve@localhost
305 HG: branch 'default'
305 HG: branch 'default'
306 HG: changed a/a
306 HG: changed a/a
307
307
308 expect "a" to no longer be present, but status otherwise unchanged
308 expect "a" to no longer be present, but status otherwise unchanged
309
309
310 $ hg status -C
310 $ hg status -C
311 A b.rename/b
311 A b.rename/b
312 b/b
312 b/b
313 A c.copy
313 A c.copy
314 c
314 c
315 R b/b
315 R b/b
316 R d
316 R d
317 $ hg shelve -l --stat
317 $ hg shelve -l --stat
318 wibble (*) wat (glob)
318 wibble (*) wat (glob)
319 a/a | 1 +
319 a/a | 1 +
320 1 files changed, 1 insertions(+), 0 deletions(-)
320 1 files changed, 1 insertions(+), 0 deletions(-)
321
321
322 and now "a/a" should reappear
322 and now "a/a" should reappear
323
323
324 $ cd a
324 $ cd a
325 $ hg unshelve -q wibble
325 $ hg unshelve -q wibble
326 $ cd ..
326 $ cd ..
327 $ hg status -C
327 $ hg status -C
328 M a/a
328 M a/a
329 A b.rename/b
329 A b.rename/b
330 b/b
330 b/b
331 A c.copy
331 A c.copy
332 c
332 c
333 R b/b
333 R b/b
334 R d
334 R d
335
335
336 ensure old shelve backups are being deleted automatically
336 ensure old shelve backups are being deleted automatically
337
337
338 $ ls .hg/shelve-backup/
338 $ ls .hg/shelve-backup/
339 default-01.hg
339 default-01.hg
340 default-01.patch
340 default-01.patch
341 default-01.shelve
341 default-01.shelve
342 wibble.hg
342 wibble.hg
343 wibble.patch
343 wibble.patch
344 wibble.shelve
344 wibble.shelve
345
345
346 cause unshelving to result in a merge with 'a' conflicting
346 cause unshelving to result in a merge with 'a' conflicting
347
347
348 $ hg shelve -q
348 $ hg shelve -q
349 $ echo c>>a/a
349 $ echo c>>a/a
350 $ hg commit -m second
350 $ hg commit -m second
351 $ hg tip --template '{files}\n'
351 $ hg tip --template '{files}\n'
352 a/a
352 a/a
353
353
354 add an unrelated change that should be preserved
354 add an unrelated change that should be preserved
355
355
356 $ mkdir foo
356 $ mkdir foo
357 $ echo foo > foo/foo
357 $ echo foo > foo/foo
358 $ hg add foo/foo
358 $ hg add foo/foo
359
359
360 force a conflicted merge to occur
360 force a conflicted merge to occur
361
361
362 $ hg unshelve
362 $ hg unshelve
363 unshelving change 'default'
363 unshelving change 'default'
364 temporarily committing pending changes (restore with 'hg unshelve --abort')
364 temporarily committing pending changes (restore with 'hg unshelve --abort')
365 rebasing shelved changes
365 rebasing shelved changes
366 merging a/a
366 merging a/a
367 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
367 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
368 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
368 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
369 [240]
369 [240]
370 $ hg status -v
370 $ hg status -v
371 M a/a
371 M a/a
372 M b.rename/b
372 M b.rename/b
373 M c.copy
373 M c.copy
374 R b/b
374 R b/b
375 R d
375 R d
376 ? a/a.orig
376 ? a/a.orig
377 # The repository is in an unfinished *unshelve* state.
377 # The repository is in an unfinished *unshelve* state.
378
378
379 # Unresolved merge conflicts:
379 # Unresolved merge conflicts:
380 #
380 #
381 # a/a
381 # a/a
382 #
382 #
383 # To mark files as resolved: hg resolve --mark FILE
383 # To mark files as resolved: hg resolve --mark FILE
384
384
385 # To continue: hg unshelve --continue
385 # To continue: hg unshelve --continue
386 # To abort: hg unshelve --abort
386 # To abort: hg unshelve --abort
387
387
388
388
389 ensure that we have a merge with unresolved conflicts
389 ensure that we have a merge with unresolved conflicts
390
390
391 #if phasebased
391 #if phasebased
392 $ hg heads -q --template '{rev}\n'
392 $ hg heads -q --template '{rev}\n'
393 8
393 8
394 5
394 5
395 $ hg parents -q --template '{rev}\n'
395 $ hg parents -q --template '{rev}\n'
396 8
396 8
397 5
397 5
398 #endif
398 #endif
399
399
400 #if stripbased
400 #if stripbased
401 $ hg heads -q --template '{rev}\n'
401 $ hg heads -q --template '{rev}\n'
402 5
402 5
403 4
403 4
404 $ hg parents -q --template '{rev}\n'
404 $ hg parents -q --template '{rev}\n'
405 4
405 4
406 5
406 5
407 #endif
407 #endif
408
408
409 $ hg status
409 $ hg status
410 M a/a
410 M a/a
411 M b.rename/b
411 M b.rename/b
412 M c.copy
412 M c.copy
413 R b/b
413 R b/b
414 R d
414 R d
415 ? a/a.orig
415 ? a/a.orig
416 $ hg diff
416 $ hg diff
417 diff --git a/a/a b/a/a
417 diff --git a/a/a b/a/a
418 --- a/a/a
418 --- a/a/a
419 +++ b/a/a
419 +++ b/a/a
420 @@ -1,2 +1,6 @@
420 @@ -1,2 +1,6 @@
421 a
421 a
422 +<<<<<<< working-copy: 2377350b6337 - shelve: pending changes temporary commit
422 +<<<<<<< working-copy: 2377350b6337 - shelve: pending changes temporary commit
423 c
423 c
424 +=======
424 +=======
425 +a
425 +a
426 +>>>>>>> shelved change: 203c9f771d2b - shelve: changes to: [mq]: second.patch
426 +>>>>>>> shelved change: 203c9f771d2b - shelve: changes to: [mq]: second.patch
427 diff --git a/b/b b/b.rename/b
427 diff --git a/b/b b/b.rename/b
428 rename from b/b
428 rename from b/b
429 rename to b.rename/b
429 rename to b.rename/b
430 diff --git a/c b/c.copy
430 diff --git a/c b/c.copy
431 copy from c
431 copy from c
432 copy to c.copy
432 copy to c.copy
433 diff --git a/d b/d
433 diff --git a/d b/d
434 deleted file mode 100644
434 deleted file mode 100644
435 --- a/d
435 --- a/d
436 +++ /dev/null
436 +++ /dev/null
437 @@ -1,1 +0,0 @@
437 @@ -1,1 +0,0 @@
438 -d
438 -d
439 $ hg resolve -l
439 $ hg resolve -l
440 U a/a
440 U a/a
441
441
442 $ hg shelve
442 $ hg shelve
443 abort: unshelve already in progress
443 abort: unshelve already in progress
444 (use 'hg unshelve --continue' or 'hg unshelve --abort')
444 (use 'hg unshelve --continue' or 'hg unshelve --abort')
445 [20]
445 [20]
446
446
447 abort the unshelve and be happy
447 abort the unshelve and be happy
448
448
449 $ hg status
449 $ hg status
450 M a/a
450 M a/a
451 M b.rename/b
451 M b.rename/b
452 M c.copy
452 M c.copy
453 R b/b
453 R b/b
454 R d
454 R d
455 ? a/a.orig
455 ? a/a.orig
456 $ hg unshelve -a
456 $ hg unshelve -a
457 unshelve of 'default' aborted
457 unshelve of 'default' aborted
458 $ hg heads -q
458 $ hg heads -q
459 [37]:2e69b451d1ea (re)
459 [37]:2e69b451d1ea (re)
460 $ hg parents
460 $ hg parents
461 changeset: [37]:2e69b451d1ea (re)
461 changeset: [37]:2e69b451d1ea (re)
462 tag: tip
462 tag: tip
463 parent: 3:509104101065 (?)
463 parent: 3:509104101065 (?)
464 user: test
464 user: test
465 date: Thu Jan 01 00:00:00 1970 +0000
465 date: Thu Jan 01 00:00:00 1970 +0000
466 summary: second
466 summary: second
467
467
468 $ hg resolve -l
468 $ hg resolve -l
469 $ hg status
469 $ hg status
470 A foo/foo
470 A foo/foo
471 ? a/a.orig
471 ? a/a.orig
472
472
473 try to continue with no unshelve underway
473 try to continue with no unshelve underway
474
474
475 $ hg unshelve -c
475 $ hg unshelve -c
476 abort: no unshelve in progress
476 abort: no unshelve in progress
477 [20]
477 [20]
478 $ hg status
478 $ hg status
479 A foo/foo
479 A foo/foo
480 ? a/a.orig
480 ? a/a.orig
481
481
482 redo the unshelve to get a conflict
482 redo the unshelve to get a conflict
483
483
484 $ hg unshelve -q
484 $ hg unshelve -q
485 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
485 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
486 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
486 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
487 [240]
487 [240]
488
488
489 attempt to continue
489 attempt to continue
490
490
491 $ hg unshelve -c
491 $ hg unshelve -c
492 abort: unresolved conflicts, can't continue
492 abort: unresolved conflicts, can't continue
493 (see 'hg resolve', then 'hg unshelve --continue')
493 (see 'hg resolve', then 'hg unshelve --continue')
494 [255]
494 [255]
495
495
496 $ hg revert -r . a/a
496 $ hg revert -r . a/a
497 $ hg resolve -m a/a
497 $ hg resolve -m a/a
498 (no more unresolved files)
498 (no more unresolved files)
499 continue: hg unshelve --continue
499 continue: hg unshelve --continue
500
500
501 $ hg commit -m 'commit while unshelve in progress'
501 $ hg commit -m 'commit while unshelve in progress'
502 abort: unshelve already in progress
502 abort: unshelve already in progress
503 (use 'hg unshelve --continue' or 'hg unshelve --abort')
503 (use 'hg unshelve --continue' or 'hg unshelve --abort')
504 [20]
504 [20]
505
505
506 $ hg graft --continue
506 $ hg graft --continue
507 abort: no graft in progress
507 abort: no graft in progress
508 (continue: hg unshelve --continue)
508 (continue: hg unshelve --continue)
509 [20]
509 [20]
510 $ hg unshelve -c
510 $ hg unshelve -c
511 unshelve of 'default' complete
511 unshelve of 'default' complete
512
512
513 ensure the repo is as we hope
513 ensure the repo is as we hope
514
514
515 $ hg parents
515 $ hg parents
516 changeset: [37]:2e69b451d1ea (re)
516 changeset: [37]:2e69b451d1ea (re)
517 tag: tip
517 tag: tip
518 parent: 3:509104101065 (?)
518 parent: 3:509104101065 (?)
519 user: test
519 user: test
520 date: Thu Jan 01 00:00:00 1970 +0000
520 date: Thu Jan 01 00:00:00 1970 +0000
521 summary: second
521 summary: second
522
522
523 $ hg heads -q
523 $ hg heads -q
524 [37]:2e69b451d1ea (re)
524 [37]:2e69b451d1ea (re)
525
525
526 $ hg status -C
526 $ hg status -C
527 A b.rename/b
527 A b.rename/b
528 b/b
528 b/b
529 A c.copy
529 A c.copy
530 c
530 c
531 A foo/foo
531 A foo/foo
532 R b/b
532 R b/b
533 R d
533 R d
534 ? a/a.orig
534 ? a/a.orig
535
535
536 there should be no shelves left
536 there should be no shelves left
537
537
538 $ hg shelve -l
538 $ hg shelve -l
539
539
540 #if execbit
540 #if execbit
541
541
542 ensure that metadata-only changes are shelved
542 ensure that metadata-only changes are shelved
543
543
544 $ chmod +x a/a
544 $ chmod +x a/a
545 $ hg shelve -q -n execbit a/a
545 $ hg shelve -q -n execbit a/a
546 $ hg status a/a
546 $ hg status a/a
547 $ hg unshelve -q execbit
547 $ hg unshelve -q execbit
548 $ hg status a/a
548 $ hg status a/a
549 M a/a
549 M a/a
550 $ hg revert a/a
550 $ hg revert a/a
551
551
552 #else
552 #else
553
553
554 Dummy shelve op, to keep rev numbers aligned
554 Dummy shelve op, to keep rev numbers aligned
555
555
556 $ echo foo > a/a
556 $ echo foo > a/a
557 $ hg shelve -q -n dummy a/a
557 $ hg shelve -q -n dummy a/a
558 $ hg unshelve -q dummy
558 $ hg unshelve -q dummy
559 $ hg revert a/a
559 $ hg revert a/a
560
560
561 #endif
561 #endif
562
562
563 #if symlink
563 #if symlink
564
564
565 $ rm a/a
565 $ rm a/a
566 $ ln -s foo a/a
566 $ ln -s foo a/a
567 $ hg shelve -q -n symlink a/a
567 $ hg shelve -q -n symlink a/a
568 $ hg status a/a
568 $ hg status a/a
569 $ hg unshelve -q -n symlink
569 $ hg unshelve -q -n symlink
570 $ hg status a/a
570 $ hg status a/a
571 M a/a
571 M a/a
572 $ hg revert a/a
572 $ hg revert a/a
573
573
574 #else
574 #else
575
575
576 Dummy shelve op, to keep rev numbers aligned
576 Dummy shelve op, to keep rev numbers aligned
577
577
578 $ echo bar > a/a
578 $ echo bar > a/a
579 $ hg shelve -q -n dummy a/a
579 $ hg shelve -q -n dummy a/a
580 $ hg unshelve -q dummy
580 $ hg unshelve -q dummy
581 $ hg revert a/a
581 $ hg revert a/a
582
582
583 #endif
583 #endif
584
584
585 set up another conflict between a commit and a shelved change
585 set up another conflict between a commit and a shelved change
586
586
587 $ hg revert -q -C -a
587 $ hg revert -q -C -a
588 $ rm a/a.orig b.rename/b c.copy
588 $ rm a/a.orig b.rename/b c.copy
589 $ echo a >> a/a
589 $ echo a >> a/a
590 $ hg shelve -q
590 $ hg shelve -q
591 $ echo x >> a/a
591 $ echo x >> a/a
592 $ hg ci -m 'create conflict'
592 $ hg ci -m 'create conflict'
593 $ hg add foo/foo
593 $ hg add foo/foo
594
594
595 if we resolve a conflict while unshelving, the unshelve should succeed
595 if we resolve a conflict while unshelving, the unshelve should succeed
596
596
597 $ hg unshelve --tool :merge-other --keep
597 $ hg unshelve --tool :merge-other --keep
598 unshelving change 'default'
598 unshelving change 'default'
599 temporarily committing pending changes (restore with 'hg unshelve --abort')
599 temporarily committing pending changes (restore with 'hg unshelve --abort')
600 rebasing shelved changes
600 rebasing shelved changes
601 merging a/a
601 merging a/a
602 $ hg parents -q
602 $ hg parents -q
603 (4|13):33f7f61e6c5e (re)
603 (4|13):33f7f61e6c5e (re)
604 $ hg shelve -l
604 $ hg shelve -l
605 default (*)* changes to: second (glob)
605 default (*)* changes to: second (glob)
606 $ hg status
606 $ hg status
607 M a/a
607 M a/a
608 A foo/foo
608 A foo/foo
609 $ cat a/a
609 $ cat a/a
610 a
610 a
611 c
611 c
612 a
612 a
613 $ cat > a/a << EOF
613 $ cat > a/a << EOF
614 > a
614 > a
615 > c
615 > c
616 > x
616 > x
617 > EOF
617 > EOF
618
618
619 $ HGMERGE=true hg unshelve
619 $ HGMERGE=true hg unshelve
620 unshelving change 'default'
620 unshelving change 'default'
621 temporarily committing pending changes (restore with 'hg unshelve --abort')
621 temporarily committing pending changes (restore with 'hg unshelve --abort')
622 rebasing shelved changes
622 rebasing shelved changes
623 merging a/a
623 merging a/a
624 note: unshelved changes already existed in the working copy
624 note: unshelved changes already existed in the working copy
625 $ hg parents -q
625 $ hg parents -q
626 (4|13):33f7f61e6c5e (re)
626 (4|13):33f7f61e6c5e (re)
627 $ hg shelve -l
627 $ hg shelve -l
628 $ hg status
628 $ hg status
629 A foo/foo
629 A foo/foo
630 $ cat a/a
630 $ cat a/a
631 a
631 a
632 c
632 c
633 x
633 x
634
634
635 test keep and cleanup
635 test keep and cleanup
636
636
637 $ hg shelve
637 $ hg shelve
638 shelved as default
638 shelved as default
639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 $ hg shelve --list
640 $ hg shelve --list
641 default (*)* changes to: create conflict (glob)
641 default (*)* changes to: create conflict (glob)
642 $ hg unshelve -k
642 $ hg unshelve -k
643 unshelving change 'default'
643 unshelving change 'default'
644 $ hg shelve --list
644 $ hg shelve --list
645 default (*)* changes to: create conflict (glob)
645 default (*)* changes to: create conflict (glob)
646 $ hg shelve --cleanup
646 $ hg shelve --cleanup
647 $ hg shelve --list
647 $ hg shelve --list
648
648
649 $ hg shelve --cleanup --delete
649 $ hg shelve --cleanup --delete
650 abort: options '--cleanup' and '--delete' may not be used together
650 abort: options '--cleanup' and '--delete' may not be used together
651 [10]
651 [10]
652 $ hg shelve --cleanup --patch
652 $ hg shelve --cleanup --patch
653 abort: options '--cleanup' and '--patch' may not be used together
653 abort: options '--cleanup' and '--patch' may not be used together
654 [10]
654 [10]
655 $ hg shelve --cleanup --message MESSAGE
655 $ hg shelve --cleanup --message MESSAGE
656 abort: options '--cleanup' and '--message' may not be used together
656 abort: options '--cleanup' and '--message' may not be used together
657 [10]
657 [10]
658
658
659 test bookmarks
659 test bookmarks
660
660
661 $ hg bookmark test
661 $ hg bookmark test
662 $ hg bookmark
662 $ hg bookmark
663 \* test (4|13):33f7f61e6c5e (re)
663 \* test (4|13):33f7f61e6c5e (re)
664 $ hg shelve
664 $ hg shelve
665 shelved as test
665 shelved as test
666 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
666 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
667 $ hg bookmark
667 $ hg bookmark
668 \* test (4|13):33f7f61e6c5e (re)
668 \* test (4|13):33f7f61e6c5e (re)
669 $ hg unshelve
669 $ hg unshelve
670 unshelving change 'test'
670 unshelving change 'test'
671 $ hg bookmark
671 $ hg bookmark
672 \* test (4|13):33f7f61e6c5e (re)
672 \* test (4|13):33f7f61e6c5e (re)
673
673
674 shelve should still work even if mq is disabled
674 shelve should still work even if mq is disabled
675
675
676 $ hg --config extensions.mq=! shelve
676 $ hg --config extensions.mq=! shelve
677 shelved as test
677 shelved as test
678 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
678 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
679 $ hg --config extensions.mq=! shelve --list
679 $ hg --config extensions.mq=! shelve --list
680 test (*)* changes to: create conflict (glob)
680 test (*)* changes to: create conflict (glob)
681 $ hg bookmark
681 $ hg bookmark
682 \* test (4|13):33f7f61e6c5e (re)
682 \* test (4|13):33f7f61e6c5e (re)
683 $ hg --config extensions.mq=! unshelve
683 $ hg --config extensions.mq=! unshelve
684 unshelving change 'test'
684 unshelving change 'test'
685 $ hg bookmark
685 $ hg bookmark
686 \* test (4|13):33f7f61e6c5e (re)
686 \* test (4|13):33f7f61e6c5e (re)
687
687
688 Recreate some conflict again
688 Recreate some conflict again
689
689
690 $ hg up -C -r 2e69b451d1ea
690 $ hg up -C -r 2e69b451d1ea
691 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
691 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
692 (leaving bookmark test)
692 (leaving bookmark test)
693 $ echo y >> a/a
693 $ echo y >> a/a
694 $ hg shelve
694 $ hg shelve
695 shelved as default
695 shelved as default
696 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
696 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
697 $ hg up test
697 $ hg up test
698 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
698 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
699 (activating bookmark test)
699 (activating bookmark test)
700 $ hg bookmark
700 $ hg bookmark
701 \* test (4|13):33f7f61e6c5e (re)
701 \* test (4|13):33f7f61e6c5e (re)
702 $ hg unshelve
702 $ hg unshelve
703 unshelving change 'default'
703 unshelving change 'default'
704 rebasing shelved changes
704 rebasing shelved changes
705 merging a/a
705 merging a/a
706 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
706 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
707 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
707 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
708 [240]
708 [240]
709 $ hg bookmark
709 $ hg bookmark
710 test (4|13):33f7f61e6c5e (re)
710 test (4|13):33f7f61e6c5e (re)
711
711
712 Test that resolving all conflicts in one direction (so that the rebase
712 Test that resolving all conflicts in one direction (so that the rebase
713 is a no-op), works (issue4398)
713 is a no-op), works (issue4398)
714
714
715 $ hg revert -a -r .
715 $ hg revert -a -r .
716 reverting a/a
716 reverting a/a
717 $ hg resolve -m a/a
717 $ hg resolve -m a/a
718 (no more unresolved files)
718 (no more unresolved files)
719 continue: hg unshelve --continue
719 continue: hg unshelve --continue
720 $ hg unshelve -c
720 $ hg unshelve -c
721 note: unshelved changes already existed in the working copy
721 note: unshelved changes already existed in the working copy
722 unshelve of 'default' complete
722 unshelve of 'default' complete
723 $ hg bookmark
723 $ hg bookmark
724 \* test (4|13):33f7f61e6c5e (re)
724 \* test (4|13):33f7f61e6c5e (re)
725 $ hg diff
725 $ hg diff
726 $ hg status
726 $ hg status
727 ? a/a.orig
727 ? a/a.orig
728 ? foo/foo
728 ? foo/foo
729 $ hg summary
729 $ hg summary
730 parent: (4|13):33f7f61e6c5e tip (re)
730 parent: (4|13):33f7f61e6c5e tip (re)
731 create conflict
731 create conflict
732 branch: default
732 branch: default
733 bookmarks: *test
733 bookmarks: *test
734 commit: 2 unknown (clean)
734 commit: 2 unknown (clean)
735 update: (current)
735 update: (current)
736 phases: 5 draft
736 phases: 5 draft
737
737
738 $ hg shelve --delete --stat
738 $ hg shelve --delete --stat
739 abort: options '--delete' and '--stat' may not be used together
739 abort: options '--delete' and '--stat' may not be used together
740 [10]
740 [10]
741 $ hg shelve --delete --name NAME
741 $ hg shelve --delete --name NAME
742 abort: options '--delete' and '--name' may not be used together
742 abort: options '--delete' and '--name' may not be used together
743 [10]
743 [10]
744
744
745 Test interactive shelve
745 Test interactive shelve
746 $ cat <<EOF >> $HGRCPATH
746 $ cat <<EOF >> $HGRCPATH
747 > [ui]
747 > [ui]
748 > interactive = true
748 > interactive = true
749 > EOF
749 > EOF
750 $ echo 'a' >> a/b
750 $ echo 'a' >> a/b
751 $ cat a/a >> a/b
751 $ cat a/a >> a/b
752 $ echo 'x' >> a/b
752 $ echo 'x' >> a/b
753 $ mv a/b a/a
753 $ mv a/b a/a
754 $ echo 'a' >> foo/foo
754 $ echo 'a' >> foo/foo
755 $ hg st
755 $ hg st
756 M a/a
756 M a/a
757 ? a/a.orig
757 ? a/a.orig
758 ? foo/foo
758 ? foo/foo
759 $ cat a/a
759 $ cat a/a
760 a
760 a
761 a
761 a
762 c
762 c
763 x
763 x
764 x
764 x
765 $ cat foo/foo
765 $ cat foo/foo
766 foo
766 foo
767 a
767 a
768 $ hg shelve --interactive --config ui.interactive=false
768 $ hg shelve --interactive --config ui.interactive=false
769 abort: running non-interactively
769 abort: running non-interactively
770 [10]
770 [10]
771 $ hg shelve --interactive << EOF
771 $ hg shelve --interactive << EOF
772 > y
772 > y
773 > y
773 > y
774 > n
774 > n
775 > EOF
775 > EOF
776 diff --git a/a/a b/a/a
776 diff --git a/a/a b/a/a
777 2 hunks, 2 lines changed
777 2 hunks, 2 lines changed
778 examine changes to 'a/a'?
778 examine changes to 'a/a'?
779 (enter ? for help) [Ynesfdaq?] y
779 (enter ? for help) [Ynesfdaq?] y
780
780
781 @@ -1,3 +1,4 @@
781 @@ -1,3 +1,4 @@
782 +a
782 +a
783 a
783 a
784 c
784 c
785 x
785 x
786 record change 1/2 to 'a/a'?
786 record change 1/2 to 'a/a'?
787 (enter ? for help) [Ynesfdaq?] y
787 (enter ? for help) [Ynesfdaq?] y
788
788
789 @@ -1,3 +2,4 @@
789 @@ -1,3 +2,4 @@
790 a
790 a
791 c
791 c
792 x
792 x
793 +x
793 +x
794 record change 2/2 to 'a/a'?
794 record change 2/2 to 'a/a'?
795 (enter ? for help) [Ynesfdaq?] n
795 (enter ? for help) [Ynesfdaq?] n
796
796
797 shelved as test
797 shelved as test
798 merging a/a
798 merging a/a
799 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
799 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
800 $ cat a/a
800 $ cat a/a
801 a
801 a
802 c
802 c
803 x
803 x
804 x
804 x
805 $ cat foo/foo
805 $ cat foo/foo
806 foo
806 foo
807 a
807 a
808 $ hg st
808 $ hg st
809 M a/a
809 M a/a
810 ? foo/foo
810 ? foo/foo
811 $ hg bookmark
811 $ hg bookmark
812 \* test (4|13):33f7f61e6c5e (re)
812 \* test (4|13):33f7f61e6c5e (re)
813 there shouldn't be a merge state
813 there shouldn't be a merge state
814 $ hg resolve -l
814 $ hg resolve -l
815 $ hg unshelve
815 $ hg unshelve
816 unshelving change 'test'
816 unshelving change 'test'
817 temporarily committing pending changes (restore with 'hg unshelve --abort')
817 temporarily committing pending changes (restore with 'hg unshelve --abort')
818 rebasing shelved changes
818 rebasing shelved changes
819 merging a/a
819 merging a/a
820 $ hg bookmark
820 $ hg bookmark
821 \* test (4|13):33f7f61e6c5e (re)
821 \* test (4|13):33f7f61e6c5e (re)
822 $ cat a/a
822 $ cat a/a
823 a
823 a
824 a
824 a
825 c
825 c
826 x
826 x
827 x
827 x
828
828
829 shelve --patch and shelve --stat should work with valid shelfnames
829 shelve --patch and shelve --stat should work with valid shelfnames
830
830
831 $ hg up --clean .
831 $ hg up --clean .
832 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
832 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
833 (leaving bookmark test)
833 (leaving bookmark test)
834 $ hg shelve --list
834 $ hg shelve --list
835 $ echo 'patch a' > shelf-patch-a
835 $ echo 'patch a' > shelf-patch-a
836 $ hg add shelf-patch-a
836 $ hg add shelf-patch-a
837 $ hg shelve
837 $ hg shelve
838 shelved as default
838 shelved as default
839 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
839 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
840 $ echo 'patch b' > shelf-patch-b
840 $ echo 'patch b' > shelf-patch-b
841 $ hg add shelf-patch-b
841 $ hg add shelf-patch-b
842 $ hg shelve
842 $ hg shelve
843 shelved as default-01
843 shelved as default-01
844 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
844 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
845 $ hg shelve --patch default default-01
845 $ hg shelve --patch default default-01
846 default-01 (*)* changes to: create conflict (glob)
846 default-01 (*)* changes to: create conflict (glob)
847
847
848 diff --git a/shelf-patch-b b/shelf-patch-b
848 diff --git a/shelf-patch-b b/shelf-patch-b
849 new file mode 100644
849 new file mode 100644
850 --- /dev/null
850 --- /dev/null
851 +++ b/shelf-patch-b
851 +++ b/shelf-patch-b
852 @@ -0,0 +1,1 @@
852 @@ -0,0 +1,1 @@
853 +patch b
853 +patch b
854 default (*)* changes to: create conflict (glob)
854 default (*)* changes to: create conflict (glob)
855
855
856 diff --git a/shelf-patch-a b/shelf-patch-a
856 diff --git a/shelf-patch-a b/shelf-patch-a
857 new file mode 100644
857 new file mode 100644
858 --- /dev/null
858 --- /dev/null
859 +++ b/shelf-patch-a
859 +++ b/shelf-patch-a
860 @@ -0,0 +1,1 @@
860 @@ -0,0 +1,1 @@
861 +patch a
861 +patch a
862 $ hg shelve --stat default default-01
862 $ hg shelve --stat default default-01
863 default-01 (*)* changes to: create conflict (glob)
863 default-01 (*)* changes to: create conflict (glob)
864 shelf-patch-b | 1 +
864 shelf-patch-b | 1 +
865 1 files changed, 1 insertions(+), 0 deletions(-)
865 1 files changed, 1 insertions(+), 0 deletions(-)
866 default (*)* changes to: create conflict (glob)
866 default (*)* changes to: create conflict (glob)
867 shelf-patch-a | 1 +
867 shelf-patch-a | 1 +
868 1 files changed, 1 insertions(+), 0 deletions(-)
868 1 files changed, 1 insertions(+), 0 deletions(-)
869 $ hg shelve --patch default
869 $ hg shelve --patch default
870 default (*)* changes to: create conflict (glob)
870 default (*)* changes to: create conflict (glob)
871
871
872 diff --git a/shelf-patch-a b/shelf-patch-a
872 diff --git a/shelf-patch-a b/shelf-patch-a
873 new file mode 100644
873 new file mode 100644
874 --- /dev/null
874 --- /dev/null
875 +++ b/shelf-patch-a
875 +++ b/shelf-patch-a
876 @@ -0,0 +1,1 @@
876 @@ -0,0 +1,1 @@
877 +patch a
877 +patch a
878 $ hg shelve --stat default
878 $ hg shelve --stat default
879 default (*)* changes to: create conflict (glob)
879 default (*)* changes to: create conflict (glob)
880 shelf-patch-a | 1 +
880 shelf-patch-a | 1 +
881 1 files changed, 1 insertions(+), 0 deletions(-)
881 1 files changed, 1 insertions(+), 0 deletions(-)
882 $ hg shelve --patch nonexistentshelf
882 $ hg shelve --patch nonexistentshelf
883 abort: cannot find shelf nonexistentshelf
883 abort: cannot find shelf nonexistentshelf
884 [255]
884 [255]
885 $ hg shelve --stat nonexistentshelf
885 $ hg shelve --stat nonexistentshelf
886 abort: cannot find shelf nonexistentshelf
886 abort: cannot find shelf nonexistentshelf
887 [255]
887 [255]
888 $ hg shelve --patch default nonexistentshelf
888 $ hg shelve --patch default nonexistentshelf
889 abort: cannot find shelf nonexistentshelf
889 abort: cannot find shelf nonexistentshelf
890 [255]
890 [255]
891
891
892 when the user asks for a patch, we assume they want the most recent shelve if
892 when the user asks for a patch, we assume they want the most recent shelve if
893 they don't provide a shelve name
893 they don't provide a shelve name
894
894
895 $ hg shelve --patch
895 $ hg shelve --patch
896 default-01 (*)* changes to: create conflict (glob)
896 default-01 (*)* changes to: create conflict (glob)
897
897
898 diff --git a/shelf-patch-b b/shelf-patch-b
898 diff --git a/shelf-patch-b b/shelf-patch-b
899 new file mode 100644
899 new file mode 100644
900 --- /dev/null
900 --- /dev/null
901 +++ b/shelf-patch-b
901 +++ b/shelf-patch-b
902 @@ -0,0 +1,1 @@
902 @@ -0,0 +1,1 @@
903 +patch b
903 +patch b
904
904
905 $ cd ..
905 $ cd ..
906
906
907 Shelve from general delta repo uses bundle2 on disk
907 Shelve from general delta repo uses bundle2 on disk
908 --------------------------------------------------
908 --------------------------------------------------
909
909
910 no general delta
910 no general delta
911
911
912 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
912 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
913 requesting all changes
913 requesting all changes
914 adding changesets
914 adding changesets
915 adding manifests
915 adding manifests
916 adding file changes
916 adding file changes
917 added 5 changesets with 8 changes to 6 files
917 added 5 changesets with 8 changes to 6 files
918 new changesets cc01e2b0c59f:33f7f61e6c5e
918 new changesets cc01e2b0c59f:33f7f61e6c5e
919 updating to branch default
919 updating to branch default
920 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
920 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
921 $ cd bundle1
921 $ cd bundle1
922 $ echo babar > jungle
922 $ echo babar > jungle
923 $ hg add jungle
923 $ hg add jungle
924 $ hg shelve
924 $ hg shelve
925 shelved as default
925 shelved as default
926 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
926 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
927 $ hg debugbundle .hg/shelved/*.hg
927 $ hg debugbundle .hg/shelved/*.hg
928 330882a04d2ce8487636b1fb292e5beea77fa1e3
928 330882a04d2ce8487636b1fb292e5beea77fa1e3
929 $ cd ..
929 $ cd ..
930
930
931 with general delta
931 with general delta
932
932
933 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
933 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
934 requesting all changes
934 requesting all changes
935 adding changesets
935 adding changesets
936 adding manifests
936 adding manifests
937 adding file changes
937 adding file changes
938 added 5 changesets with 8 changes to 6 files
938 added 5 changesets with 8 changes to 6 files
939 new changesets cc01e2b0c59f:33f7f61e6c5e
939 new changesets cc01e2b0c59f:33f7f61e6c5e
940 updating to branch default
940 updating to branch default
941 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
941 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
942 $ cd bundle2
942 $ cd bundle2
943 $ echo babar > jungle
943 $ echo babar > jungle
944 $ hg add jungle
944 $ hg add jungle
945 $ hg shelve
945 $ hg shelve
946 shelved as default
946 shelved as default
947 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
947 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
948 $ hg debugbundle .hg/shelved/*.hg
948 $ hg debugbundle .hg/shelved/*.hg
949 Stream params: {Compression: BZ}
949 Stream params: {Compression: BZ}
950 changegroup -- {nbchanges: 1, version: 02} (mandatory: True)
950 changegroup -- {nbchanges: 1, version: 02} (mandatory: True)
951 330882a04d2ce8487636b1fb292e5beea77fa1e3
951 330882a04d2ce8487636b1fb292e5beea77fa1e3
952
952
953 Test shelve --keep
953 Test shelve --keep
954
954
955 $ hg unshelve
955 $ hg unshelve
956 unshelving change 'default'
956 unshelving change 'default'
957 $ hg shelve --keep --list
957 $ hg shelve --keep --list
958 abort: options '--list' and '--keep' may not be used together
958 abort: options '--list' and '--keep' may not be used together
959 [10]
959 [10]
960 $ hg shelve --keep --patch
960 $ hg shelve --keep --patch
961 abort: options '--patch' and '--keep' may not be used together
961 abort: options '--patch' and '--keep' may not be used together
962 [10]
962 [10]
963 $ hg shelve --keep --delete
963 $ hg shelve --keep --delete
964 abort: options '--delete' and '--keep' may not be used together
964 abort: options '--delete' and '--keep' may not be used together
965 [10]
965 [10]
966 $ hg shelve --keep
966 $ hg shelve --keep
967 shelved as default
967 shelved as default
968 $ hg diff
968 $ hg diff
969 diff --git a/jungle b/jungle
969 diff --git a/jungle b/jungle
970 new file mode 100644
970 new file mode 100644
971 --- /dev/null
971 --- /dev/null
972 +++ b/jungle
972 +++ b/jungle
973 @@ -0,0 +1,1 @@
973 @@ -0,0 +1,1 @@
974 +babar
974 +babar
975
975
976 Test shelve --delete
976 Test shelve --delete
977
977
978 $ hg shelve --list
978 $ hg shelve --list
979 default (*s ago) * changes to: create conflict (glob)
979 default (*s ago) * changes to: create conflict (glob)
980 $ hg shelve --delete doesnotexist
980 $ hg shelve --delete doesnotexist
981 abort: shelved change 'doesnotexist' not found
981 abort: shelved change 'doesnotexist' not found
982 [10]
982 [10]
983 $ hg shelve --delete default
983 $ hg shelve --delete default
984
984
985 $ cd ..
985 $ cd ..
986
986
987 Test visibility of in-memory changes inside transaction to external hook
987 Test visibility of in-memory changes inside transaction to external hook
988 ------------------------------------------------------------------------
988 ------------------------------------------------------------------------
989
989
990 $ cd repo
990 $ cd repo
991
991
992 $ echo xxxx >> x
992 $ echo xxxx >> x
993 $ hg commit -m "#5: changes to invoke rebase"
993 $ hg commit -m "#5: changes to invoke rebase"
994
994
995 $ cat > $TESTTMP/checkvisibility.sh <<EOF
995 $ cat > $TESTTMP/checkvisibility.sh <<EOF
996 > echo "==== \$1:"
996 > echo "==== \$1:"
997 > hg parents --template "VISIBLE {rev}:{node|short}\n"
997 > hg parents --template "VISIBLE {rev}:{node|short}\n"
998 > # test that pending changes are hidden
998 > # test that pending changes are hidden
999 > unset HG_PENDING
999 > unset HG_PENDING
1000 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1000 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1001 > echo "===="
1001 > echo "===="
1002 > EOF
1002 > EOF
1003
1003
1004 $ cat >> .hg/hgrc <<EOF
1004 $ cat >> .hg/hgrc <<EOF
1005 > [defaults]
1005 > [defaults]
1006 > # to fix hash id of temporary revisions
1006 > # to fix hash id of temporary revisions
1007 > unshelve = --date '0 0'
1007 > unshelve = --date '0 0'
1008 > EOF
1008 > EOF
1009
1009
1010 "hg unshelve" at REV5 implies steps below:
1010 "hg unshelve" at REV5 implies steps below:
1011
1011
1012 (1) commit changes in the working directory (REV6)
1012 (1) commit changes in the working directory (REV6)
1013 (2) unbundle shelved revision (REV7)
1013 (2) unbundle shelved revision (REV7)
1014 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1014 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1015 (4) rebase: commit merged revision (REV8)
1015 (4) rebase: commit merged revision (REV8)
1016 (5) rebase: update to REV6 (REV8 => REV6)
1016 (5) rebase: update to REV6 (REV8 => REV6)
1017 (6) update to REV5 (REV6 => REV5)
1017 (6) update to REV5 (REV6 => REV5)
1018 (7) abort transaction
1018 (7) abort transaction
1019
1019
1020 == test visibility to external preupdate hook
1020 == test visibility to external preupdate hook
1021
1021
1022 $ cat >> .hg/hgrc <<EOF
1022 $ cat >> .hg/hgrc <<EOF
1023 > [hooks]
1023 > [hooks]
1024 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1024 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1025 > EOF
1025 > EOF
1026
1026
1027 $ echo nnnn >> n
1027 $ echo nnnn >> n
1028
1028
1029 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1029 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1030 ==== before-unshelving:
1030 ==== before-unshelving:
1031 VISIBLE (5|19):703117a2acfb (re)
1031 VISIBLE (5|19):703117a2acfb (re)
1032 ACTUAL (5|19):703117a2acfb (re)
1032 ACTUAL (5|19):703117a2acfb (re)
1033 ====
1033 ====
1034
1034
1035 $ hg unshelve --keep default
1035 $ hg unshelve --keep default
1036 temporarily committing pending changes (restore with 'hg unshelve --abort')
1036 temporarily committing pending changes (restore with 'hg unshelve --abort')
1037 rebasing shelved changes
1037 rebasing shelved changes
1038 ==== preupdate:
1038 ==== preupdate:
1039 VISIBLE (6|20):54c00d20fb3f (re)
1039 VISIBLE (6|20):54c00d20fb3f (re)
1040 ACTUAL (5|19):703117a2acfb (re)
1040 ACTUAL (5|19):703117a2acfb (re)
1041 ====
1041 ====
1042 ==== preupdate:
1042 ==== preupdate:
1043 VISIBLE (8|21):8efe6f7537dc (re)
1043 VISIBLE (8|21):8efe6f7537dc (re)
1044 ACTUAL (5|19):703117a2acfb (re)
1044 ACTUAL (5|19):703117a2acfb (re)
1045 ====
1045 ====
1046 ==== preupdate:
1046 ==== preupdate:
1047 VISIBLE (6|20):54c00d20fb3f (re)
1047 VISIBLE (6|20):54c00d20fb3f (re)
1048 ACTUAL (5|19):703117a2acfb (re)
1048 ACTUAL (5|19):703117a2acfb (re)
1049 ====
1049 ====
1050
1050
1051 $ cat >> .hg/hgrc <<EOF
1051 $ cat >> .hg/hgrc <<EOF
1052 > [hooks]
1052 > [hooks]
1053 > preupdate.visibility =
1053 > preupdate.visibility =
1054 > EOF
1054 > EOF
1055
1055
1056 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1056 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1057 ==== after-unshelving:
1057 ==== after-unshelving:
1058 VISIBLE (5|19):703117a2acfb (re)
1058 VISIBLE (5|19):703117a2acfb (re)
1059 ACTUAL (5|19):703117a2acfb (re)
1059 ACTUAL (5|19):703117a2acfb (re)
1060 ====
1060 ====
1061
1061
1062 == test visibility to external update hook
1062 == test visibility to external update hook
1063
1063
1064 $ hg update -q -C 703117a2acfb
1064 $ hg update -q -C 703117a2acfb
1065
1065
1066 $ cat >> .hg/hgrc <<EOF
1066 $ cat >> .hg/hgrc <<EOF
1067 > [hooks]
1067 > [hooks]
1068 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1068 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1069 > EOF
1069 > EOF
1070
1070
1071 $ echo nnnn >> n
1071 $ echo nnnn >> n
1072
1072
1073 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1073 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1074 ==== before-unshelving:
1074 ==== before-unshelving:
1075 VISIBLE (5|19):703117a2acfb (re)
1075 VISIBLE (5|19):703117a2acfb (re)
1076 ACTUAL (5|19):703117a2acfb (re)
1076 ACTUAL (5|19):703117a2acfb (re)
1077 ====
1077 ====
1078
1078
1079 $ hg unshelve --keep default
1079 $ hg unshelve --keep default
1080 temporarily committing pending changes (restore with 'hg unshelve --abort')
1080 temporarily committing pending changes (restore with 'hg unshelve --abort')
1081 rebasing shelved changes
1081 rebasing shelved changes
1082 ==== update:
1082 ==== update:
1083 VISIBLE (6|20):54c00d20fb3f (re)
1083 VISIBLE (6|20):54c00d20fb3f (re)
1084 VISIBLE 1?7:492ed9d705e5 (re)
1084 VISIBLE 1?7:492ed9d705e5 (re)
1085 ACTUAL (5|19):703117a2acfb (re)
1085 ACTUAL (5|19):703117a2acfb (re)
1086 ====
1086 ====
1087 ==== update:
1087 ==== update:
1088 VISIBLE (6|20):54c00d20fb3f (re)
1088 VISIBLE (6|20):54c00d20fb3f (re)
1089 ACTUAL (5|19):703117a2acfb (re)
1089 ACTUAL (5|19):703117a2acfb (re)
1090 ====
1090 ====
1091 ==== update:
1091 ==== update:
1092 VISIBLE (5|19):703117a2acfb (re)
1092 VISIBLE (5|19):703117a2acfb (re)
1093 ACTUAL (5|19):703117a2acfb (re)
1093 ACTUAL (5|19):703117a2acfb (re)
1094 ====
1094 ====
1095
1095
1096 $ cat >> .hg/hgrc <<EOF
1096 $ cat >> .hg/hgrc <<EOF
1097 > [hooks]
1097 > [hooks]
1098 > update.visibility =
1098 > update.visibility =
1099 > EOF
1099 > EOF
1100
1100
1101 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1101 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1102 ==== after-unshelving:
1102 ==== after-unshelving:
1103 VISIBLE (5|19):703117a2acfb (re)
1103 VISIBLE (5|19):703117a2acfb (re)
1104 ACTUAL (5|19):703117a2acfb (re)
1104 ACTUAL (5|19):703117a2acfb (re)
1105 ====
1105 ====
1106
1106
1107 $ cd ..
1107 $ cd ..
1108
1108
1109 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1109 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1110 -----------------------------------------------------------------------
1110 -----------------------------------------------------------------------
1111
1111
1112 $ cat <<EOF >> $HGRCPATH
1112 $ cat <<EOF >> $HGRCPATH
1113 > [extensions]
1113 > [extensions]
1114 > share =
1114 > share =
1115 > EOF
1115 > EOF
1116
1116
1117 $ hg bookmarks -R repo
1117 $ hg bookmarks -R repo
1118 test (4|13):33f7f61e6c5e (re)
1118 test (4|13):33f7f61e6c5e (re)
1119 $ hg share -B repo share
1119 $ hg share -B repo share
1120 updating working directory
1120 updating working directory
1121 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1121 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1122 $ cd share
1122 $ cd share
1123
1123
1124 $ hg bookmarks
1124 $ hg bookmarks
1125 test (4|13):33f7f61e6c5e (re)
1125 test (4|13):33f7f61e6c5e (re)
1126 $ hg bookmarks foo
1126 $ hg bookmarks foo
1127 $ hg bookmarks
1127 $ hg bookmarks
1128 \* foo (5|19):703117a2acfb (re)
1128 \* foo (5|19):703117a2acfb (re)
1129 test (4|13):33f7f61e6c5e (re)
1129 test (4|13):33f7f61e6c5e (re)
1130 $ echo x >> x
1130 $ echo x >> x
1131 $ hg shelve
1131 $ hg shelve
1132 shelved as foo
1132 shelved as foo
1133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1134 $ hg bookmarks
1134 $ hg bookmarks
1135 \* foo (5|19):703117a2acfb (re)
1135 \* foo (5|19):703117a2acfb (re)
1136 test (4|13):33f7f61e6c5e (re)
1136 test (4|13):33f7f61e6c5e (re)
1137
1137
1138 $ hg unshelve
1138 $ hg unshelve
1139 unshelving change 'foo'
1139 unshelving change 'foo'
1140 $ hg bookmarks
1140 $ hg bookmarks
1141 \* foo (5|19):703117a2acfb (re)
1141 \* foo (5|19):703117a2acfb (re)
1142 test (4|13):33f7f61e6c5e (re)
1142 test (4|13):33f7f61e6c5e (re)
1143
1143
1144 $ cd ..
1144 $ cd ..
1145
1145
1146 Abort unshelve while merging (issue5123)
1146 Abort unshelve while merging (issue5123)
1147 ----------------------------------------
1147 ----------------------------------------
1148
1148
1149 $ hg init issue5123
1149 $ hg init issue5123
1150 $ cd issue5123
1150 $ cd issue5123
1151 $ echo > a
1151 $ echo > a
1152 $ hg ci -Am a
1152 $ hg ci -Am a
1153 adding a
1153 adding a
1154 $ hg co null
1154 $ hg co null
1155 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1155 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1156 $ echo > b
1156 $ echo > b
1157 $ hg ci -Am b
1157 $ hg ci -Am b
1158 adding b
1158 adding b
1159 created new head
1159 created new head
1160 $ echo > c
1160 $ echo > c
1161 $ hg add c
1161 $ hg add c
1162 $ hg shelve
1162 $ hg shelve
1163 shelved as default
1163 shelved as default
1164 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1164 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1165 $ hg co 1
1165 $ hg co 1
1166 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1166 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1167 $ hg merge 0
1167 $ hg merge 0
1168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1169 (branch merge, don't forget to commit)
1169 (branch merge, don't forget to commit)
1170 -- successful merge with two parents
1170 -- successful merge with two parents
1171 $ hg log -G
1171 $ hg log -G
1172 @ changeset: 1:406bf70c274f
1172 @ changeset: 1:406bf70c274f
1173 tag: tip
1173 tag: tip
1174 parent: -1:000000000000
1174 parent: -1:000000000000
1175 user: test
1175 user: test
1176 date: Thu Jan 01 00:00:00 1970 +0000
1176 date: Thu Jan 01 00:00:00 1970 +0000
1177 summary: b
1177 summary: b
1178
1178
1179 @ changeset: 0:ada8c9eb8252
1179 @ changeset: 0:ada8c9eb8252
1180 user: test
1180 user: test
1181 date: Thu Jan 01 00:00:00 1970 +0000
1181 date: Thu Jan 01 00:00:00 1970 +0000
1182 summary: a
1182 summary: a
1183
1183
1184 -- trying to pull in the shelve bits
1184 -- trying to pull in the shelve bits
1185 -- unshelve should abort otherwise, it'll eat my second parent.
1185 -- unshelve should abort otherwise, it'll eat my second parent.
1186 $ hg unshelve
1186 $ hg unshelve
1187 abort: outstanding uncommitted merge
1187 abort: outstanding uncommitted merge
1188 (use 'hg commit' or 'hg merge --abort')
1188 (use 'hg commit' or 'hg merge --abort')
1189 [20]
1189 [20]
1190
1190
1191 $ cd ..
1191 $ cd ..
1192
1192
1193 -- test for interactive mode on unshelve
1193 -- test for interactive mode on unshelve
1194
1194
1195 $ hg init a
1195 $ hg init a
1196 $ cd a
1196 $ cd a
1197 $ echo > b
1197 $ echo > b
1198 $ hg ci -Am b
1198 $ hg ci -Am b
1199 adding b
1199 adding b
1200 $ echo > c
1200 $ echo > c
1201 $ echo > d
1201 $ echo > d
1202 $ hg add .
1202 $ hg add .
1203 adding c
1203 adding c
1204 adding d
1204 adding d
1205 $ hg shelve
1205 $ hg shelve
1206 shelved as default
1206 shelved as default
1207 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1207 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1208 $ echo > e
1208 $ echo > e
1209 $ hg add e
1209 $ hg add e
1210 $ hg ci -m e
1210 $ hg ci -m e
1211 $ hg shelve --patch
1211 $ hg shelve --patch
1212 default (*s ago) * changes to: b (glob)
1212 default (*s ago) * changes to: b (glob)
1213
1213
1214 diff --git a/c b/c
1214 diff --git a/c b/c
1215 new file mode 100644
1215 new file mode 100644
1216 --- /dev/null
1216 --- /dev/null
1217 +++ b/c
1217 +++ b/c
1218 @@ -0,0 +1,1 @@
1218 @@ -0,0 +1,1 @@
1219 +
1219 +
1220 diff --git a/d b/d
1220 diff --git a/d b/d
1221 new file mode 100644
1221 new file mode 100644
1222 --- /dev/null
1222 --- /dev/null
1223 +++ b/d
1223 +++ b/d
1224 @@ -0,0 +1,1 @@
1224 @@ -0,0 +1,1 @@
1225 +
1225 +
1226 $ hg unshelve -i <<EOF
1226 $ hg unshelve -i <<EOF
1227 > y
1227 > y
1228 > y
1228 > y
1229 > y
1229 > y
1230 > n
1230 > n
1231 > EOF
1231 > EOF
1232 unshelving change 'default'
1232 unshelving change 'default'
1233 rebasing shelved changes
1233 rebasing shelved changes
1234 diff --git a/c b/c
1234 diff --git a/c b/c
1235 new file mode 100644
1235 new file mode 100644
1236 examine changes to 'c'?
1236 examine changes to 'c'?
1237 (enter ? for help) [Ynesfdaq?] y
1237 (enter ? for help) [Ynesfdaq?] y
1238
1238
1239 @@ -0,0 +1,1 @@
1239 @@ -0,0 +1,1 @@
1240 +
1240 +
1241 record change 1/2 to 'c'?
1241 record change 1/2 to 'c'?
1242 (enter ? for help) [Ynesfdaq?] y
1242 (enter ? for help) [Ynesfdaq?] y
1243
1243
1244 diff --git a/d b/d
1244 diff --git a/d b/d
1245 new file mode 100644
1245 new file mode 100644
1246 examine changes to 'd'?
1246 examine changes to 'd'?
1247 (enter ? for help) [Ynesfdaq?] y
1247 (enter ? for help) [Ynesfdaq?] y
1248
1248
1249 @@ -0,0 +1,1 @@
1249 @@ -0,0 +1,1 @@
1250 +
1250 +
1251 record change 2/2 to 'd'?
1251 record change 2/2 to 'd'?
1252 (enter ? for help) [Ynesfdaq?] n
1252 (enter ? for help) [Ynesfdaq?] n
1253
1253
1254 $ ls -A
1254 $ ls -A
1255 .hg
1255 .hg
1256 b
1256 b
1257 c
1257 c
1258 e
1258 e
1259 -- shelve should not contain `c` now
1259 -- shelve should not contain `c` now
1260 $ hg shelve --patch
1260 $ hg shelve --patch
1261 default (*s ago) * changes to: b (glob)
1261 default (*s ago) * changes to: b (glob)
1262
1262
1263 diff --git a/d b/d
1263 diff --git a/d b/d
1264 new file mode 100644
1264 new file mode 100644
1265 --- /dev/null
1265 --- /dev/null
1266 +++ b/d
1266 +++ b/d
1267 @@ -0,0 +1,1 @@
1267 @@ -0,0 +1,1 @@
1268 +
1268 +
1269 $ hg unshelve -i <<EOF
1269 $ hg unshelve -i <<EOF
1270 > y
1270 > y
1271 > y
1271 > y
1272 > EOF
1272 > EOF
1273 unshelving change 'default'
1273 unshelving change 'default'
1274 temporarily committing pending changes (restore with 'hg unshelve --abort')
1274 temporarily committing pending changes (restore with 'hg unshelve --abort')
1275 rebasing shelved changes
1275 rebasing shelved changes
1276 diff --git a/d b/d
1276 diff --git a/d b/d
1277 new file mode 100644
1277 new file mode 100644
1278 examine changes to 'd'?
1278 examine changes to 'd'?
1279 (enter ? for help) [Ynesfdaq?] y
1279 (enter ? for help) [Ynesfdaq?] y
1280
1280
1281 @@ -0,0 +1,1 @@
1281 @@ -0,0 +1,1 @@
1282 +
1282 +
1283 record this change to 'd'?
1283 record this change to 'd'?
1284 (enter ? for help) [Ynesfdaq?] y
1284 (enter ? for help) [Ynesfdaq?] y
1285
1285
1286
1286
1287 $ hg status -v
1287 $ hg status -v
1288 A c
1288 A c
1289 A d
1289 A d
1290 $ ls -A
1290 $ ls -A
1291 .hg
1291 .hg
1292 b
1292 b
1293 c
1293 c
1294 d
1294 d
1295 e
1295 e
1296 $ hg shelve --list
1296 $ hg shelve --list
1297
1297
1298 -- now, unshelve selected changes from a file
1298 -- now, unshelve selected changes from a file
1299
1299
1300 $ echo B > foo
1300 $ echo B > foo
1301 $ hg add foo
1301 $ hg add foo
1302 $ hg ci -m 'add B to foo'
1302 $ hg ci -m 'add B to foo'
1303 $ cat > foo <<EOF
1303 $ cat > foo <<EOF
1304 > A
1304 > A
1305 > B
1305 > B
1306 > C
1306 > C
1307 > EOF
1307 > EOF
1308 $ echo > garbage
1308 $ echo > garbage
1309 $ hg st
1309 $ hg st
1310 M foo
1310 M foo
1311 ? garbage
1311 ? garbage
1312 $ hg shelve --unknown
1312 $ hg shelve --unknown
1313 shelved as default
1313 shelved as default
1314 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1314 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1315 $ cat foo
1315 $ cat foo
1316 B
1316 B
1317 $ hg unshelve -i <<EOF
1317 $ hg unshelve -i <<EOF
1318 > y
1318 > y
1319 > y
1319 > y
1320 > n
1320 > n
1321 > y
1321 > y
1322 > y
1322 > y
1323 > EOF
1323 > EOF
1324 unshelving change 'default'
1324 unshelving change 'default'
1325 rebasing shelved changes
1325 rebasing shelved changes
1326 diff --git a/foo b/foo
1326 diff --git a/foo b/foo
1327 2 hunks, 2 lines changed
1327 2 hunks, 2 lines changed
1328 examine changes to 'foo'?
1328 examine changes to 'foo'?
1329 (enter ? for help) [Ynesfdaq?] y
1329 (enter ? for help) [Ynesfdaq?] y
1330
1330
1331 @@ -1,1 +1,2 @@
1331 @@ -1,1 +1,2 @@
1332 +A
1332 +A
1333 B
1333 B
1334 record change 1/3 to 'foo'?
1334 record change 1/3 to 'foo'?
1335 (enter ? for help) [Ynesfdaq?] y
1335 (enter ? for help) [Ynesfdaq?] y
1336
1336
1337 @@ -1,1 +2,2 @@
1337 @@ -1,1 +2,2 @@
1338 B
1338 B
1339 +C
1339 +C
1340 record change 2/3 to 'foo'?
1340 record change 2/3 to 'foo'?
1341 (enter ? for help) [Ynesfdaq?] n
1341 (enter ? for help) [Ynesfdaq?] n
1342
1342
1343 diff --git a/garbage b/garbage
1343 diff --git a/garbage b/garbage
1344 new file mode 100644
1344 new file mode 100644
1345 examine changes to 'garbage'?
1345 examine changes to 'garbage'?
1346 (enter ? for help) [Ynesfdaq?] y
1346 (enter ? for help) [Ynesfdaq?] y
1347
1347
1348 @@ -0,0 +1,1 @@
1348 @@ -0,0 +1,1 @@
1349 +
1349 +
1350 record change 3/3 to 'garbage'?
1350 record change 3/3 to 'garbage'?
1351 (enter ? for help) [Ynesfdaq?] y
1351 (enter ? for help) [Ynesfdaq?] y
1352
1352
1353 $ hg st
1353 $ hg st
1354 M foo
1354 M foo
1355 ? garbage
1355 ? garbage
1356 $ cat foo
1356 $ cat foo
1357 A
1357 A
1358 B
1358 B
1359 $ hg shelve --patch
1359 $ hg shelve --patch
1360 default (*s ago) * changes to: add B to foo (glob)
1360 default (*s ago) * changes to: add B to foo (glob)
1361
1361
1362 diff --git a/foo b/foo
1362 diff --git a/foo b/foo
1363 --- a/foo
1363 --- a/foo
1364 +++ b/foo
1364 +++ b/foo
1365 @@ -1,2 +1,3 @@
1365 @@ -1,2 +1,3 @@
1366 A
1366 A
1367 B
1367 B
1368 +C
1368 +C
1369
1369
1370 -- unshelve interactive on conflicts
1370 -- unshelve interactive on conflicts
1371
1371
1372 $ echo A >> bar1
1372 $ echo A >> bar1
1373 $ echo A >> bar2
1373 $ echo A >> bar2
1374 $ hg add bar1 bar2
1374 $ hg add bar1 bar2
1375 $ hg ci -m 'add A to bars'
1375 $ hg ci -m 'add A to bars'
1376 $ echo B >> bar1
1376 $ echo B >> bar1
1377 $ echo B >> bar2
1377 $ echo B >> bar2
1378 $ hg shelve
1378 $ hg shelve
1379 shelved as default-01
1379 shelved as default-01
1380 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1380 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1381 $ echo C >> bar1
1381 $ echo C >> bar1
1382 $ echo C >> bar2
1382 $ echo C >> bar2
1383 $ hg ci -m 'add C to bars'
1383 $ hg ci -m 'add C to bars'
1384 $ hg unshelve -i
1384 $ hg unshelve -i
1385 unshelving change 'default-01'
1385 unshelving change 'default-01'
1386 rebasing shelved changes
1386 rebasing shelved changes
1387 merging bar1
1387 merging bar1
1388 warning: conflicts while merging bar1! (edit, then use 'hg resolve --mark')
1388 warning: conflicts while merging bar1! (edit, then use 'hg resolve --mark')
1389 merging bar2
1389 merging bar2
1390 warning: conflicts while merging bar2! (edit, then use 'hg resolve --mark')
1390 warning: conflicts while merging bar2! (edit, then use 'hg resolve --mark')
1391 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1391 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1392 [240]
1392 [240]
1393
1393
1394 $ cat > bar1 <<EOF
1394 $ cat > bar1 <<EOF
1395 > A
1395 > A
1396 > B
1396 > B
1397 > C
1397 > C
1398 > EOF
1398 > EOF
1399 $ cat > bar2 <<EOF
1399 $ cat > bar2 <<EOF
1400 > A
1400 > A
1401 > B
1401 > B
1402 > C
1402 > C
1403 > EOF
1403 > EOF
1404 $ hg resolve -m bar1 bar2
1404 $ hg resolve -m bar1 bar2
1405 (no more unresolved files)
1405 (no more unresolved files)
1406 continue: hg unshelve --continue
1406 continue: hg unshelve --continue
1407
1407
1408 -- using --continue with --interactive should throw an error
1408 -- using --continue with --interactive should throw an error
1409 $ hg unshelve --continue -i
1409 $ hg unshelve --continue -i
1410 abort: cannot use both continue and interactive
1410 abort: cannot use both continue and interactive
1411 [10]
1411 [10]
1412
1412
1413 $ cat bar1
1413 $ cat bar1
1414 A
1414 A
1415 B
1415 B
1416 C
1416 C
1417
1417
1418 #if stripbased
1418 #if stripbased
1419 $ hg log -r 3:: -G
1419 $ hg log -r 3:: -G
1420 @ changeset: 5:f1d5f53e397b
1420 @ changeset: 5:f1d5f53e397b
1421 | tag: tip
1421 | tag: tip
1422 | parent: 3:e28fd7fa7938
1422 | parent: 3:e28fd7fa7938
1423 | user: shelve@localhost
1423 | user: shelve@localhost
1424 | date: Thu Jan 01 00:00:00 1970 +0000
1424 | date: Thu Jan 01 00:00:00 1970 +0000
1425 | summary: changes to: add A to bars
1425 | summary: changes to: add A to bars
1426 |
1426 |
1427 | @ changeset: 4:fe451a778c81
1427 | @ changeset: 4:fe451a778c81
1428 |/ user: test
1428 |/ user: test
1429 | date: Thu Jan 01 00:00:00 1970 +0000
1429 | date: Thu Jan 01 00:00:00 1970 +0000
1430 | summary: add C to bars
1430 | summary: add C to bars
1431 |
1431 |
1432 o changeset: 3:e28fd7fa7938
1432 o changeset: 3:e28fd7fa7938
1433 | user: test
1433 | user: test
1434 ~ date: Thu Jan 01 00:00:00 1970 +0000
1434 ~ date: Thu Jan 01 00:00:00 1970 +0000
1435 summary: add A to bars
1435 summary: add A to bars
1436
1436
1437 #endif
1437 #endif
1438
1438
1439 $ hg unshelve --continue <<EOF
1439 $ hg unshelve --continue <<EOF
1440 > y
1440 > y
1441 > y
1441 > y
1442 > y
1442 > y
1443 > n
1443 > n
1444 > EOF
1444 > EOF
1445 diff --git a/bar1 b/bar1
1445 diff --git a/bar1 b/bar1
1446 1 hunks, 1 lines changed
1446 1 hunks, 1 lines changed
1447 examine changes to 'bar1'?
1447 examine changes to 'bar1'?
1448 (enter ? for help) [Ynesfdaq?] y
1448 (enter ? for help) [Ynesfdaq?] y
1449
1449
1450 @@ -1,2 +1,3 @@
1450 @@ -1,2 +1,3 @@
1451 A
1451 A
1452 +B
1452 +B
1453 C
1453 C
1454 record change 1/2 to 'bar1'?
1454 record change 1/2 to 'bar1'?
1455 (enter ? for help) [Ynesfdaq?] y
1455 (enter ? for help) [Ynesfdaq?] y
1456
1456
1457 diff --git a/bar2 b/bar2
1457 diff --git a/bar2 b/bar2
1458 1 hunks, 1 lines changed
1458 1 hunks, 1 lines changed
1459 examine changes to 'bar2'?
1459 examine changes to 'bar2'?
1460 (enter ? for help) [Ynesfdaq?] y
1460 (enter ? for help) [Ynesfdaq?] y
1461
1461
1462 @@ -1,2 +1,3 @@
1462 @@ -1,2 +1,3 @@
1463 A
1463 A
1464 +B
1464 +B
1465 C
1465 C
1466 record change 2/2 to 'bar2'?
1466 record change 2/2 to 'bar2'?
1467 (enter ? for help) [Ynesfdaq?] n
1467 (enter ? for help) [Ynesfdaq?] n
1468
1468
1469 unshelve of 'default-01' complete
1469 unshelve of 'default-01' complete
1470
1470
1471 #if stripbased
1471 #if stripbased
1472 $ hg log -r 3:: -G
1472 $ hg log -r 3:: -G
1473 @ changeset: 4:fe451a778c81
1473 @ changeset: 4:fe451a778c81
1474 | tag: tip
1474 | tag: tip
1475 | user: test
1475 | user: test
1476 | date: Thu Jan 01 00:00:00 1970 +0000
1476 | date: Thu Jan 01 00:00:00 1970 +0000
1477 | summary: add C to bars
1477 | summary: add C to bars
1478 |
1478 |
1479 o changeset: 3:e28fd7fa7938
1479 o changeset: 3:e28fd7fa7938
1480 | user: test
1480 | user: test
1481 ~ date: Thu Jan 01 00:00:00 1970 +0000
1481 ~ date: Thu Jan 01 00:00:00 1970 +0000
1482 summary: add A to bars
1482 summary: add A to bars
1483
1483
1484 #endif
1484 #endif
1485
1485
1486 $ hg unshelve --continue
1486 $ hg unshelve --continue
1487 abort: no unshelve in progress
1487 abort: no unshelve in progress
1488 [20]
1488 [20]
1489
1489
1490 $ hg shelve --list
1490 $ hg shelve --list
1491 default-01 (*)* changes to: add A to bars (glob)
1491 default-01 (*)* changes to: add A to bars (glob)
1492 default (*)* changes to: add B to foo (glob)
1492 default (*)* changes to: add B to foo (glob)
1493 $ hg unshelve -n default-01 -i <<EOF
1493 $ hg unshelve -n default-01 -i <<EOF
1494 > y
1494 > y
1495 > y
1495 > y
1496 > EOF
1496 > EOF
1497 temporarily committing pending changes (restore with 'hg unshelve --abort')
1497 temporarily committing pending changes (restore with 'hg unshelve --abort')
1498 rebasing shelved changes
1498 rebasing shelved changes
1499 diff --git a/bar2 b/bar2
1499 diff --git a/bar2 b/bar2
1500 1 hunks, 1 lines changed
1500 1 hunks, 1 lines changed
1501 examine changes to 'bar2'?
1501 examine changes to 'bar2'?
1502 (enter ? for help) [Ynesfdaq?] y
1502 (enter ? for help) [Ynesfdaq?] y
1503
1503
1504 @@ -1,2 +1,3 @@
1504 @@ -1,2 +1,3 @@
1505 A
1505 A
1506 +B
1506 +B
1507 C
1507 C
1508 record this change to 'bar2'?
1508 record this change to 'bar2'?
1509 (enter ? for help) [Ynesfdaq?] y
1509 (enter ? for help) [Ynesfdaq?] y
1510
1510
1511 -- test for --interactive --keep
1511 -- test for --interactive --keep
1512 $ hg unshelve -i --keep
1512 $ hg unshelve -i --keep
1513 abort: --keep on --interactive is not yet supported
1513 abort: --keep on --interactive is not yet supported
1514 [10]
1514 [10]
1515
1515
1516 $ hg update -q --clean .
1516 $ hg update -q --clean .
1517
1517
1518 Test that we can successfully shelve and unshelve a file with a trailing space
1518 Test that we can successfully shelve and unshelve a file with a trailing space
1519 in the filename. Such filenames are supposedly unsupported on Windows, so we
1519 in the filename. Such filenames are supposedly unsupported on Windows, so we
1520 wrap it in the no-windows check. Also test `hg patch` of the .patch file
1520 wrap it in the no-windows check. Also test `hg patch` of the .patch file
1521 produced by `hg shelve`.
1521 produced by `hg shelve`.
1522 #if no-windows
1522 #if no-windows
1523 $ echo hi > 'my filename '
1523 $ echo hi > 'my filename '
1524 $ hg add 'my filename '
1524 $ hg add 'my filename '
1525 warning: filename ends with ' ', which is not allowed on Windows: 'my filename '
1525 warning: filename ends with ' ', which is not allowed on Windows: 'my filename '
1526 $ hg shelve
1526 $ hg shelve
1527 shelved as default-01
1527 shelved as default-01
1528 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1528 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1529 $ cp .hg/shelved/default-01.patch test_patch.patch
1529 $ cp .hg/shelved/default-01.patch test_patch.patch
1530 $ hg unshelve
1530 $ hg unshelve
1531 unshelving change 'default-01'
1531 unshelving change 'default-01'
1532 $ cat 'my filename '
1532 $ cat 'my filename '
1533 hi
1533 hi
1534 $ hg update -q --clean .
1534 $ hg update -q --clean .
1535 $ hg patch -p1 test_patch.patch
1535 $ hg patch -p1 test_patch.patch
1536 applying test_patch.patch
1536 applying test_patch.patch
1537 #endif
1537 #endif
1538
1538
1539 -- if phasebased, shelve works without patch and bundle
1539 -- if phasebased, shelve works without patch and bundle
1540
1540
1541 $ hg update -q --clean .
1541 $ hg update -q --clean .
1542 $ hg strip -q -r 0
1542 $ hg strip -q -r 0
1543 $ rm -r .hg/shelve*
1543 $ rm -r .hg/shelve*
1544 $ echo import antigravity >> somefile.py
1544 $ echo import antigravity >> somefile.py
1545 $ hg add somefile.py
1545 $ hg add somefile.py
1546 $ hg shelve -q
1546 $ hg shelve -q
1547 #if phasebased
1547 #if phasebased
1548 $ rm .hg/shelved/default.hg
1548 $ rm .hg/shelved/default.hg
1549 $ rm .hg/shelved/default.patch
1549 $ rm .hg/shelved/default.patch
1550 #endif
1550 #endif
1551
1551
1552 shelve --list --patch should work even with no patch file.
1552 shelve --list --patch should work even with no patch file.
1553
1553
1554 $ hg shelve --list --patch
1554 $ hg shelve --list --patch
1555 default (*s ago) * (changes in empty repository) (glob)
1555 default (*s ago) * (changes in empty repository) (glob)
1556
1556
1557 diff --git a/somefile.py b/somefile.py
1557 diff --git a/somefile.py b/somefile.py
1558 new file mode 100644
1558 new file mode 100644
1559 --- /dev/null
1559 --- /dev/null
1560 +++ b/somefile.py
1560 +++ b/somefile.py
1561 @@ -0,0 +1,1 @@
1561 @@ -0,0 +1,1 @@
1562 +import antigravity
1562 +import antigravity
1563
1563
1564 $ hg unshelve
1564 $ hg unshelve
1565 unshelving change 'default'
1565 unshelving change 'default'
1566
1566
1567 #if phasebased
1567 #if phasebased
1568 $ ls .hg/shelve-backup
1568 $ ls .hg/shelve-backup
1569 default.shelve
1569 default.shelve
1570 #endif
1570 #endif
1571
1571
1572 #if stripbased
1572 #if stripbased
1573 $ ls .hg/shelve-backup
1573 $ ls .hg/shelve-backup
1574 default.hg
1574 default.hg
1575 default.patch
1575 default.patch
1576 default.shelve
1576 default.shelve
1577 #endif
1577 #endif
1578
1578
1579
1579
1580 -- allow for phase-based shelves to be disabled
1580 -- allow for phase-based shelves to be disabled
1581
1581
1582 $ hg update -q --clean .
1582 $ hg update -q --clean .
1583 $ hg strip -q --hidden -r 0
1583 $ hg strip -q --hidden -r 0
1584 $ rm -r .hg/shelve*
1584 $ rm -r .hg/shelve*
1585
1585
1586 #if phasebased
1586 #if phasebased
1587 $ cat <<EOF >> $HGRCPATH
1587 $ cat <<EOF >> $HGRCPATH
1588 > [shelve]
1588 > [shelve]
1589 > store = strip
1589 > store = strip
1590 > EOF
1590 > EOF
1591 #endif
1591 #endif
1592
1592
1593 $ echo import this >> somefile.py
1593 $ echo import this >> somefile.py
1594 $ hg add somefile.py
1594 $ hg add somefile.py
1595 $ hg shelve -q
1595 $ hg shelve -q
1596 $ hg log --hidden
1596 $ hg log --hidden
1597 $ ls .hg/shelved
1597 $ ls .hg/shelved
1598 default.hg
1598 default.hg
1599 default.patch
1599 default.patch
1600 default.shelve
1600 default.shelve
1601 $ hg unshelve -q
1601 $ hg unshelve -q
@@ -1,994 +1,994 b''
1 #testcases stripbased phasebased
1 #testcases stripbased phasebased
2 #testcases abortflag abortcommand
2 #testcases abortflag abortcommand
3 #testcases continueflag continuecommand
3 #testcases continueflag continuecommand
4
4
5 $ cat <<EOF >> $HGRCPATH
5 $ cat <<EOF >> $HGRCPATH
6 > [extensions]
6 > [extensions]
7 > mq =
7 > mq =
8 > [defaults]
8 > [defaults]
9 > diff = --nodates --git
9 > diff = --nodates --git
10 > qnew = --date '0 0'
10 > qnew = --date '0 0'
11 > [shelve]
11 > [shelve]
12 > maxbackups = 2
12 > maxbackups = 2
13 > EOF
13 > EOF
14
14
15 #if phasebased
15 #if phasebased
16
16
17 $ cat <<EOF >> $HGRCPATH
17 $ cat <<EOF >> $HGRCPATH
18 > [format]
18 > [format]
19 > internal-phase = yes
19 > use-internal-phase = yes
20 > EOF
20 > EOF
21
21
22 #endif
22 #endif
23
23
24 #if abortflag
24 #if abortflag
25 $ cat >> $HGRCPATH <<EOF
25 $ cat >> $HGRCPATH <<EOF
26 > [alias]
26 > [alias]
27 > abort = unshelve --abort
27 > abort = unshelve --abort
28 > EOF
28 > EOF
29 #endif
29 #endif
30
30
31 #if continueflag
31 #if continueflag
32 $ cat >> $HGRCPATH <<EOF
32 $ cat >> $HGRCPATH <<EOF
33 > [alias]
33 > [alias]
34 > continue = unshelve --continue
34 > continue = unshelve --continue
35 > EOF
35 > EOF
36 #endif
36 #endif
37
37
38 shelve should leave dirstate clean (issue4055)
38 shelve should leave dirstate clean (issue4055)
39
39
40 $ hg init shelverebase
40 $ hg init shelverebase
41 $ cd shelverebase
41 $ cd shelverebase
42 $ printf 'x\ny\n' > x
42 $ printf 'x\ny\n' > x
43 $ echo z > z
43 $ echo z > z
44 $ hg commit -Aqm xy
44 $ hg commit -Aqm xy
45 $ echo z >> x
45 $ echo z >> x
46 $ hg commit -Aqm z
46 $ hg commit -Aqm z
47 $ hg up 5c4c67fb7dce
47 $ hg up 5c4c67fb7dce
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 $ printf 'a\nx\ny\nz\n' > x
49 $ printf 'a\nx\ny\nz\n' > x
50 $ hg commit -Aqm xyz
50 $ hg commit -Aqm xyz
51 $ echo c >> z
51 $ echo c >> z
52 $ hg shelve
52 $ hg shelve
53 shelved as default
53 shelved as default
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55
55
56 $ hg rebase -d 6c103be8f4e4 --config extensions.rebase=
56 $ hg rebase -d 6c103be8f4e4 --config extensions.rebase=
57 rebasing 2:323bfa07f744( tip)? "xyz" (re)
57 rebasing 2:323bfa07f744( tip)? "xyz" (re)
58 merging x
58 merging x
59 saved backup bundle to \$TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-(78114325|7ae538ef)-rebase.hg (re)
59 saved backup bundle to \$TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-(78114325|7ae538ef)-rebase.hg (re)
60 $ hg unshelve
60 $ hg unshelve
61 unshelving change 'default'
61 unshelving change 'default'
62 rebasing shelved changes
62 rebasing shelved changes
63 $ hg status
63 $ hg status
64 M z
64 M z
65
65
66 $ cd ..
66 $ cd ..
67
67
68 shelve should only unshelve pending changes (issue4068)
68 shelve should only unshelve pending changes (issue4068)
69
69
70 $ hg init onlypendingchanges
70 $ hg init onlypendingchanges
71 $ cd onlypendingchanges
71 $ cd onlypendingchanges
72 $ touch a
72 $ touch a
73 $ hg ci -Aqm a
73 $ hg ci -Aqm a
74 $ touch b
74 $ touch b
75 $ hg ci -Aqm b
75 $ hg ci -Aqm b
76 $ hg up -q 3903775176ed
76 $ hg up -q 3903775176ed
77 $ touch c
77 $ touch c
78 $ hg ci -Aqm c
78 $ hg ci -Aqm c
79
79
80 $ touch d
80 $ touch d
81 $ hg add d
81 $ hg add d
82 $ hg shelve
82 $ hg shelve
83 shelved as default
83 shelved as default
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ hg up -q 0e067c57feba
85 $ hg up -q 0e067c57feba
86 $ hg unshelve
86 $ hg unshelve
87 unshelving change 'default'
87 unshelving change 'default'
88 rebasing shelved changes
88 rebasing shelved changes
89 $ hg status
89 $ hg status
90 A d
90 A d
91
91
92 unshelve should work on an ancestor of the original commit
92 unshelve should work on an ancestor of the original commit
93
93
94 $ hg shelve
94 $ hg shelve
95 shelved as default
95 shelved as default
96 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
96 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
97 $ hg up 3903775176ed
97 $ hg up 3903775176ed
98 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
98 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
99 $ hg unshelve
99 $ hg unshelve
100 unshelving change 'default'
100 unshelving change 'default'
101 rebasing shelved changes
101 rebasing shelved changes
102 $ hg status
102 $ hg status
103 A d
103 A d
104
104
105 test bug 4073 we need to enable obsolete markers for it
105 test bug 4073 we need to enable obsolete markers for it
106
106
107 $ cat >> $HGRCPATH << EOF
107 $ cat >> $HGRCPATH << EOF
108 > [experimental]
108 > [experimental]
109 > evolution.createmarkers=True
109 > evolution.createmarkers=True
110 > EOF
110 > EOF
111 $ hg shelve
111 $ hg shelve
112 shelved as default
112 shelved as default
113 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
113 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
114 $ hg debugobsolete `hg log -r 0e067c57feba -T '{node}'`
114 $ hg debugobsolete `hg log -r 0e067c57feba -T '{node}'`
115 1 new obsolescence markers
115 1 new obsolescence markers
116 obsoleted 1 changesets
116 obsoleted 1 changesets
117 $ hg unshelve
117 $ hg unshelve
118 unshelving change 'default'
118 unshelving change 'default'
119
119
120 unshelve should leave unknown files alone (issue4113)
120 unshelve should leave unknown files alone (issue4113)
121
121
122 $ echo e > e
122 $ echo e > e
123 $ hg shelve
123 $ hg shelve
124 shelved as default
124 shelved as default
125 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
125 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
126 $ hg status
126 $ hg status
127 ? e
127 ? e
128 $ hg unshelve
128 $ hg unshelve
129 unshelving change 'default'
129 unshelving change 'default'
130 $ hg status
130 $ hg status
131 A d
131 A d
132 ? e
132 ? e
133 $ cat e
133 $ cat e
134 e
134 e
135
135
136 unshelve should keep a copy of unknown files
136 unshelve should keep a copy of unknown files
137
137
138 $ hg add e
138 $ hg add e
139 $ hg shelve
139 $ hg shelve
140 shelved as default
140 shelved as default
141 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
142 $ echo z > e
142 $ echo z > e
143 $ hg unshelve
143 $ hg unshelve
144 unshelving change 'default'
144 unshelving change 'default'
145 $ cat e
145 $ cat e
146 e
146 e
147 $ cat e.orig
147 $ cat e.orig
148 z
148 z
149 $ rm e.orig
149 $ rm e.orig
150
150
151 restores backup of unknown file to right directory
151 restores backup of unknown file to right directory
152
152
153 $ hg shelve
153 $ hg shelve
154 shelved as default
154 shelved as default
155 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
155 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
156 $ echo z > e
156 $ echo z > e
157 $ mkdir dir
157 $ mkdir dir
158 $ hg unshelve --cwd dir
158 $ hg unshelve --cwd dir
159 unshelving change 'default'
159 unshelving change 'default'
160 $ rmdir dir
160 $ rmdir dir
161 $ cat e
161 $ cat e
162 e
162 e
163 $ cat e.orig
163 $ cat e.orig
164 z
164 z
165
165
166 unshelve and conflicts with tracked and untracked files
166 unshelve and conflicts with tracked and untracked files
167
167
168 preparing:
168 preparing:
169
169
170 $ rm -f *.orig
170 $ rm -f *.orig
171 $ hg ci -qm 'commit stuff'
171 $ hg ci -qm 'commit stuff'
172 $ hg phase -p null:
172 $ hg phase -p null:
173
173
174 no other changes - no merge:
174 no other changes - no merge:
175
175
176 $ echo f > f
176 $ echo f > f
177 $ hg add f
177 $ hg add f
178 $ hg shelve
178 $ hg shelve
179 shelved as default
179 shelved as default
180 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
180 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
181 $ echo g > f
181 $ echo g > f
182 $ hg unshelve
182 $ hg unshelve
183 unshelving change 'default'
183 unshelving change 'default'
184 $ hg st
184 $ hg st
185 A f
185 A f
186 ? f.orig
186 ? f.orig
187 $ cat f
187 $ cat f
188 f
188 f
189 $ cat f.orig
189 $ cat f.orig
190 g
190 g
191
191
192 other uncommitted changes - merge:
192 other uncommitted changes - merge:
193
193
194 $ hg st
194 $ hg st
195 A f
195 A f
196 ? f.orig
196 ? f.orig
197 $ hg shelve
197 $ hg shelve
198 shelved as default
198 shelved as default
199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
200 #if repobundlerepo
200 #if repobundlerepo
201 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()' --hidden
201 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()' --hidden
202 o [48] changes to: commit stuff shelve@localhost (re)
202 o [48] changes to: commit stuff shelve@localhost (re)
203 |
203 |
204 ~
204 ~
205 #endif
205 #endif
206 $ hg log -G --template '{rev} {desc|firstline} {author}'
206 $ hg log -G --template '{rev} {desc|firstline} {author}'
207 @ [37] commit stuff test (re)
207 @ [37] commit stuff test (re)
208 |
208 |
209 | o 2 c test
209 | o 2 c test
210 |/
210 |/
211 o 0 a test
211 o 0 a test
212
212
213 $ mv f.orig f
213 $ mv f.orig f
214 $ echo 1 > a
214 $ echo 1 > a
215 $ hg unshelve --date '1073741824 0'
215 $ hg unshelve --date '1073741824 0'
216 unshelving change 'default'
216 unshelving change 'default'
217 temporarily committing pending changes (restore with 'hg unshelve --abort')
217 temporarily committing pending changes (restore with 'hg unshelve --abort')
218 rebasing shelved changes
218 rebasing shelved changes
219 merging f
219 merging f
220 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
220 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
221 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
221 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
222 [240]
222 [240]
223
223
224 #if phasebased
224 #if phasebased
225 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
225 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
226 @ 9 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
226 @ 9 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
227 |
227 |
228 | @ 8 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
228 | @ 8 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
229 |/
229 |/
230 o 7 commit stuff test 1970-01-01 00:00 +0000
230 o 7 commit stuff test 1970-01-01 00:00 +0000
231 |
231 |
232 | o 2 c test 1970-01-01 00:00 +0000
232 | o 2 c test 1970-01-01 00:00 +0000
233 |/
233 |/
234 o 0 a test 1970-01-01 00:00 +0000
234 o 0 a test 1970-01-01 00:00 +0000
235
235
236 #endif
236 #endif
237
237
238 #if stripbased
238 #if stripbased
239 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
239 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
240 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
240 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
241 |
241 |
242 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
242 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
243 |/
243 |/
244 o 3 commit stuff test 1970-01-01 00:00 +0000
244 o 3 commit stuff test 1970-01-01 00:00 +0000
245 |
245 |
246 | o 2 c test 1970-01-01 00:00 +0000
246 | o 2 c test 1970-01-01 00:00 +0000
247 |/
247 |/
248 o 0 a test 1970-01-01 00:00 +0000
248 o 0 a test 1970-01-01 00:00 +0000
249
249
250 #endif
250 #endif
251
251
252 $ hg st
252 $ hg st
253 M f
253 M f
254 ? f.orig
254 ? f.orig
255 $ cat f
255 $ cat f
256 <<<<<<< working-copy: d44eae5c3d33 - shelve: pending changes temporary commit
256 <<<<<<< working-copy: d44eae5c3d33 - shelve: pending changes temporary commit
257 g
257 g
258 =======
258 =======
259 f
259 f
260 >>>>>>> shelved change: aef214a5229c - shelve: changes to: commit stuff
260 >>>>>>> shelved change: aef214a5229c - shelve: changes to: commit stuff
261 $ cat f.orig
261 $ cat f.orig
262 g
262 g
263 $ hg unshelve --abort -t false
263 $ hg unshelve --abort -t false
264 tool option will be ignored
264 tool option will be ignored
265 unshelve of 'default' aborted
265 unshelve of 'default' aborted
266 $ hg st
266 $ hg st
267 M a
267 M a
268 ? f.orig
268 ? f.orig
269 $ cat f.orig
269 $ cat f.orig
270 g
270 g
271 $ hg unshelve
271 $ hg unshelve
272 unshelving change 'default'
272 unshelving change 'default'
273 temporarily committing pending changes (restore with 'hg unshelve --abort')
273 temporarily committing pending changes (restore with 'hg unshelve --abort')
274 rebasing shelved changes
274 rebasing shelved changes
275 $ hg st
275 $ hg st
276 M a
276 M a
277 A f
277 A f
278 ? f.orig
278 ? f.orig
279
279
280 other committed changes - merge:
280 other committed changes - merge:
281
281
282 $ hg shelve f
282 $ hg shelve f
283 shelved as default
283 shelved as default
284 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
284 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
285 $ hg ci a -m 'intermediate other change'
285 $ hg ci a -m 'intermediate other change'
286 $ mv f.orig f
286 $ mv f.orig f
287 $ hg unshelve
287 $ hg unshelve
288 unshelving change 'default'
288 unshelving change 'default'
289 rebasing shelved changes
289 rebasing shelved changes
290 merging f
290 merging f
291 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
291 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
292 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
292 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
293 [240]
293 [240]
294 $ hg st
294 $ hg st
295 M f
295 M f
296 ? f.orig
296 ? f.orig
297 $ cat f
297 $ cat f
298 <<<<<<< working-copy: 6b563750f973 - test: intermediate other change
298 <<<<<<< working-copy: 6b563750f973 - test: intermediate other change
299 g
299 g
300 =======
300 =======
301 f
301 f
302 >>>>>>> shelved change: aef214a5229c - shelve: changes to: commit stuff
302 >>>>>>> shelved change: aef214a5229c - shelve: changes to: commit stuff
303 $ cat f.orig
303 $ cat f.orig
304 g
304 g
305
305
306 #if abortcommand
306 #if abortcommand
307 when in dry-run mode
307 when in dry-run mode
308 $ hg abort --dry-run
308 $ hg abort --dry-run
309 unshelve in progress, will be aborted
309 unshelve in progress, will be aborted
310 #endif
310 #endif
311
311
312 $ hg abort
312 $ hg abort
313 unshelve of 'default' aborted
313 unshelve of 'default' aborted
314 $ hg st
314 $ hg st
315 ? f.orig
315 ? f.orig
316 $ cat f.orig
316 $ cat f.orig
317 g
317 g
318 $ hg shelve --delete default
318 $ hg shelve --delete default
319 $ cd ..
319 $ cd ..
320
320
321 you shouldn't be able to ask for the patch/stats of the most recent shelve if
321 you shouldn't be able to ask for the patch/stats of the most recent shelve if
322 there are no shelves
322 there are no shelves
323
323
324 $ hg init noshelves
324 $ hg init noshelves
325 $ cd noshelves
325 $ cd noshelves
326
326
327 $ hg shelve --patch
327 $ hg shelve --patch
328 abort: there are no shelves to show
328 abort: there are no shelves to show
329 [255]
329 [255]
330 $ hg shelve --stat
330 $ hg shelve --stat
331 abort: there are no shelves to show
331 abort: there are no shelves to show
332 [255]
332 [255]
333
333
334 $ cd ..
334 $ cd ..
335
335
336 test .orig files go where the user wants them to
336 test .orig files go where the user wants them to
337 ---------------------------------------------------------------
337 ---------------------------------------------------------------
338 $ hg init salvage
338 $ hg init salvage
339 $ cd salvage
339 $ cd salvage
340 $ echo 'content' > root
340 $ echo 'content' > root
341 $ hg commit -A -m 'root' -q
341 $ hg commit -A -m 'root' -q
342 $ echo '' > root
342 $ echo '' > root
343 $ hg shelve -q
343 $ hg shelve -q
344 $ echo 'contADDent' > root
344 $ echo 'contADDent' > root
345 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
345 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
346 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
346 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
347 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
347 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
348 [240]
348 [240]
349 $ ls .hg/origbackups
349 $ ls .hg/origbackups
350 root
350 root
351 $ rm -rf .hg/origbackups
351 $ rm -rf .hg/origbackups
352
352
353 test Abort unshelve always gets user out of the unshelved state
353 test Abort unshelve always gets user out of the unshelved state
354 ---------------------------------------------------------------
354 ---------------------------------------------------------------
355
355
356 with a corrupted shelve state file
356 with a corrupted shelve state file
357 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
357 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
358 $ mv ../corrupt-shelvedstate .hg/shelvestate
358 $ mv ../corrupt-shelvedstate .hg/shelvestate
359 $ hg unshelve --abort 2>&1 | grep 'aborted'
359 $ hg unshelve --abort 2>&1 | grep 'aborted'
360 unshelve of 'default' aborted
360 unshelve of 'default' aborted
361 $ hg summary
361 $ hg summary
362 parent: 0:ae8c668541e8 tip
362 parent: 0:ae8c668541e8 tip
363 root
363 root
364 branch: default
364 branch: default
365 commit: 1 modified
365 commit: 1 modified
366 update: (current)
366 update: (current)
367 phases: 1 draft
367 phases: 1 draft
368 $ hg up -C .
368 $ hg up -C .
369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
370
370
371 $ cd ..
371 $ cd ..
372
372
373 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
373 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
374 unknown file is the same as a shelved added file, except that it will be in
374 unknown file is the same as a shelved added file, except that it will be in
375 unknown state after unshelve if and only if it was either absent or unknown
375 unknown state after unshelve if and only if it was either absent or unknown
376 before the unshelve operation.
376 before the unshelve operation.
377
377
378 $ hg init unknowns
378 $ hg init unknowns
379 $ cd unknowns
379 $ cd unknowns
380
380
381 The simplest case is if I simply have an unknown file that I shelve and unshelve
381 The simplest case is if I simply have an unknown file that I shelve and unshelve
382
382
383 $ echo unknown > unknown
383 $ echo unknown > unknown
384 $ hg status
384 $ hg status
385 ? unknown
385 ? unknown
386 $ hg shelve --unknown
386 $ hg shelve --unknown
387 shelved as default
387 shelved as default
388 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
388 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
389 $ hg status
389 $ hg status
390 $ hg unshelve
390 $ hg unshelve
391 unshelving change 'default'
391 unshelving change 'default'
392 $ hg status
392 $ hg status
393 ? unknown
393 ? unknown
394 $ rm unknown
394 $ rm unknown
395
395
396 If I shelve, add the file, and unshelve, does it stay added?
396 If I shelve, add the file, and unshelve, does it stay added?
397
397
398 $ echo unknown > unknown
398 $ echo unknown > unknown
399 $ hg shelve -u
399 $ hg shelve -u
400 shelved as default
400 shelved as default
401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
402 $ hg status
402 $ hg status
403 $ touch unknown
403 $ touch unknown
404 $ hg add unknown
404 $ hg add unknown
405 $ hg status
405 $ hg status
406 A unknown
406 A unknown
407 $ hg unshelve
407 $ hg unshelve
408 unshelving change 'default'
408 unshelving change 'default'
409 temporarily committing pending changes (restore with 'hg unshelve --abort')
409 temporarily committing pending changes (restore with 'hg unshelve --abort')
410 rebasing shelved changes
410 rebasing shelved changes
411 merging unknown
411 merging unknown
412 $ hg status
412 $ hg status
413 A unknown
413 A unknown
414 $ hg forget unknown
414 $ hg forget unknown
415 $ rm unknown
415 $ rm unknown
416
416
417 And if I shelve, commit, then unshelve, does it become modified?
417 And if I shelve, commit, then unshelve, does it become modified?
418
418
419 $ echo unknown > unknown
419 $ echo unknown > unknown
420 $ hg shelve -u
420 $ hg shelve -u
421 shelved as default
421 shelved as default
422 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
422 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
423 $ hg status
423 $ hg status
424 $ touch unknown
424 $ touch unknown
425 $ hg add unknown
425 $ hg add unknown
426 $ hg commit -qm "Add unknown"
426 $ hg commit -qm "Add unknown"
427 $ hg status
427 $ hg status
428 $ hg unshelve
428 $ hg unshelve
429 unshelving change 'default'
429 unshelving change 'default'
430 rebasing shelved changes
430 rebasing shelved changes
431 merging unknown
431 merging unknown
432 $ hg status
432 $ hg status
433 M unknown
433 M unknown
434 $ hg remove --force unknown
434 $ hg remove --force unknown
435 $ hg commit -qm "Remove unknown"
435 $ hg commit -qm "Remove unknown"
436
436
437 $ cd ..
437 $ cd ..
438
438
439 We expects that non-bare shelve keeps newly created branch in
439 We expects that non-bare shelve keeps newly created branch in
440 working directory.
440 working directory.
441
441
442 $ hg init shelve-preserve-new-branch
442 $ hg init shelve-preserve-new-branch
443 $ cd shelve-preserve-new-branch
443 $ cd shelve-preserve-new-branch
444 $ echo "a" >> a
444 $ echo "a" >> a
445 $ hg add a
445 $ hg add a
446 $ echo "b" >> b
446 $ echo "b" >> b
447 $ hg add b
447 $ hg add b
448 $ hg commit -m "ab"
448 $ hg commit -m "ab"
449 $ echo "aa" >> a
449 $ echo "aa" >> a
450 $ echo "bb" >> b
450 $ echo "bb" >> b
451 $ hg branch new-branch
451 $ hg branch new-branch
452 marked working directory as branch new-branch
452 marked working directory as branch new-branch
453 (branches are permanent and global, did you want a bookmark?)
453 (branches are permanent and global, did you want a bookmark?)
454 $ hg status
454 $ hg status
455 M a
455 M a
456 M b
456 M b
457 $ hg branch
457 $ hg branch
458 new-branch
458 new-branch
459 $ hg shelve a
459 $ hg shelve a
460 shelved as default
460 shelved as default
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ hg branch
462 $ hg branch
463 new-branch
463 new-branch
464 $ hg status
464 $ hg status
465 M b
465 M b
466 $ touch "c" >> c
466 $ touch "c" >> c
467 $ hg add c
467 $ hg add c
468 $ hg status
468 $ hg status
469 M b
469 M b
470 A c
470 A c
471 $ hg shelve --exclude c
471 $ hg shelve --exclude c
472 shelved as default-01
472 shelved as default-01
473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 $ hg branch
474 $ hg branch
475 new-branch
475 new-branch
476 $ hg status
476 $ hg status
477 A c
477 A c
478 $ hg shelve --include c
478 $ hg shelve --include c
479 shelved as default-02
479 shelved as default-02
480 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
480 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
481 $ hg branch
481 $ hg branch
482 new-branch
482 new-branch
483 $ hg status
483 $ hg status
484 $ echo "d" >> d
484 $ echo "d" >> d
485 $ hg add d
485 $ hg add d
486 $ hg status
486 $ hg status
487 A d
487 A d
488
488
489 We expect that bare-shelve will not keep branch in current working directory.
489 We expect that bare-shelve will not keep branch in current working directory.
490
490
491 $ hg shelve
491 $ hg shelve
492 shelved as default-03
492 shelved as default-03
493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
494 $ hg branch
494 $ hg branch
495 default
495 default
496 $ cd ..
496 $ cd ..
497
497
498 When i shelve commit on newly created branch i expect
498 When i shelve commit on newly created branch i expect
499 that after unshelve newly created branch will be preserved.
499 that after unshelve newly created branch will be preserved.
500
500
501 $ hg init shelve_on_new_branch_simple
501 $ hg init shelve_on_new_branch_simple
502 $ cd shelve_on_new_branch_simple
502 $ cd shelve_on_new_branch_simple
503 $ echo "aaa" >> a
503 $ echo "aaa" >> a
504 $ hg commit -A -m "a"
504 $ hg commit -A -m "a"
505 adding a
505 adding a
506 $ hg branch
506 $ hg branch
507 default
507 default
508 $ hg branch test
508 $ hg branch test
509 marked working directory as branch test
509 marked working directory as branch test
510 (branches are permanent and global, did you want a bookmark?)
510 (branches are permanent and global, did you want a bookmark?)
511 $ echo "bbb" >> a
511 $ echo "bbb" >> a
512 $ hg status
512 $ hg status
513 M a
513 M a
514 $ hg shelve
514 $ hg shelve
515 shelved as default
515 shelved as default
516 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
517 $ hg branch
517 $ hg branch
518 default
518 default
519 $ echo "bbb" >> b
519 $ echo "bbb" >> b
520 $ hg status
520 $ hg status
521 ? b
521 ? b
522 $ hg unshelve
522 $ hg unshelve
523 unshelving change 'default'
523 unshelving change 'default'
524 marked working directory as branch test
524 marked working directory as branch test
525 $ hg status
525 $ hg status
526 M a
526 M a
527 ? b
527 ? b
528 $ hg branch
528 $ hg branch
529 test
529 test
530 $ cd ..
530 $ cd ..
531
531
532 When i shelve commit on newly created branch, make
532 When i shelve commit on newly created branch, make
533 some changes, unshelve it and running into merge
533 some changes, unshelve it and running into merge
534 conflicts i expect that after fixing them and
534 conflicts i expect that after fixing them and
535 running unshelve --continue newly created branch
535 running unshelve --continue newly created branch
536 will be preserved.
536 will be preserved.
537
537
538 $ hg init shelve_on_new_branch_conflict
538 $ hg init shelve_on_new_branch_conflict
539 $ cd shelve_on_new_branch_conflict
539 $ cd shelve_on_new_branch_conflict
540 $ echo "aaa" >> a
540 $ echo "aaa" >> a
541 $ hg commit -A -m "a"
541 $ hg commit -A -m "a"
542 adding a
542 adding a
543 $ hg branch
543 $ hg branch
544 default
544 default
545 $ hg branch test
545 $ hg branch test
546 marked working directory as branch test
546 marked working directory as branch test
547 (branches are permanent and global, did you want a bookmark?)
547 (branches are permanent and global, did you want a bookmark?)
548 $ echo "bbb" >> a
548 $ echo "bbb" >> a
549 $ hg status
549 $ hg status
550 M a
550 M a
551 $ hg shelve
551 $ hg shelve
552 shelved as default
552 shelved as default
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 branch
554 $ hg branch
555 default
555 default
556 $ echo "ccc" >> a
556 $ echo "ccc" >> a
557 $ hg status
557 $ hg status
558 M a
558 M a
559 $ hg unshelve
559 $ hg unshelve
560 unshelving change 'default'
560 unshelving change 'default'
561 temporarily committing pending changes (restore with 'hg unshelve --abort')
561 temporarily committing pending changes (restore with 'hg unshelve --abort')
562 rebasing shelved changes
562 rebasing shelved changes
563 merging a
563 merging a
564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
565 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
565 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
566 [240]
566 [240]
567 $ echo "aaabbbccc" > a
567 $ echo "aaabbbccc" > a
568 $ rm a.orig
568 $ rm a.orig
569 $ hg resolve --mark a
569 $ hg resolve --mark a
570 (no more unresolved files)
570 (no more unresolved files)
571 continue: hg unshelve --continue
571 continue: hg unshelve --continue
572 $ hg continue
572 $ hg continue
573 marked working directory as branch test
573 marked working directory as branch test
574 unshelve of 'default' complete
574 unshelve of 'default' complete
575 $ cat a
575 $ cat a
576 aaabbbccc
576 aaabbbccc
577 $ hg status
577 $ hg status
578 M a
578 M a
579 $ hg branch
579 $ hg branch
580 test
580 test
581 $ hg commit -m "test-commit"
581 $ hg commit -m "test-commit"
582
582
583 When i shelve on test branch, update to default branch
583 When i shelve on test branch, update to default branch
584 and unshelve i expect that it will not preserve previous
584 and unshelve i expect that it will not preserve previous
585 test branch.
585 test branch.
586
586
587 $ echo "xxx" > b
587 $ echo "xxx" > b
588 $ hg add b
588 $ hg add b
589 $ hg shelve
589 $ hg shelve
590 shelved as test
590 shelved as test
591 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
591 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
592 $ hg update -r 7049e48789d7
592 $ hg update -r 7049e48789d7
593 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
593 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 $ hg unshelve
594 $ hg unshelve
595 unshelving change 'test'
595 unshelving change 'test'
596 rebasing shelved changes
596 rebasing shelved changes
597 $ hg status
597 $ hg status
598 A b
598 A b
599 $ hg branch
599 $ hg branch
600 default
600 default
601 $ cd ..
601 $ cd ..
602
602
603 When i unshelve resulting in merge conflicts and makes saved
603 When i unshelve resulting in merge conflicts and makes saved
604 file shelvedstate looks like in previous versions in
604 file shelvedstate looks like in previous versions in
605 mercurial(without restore branch information in 7th line) i
605 mercurial(without restore branch information in 7th line) i
606 expect that after resolving conflicts and successfully
606 expect that after resolving conflicts and successfully
607 running 'shelve --continue' the branch information won't be
607 running 'shelve --continue' the branch information won't be
608 restored and branch will be unchanged.
608 restored and branch will be unchanged.
609
609
610 shelve on new branch, conflict with previous shelvedstate
610 shelve on new branch, conflict with previous shelvedstate
611
611
612 $ hg init conflict
612 $ hg init conflict
613 $ cd conflict
613 $ cd conflict
614 $ echo "aaa" >> a
614 $ echo "aaa" >> a
615 $ hg commit -A -m "a"
615 $ hg commit -A -m "a"
616 adding a
616 adding a
617 $ hg branch
617 $ hg branch
618 default
618 default
619 $ hg branch test
619 $ hg branch test
620 marked working directory as branch test
620 marked working directory as branch test
621 (branches are permanent and global, did you want a bookmark?)
621 (branches are permanent and global, did you want a bookmark?)
622 $ echo "bbb" >> a
622 $ echo "bbb" >> a
623 $ hg status
623 $ hg status
624 M a
624 M a
625 $ hg shelve
625 $ hg shelve
626 shelved as default
626 shelved as default
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 $ hg branch
628 $ hg branch
629 default
629 default
630 $ echo "ccc" >> a
630 $ echo "ccc" >> a
631 $ hg status
631 $ hg status
632 M a
632 M a
633 $ hg unshelve
633 $ hg unshelve
634 unshelving change 'default'
634 unshelving change 'default'
635 temporarily committing pending changes (restore with 'hg unshelve --abort')
635 temporarily committing pending changes (restore with 'hg unshelve --abort')
636 rebasing shelved changes
636 rebasing shelved changes
637 merging a
637 merging a
638 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
638 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
639 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
639 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
640 [240]
640 [240]
641
641
642 Removing restore branch information from shelvedstate file(making it looks like
642 Removing restore branch information from shelvedstate file(making it looks like
643 in previous versions) and running unshelve --continue
643 in previous versions) and running unshelve --continue
644
644
645 $ cp .hg/shelvedstate .hg/shelvedstate_old
645 $ cp .hg/shelvedstate .hg/shelvedstate_old
646 $ cat .hg/shelvedstate_old | grep -v 'branchtorestore' > .hg/shelvedstate
646 $ cat .hg/shelvedstate_old | grep -v 'branchtorestore' > .hg/shelvedstate
647
647
648 $ echo "aaabbbccc" > a
648 $ echo "aaabbbccc" > a
649 $ rm a.orig
649 $ rm a.orig
650 $ hg resolve --mark a
650 $ hg resolve --mark a
651 (no more unresolved files)
651 (no more unresolved files)
652 continue: hg unshelve --continue
652 continue: hg unshelve --continue
653
653
654 #if continuecommand
654 #if continuecommand
655 $ hg continue --dry-run
655 $ hg continue --dry-run
656 unshelve in progress, will be resumed
656 unshelve in progress, will be resumed
657 #endif
657 #endif
658
658
659 $ hg continue
659 $ hg continue
660 unshelve of 'default' complete
660 unshelve of 'default' complete
661 $ cat a
661 $ cat a
662 aaabbbccc
662 aaabbbccc
663 $ hg status
663 $ hg status
664 M a
664 M a
665 $ hg branch
665 $ hg branch
666 default
666 default
667 $ cd ..
667 $ cd ..
668
668
669 On non bare shelve the branch information shouldn't be restored
669 On non bare shelve the branch information shouldn't be restored
670
670
671 $ hg init bare_shelve_on_new_branch
671 $ hg init bare_shelve_on_new_branch
672 $ cd bare_shelve_on_new_branch
672 $ cd bare_shelve_on_new_branch
673 $ echo "aaa" >> a
673 $ echo "aaa" >> a
674 $ hg commit -A -m "a"
674 $ hg commit -A -m "a"
675 adding a
675 adding a
676 $ hg branch
676 $ hg branch
677 default
677 default
678 $ hg branch test
678 $ hg branch test
679 marked working directory as branch test
679 marked working directory as branch test
680 (branches are permanent and global, did you want a bookmark?)
680 (branches are permanent and global, did you want a bookmark?)
681 $ echo "bbb" >> a
681 $ echo "bbb" >> a
682 $ hg status
682 $ hg status
683 M a
683 M a
684 $ hg shelve a
684 $ hg shelve a
685 shelved as default
685 shelved as default
686 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
686 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
687 $ hg branch
687 $ hg branch
688 test
688 test
689 $ hg branch default
689 $ hg branch default
690 marked working directory as branch default
690 marked working directory as branch default
691 (branches are permanent and global, did you want a bookmark?)
691 (branches are permanent and global, did you want a bookmark?)
692 $ echo "bbb" >> b
692 $ echo "bbb" >> b
693 $ hg status
693 $ hg status
694 ? b
694 ? b
695 $ hg unshelve
695 $ hg unshelve
696 unshelving change 'default'
696 unshelving change 'default'
697 $ hg status
697 $ hg status
698 M a
698 M a
699 ? b
699 ? b
700 $ hg branch
700 $ hg branch
701 default
701 default
702 $ cd ..
702 $ cd ..
703
703
704 Prepare unshelve with a corrupted shelvedstate
704 Prepare unshelve with a corrupted shelvedstate
705 $ hg init r1 && cd r1
705 $ hg init r1 && cd r1
706 $ echo text1 > file && hg add file
706 $ echo text1 > file && hg add file
707 $ hg shelve
707 $ hg shelve
708 shelved as default
708 shelved as default
709 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
709 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
710 $ echo text2 > file && hg ci -Am text1
710 $ echo text2 > file && hg ci -Am text1
711 adding file
711 adding file
712 $ hg unshelve
712 $ hg unshelve
713 unshelving change 'default'
713 unshelving change 'default'
714 rebasing shelved changes
714 rebasing shelved changes
715 merging file
715 merging file
716 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
716 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
717 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
717 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
718 [240]
718 [240]
719 $ echo somethingsomething > .hg/shelvedstate
719 $ echo somethingsomething > .hg/shelvedstate
720
720
721 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
721 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
722 $ hg continue
722 $ hg continue
723 abort: corrupted shelved state file
723 abort: corrupted shelved state file
724 (please run hg unshelve --abort to abort unshelve operation)
724 (please run hg unshelve --abort to abort unshelve operation)
725 [255]
725 [255]
726
726
727 Unshelve --abort works with a corrupted shelvedstate
727 Unshelve --abort works with a corrupted shelvedstate
728 $ hg abort
728 $ hg abort
729 abort: could not read shelved state file, your working copy may be in an unexpected state
729 abort: could not read shelved state file, your working copy may be in an unexpected state
730 please update to some commit
730 please update to some commit
731
731
732 [255]
732 [255]
733
733
734 Unshelve --abort fails with appropriate message if there's no unshelve in
734 Unshelve --abort fails with appropriate message if there's no unshelve in
735 progress
735 progress
736
736
737 #if abortflag
737 #if abortflag
738 $ hg unshelve --abort
738 $ hg unshelve --abort
739 abort: no unshelve in progress
739 abort: no unshelve in progress
740 [20]
740 [20]
741 #else
741 #else
742 $ hg abort
742 $ hg abort
743 aborting the merge, updating back to 9451eaa6eee3
743 aborting the merge, updating back to 9451eaa6eee3
744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
745 #endif
745 #endif
746 $ cd ..
746 $ cd ..
747
747
748 Test corrupt shelves (in .hg/shelved/, not .hg/shelvestate)
748 Test corrupt shelves (in .hg/shelved/, not .hg/shelvestate)
749 $ hg init corrupt-shelves
749 $ hg init corrupt-shelves
750 $ cd corrupt-shelves
750 $ cd corrupt-shelves
751 $ mkdir .hg/shelved
751 $ mkdir .hg/shelved
752
752
753 # A (corrupt) .patch file without a .hg file
753 # A (corrupt) .patch file without a .hg file
754 $ touch .hg/shelved/junk1.patch
754 $ touch .hg/shelved/junk1.patch
755 $ hg shelve -l
755 $ hg shelve -l
756 $ hg unshelve
756 $ hg unshelve
757 abort: no shelved changes to apply!
757 abort: no shelved changes to apply!
758 [20]
758 [20]
759 $ hg shelve -d junk1
759 $ hg shelve -d junk1
760 abort: shelved change 'junk1' not found
760 abort: shelved change 'junk1' not found
761 [10]
761 [10]
762 $ find .hg/shelve* | sort
762 $ find .hg/shelve* | sort
763 .hg/shelved
763 .hg/shelved
764 .hg/shelved/junk1.patch
764 .hg/shelved/junk1.patch
765
765
766 # A .hg file without a .patch file
766 # A .hg file without a .patch file
767 $ touch .hg/shelved/junk2.hg
767 $ touch .hg/shelved/junk2.hg
768 $ hg shelve -l
768 $ hg shelve -l
769 $ hg unshelve
769 $ hg unshelve
770 abort: no shelved changes to apply!
770 abort: no shelved changes to apply!
771 [20]
771 [20]
772 $ hg shelve -d junk2
772 $ hg shelve -d junk2
773 abort: shelved change 'junk2' not found
773 abort: shelved change 'junk2' not found
774 [10]
774 [10]
775 $ find .hg/shelve* | sort
775 $ find .hg/shelve* | sort
776 .hg/shelved
776 .hg/shelved
777 .hg/shelved/junk1.patch
777 .hg/shelved/junk1.patch
778 .hg/shelved/junk2.hg
778 .hg/shelved/junk2.hg
779
779
780 # A file with an unexpected extension
780 # A file with an unexpected extension
781 $ touch .hg/shelved/junk3
781 $ touch .hg/shelved/junk3
782 $ hg shelve -l
782 $ hg shelve -l
783 $ hg unshelve
783 $ hg unshelve
784 abort: no shelved changes to apply!
784 abort: no shelved changes to apply!
785 [20]
785 [20]
786 $ hg shelve -d junk3
786 $ hg shelve -d junk3
787 abort: shelved change 'junk3' not found
787 abort: shelved change 'junk3' not found
788 [10]
788 [10]
789 $ find .hg/shelve* | sort
789 $ find .hg/shelve* | sort
790 .hg/shelved
790 .hg/shelved
791 .hg/shelved/junk1.patch
791 .hg/shelved/junk1.patch
792 .hg/shelved/junk2.hg
792 .hg/shelved/junk2.hg
793 .hg/shelved/junk3
793 .hg/shelved/junk3
794
794
795 $ cd ..
795 $ cd ..
796
796
797 Unshelve respects --keep even if user intervention is needed
797 Unshelve respects --keep even if user intervention is needed
798 $ hg init unshelvekeep && cd unshelvekeep
798 $ hg init unshelvekeep && cd unshelvekeep
799 $ echo 1 > file && hg ci -Am 1
799 $ echo 1 > file && hg ci -Am 1
800 adding file
800 adding file
801 $ echo 2 >> file
801 $ echo 2 >> file
802 $ hg shelve
802 $ hg shelve
803 shelved as default
803 shelved as default
804 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
804 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
805 $ echo 3 >> file && hg ci -Am 13
805 $ echo 3 >> file && hg ci -Am 13
806 $ hg shelve --list
806 $ hg shelve --list
807 default (*s ago) * changes to: 1 (glob)
807 default (*s ago) * changes to: 1 (glob)
808 $ hg unshelve --keep
808 $ hg unshelve --keep
809 unshelving change 'default'
809 unshelving change 'default'
810 rebasing shelved changes
810 rebasing shelved changes
811 merging file
811 merging file
812 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
812 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
813 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
813 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
814 [240]
814 [240]
815 $ hg resolve --mark file
815 $ hg resolve --mark file
816 (no more unresolved files)
816 (no more unresolved files)
817 continue: hg unshelve --continue
817 continue: hg unshelve --continue
818 $ hg continue
818 $ hg continue
819 unshelve of 'default' complete
819 unshelve of 'default' complete
820 $ hg shelve --list
820 $ hg shelve --list
821 default (*s ago) * changes to: 1 (glob)
821 default (*s ago) * changes to: 1 (glob)
822 $ cd ..
822 $ cd ..
823
823
824 Unshelving when there are deleted files does not crash (issue4176)
824 Unshelving when there are deleted files does not crash (issue4176)
825 $ hg init unshelve-deleted-file && cd unshelve-deleted-file
825 $ hg init unshelve-deleted-file && cd unshelve-deleted-file
826 $ echo a > a && echo b > b && hg ci -Am ab
826 $ echo a > a && echo b > b && hg ci -Am ab
827 adding a
827 adding a
828 adding b
828 adding b
829 $ echo aa > a && hg shelve
829 $ echo aa > a && hg shelve
830 shelved as default
830 shelved as default
831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
832 $ rm b
832 $ rm b
833 $ hg st
833 $ hg st
834 ! b
834 ! b
835 $ hg unshelve
835 $ hg unshelve
836 unshelving change 'default'
836 unshelving change 'default'
837 $ hg shelve
837 $ hg shelve
838 shelved as default
838 shelved as default
839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
840 $ rm a && echo b > b
840 $ rm a && echo b > b
841 $ hg st
841 $ hg st
842 ! a
842 ! a
843 $ hg unshelve
843 $ hg unshelve
844 unshelving change 'default'
844 unshelving change 'default'
845 abort: shelved change touches missing files
845 abort: shelved change touches missing files
846 (run hg status to see which files are missing)
846 (run hg status to see which files are missing)
847 [255]
847 [255]
848 $ hg st
848 $ hg st
849 ! a
849 ! a
850 $ cd ..
850 $ cd ..
851
851
852 New versions of Mercurial know how to read onld shelvedstate files
852 New versions of Mercurial know how to read onld shelvedstate files
853 $ hg init oldshelvedstate
853 $ hg init oldshelvedstate
854 $ cd oldshelvedstate
854 $ cd oldshelvedstate
855 $ echo root > root && hg ci -Am root
855 $ echo root > root && hg ci -Am root
856 adding root
856 adding root
857 $ echo 1 > a
857 $ echo 1 > a
858 $ hg add a
858 $ hg add a
859 $ hg shelve --name ashelve
859 $ hg shelve --name ashelve
860 shelved as ashelve
860 shelved as ashelve
861 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
861 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
862 $ echo 2 > a
862 $ echo 2 > a
863 $ hg ci -Am a
863 $ hg ci -Am a
864 adding a
864 adding a
865 $ hg unshelve
865 $ hg unshelve
866 unshelving change 'ashelve'
866 unshelving change 'ashelve'
867 rebasing shelved changes
867 rebasing shelved changes
868 merging a
868 merging a
869 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
869 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
870 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
870 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
871 [240]
871 [240]
872 putting v1 shelvedstate file in place of a created v2
872 putting v1 shelvedstate file in place of a created v2
873 $ cat << EOF > .hg/shelvedstate
873 $ cat << EOF > .hg/shelvedstate
874 > 1
874 > 1
875 > ashelve
875 > ashelve
876 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
876 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
877 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
877 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
878 > 8b058dae057a5a78f393f4535d9e363dd5efac9d f543b27db2cdb41737e2e0008dc524c471da1446
878 > 8b058dae057a5a78f393f4535d9e363dd5efac9d f543b27db2cdb41737e2e0008dc524c471da1446
879 > f543b27db2cdb41737e2e0008dc524c471da1446
879 > f543b27db2cdb41737e2e0008dc524c471da1446
880 >
880 >
881 > nokeep
881 > nokeep
882 > :no-active-bookmark
882 > :no-active-bookmark
883 > EOF
883 > EOF
884 $ echo 1 > a
884 $ echo 1 > a
885 $ hg resolve --mark a
885 $ hg resolve --mark a
886 (no more unresolved files)
886 (no more unresolved files)
887 continue: hg unshelve --continue
887 continue: hg unshelve --continue
888 mercurial does not crash
888 mercurial does not crash
889 $ hg continue
889 $ hg continue
890 unshelve of 'ashelve' complete
890 unshelve of 'ashelve' complete
891
891
892 #if phasebased
892 #if phasebased
893
893
894 Unshelve with some metadata file missing
894 Unshelve with some metadata file missing
895 ----------------------------------------
895 ----------------------------------------
896
896
897 $ hg shelve
897 $ hg shelve
898 shelved as default
898 shelved as default
899 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
899 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
900 $ echo 3 > a
900 $ echo 3 > a
901
901
902 Test with the `.shelve` missing, but the changeset still in the repo (non-natural case)
902 Test with the `.shelve` missing, but the changeset still in the repo (non-natural case)
903
903
904 $ rm .hg/shelved/default.shelve
904 $ rm .hg/shelved/default.shelve
905 $ hg unshelve
905 $ hg unshelve
906 unshelving change 'default'
906 unshelving change 'default'
907 temporarily committing pending changes (restore with 'hg unshelve --abort')
907 temporarily committing pending changes (restore with 'hg unshelve --abort')
908 rebasing shelved changes
908 rebasing shelved changes
909 merging a
909 merging a
910 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
910 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
911 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
911 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
912 [240]
912 [240]
913 $ hg abort
913 $ hg abort
914 unshelve of 'default' aborted
914 unshelve of 'default' aborted
915
915
916 Unshelve without .shelve metadata (can happen when upgrading a repository with old shelve)
916 Unshelve without .shelve metadata (can happen when upgrading a repository with old shelve)
917
917
918 $ cat .hg/shelved/default.shelve
918 $ cat .hg/shelved/default.shelve
919 node=82e0cb9893247d12667017593ce1e5655860f1ac
919 node=82e0cb9893247d12667017593ce1e5655860f1ac
920 $ hg strip --hidden --rev 82e0cb989324 --no-backup
920 $ hg strip --hidden --rev 82e0cb989324 --no-backup
921 $ rm .hg/shelved/default.shelve
921 $ rm .hg/shelved/default.shelve
922 $ hg unshelve
922 $ hg unshelve
923 unshelving change 'default'
923 unshelving change 'default'
924 temporarily committing pending changes (restore with 'hg unshelve --abort')
924 temporarily committing pending changes (restore with 'hg unshelve --abort')
925 rebasing shelved changes
925 rebasing shelved changes
926 merging a
926 merging a
927 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
927 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
928 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
928 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
929 [240]
929 [240]
930 $ cat .hg/shelved/default.shelve
930 $ cat .hg/shelved/default.shelve
931 node=82e0cb9893247d12667017593ce1e5655860f1ac
931 node=82e0cb9893247d12667017593ce1e5655860f1ac
932 $ hg abort
932 $ hg abort
933 unshelve of 'default' aborted
933 unshelve of 'default' aborted
934
934
935 #endif
935 #endif
936
936
937 $ cd ..
937 $ cd ..
938
938
939 Block merge abort when unshelve in progress(issue6160)
939 Block merge abort when unshelve in progress(issue6160)
940 ------------------------------------------------------
940 ------------------------------------------------------
941
941
942 $ hg init a
942 $ hg init a
943 $ cd a
943 $ cd a
944 $ echo foo > a ; hg commit -qAm "initial commit"
944 $ echo foo > a ; hg commit -qAm "initial commit"
945 $ echo bar > a
945 $ echo bar > a
946 $ hg shelve
946 $ hg shelve
947 shelved as default
947 shelved as default
948 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
948 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
949 $ echo foobar > a
949 $ echo foobar > a
950 $ hg unshelve
950 $ hg unshelve
951 unshelving change 'default'
951 unshelving change 'default'
952 temporarily committing pending changes (restore with 'hg unshelve --abort')
952 temporarily committing pending changes (restore with 'hg unshelve --abort')
953 rebasing shelved changes
953 rebasing shelved changes
954 merging a
954 merging a
955 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
955 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
956 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
956 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
957 [240]
957 [240]
958
958
959 $ hg log --template '{desc|firstline} {author} {date|isodate} \n' -r .
959 $ hg log --template '{desc|firstline} {author} {date|isodate} \n' -r .
960 pending changes temporary commit shelve@localhost 1970-01-01 00:00 +0000
960 pending changes temporary commit shelve@localhost 1970-01-01 00:00 +0000
961 $ hg merge --abort
961 $ hg merge --abort
962 abort: cannot abort merge with unshelve in progress
962 abort: cannot abort merge with unshelve in progress
963 (use 'hg unshelve --continue' or 'hg unshelve --abort')
963 (use 'hg unshelve --continue' or 'hg unshelve --abort')
964 [20]
964 [20]
965
965
966 $ hg unshelve --abort
966 $ hg unshelve --abort
967 unshelve of 'default' aborted
967 unshelve of 'default' aborted
968
968
969 $ hg log -G --template '{desc|firstline} {author} {date|isodate} \n' -r .
969 $ hg log -G --template '{desc|firstline} {author} {date|isodate} \n' -r .
970 @ initial commit test 1970-01-01 00:00 +0000
970 @ initial commit test 1970-01-01 00:00 +0000
971
971
972 $ cd ..
972 $ cd ..
973
973
974 Demonstrate that the labels are correct in the merge conflict
974 Demonstrate that the labels are correct in the merge conflict
975 -------------------------------------------------------------
975 -------------------------------------------------------------
976 $ hg init labels
976 $ hg init labels
977 $ cd labels
977 $ cd labels
978 $ echo r0 > foo
978 $ echo r0 > foo
979 $ hg ci -qAm r0
979 $ hg ci -qAm r0
980 $ echo "this will be shelved" >> foo
980 $ echo "this will be shelved" >> foo
981 $ hg shelve -q
981 $ hg shelve -q
982 $ echo "this is in wdir, conflicts with shelve" >> foo
982 $ echo "this is in wdir, conflicts with shelve" >> foo
983 $ hg unshelve -q
983 $ hg unshelve -q
984 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
984 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
985 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
985 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
986 [240]
986 [240]
987 $ cat foo
987 $ cat foo
988 r0
988 r0
989 <<<<<<< working-copy: 0b2fcf2a90e9 - shelve: pending changes temporary commit
989 <<<<<<< working-copy: 0b2fcf2a90e9 - shelve: pending changes temporary commit
990 this is in wdir, conflicts with shelve
990 this is in wdir, conflicts with shelve
991 =======
991 =======
992 this will be shelved
992 this will be shelved
993 >>>>>>> shelved change: 9c072a2163db - shelve: changes to: r0
993 >>>>>>> shelved change: 9c072a2163db - shelve: changes to: r0
994 $ cd ..
994 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now