##// END OF EJS Templates
admin-command: add verify command...
Raphaël Gomès -
r51882:752c5a5b default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,341 b''
1 # admin/verify.py - better repository integrity checking for Mercurial
2 #
3 # Copyright 2023 Octobus <contact@octobus.net>
4 #
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.
7
8 import collections
9 import copy
10 import functools
11
12 from ..i18n import _
13 from .. import error, pycompat, registrar, requirements
14 from ..utils import stringutil
15
16
17 verify_table = {}
18 verify_alias_table = {}
19 check = registrar.verify_check(verify_table, verify_alias_table)
20
21
22 # Use this to declare options/aliases in the middle of the hierarchy.
23 # Checks like these are not run themselves and cannot have a body.
24 # For an example, see the `revlogs` check.
25 def noop_func(*args, **kwargs):
26 return
27
28
29 @check(b"working-copy.dirstate", alias=b"dirstate")
30 def check_dirstate(ui, repo, **options):
31 ui.status(_(b"checking dirstate\n"))
32
33 parent1, parent2 = repo.dirstate.parents()
34 m1 = repo[parent1].manifest()
35 m2 = repo[parent2].manifest()
36 errors = 0
37
38 is_narrow = requirements.NARROW_REQUIREMENT in repo.requirements
39 narrow_matcher = repo.narrowmatch() if is_narrow else None
40
41 for err in repo.dirstate.verify(m1, m2, narrow_matcher):
42 ui.warn(err[0] % err[1:])
43 errors += 1
44
45 return errors
46
47
48 # Tree of all checks and their associated function
49 pyramid = {}
50
51
52 def build_pyramid(table, full_pyramid):
53 """Create a pyramid of checks of the registered checks.
54 It is a name-based hierarchy that can be arbitrarily nested."""
55 for entry, func in sorted(table.items(), key=lambda x: x[0], reverse=True):
56 cursor = full_pyramid
57 levels = entry.split(b".")
58 for level in levels[:-1]:
59 current_node = cursor.setdefault(level, {})
60 cursor = current_node
61 if cursor.get(levels[-1]) is None:
62 cursor[levels[-1]] = (entry, func)
63 elif func is not noop_func:
64 m = b"intermediate checks need to use `verify.noop_func`"
65 raise error.ProgrammingError(m)
66
67
68 def find_checks(name, table=None, alias_table=None, full_pyramid=None):
69 """Find all checks for a given name and returns a dict of
70 (qualified_check_name, check_function)
71
72 # Examples
73
74 Using a full qualified name:
75 "working-copy.dirstate" -> {
76 "working-copy.dirstate": CF,
77 }
78
79 Using a *prefix* of a qualified name:
80 "store.revlogs" -> {
81 "store.revlogs.changelog": CF,
82 "store.revlogs.manifestlog": CF,
83 "store.revlogs.filelog": CF,
84 }
85
86 Using a defined alias:
87 "revlogs" -> {
88 "store.revlogs.changelog": CF,
89 "store.revlogs.manifestlog": CF,
90 "store.revlogs.filelog": CF,
91 }
92
93 Using something that is none of the above will be an error.
94 """
95 if table is None:
96 table = verify_table
97 if alias_table is None:
98 alias_table = verify_alias_table
99
100 if name == b"full":
101 return table
102 checks = {}
103
104 # is it a full name?
105 check = table.get(name)
106
107 if check is None:
108 # is it an alias?
109 qualified_name = alias_table.get(name)
110 if qualified_name is not None:
111 name = qualified_name
112 check = table.get(name)
113 else:
114 split = name.split(b".", 1)
115 if len(split) == 2:
116 # split[0] can be an alias
117 qualified_name = alias_table.get(split[0])
118 if qualified_name is not None:
119 name = b"%s.%s" % (qualified_name, split[1])
120 check = table.get(name)
121 else:
122 qualified_name = name
123
124 # Maybe it's a subtree in the check hierarchy that does not
125 # have an explicit alias.
126 levels = name.split(b".")
127 if full_pyramid is not None:
128 if not full_pyramid:
129 build_pyramid(table, full_pyramid)
130
131 pyramid.clear()
132 pyramid.update(full_pyramid.items())
133 else:
134 build_pyramid(table, pyramid)
135
136 subtree = pyramid
137 # Find subtree
138 for level in levels:
139 subtree = subtree.get(level)
140 if subtree is None:
141 hint = error.getsimilar(list(alias_table) + list(table), name)
142 hint = error.similarity_hint(hint)
143
144 raise error.InputError(_(b"unknown check %s" % name), hint=hint)
145
146 # Get all checks in that subtree
147 if isinstance(subtree, dict):
148 stack = list(subtree.items())
149 while stack:
150 current_name, entry = stack.pop()
151 if isinstance(entry, dict):
152 stack.extend(entry.items())
153 else:
154 # (qualified_name, func)
155 checks[entry[0]] = entry[1]
156 else:
157 checks[name] = check
158
159 return checks
160
161
162 def pass_options(
163 ui,
164 checks,
165 options,
166 table=None,
167 alias_table=None,
168 full_pyramid=None,
169 ):
170 """Given a dict of checks (fully qualified name to function), and a list
171 of options as given by the user, pass each option down to the right check
172 function."""
173 ui.debug(b"passing options to check functions\n")
174 to_modify = collections.defaultdict(dict)
175
176 if not checks:
177 raise error.Error(_(b"`checks` required"))
178
179 for option in sorted(options):
180 split = option.split(b":")
181 hint = _(
182 b"syntax is 'check:option=value', "
183 b"eg. revlogs.changelog:copies=yes"
184 )
185 option_error = error.InputError(
186 _(b"invalid option '%s'") % option, hint=hint
187 )
188 if len(split) != 2:
189 raise option_error
190
191 check_name, option_value = split
192 if not option_value:
193 raise option_error
194
195 split = option_value.split(b"=")
196 if len(split) != 2:
197 raise option_error
198
199 option_name, value = split
200 if not value:
201 raise option_error
202
203 path = b"%s:%s" % (check_name, option_name)
204
205 matching_checks = find_checks(
206 check_name,
207 table=table,
208 alias_table=alias_table,
209 full_pyramid=full_pyramid,
210 )
211 for name in matching_checks:
212 check = checks.get(name)
213 if check is None:
214 msg = _(b"specified option '%s' for unselected check '%s'\n")
215 raise error.InputError(msg % (name, option_name))
216
217 assert hasattr(check, "func") # help Pytype
218
219 if not hasattr(check.func, "options"):
220 raise error.InputError(
221 _(b"check '%s' has no option '%s'") % (name, option_name)
222 )
223
224 try:
225 matching_option = next(
226 (o for o in check.func.options if o[0] == option_name)
227 )
228 except StopIteration:
229 raise error.InputError(
230 _(b"check '%s' has no option '%s'") % (name, option_name)
231 )
232
233 # transform the argument from cli string to the expected Python type
234 _name, typ, _docstring = matching_option
235
236 as_typed = None
237 if isinstance(typ, bool):
238 as_bool = stringutil.parsebool(value)
239 if as_bool is None:
240 raise error.InputError(
241 _(b"'%s' is not a boolean ('%s')") % (path, value)
242 )
243 as_typed = as_bool
244 elif isinstance(typ, list):
245 as_list = stringutil.parselist(value)
246 if as_list is None:
247 raise error.InputError(
248 _(b"'%s' is not a list ('%s')") % (path, value)
249 )
250 as_typed = as_list
251 else:
252 raise error.ProgrammingError(b"unsupported type %s", type(typ))
253
254 if option_name in to_modify[name]:
255 raise error.InputError(
256 _(b"duplicated option '%s' for '%s'") % (option_name, name)
257 )
258 else:
259 assert as_typed is not None
260 to_modify[name][option_name] = as_typed
261
262 # Manage case where a check is set but without command line options
263 # it will later be set with default check options values
264 for name, f in checks.items():
265 if name not in to_modify:
266 to_modify[name] = {}
267
268 # Merge default options with command line options
269 for check_name, cmd_options in to_modify.items():
270 check = checks.get(check_name)
271 func = checks[check_name]
272 merged_options = {}
273 # help Pytype
274 assert check is not None
275 assert check.func is not None
276 assert hasattr(check.func, "options")
277
278 if check.func.options:
279 # copy the default value in case it's mutable (list, etc.)
280 merged_options = {
281 o[0]: copy.deepcopy(o[1]) for o in check.func.options
282 }
283 if cmd_options:
284 for k, v in cmd_options.items():
285 merged_options[k] = v
286 options = pycompat.strkwargs(merged_options)
287 checks[check_name] = functools.partial(func, **options)
288 ui.debug(b"merged options for '%s': '%r'\n" % (check_name, options))
289
290 return checks
291
292
293 def get_checks(
294 repo,
295 ui,
296 names=None,
297 options=None,
298 table=None,
299 alias_table=None,
300 full_pyramid=None,
301 ):
302 """Given a list of function names and optionally a list of
303 options, return matched checks with merged options (command line options
304 values take precedence on default ones)
305
306 It runs find checks, then resolve options and returns a dict of matched
307 functions with resolved options.
308 """
309 funcs = {}
310
311 if names is None:
312 names = []
313
314 if options is None:
315 options = []
316
317 # find checks
318 for name in names:
319 matched = find_checks(
320 name,
321 table=table,
322 alias_table=alias_table,
323 full_pyramid=full_pyramid,
324 )
325 matched_names = b", ".join(matched)
326 ui.debug(b"found checks '%s' for name '%s'\n" % (matched_names, name))
327 funcs.update(matched)
328
329 funcs = {n: functools.partial(f, ui, repo) for n, f in funcs.items()}
330
331 # resolve options
332 checks = pass_options(
333 ui,
334 funcs,
335 options,
336 table=table,
337 alias_table=alias_table,
338 full_pyramid=full_pyramid,
339 )
340
341 return checks
@@ -0,0 +1,399 b''
1 # Test admin commands
2
3 import functools
4 import unittest
5 from mercurial.i18n import _
6 from mercurial import error, ui as uimod
7 from mercurial import registrar
8 from mercurial.admin import verify
9
10
11 class TestAdminVerifyFindChecks(unittest.TestCase):
12 def __init__(self, *args, **kwargs):
13 super().__init__(*args, **kwargs)
14 self.ui = uimod.ui.load()
15 self.repo = b"fake-repo"
16
17 def cleanup_table(self):
18 self.table = {}
19 self.alias_table = {}
20 self.pyramid = {}
21
22 self.addCleanup(cleanup_table, self)
23
24 def setUp(self):
25 self.table = {}
26 self.alias_table = {}
27 self.pyramid = {}
28 check = registrar.verify_check(self.table, self.alias_table)
29
30 # mock some fake check method for tests purpose
31 @check(
32 b"test.dummy",
33 alias=b"dummy",
34 options=[],
35 )
36 def check_dummy(ui, repo, **options):
37 return options
38
39 @check(
40 b"test.fake",
41 alias=b"fake",
42 options=[
43 (b'a', False, _(b'a boolean value (default: False)')),
44 (b'b', True, _(b'a boolean value (default: True)')),
45 (b'c', [], _(b'a list')),
46 ],
47 )
48 def check_fake(ui, repo, **options):
49 return options
50
51 # alias in the middle of a hierarchy
52 check(
53 b"test.noop",
54 alias=b"noop",
55 options=[],
56 )(verify.noop_func)
57
58 @check(
59 b"test.noop.deeper",
60 alias=b"deeper",
61 options=[
62 (b'y', True, _(b'a boolean value (default: True)')),
63 (b'z', [], _(b'a list')),
64 ],
65 )
66 def check_noop_deeper(ui, repo, **options):
67 return options
68
69 # args wrapper utilities
70 def find_checks(self, name):
71 return verify.find_checks(
72 name=name,
73 table=self.table,
74 alias_table=self.alias_table,
75 full_pyramid=self.pyramid,
76 )
77
78 def pass_options(self, checks, options):
79 return verify.pass_options(
80 self.ui,
81 checks,
82 options,
83 table=self.table,
84 alias_table=self.alias_table,
85 full_pyramid=self.pyramid,
86 )
87
88 def get_checks(self, names, options):
89 return verify.get_checks(
90 self.repo,
91 self.ui,
92 names=names,
93 options=options,
94 table=self.table,
95 alias_table=self.alias_table,
96 full_pyramid=self.pyramid,
97 )
98
99 # tests find_checks
100 def test_find_checks_empty_name(self):
101 with self.assertRaises(error.InputError):
102 self.find_checks(name=b"")
103
104 def test_find_checks_wrong_name(self):
105 with self.assertRaises(error.InputError):
106 self.find_checks(name=b"unknown")
107
108 def test_find_checks_dummy(self):
109 name = b"test.dummy"
110 found = self.find_checks(name=name)
111 self.assertEqual(len(found), 1)
112 self.assertIn(name, found)
113 meth = found[name]
114 self.assertTrue(callable(meth))
115 self.assertEqual(len(meth.options), 0)
116
117 def test_find_checks_fake(self):
118 name = b"test.fake"
119 found = self.find_checks(name=name)
120 self.assertEqual(len(found), 1)
121 self.assertIn(name, found)
122 meth = found[name]
123 self.assertTrue(callable(meth))
124 self.assertEqual(len(meth.options), 3)
125
126 def test_find_checks_noop(self):
127 name = b"test.noop.deeper"
128 found = self.find_checks(name=name)
129 self.assertEqual(len(found), 1)
130 self.assertIn(name, found)
131 meth = found[name]
132 self.assertTrue(callable(meth))
133 self.assertEqual(len(meth.options), 2)
134
135 def test_find_checks_from_aliases(self):
136 found = self.find_checks(name=b"dummy")
137 self.assertEqual(len(found), 1)
138 self.assertIn(b"test.dummy", found)
139
140 found = self.find_checks(name=b"fake")
141 self.assertEqual(len(found), 1)
142 self.assertIn(b"test.fake", found)
143
144 found = self.find_checks(name=b"deeper")
145 self.assertEqual(len(found), 1)
146 self.assertIn(b"test.noop.deeper", found)
147
148 def test_find_checks_from_root(self):
149 found = self.find_checks(name=b"test")
150 self.assertEqual(len(found), 3)
151 self.assertIn(b"test.dummy", found)
152 self.assertIn(b"test.fake", found)
153 self.assertIn(b"test.noop.deeper", found)
154
155 def test_find_checks_from_intermediate(self):
156 found = self.find_checks(name=b"test.noop")
157 self.assertEqual(len(found), 1)
158 self.assertIn(b"test.noop.deeper", found)
159
160 def test_find_checks_from_parent_dot_name(self):
161 found = self.find_checks(name=b"noop.deeper")
162 self.assertEqual(len(found), 1)
163 self.assertIn(b"test.noop.deeper", found)
164
165 # tests pass_options
166 def test_pass_options_no_checks_no_options(self):
167 checks = {}
168 options = []
169
170 with self.assertRaises(error.Error):
171 self.pass_options(checks=checks, options=options)
172
173 def test_pass_options_fake_empty_options(self):
174 checks = self.find_checks(name=b"test.fake")
175 funcs = {
176 n: functools.partial(f, self.ui, self.repo)
177 for n, f in checks.items()
178 }
179 options = []
180 # should end with default options
181 expected_options = {"a": False, "b": True, "c": []}
182 func = self.pass_options(checks=funcs, options=options)
183
184 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
185
186 def test_pass_options_fake_non_existing_options(self):
187 checks = self.find_checks(name=b"test.fake")
188 funcs = {
189 n: functools.partial(f, self.ui, self.repo)
190 for n, f in checks.items()
191 }
192
193 with self.assertRaises(error.InputError):
194 options = [b"test.fake:boom=yes"]
195 self.pass_options(checks=funcs, options=options)
196
197 def test_pass_options_fake_unrelated_options(self):
198 checks = self.find_checks(name=b"test.fake")
199 funcs = {
200 n: functools.partial(f, self.ui, self.repo)
201 for n, f in checks.items()
202 }
203 options = [b"test.noop.deeper:y=yes"]
204
205 with self.assertRaises(error.InputError):
206 self.pass_options(checks=funcs, options=options)
207
208 def test_pass_options_fake_set_option(self):
209 checks = self.find_checks(name=b"test.fake")
210 funcs = {
211 n: functools.partial(f, self.ui, self.repo)
212 for n, f in checks.items()
213 }
214 options = [b"test.fake:a=yes"]
215 expected_options = {"a": True, "b": True, "c": []}
216 func = self.pass_options(checks=funcs, options=options)
217
218 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
219
220 def test_pass_options_fake_set_option_with_alias(self):
221 checks = self.find_checks(name=b"test.fake")
222 funcs = {
223 n: functools.partial(f, self.ui, self.repo)
224 for n, f in checks.items()
225 }
226 options = [b"fake:a=yes"]
227 expected_options = {"a": True, "b": True, "c": []}
228 func = self.pass_options(checks=funcs, options=options)
229
230 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
231
232 def test_pass_options_fake_set_all_option(self):
233 checks = self.find_checks(name=b"test.fake")
234 funcs = {
235 n: functools.partial(f, self.ui, self.repo)
236 for n, f in checks.items()
237 }
238 options = [b"test.fake:a=yes", b"test.fake:b=no", b"test.fake:c=0,1,2"]
239 expected_options = {"a": True, "b": False, "c": [b"0", b"1", b"2"]}
240 func = self.pass_options(checks=funcs, options=options)
241
242 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
243
244 def test_pass_options_fake_set_all_option_plus_unexisting(self):
245 checks = self.find_checks(name=b"test.fake")
246 funcs = {
247 n: functools.partial(f, self.ui, self.repo)
248 for n, f in checks.items()
249 }
250 options = [
251 b"test.fake:a=yes",
252 b"test.fake:b=no",
253 b"test.fake:c=0,1,2",
254 b"test.fake:d=0",
255 ]
256
257 with self.assertRaises(error.InputError):
258 self.pass_options(checks=funcs, options=options)
259
260 def test_pass_options_fake_duplicate_option(self):
261 checks = self.find_checks(name=b"test.fake")
262 funcs = {
263 n: functools.partial(f, self.ui, self.repo)
264 for n, f in checks.items()
265 }
266 options = [
267 b"test.fake:a=yes",
268 b"test.fake:a=no",
269 ]
270
271 with self.assertRaises(error.InputError):
272 self.pass_options(checks=funcs, options=options)
273
274 def test_pass_options_fake_set_malformed_option(self):
275 checks = self.find_checks(name=b"test.fake")
276 funcs = {
277 n: functools.partial(f, self.ui, self.repo)
278 for n, f in checks.items()
279 }
280 options = [
281 b"test.fake:ayes",
282 b"test.fake:b==no",
283 b"test.fake=",
284 b"test.fake:",
285 b"test.fa=ke:d=0",
286 b"test.fa=ke:d=0",
287 ]
288
289 for opt in options:
290 with self.assertRaises(error.InputError):
291 self.pass_options(checks=funcs, options=[opt])
292
293 def test_pass_options_types(self):
294 checks = self.find_checks(name=b"test.fake")
295 funcs = {
296 n: functools.partial(f, self.ui, self.repo)
297 for n, f in checks.items()
298 }
299 # boolean, yes/no
300 options = [b"test.fake:a=yes", b"test.fake:b=no"]
301 expected_options = {"a": True, "b": False, "c": []}
302 func = self.pass_options(checks=funcs, options=options)
303
304 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
305
306 # boolean, 0/1
307 options = [b"test.fake:a=1", b"test.fake:b=0"]
308 expected_options = {"a": True, "b": False, "c": []}
309 func = self.pass_options(checks=funcs, options=options)
310
311 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
312
313 # boolean, true/false
314 options = [b"test.fake:a=true", b"test.fake:b=false"]
315 expected_options = {"a": True, "b": False, "c": []}
316 func = self.pass_options(checks=funcs, options=options)
317
318 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
319
320 # boolean, wrong type
321 options = [b"test.fake:a=si"]
322 with self.assertRaises(error.InputError):
323 self.pass_options(checks=funcs, options=options)
324
325 # lists
326 options = [b"test.fake:c=0,1,2"]
327 expected_options = {"a": False, "b": True, "c": [b"0", b"1", b"2"]}
328 func = self.pass_options(checks=funcs, options=options)
329
330 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
331
332 options = [b"test.fake:c=x,y,z"]
333 expected_options = {"a": False, "b": True, "c": [b"x", b"y", b"z"]}
334 func = self.pass_options(checks=funcs, options=options)
335
336 self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
337
338 # tests get_checks
339 def test_get_checks_fake(self):
340 funcs = self.get_checks(
341 names=[b"test.fake"], options=[b"test.fake:a=yes"]
342 )
343 options = funcs.get(b"test.fake").keywords
344 expected_options = {"a": True, "b": True, "c": []}
345 self.assertDictEqual(options, expected_options)
346
347 def test_get_checks_multiple_mixed_with_defaults(self):
348 funcs = self.get_checks(
349 names=[b"test.fake", b"test.noop.deeper", b"test.dummy"],
350 options=[
351 b"test.noop.deeper:y=no",
352 b"test.noop.deeper:z=-1,0,1",
353 ],
354 )
355 options = funcs.get(b"test.fake").keywords
356 expected_options = {"a": False, "b": True, "c": []}
357 self.assertDictEqual(options, expected_options)
358
359 options = funcs.get(b"test.noop.deeper").keywords
360 expected_options = {"y": False, "z": [b"-1", b"0", b"1"]}
361 self.assertDictEqual(options, expected_options)
362
363 options = funcs.get(b"test.dummy").keywords
364 expected_options = {}
365 self.assertDictEqual(options, expected_options)
366
367 def test_broken_pyramid(self):
368 """Check that we detect pyramids that can't resolve"""
369 table = {}
370 alias_table = {}
371 pyramid = {}
372 check = registrar.verify_check(table, alias_table)
373
374 # Create two checks that clash
375 @check(b"test.wrong.intermediate")
376 def check_dummy(ui, repo, **options):
377 return options
378
379 @check(b"test.wrong.intermediate.thing")
380 def check_fake(ui, repo, **options):
381 return options
382
383 with self.assertRaises(error.ProgrammingError) as e:
384 verify.get_checks(
385 self.repo,
386 self.ui,
387 names=[b"test.wrong.intermediate"],
388 options=[],
389 table=table,
390 alias_table=alias_table,
391 full_pyramid=pyramid,
392 )
393 assert "`verify.noop_func`" in str(e.exception), str(e.exception)
394
395
396 if __name__ == '__main__':
397 import silenttestrunner
398
399 silenttestrunner.main(__name__)
@@ -0,0 +1,49 b''
1 Test admin::verify
2
3 $ hg init admin-verify
4 $ cd admin-verify
5
6 Test normal output
7
8 $ hg admin::verify -c dirstate
9 running 1 checks
10 running working-copy.dirstate
11 checking dirstate
12
13 Quiet works
14
15 $ hg admin::verify -c dirstate --quiet
16
17 Test no check no options
18
19 $ hg admin::verify
20 abort: `checks` required
21 [255]
22
23 Test single check without options
24
25 $ hg admin::verify -c working-copy.dirstate
26 running 1 checks
27 running working-copy.dirstate
28 checking dirstate
29
30 Test single check (alias) without options
31
32 $ hg admin::verify -c dirstate
33 running 1 checks
34 running working-copy.dirstate
35 checking dirstate
36
37 Test wrong check name without options
38
39 $ hg admin::verify -c working-copy.dir
40 abort: unknown check working-copy.dir
41 (did you mean working-copy.dirstate?)
42 [10]
43
44 Test wrong alias without options
45
46 $ hg admin::verify -c dir
47 abort: unknown check dir
48 [10]
49
@@ -1,11 +1,49 b''
1 1 # admin_commands.py - command processing for admin* commands
2 2 #
3 3 # Copyright 2022 Mercurial Developers
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 from . import registrar
8 from .i18n import _
9 from .admin import verify
10 from . import error, registrar, transaction
11
9 12
10 13 table = {}
11 14 command = registrar.command(table)
15
16
17 @command(
18 b'admin::verify',
19 [
20 (b'c', b'check', [], _(b'add a check'), _(b'CHECK')),
21 (b'o', b'option', [], _(b'pass an option to a check'), _(b'OPTION')),
22 ],
23 helpcategory=command.CATEGORY_MAINTENANCE,
24 )
25 def admin_verify(ui, repo, **opts):
26 """verify the integrity of the repository
27
28 Alternative UI to `hg verify` with a lot more control over the
29 verification process and better error reporting.
30 """
31
32 if not repo.url().startswith(b'file:'):
33 raise error.Abort(_(b"cannot verify bundle or remote repos"))
34
35 if transaction.has_abandoned_transaction(repo):
36 ui.warn(_(b"abandoned transaction found - run hg recover\n"))
37
38 checks = opts.get("check", [])
39 options = opts.get("option", [])
40
41 funcs = verify.get_checks(repo, ui, names=checks, options=options)
42
43 ui.status(_(b"running %d checks\n") % len(funcs))
44 # Done in two times so the execution is separated from the resolving step
45 for name, func in sorted(funcs.items(), key=lambda x: x[0]):
46 ui.status(_(b"running %s\n") % name)
47 errors = func()
48 if errors:
49 ui.warn(_(b"found %d errors\n") % len(errors))
@@ -1,8049 +1,8052 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8
9 9 import os
10 10 import re
11 11 import sys
12 12
13 13 from .i18n import _
14 14 from .node import (
15 15 hex,
16 16 nullid,
17 17 nullrev,
18 18 short,
19 19 wdirrev,
20 20 )
21 21 from . import (
22 22 admin_commands as admin_commands_mod,
23 23 archival,
24 24 bookmarks,
25 25 bundle2,
26 26 bundlecaches,
27 27 changegroup,
28 28 cmdutil,
29 29 copies,
30 30 debugcommands as debugcommandsmod,
31 31 destutil,
32 32 discovery,
33 33 encoding,
34 34 error,
35 35 exchange,
36 36 extensions,
37 37 filemerge,
38 38 formatter,
39 39 graphmod,
40 40 grep as grepmod,
41 41 hbisect,
42 42 help,
43 43 hg,
44 44 logcmdutil,
45 45 merge as mergemod,
46 46 mergestate as mergestatemod,
47 47 narrowspec,
48 48 obsolete,
49 49 obsutil,
50 50 patch,
51 51 phases,
52 52 pycompat,
53 53 rcutil,
54 54 registrar,
55 55 requirements,
56 56 revsetlang,
57 57 rewriteutil,
58 58 scmutil,
59 59 server,
60 60 shelve as shelvemod,
61 61 state as statemod,
62 62 streamclone,
63 63 tags as tagsmod,
64 64 ui as uimod,
65 65 util,
66 66 verify as verifymod,
67 67 vfs as vfsmod,
68 68 wireprotoserver,
69 69 )
70 70 from .utils import (
71 71 dateutil,
72 72 procutil,
73 73 stringutil,
74 74 urlutil,
75 75 )
76 76
77 77 table = {}
78 78 table.update(debugcommandsmod.command._table)
79 79 table.update(admin_commands_mod.command._table)
80 80
81 81 command = registrar.command(table)
82 82 INTENT_READONLY = registrar.INTENT_READONLY
83 83
84 84 # common command options
85 85
86 86 globalopts = [
87 87 (
88 88 b'R',
89 89 b'repository',
90 90 b'',
91 91 _(b'repository root directory or name of overlay bundle file'),
92 92 _(b'REPO'),
93 93 ),
94 94 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
95 95 (
96 96 b'y',
97 97 b'noninteractive',
98 98 None,
99 99 _(
100 100 b'do not prompt, automatically pick the first choice for all prompts'
101 101 ),
102 102 ),
103 103 (b'q', b'quiet', None, _(b'suppress output')),
104 104 (b'v', b'verbose', None, _(b'enable additional output')),
105 105 (
106 106 b'',
107 107 b'color',
108 108 b'',
109 109 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
110 110 # and should not be translated
111 111 _(b"when to colorize (boolean, always, auto, never, or debug)"),
112 112 _(b'TYPE'),
113 113 ),
114 114 (
115 115 b'',
116 116 b'config',
117 117 [],
118 118 _(b'set/override config option (use \'section.name=value\')'),
119 119 _(b'CONFIG'),
120 120 ),
121 121 (b'', b'debug', None, _(b'enable debugging output')),
122 122 (b'', b'debugger', None, _(b'start debugger')),
123 123 (
124 124 b'',
125 125 b'encoding',
126 126 encoding.encoding,
127 127 _(b'set the charset encoding'),
128 128 _(b'ENCODE'),
129 129 ),
130 130 (
131 131 b'',
132 132 b'encodingmode',
133 133 encoding.encodingmode,
134 134 _(b'set the charset encoding mode'),
135 135 _(b'MODE'),
136 136 ),
137 137 (b'', b'traceback', None, _(b'always print a traceback on exception')),
138 138 (b'', b'time', None, _(b'time how long the command takes')),
139 139 (b'', b'profile', None, _(b'print command execution profile')),
140 140 (b'', b'version', None, _(b'output version information and exit')),
141 141 (b'h', b'help', None, _(b'display help and exit')),
142 142 (b'', b'hidden', False, _(b'consider hidden changesets')),
143 143 (
144 144 b'',
145 145 b'pager',
146 146 b'auto',
147 147 _(b"when to paginate (boolean, always, auto, or never)"),
148 148 _(b'TYPE'),
149 149 ),
150 150 ]
151 151
152 152 dryrunopts = cmdutil.dryrunopts
153 153 remoteopts = cmdutil.remoteopts
154 154 walkopts = cmdutil.walkopts
155 155 commitopts = cmdutil.commitopts
156 156 commitopts2 = cmdutil.commitopts2
157 157 commitopts3 = cmdutil.commitopts3
158 158 formatteropts = cmdutil.formatteropts
159 159 templateopts = cmdutil.templateopts
160 160 logopts = cmdutil.logopts
161 161 diffopts = cmdutil.diffopts
162 162 diffwsopts = cmdutil.diffwsopts
163 163 diffopts2 = cmdutil.diffopts2
164 164 mergetoolopts = cmdutil.mergetoolopts
165 165 similarityopts = cmdutil.similarityopts
166 166 subrepoopts = cmdutil.subrepoopts
167 167 debugrevlogopts = cmdutil.debugrevlogopts
168 168
169 169 # Commands start here, listed alphabetically
170 170
171 171
172 172 @command(
173 173 b'abort',
174 174 dryrunopts,
175 175 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
176 176 helpbasic=True,
177 177 )
178 178 def abort(ui, repo, **opts):
179 179 """abort an unfinished operation (EXPERIMENTAL)
180 180
181 181 Aborts a multistep operation like graft, histedit, rebase, merge,
182 182 and unshelve if they are in an unfinished state.
183 183
184 184 use --dry-run/-n to dry run the command.
185 185 """
186 186 dryrun = opts.get('dry_run')
187 187 abortstate = cmdutil.getunfinishedstate(repo)
188 188 if not abortstate:
189 189 raise error.StateError(_(b'no operation in progress'))
190 190 if not abortstate.abortfunc:
191 191 raise error.InputError(
192 192 (
193 193 _(b"%s in progress but does not support 'hg abort'")
194 194 % (abortstate._opname)
195 195 ),
196 196 hint=abortstate.hint(),
197 197 )
198 198 if dryrun:
199 199 ui.status(
200 200 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
201 201 )
202 202 return
203 203 return abortstate.abortfunc(ui, repo)
204 204
205 205
206 206 @command(
207 207 b'add',
208 208 walkopts + subrepoopts + dryrunopts,
209 209 _(b'[OPTION]... [FILE]...'),
210 210 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
211 211 helpbasic=True,
212 212 inferrepo=True,
213 213 )
214 214 def add(ui, repo, *pats, **opts):
215 215 """add the specified files on the next commit
216 216
217 217 Schedule files to be version controlled and added to the
218 218 repository.
219 219
220 220 The files will be added to the repository at the next commit. To
221 221 undo an add before that, see :hg:`forget`.
222 222
223 223 If no names are given, add all files to the repository (except
224 224 files matching ``.hgignore``).
225 225
226 226 .. container:: verbose
227 227
228 228 Examples:
229 229
230 230 - New (unknown) files are added
231 231 automatically by :hg:`add`::
232 232
233 233 $ ls
234 234 foo.c
235 235 $ hg status
236 236 ? foo.c
237 237 $ hg add
238 238 adding foo.c
239 239 $ hg status
240 240 A foo.c
241 241
242 242 - Specific files to be added can be specified::
243 243
244 244 $ ls
245 245 bar.c foo.c
246 246 $ hg status
247 247 ? bar.c
248 248 ? foo.c
249 249 $ hg add bar.c
250 250 $ hg status
251 251 A bar.c
252 252 ? foo.c
253 253
254 254 Returns 0 if all files are successfully added.
255 255 """
256 256
257 257 with repo.wlock(), repo.dirstate.changing_files(repo):
258 258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
260 260 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
261 261 return rejected and 1 or 0
262 262
263 263
264 264 @command(
265 265 b'addremove',
266 266 similarityopts + subrepoopts + walkopts + dryrunopts,
267 267 _(b'[OPTION]... [FILE]...'),
268 268 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
269 269 inferrepo=True,
270 270 )
271 271 def addremove(ui, repo, *pats, **opts):
272 272 """add all new files, delete all missing files
273 273
274 274 Add all new files and remove all missing files from the
275 275 repository.
276 276
277 277 Unless names are given, new files are ignored if they match any of
278 278 the patterns in ``.hgignore``. As with add, these changes take
279 279 effect at the next commit.
280 280
281 281 Use the -s/--similarity option to detect renamed files. This
282 282 option takes a percentage between 0 (disabled) and 100 (files must
283 283 be identical) as its parameter. With a parameter greater than 0,
284 284 this compares every removed file with every added file and records
285 285 those similar enough as renames. Detecting renamed files this way
286 286 can be expensive. After using this option, :hg:`status -C` can be
287 287 used to check which files were identified as moved or renamed. If
288 288 not specified, -s/--similarity defaults to 100 and only renames of
289 289 identical files are detected.
290 290
291 291 .. container:: verbose
292 292
293 293 Examples:
294 294
295 295 - A number of files (bar.c and foo.c) are new,
296 296 while foobar.c has been removed (without using :hg:`remove`)
297 297 from the repository::
298 298
299 299 $ ls
300 300 bar.c foo.c
301 301 $ hg status
302 302 ! foobar.c
303 303 ? bar.c
304 304 ? foo.c
305 305 $ hg addremove
306 306 adding bar.c
307 307 adding foo.c
308 308 removing foobar.c
309 309 $ hg status
310 310 A bar.c
311 311 A foo.c
312 312 R foobar.c
313 313
314 314 - A file foobar.c was moved to foo.c without using :hg:`rename`.
315 315 Afterwards, it was edited slightly::
316 316
317 317 $ ls
318 318 foo.c
319 319 $ hg status
320 320 ! foobar.c
321 321 ? foo.c
322 322 $ hg addremove --similarity 90
323 323 removing foobar.c
324 324 adding foo.c
325 325 recording removal of foobar.c as rename to foo.c (94% similar)
326 326 $ hg status -C
327 327 A foo.c
328 328 foobar.c
329 329 R foobar.c
330 330
331 331 Returns 0 if all files are successfully added.
332 332 """
333 333 opts = pycompat.byteskwargs(opts)
334 334 if not opts.get(b'similarity'):
335 335 opts[b'similarity'] = b'100'
336 336 with repo.wlock(), repo.dirstate.changing_files(repo):
337 337 matcher = scmutil.match(repo[None], pats, opts)
338 338 relative = scmutil.anypats(pats, opts)
339 339 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
340 340 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
341 341
342 342
343 343 @command(
344 344 b'annotate|blame',
345 345 [
346 346 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
347 347 (
348 348 b'',
349 349 b'follow',
350 350 None,
351 351 _(b'follow copies/renames and list the filename (DEPRECATED)'),
352 352 ),
353 353 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
354 354 (b'a', b'text', None, _(b'treat all files as text')),
355 355 (b'u', b'user', None, _(b'list the author (long with -v)')),
356 356 (b'f', b'file', None, _(b'list the filename')),
357 357 (b'd', b'date', None, _(b'list the date (short with -q)')),
358 358 (b'n', b'number', None, _(b'list the revision number (default)')),
359 359 (b'c', b'changeset', None, _(b'list the changeset')),
360 360 (
361 361 b'l',
362 362 b'line-number',
363 363 None,
364 364 _(b'show line number at the first appearance'),
365 365 ),
366 366 (
367 367 b'',
368 368 b'skip',
369 369 [],
370 370 _(b'revset to not display (EXPERIMENTAL)'),
371 371 _(b'REV'),
372 372 ),
373 373 ]
374 374 + diffwsopts
375 375 + walkopts
376 376 + formatteropts,
377 377 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
378 378 helpcategory=command.CATEGORY_FILE_CONTENTS,
379 379 helpbasic=True,
380 380 inferrepo=True,
381 381 )
382 382 def annotate(ui, repo, *pats, **opts):
383 383 """show changeset information by line for each file
384 384
385 385 List changes in files, showing the revision id responsible for
386 386 each line.
387 387
388 388 This command is useful for discovering when a change was made and
389 389 by whom.
390 390
391 391 If you include --file, --user, or --date, the revision number is
392 392 suppressed unless you also include --number.
393 393
394 394 Without the -a/--text option, annotate will avoid processing files
395 395 it detects as binary. With -a, annotate will annotate the file
396 396 anyway, although the results will probably be neither useful
397 397 nor desirable.
398 398
399 399 .. container:: verbose
400 400
401 401 Template:
402 402
403 403 The following keywords are supported in addition to the common template
404 404 keywords and functions. See also :hg:`help templates`.
405 405
406 406 :lines: List of lines with annotation data.
407 407 :path: String. Repository-absolute path of the specified file.
408 408
409 409 And each entry of ``{lines}`` provides the following sub-keywords in
410 410 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
411 411
412 412 :line: String. Line content.
413 413 :lineno: Integer. Line number at that revision.
414 414 :path: String. Repository-absolute path of the file at that revision.
415 415
416 416 See :hg:`help templates.operators` for the list expansion syntax.
417 417
418 418 Returns 0 on success.
419 419 """
420 420 opts = pycompat.byteskwargs(opts)
421 421 if not pats:
422 422 raise error.InputError(
423 423 _(b'at least one filename or pattern is required')
424 424 )
425 425
426 426 if opts.get(b'follow'):
427 427 # --follow is deprecated and now just an alias for -f/--file
428 428 # to mimic the behavior of Mercurial before version 1.5
429 429 opts[b'file'] = True
430 430
431 431 if (
432 432 not opts.get(b'user')
433 433 and not opts.get(b'changeset')
434 434 and not opts.get(b'date')
435 435 and not opts.get(b'file')
436 436 ):
437 437 opts[b'number'] = True
438 438
439 439 linenumber = opts.get(b'line_number') is not None
440 440 if (
441 441 linenumber
442 442 and (not opts.get(b'changeset'))
443 443 and (not opts.get(b'number'))
444 444 ):
445 445 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
446 446
447 447 rev = opts.get(b'rev')
448 448 if rev:
449 449 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
450 450 ctx = logcmdutil.revsingle(repo, rev)
451 451
452 452 ui.pager(b'annotate')
453 453 rootfm = ui.formatter(b'annotate', opts)
454 454 if ui.debugflag:
455 455 shorthex = pycompat.identity
456 456 else:
457 457
458 458 def shorthex(h):
459 459 return h[:12]
460 460
461 461 if ui.quiet:
462 462 datefunc = dateutil.shortdate
463 463 else:
464 464 datefunc = dateutil.datestr
465 465 if ctx.rev() is None:
466 466 if opts.get(b'changeset'):
467 467 # omit "+" suffix which is appended to node hex
468 468 def formatrev(rev):
469 469 if rev == wdirrev:
470 470 return b'%d' % ctx.p1().rev()
471 471 else:
472 472 return b'%d' % rev
473 473
474 474 else:
475 475
476 476 def formatrev(rev):
477 477 if rev == wdirrev:
478 478 return b'%d+' % ctx.p1().rev()
479 479 else:
480 480 return b'%d ' % rev
481 481
482 482 def formathex(h):
483 483 if h == repo.nodeconstants.wdirhex:
484 484 return b'%s+' % shorthex(hex(ctx.p1().node()))
485 485 else:
486 486 return b'%s ' % shorthex(h)
487 487
488 488 else:
489 489 formatrev = b'%d'.__mod__
490 490 formathex = shorthex
491 491
492 492 opmap = [
493 493 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
494 494 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
495 495 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
496 496 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
497 497 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
498 498 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
499 499 ]
500 500 opnamemap = {
501 501 b'rev': b'number',
502 502 b'node': b'changeset',
503 503 b'path': b'file',
504 504 b'lineno': b'line_number',
505 505 }
506 506
507 507 if rootfm.isplain():
508 508
509 509 def makefunc(get, fmt):
510 510 return lambda x: fmt(get(x))
511 511
512 512 else:
513 513
514 514 def makefunc(get, fmt):
515 515 return get
516 516
517 517 datahint = rootfm.datahint()
518 518 funcmap = [
519 519 (makefunc(get, fmt), sep)
520 520 for fn, sep, get, fmt in opmap
521 521 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
522 522 ]
523 523 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
524 524 fields = b' '.join(
525 525 fn
526 526 for fn, sep, get, fmt in opmap
527 527 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
528 528 )
529 529
530 530 def bad(x, y):
531 531 raise error.InputError(b"%s: %s" % (x, y))
532 532
533 533 m = scmutil.match(ctx, pats, opts, badfn=bad)
534 534
535 535 follow = not opts.get(b'no_follow')
536 536 diffopts = patch.difffeatureopts(
537 537 ui, opts, section=b'annotate', whitespace=True
538 538 )
539 539 skiprevs = opts.get(b'skip')
540 540 if skiprevs:
541 541 skiprevs = logcmdutil.revrange(repo, skiprevs)
542 542
543 543 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
544 544 for abs in ctx.walk(m):
545 545 fctx = ctx[abs]
546 546 rootfm.startitem()
547 547 rootfm.data(path=abs)
548 548 if not opts.get(b'text') and fctx.isbinary():
549 549 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
550 550 continue
551 551
552 552 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
553 553 lines = fctx.annotate(
554 554 follow=follow, skiprevs=skiprevs, diffopts=diffopts
555 555 )
556 556 if not lines:
557 557 fm.end()
558 558 continue
559 559 formats = []
560 560 pieces = []
561 561
562 562 for f, sep in funcmap:
563 563 l = [f(n) for n in lines]
564 564 if fm.isplain():
565 565 sizes = [encoding.colwidth(x) for x in l]
566 566 ml = max(sizes)
567 567 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
568 568 else:
569 569 formats.append([b'%s'] * len(l))
570 570 pieces.append(l)
571 571
572 572 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
573 573 fm.startitem()
574 574 fm.context(fctx=n.fctx)
575 575 fm.write(fields, b"".join(f), *p)
576 576 if n.skip:
577 577 fmt = b"* %s"
578 578 else:
579 579 fmt = b": %s"
580 580 fm.write(b'line', fmt, n.text)
581 581
582 582 if not lines[-1].text.endswith(b'\n'):
583 583 fm.plain(b'\n')
584 584 fm.end()
585 585
586 586 rootfm.end()
587 587
588 588
589 589 @command(
590 590 b'archive',
591 591 [
592 592 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
593 593 (
594 594 b'p',
595 595 b'prefix',
596 596 b'',
597 597 _(b'directory prefix for files in archive'),
598 598 _(b'PREFIX'),
599 599 ),
600 600 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
601 601 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
602 602 ]
603 603 + subrepoopts
604 604 + walkopts,
605 605 _(b'[OPTION]... DEST'),
606 606 helpcategory=command.CATEGORY_IMPORT_EXPORT,
607 607 )
608 608 def archive(ui, repo, dest, **opts):
609 609 """create an unversioned archive of a repository revision
610 610
611 611 By default, the revision used is the parent of the working
612 612 directory; use -r/--rev to specify a different revision.
613 613
614 614 The archive type is automatically detected based on file
615 615 extension (to override, use -t/--type).
616 616
617 617 .. container:: verbose
618 618
619 619 Examples:
620 620
621 621 - create a zip file containing the 1.0 release::
622 622
623 623 hg archive -r 1.0 project-1.0.zip
624 624
625 625 - create a tarball excluding .hg files::
626 626
627 627 hg archive project.tar.gz -X ".hg*"
628 628
629 629 Valid types are:
630 630
631 631 :``files``: a directory full of files (default)
632 632 :``tar``: tar archive, uncompressed
633 633 :``tbz2``: tar archive, compressed using bzip2
634 634 :``tgz``: tar archive, compressed using gzip
635 635 :``txz``: tar archive, compressed using lzma (only in Python 3)
636 636 :``uzip``: zip archive, uncompressed
637 637 :``zip``: zip archive, compressed using deflate
638 638
639 639 The exact name of the destination archive or directory is given
640 640 using a format string; see :hg:`help export` for details.
641 641
642 642 Each member added to an archive file has a directory prefix
643 643 prepended. Use -p/--prefix to specify a format string for the
644 644 prefix. The default is the basename of the archive, with suffixes
645 645 removed.
646 646
647 647 Returns 0 on success.
648 648 """
649 649
650 650 rev = opts.get('rev')
651 651 if rev:
652 652 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
653 653 ctx = logcmdutil.revsingle(repo, rev)
654 654 if not ctx:
655 655 raise error.InputError(
656 656 _(b'no working directory: please specify a revision')
657 657 )
658 658 node = ctx.node()
659 659 dest = cmdutil.makefilename(ctx, dest)
660 660 if os.path.realpath(dest) == repo.root:
661 661 raise error.InputError(_(b'repository root cannot be destination'))
662 662
663 663 kind = opts.get('type') or archival.guesskind(dest) or b'files'
664 664 prefix = opts.get('prefix')
665 665
666 666 if dest == b'-':
667 667 if kind == b'files':
668 668 raise error.InputError(_(b'cannot archive plain files to stdout'))
669 669 dest = cmdutil.makefileobj(ctx, dest)
670 670 if not prefix:
671 671 prefix = os.path.basename(repo.root) + b'-%h'
672 672
673 673 prefix = cmdutil.makefilename(ctx, prefix)
674 674 match = scmutil.match(ctx, [], pycompat.byteskwargs(opts))
675 675 archival.archive(
676 676 repo,
677 677 dest,
678 678 node,
679 679 kind,
680 680 not opts.get('no_decode'),
681 681 match,
682 682 prefix,
683 683 subrepos=opts.get('subrepos'),
684 684 )
685 685
686 686
687 687 @command(
688 688 b'backout',
689 689 [
690 690 (
691 691 b'',
692 692 b'merge',
693 693 None,
694 694 _(b'merge with old dirstate parent after backout'),
695 695 ),
696 696 (
697 697 b'',
698 698 b'commit',
699 699 None,
700 700 _(b'commit if no conflicts were encountered (DEPRECATED)'),
701 701 ),
702 702 (b'', b'no-commit', None, _(b'do not commit')),
703 703 (
704 704 b'',
705 705 b'parent',
706 706 b'',
707 707 _(b'parent to choose when backing out merge (DEPRECATED)'),
708 708 _(b'REV'),
709 709 ),
710 710 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
711 711 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
712 712 ]
713 713 + mergetoolopts
714 714 + walkopts
715 715 + commitopts
716 716 + commitopts2,
717 717 _(b'[OPTION]... [-r] REV'),
718 718 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
719 719 )
720 720 def backout(ui, repo, node=None, rev=None, **opts):
721 721 """reverse effect of earlier changeset
722 722
723 723 Prepare a new changeset with the effect of REV undone in the
724 724 current working directory. If no conflicts were encountered,
725 725 it will be committed immediately.
726 726
727 727 If REV is the parent of the working directory, then this new changeset
728 728 is committed automatically (unless --no-commit is specified).
729 729
730 730 .. note::
731 731
732 732 :hg:`backout` cannot be used to fix either an unwanted or
733 733 incorrect merge.
734 734
735 735 .. container:: verbose
736 736
737 737 Examples:
738 738
739 739 - Reverse the effect of the parent of the working directory.
740 740 This backout will be committed immediately::
741 741
742 742 hg backout -r .
743 743
744 744 - Reverse the effect of previous bad revision 23::
745 745
746 746 hg backout -r 23
747 747
748 748 - Reverse the effect of previous bad revision 23 and
749 749 leave changes uncommitted::
750 750
751 751 hg backout -r 23 --no-commit
752 752 hg commit -m "Backout revision 23"
753 753
754 754 By default, the pending changeset will have one parent,
755 755 maintaining a linear history. With --merge, the pending
756 756 changeset will instead have two parents: the old parent of the
757 757 working directory and a new child of REV that simply undoes REV.
758 758
759 759 Before version 1.7, the behavior without --merge was equivalent
760 760 to specifying --merge followed by :hg:`update --clean .` to
761 761 cancel the merge and leave the child of REV as a head to be
762 762 merged separately.
763 763
764 764 See :hg:`help dates` for a list of formats valid for -d/--date.
765 765
766 766 See :hg:`help revert` for a way to restore files to the state
767 767 of another revision.
768 768
769 769 Returns 0 on success, 1 if nothing to backout or there are unresolved
770 770 files.
771 771 """
772 772 with repo.wlock(), repo.lock():
773 773 return _dobackout(ui, repo, node, rev, **opts)
774 774
775 775
776 776 def _dobackout(ui, repo, node=None, rev=None, **opts):
777 777 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
778 778
779 779 if rev and node:
780 780 raise error.InputError(_(b"please specify just one revision"))
781 781
782 782 if not rev:
783 783 rev = node
784 784
785 785 if not rev:
786 786 raise error.InputError(_(b"please specify a revision to backout"))
787 787
788 788 date = opts.get('date')
789 789 if date:
790 790 opts['date'] = dateutil.parsedate(date)
791 791
792 792 cmdutil.checkunfinished(repo)
793 793 cmdutil.bailifchanged(repo)
794 794 ctx = logcmdutil.revsingle(repo, rev)
795 795 node = ctx.node()
796 796
797 797 op1, op2 = repo.dirstate.parents()
798 798 if not repo.changelog.isancestor(node, op1):
799 799 raise error.InputError(
800 800 _(b'cannot backout change that is not an ancestor')
801 801 )
802 802
803 803 p1, p2 = repo.changelog.parents(node)
804 804 if p1 == repo.nullid:
805 805 raise error.InputError(_(b'cannot backout a change with no parents'))
806 806 if p2 != repo.nullid:
807 807 if not opts.get('parent'):
808 808 raise error.InputError(_(b'cannot backout a merge changeset'))
809 809 p = repo.lookup(opts['parent'])
810 810 if p not in (p1, p2):
811 811 raise error.InputError(
812 812 _(b'%s is not a parent of %s') % (short(p), short(node))
813 813 )
814 814 parent = p
815 815 else:
816 816 if opts.get('parent'):
817 817 raise error.InputError(
818 818 _(b'cannot use --parent on non-merge changeset')
819 819 )
820 820 parent = p1
821 821
822 822 # the backout should appear on the same branch
823 823 branch = repo.dirstate.branch()
824 824 bheads = repo.branchheads(branch)
825 825 rctx = scmutil.revsingle(repo, hex(parent))
826 826 if not opts.get('merge') and op1 != node:
827 827 with repo.transaction(b"backout"):
828 828 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
829 829 with ui.configoverride(overrides, b'backout'):
830 830 stats = mergemod.back_out(ctx, parent=repo[parent])
831 831 repo.setparents(op1, op2)
832 832 hg._showstats(repo, stats)
833 833 if stats.unresolvedcount:
834 834 repo.ui.status(
835 835 _(b"use 'hg resolve' to retry unresolved file merges\n")
836 836 )
837 837 return 1
838 838 else:
839 839 hg.clean(repo, node, show_stats=False)
840 840 repo.dirstate.setbranch(branch, repo.currenttransaction())
841 841 cmdutil.revert(ui, repo, rctx)
842 842
843 843 if opts.get('no_commit'):
844 844 msg = _(b"changeset %s backed out, don't forget to commit.\n")
845 845 ui.status(msg % short(node))
846 846 return 0
847 847
848 848 def commitfunc(ui, repo, message, match, opts):
849 849 editform = b'backout'
850 850 e = cmdutil.getcommiteditor(
851 851 editform=editform, **pycompat.strkwargs(opts)
852 852 )
853 853 if not message:
854 854 # we don't translate commit messages
855 855 message = b"Backed out changeset %s" % short(node)
856 856 e = cmdutil.getcommiteditor(edit=True, editform=editform)
857 857 return repo.commit(
858 858 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
859 859 )
860 860
861 861 # save to detect changes
862 862 tip = repo.changelog.tip()
863 863
864 864 newnode = cmdutil.commit(
865 865 ui, repo, commitfunc, [], pycompat.byteskwargs(opts)
866 866 )
867 867 if not newnode:
868 868 ui.status(_(b"nothing changed\n"))
869 869 return 1
870 870 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
871 871
872 872 def nice(node):
873 873 return b'%d:%s' % (repo.changelog.rev(node), short(node))
874 874
875 875 ui.status(
876 876 _(b'changeset %s backs out changeset %s\n')
877 877 % (nice(newnode), nice(node))
878 878 )
879 879 if opts.get('merge') and op1 != node:
880 880 hg.clean(repo, op1, show_stats=False)
881 881 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
882 882 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
883 883 with ui.configoverride(overrides, b'backout'):
884 884 return hg.merge(repo[b'tip'])
885 885 return 0
886 886
887 887
888 888 @command(
889 889 b'bisect',
890 890 [
891 891 (b'r', b'reset', False, _(b'reset bisect state')),
892 892 (b'g', b'good', False, _(b'mark changeset good')),
893 893 (b'b', b'bad', False, _(b'mark changeset bad')),
894 894 (b's', b'skip', False, _(b'skip testing changeset')),
895 895 (b'e', b'extend', False, _(b'extend the bisect range')),
896 896 (
897 897 b'c',
898 898 b'command',
899 899 b'',
900 900 _(b'use command to check changeset state'),
901 901 _(b'CMD'),
902 902 ),
903 903 (b'U', b'noupdate', False, _(b'do not update to target')),
904 904 ],
905 905 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
906 906 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
907 907 )
908 908 def bisect(
909 909 ui,
910 910 repo,
911 911 positional_1=None,
912 912 positional_2=None,
913 913 command=None,
914 914 reset=None,
915 915 good=None,
916 916 bad=None,
917 917 skip=None,
918 918 extend=None,
919 919 noupdate=None,
920 920 ):
921 921 """subdivision search of changesets
922 922
923 923 This command helps to find changesets which introduce problems. To
924 924 use, mark the earliest changeset you know exhibits the problem as
925 925 bad, then mark the latest changeset which is free from the problem
926 926 as good. Bisect will update your working directory to a revision
927 927 for testing (unless the -U/--noupdate option is specified). Once
928 928 you have performed tests, mark the working directory as good or
929 929 bad, and bisect will either update to another candidate changeset
930 930 or announce that it has found the bad revision.
931 931
932 932 As a shortcut, you can also use the revision argument to mark a
933 933 revision as good or bad without checking it out first.
934 934
935 935 If you supply a command, it will be used for automatic bisection.
936 936 The environment variable HG_NODE will contain the ID of the
937 937 changeset being tested. The exit status of the command will be
938 938 used to mark revisions as good or bad: status 0 means good, 125
939 939 means to skip the revision, 127 (command not found) will abort the
940 940 bisection, and any other non-zero exit status means the revision
941 941 is bad.
942 942
943 943 .. container:: verbose
944 944
945 945 Some examples:
946 946
947 947 - start a bisection with known bad revision 34, and good revision 12::
948 948
949 949 hg bisect --bad 34
950 950 hg bisect --good 12
951 951
952 952 - advance the current bisection by marking current revision as good or
953 953 bad::
954 954
955 955 hg bisect --good
956 956 hg bisect --bad
957 957
958 958 - mark the current revision, or a known revision, to be skipped (e.g. if
959 959 that revision is not usable because of another issue)::
960 960
961 961 hg bisect --skip
962 962 hg bisect --skip 23
963 963
964 964 - skip all revisions that do not touch directories ``foo`` or ``bar``::
965 965
966 966 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
967 967
968 968 - forget the current bisection::
969 969
970 970 hg bisect --reset
971 971
972 972 - use 'make && make tests' to automatically find the first broken
973 973 revision::
974 974
975 975 hg bisect --reset
976 976 hg bisect --bad 34
977 977 hg bisect --good 12
978 978 hg bisect --command "make && make tests"
979 979
980 980 - see all changesets whose states are already known in the current
981 981 bisection::
982 982
983 983 hg log -r "bisect(pruned)"
984 984
985 985 - see the changeset currently being bisected (especially useful
986 986 if running with -U/--noupdate)::
987 987
988 988 hg log -r "bisect(current)"
989 989
990 990 - see all changesets that took part in the current bisection::
991 991
992 992 hg log -r "bisect(range)"
993 993
994 994 - you can even get a nice graph::
995 995
996 996 hg log --graph -r "bisect(range)"
997 997
998 998 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
999 999
1000 1000 Returns 0 on success.
1001 1001 """
1002 1002 rev = []
1003 1003 # backward compatibility
1004 1004 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1005 1005 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1006 1006 cmd = positional_1
1007 1007 rev.append(positional_2)
1008 1008 if cmd == b"good":
1009 1009 good = True
1010 1010 elif cmd == b"bad":
1011 1011 bad = True
1012 1012 else:
1013 1013 reset = True
1014 1014 elif positional_2:
1015 1015 raise error.InputError(_(b'incompatible arguments'))
1016 1016 elif positional_1 is not None:
1017 1017 rev.append(positional_1)
1018 1018
1019 1019 incompatibles = {
1020 1020 b'--bad': bad,
1021 1021 b'--command': bool(command),
1022 1022 b'--extend': extend,
1023 1023 b'--good': good,
1024 1024 b'--reset': reset,
1025 1025 b'--skip': skip,
1026 1026 }
1027 1027
1028 1028 enabled = [x for x in incompatibles if incompatibles[x]]
1029 1029
1030 1030 if len(enabled) > 1:
1031 1031 raise error.InputError(
1032 1032 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1033 1033 )
1034 1034
1035 1035 if reset:
1036 1036 hbisect.resetstate(repo)
1037 1037 return
1038 1038
1039 1039 state = hbisect.load_state(repo)
1040 1040
1041 1041 if rev:
1042 1042 revs = logcmdutil.revrange(repo, rev)
1043 1043 goodnodes = state[b'good']
1044 1044 badnodes = state[b'bad']
1045 1045 if goodnodes and badnodes:
1046 1046 candidates = repo.revs(b'(%ln)::(%ln)', goodnodes, badnodes)
1047 1047 candidates += repo.revs(b'(%ln)::(%ln)', badnodes, goodnodes)
1048 1048 revs = candidates & revs
1049 1049 nodes = [repo.changelog.node(i) for i in revs]
1050 1050 else:
1051 1051 nodes = [repo.lookup(b'.')]
1052 1052
1053 1053 # update state
1054 1054 if good or bad or skip:
1055 1055 if good:
1056 1056 state[b'good'] += nodes
1057 1057 elif bad:
1058 1058 state[b'bad'] += nodes
1059 1059 elif skip:
1060 1060 state[b'skip'] += nodes
1061 1061 hbisect.save_state(repo, state)
1062 1062 if not (state[b'good'] and state[b'bad']):
1063 1063 return
1064 1064
1065 1065 def mayupdate(repo, node, show_stats=True):
1066 1066 """common used update sequence"""
1067 1067 if noupdate:
1068 1068 return
1069 1069 cmdutil.checkunfinished(repo)
1070 1070 cmdutil.bailifchanged(repo)
1071 1071 return hg.clean(repo, node, show_stats=show_stats)
1072 1072
1073 1073 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1074 1074
1075 1075 if command:
1076 1076 changesets = 1
1077 1077 if noupdate:
1078 1078 try:
1079 1079 node = state[b'current'][0]
1080 1080 except LookupError:
1081 1081 raise error.StateError(
1082 1082 _(
1083 1083 b'current bisect revision is unknown - '
1084 1084 b'start a new bisect to fix'
1085 1085 )
1086 1086 )
1087 1087 else:
1088 1088 node, p2 = repo.dirstate.parents()
1089 1089 if p2 != repo.nullid:
1090 1090 raise error.StateError(_(b'current bisect revision is a merge'))
1091 1091 if rev:
1092 1092 if not nodes:
1093 1093 raise error.InputError(_(b'empty revision set'))
1094 1094 node = repo[nodes[-1]].node()
1095 1095 with hbisect.restore_state(repo, state, node):
1096 1096 while changesets:
1097 1097 # update state
1098 1098 state[b'current'] = [node]
1099 1099 hbisect.save_state(repo, state)
1100 1100 status = ui.system(
1101 1101 command,
1102 1102 environ={b'HG_NODE': hex(node)},
1103 1103 blockedtag=b'bisect_check',
1104 1104 )
1105 1105 if status == 125:
1106 1106 transition = b"skip"
1107 1107 elif status == 0:
1108 1108 transition = b"good"
1109 1109 # status < 0 means process was killed
1110 1110 elif status == 127:
1111 1111 raise error.Abort(_(b"failed to execute %s") % command)
1112 1112 elif status < 0:
1113 1113 raise error.Abort(_(b"%s killed") % command)
1114 1114 else:
1115 1115 transition = b"bad"
1116 1116 state[transition].append(node)
1117 1117 ctx = repo[node]
1118 1118 summary = cmdutil.format_changeset_summary(ui, ctx, b'bisect')
1119 1119 ui.status(_(b'changeset %s: %s\n') % (summary, transition))
1120 1120 hbisect.checkstate(state)
1121 1121 # bisect
1122 1122 nodes, changesets, bgood = hbisect.bisect(repo, state)
1123 1123 # update to next check
1124 1124 node = nodes[0]
1125 1125 mayupdate(repo, node, show_stats=False)
1126 1126 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1127 1127 return
1128 1128
1129 1129 hbisect.checkstate(state)
1130 1130
1131 1131 # actually bisect
1132 1132 nodes, changesets, good = hbisect.bisect(repo, state)
1133 1133 if extend:
1134 1134 if not changesets:
1135 1135 extendctx = hbisect.extendrange(repo, state, nodes, good)
1136 1136 if extendctx is not None:
1137 1137 ui.write(
1138 1138 _(b"Extending search to changeset %s\n")
1139 1139 % cmdutil.format_changeset_summary(ui, extendctx, b'bisect')
1140 1140 )
1141 1141 state[b'current'] = [extendctx.node()]
1142 1142 hbisect.save_state(repo, state)
1143 1143 return mayupdate(repo, extendctx.node())
1144 1144 raise error.StateError(_(b"nothing to extend"))
1145 1145
1146 1146 if changesets == 0:
1147 1147 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1148 1148 else:
1149 1149 assert len(nodes) == 1 # only a single node can be tested next
1150 1150 node = nodes[0]
1151 1151 # compute the approximate number of remaining tests
1152 1152 tests, size = 0, 2
1153 1153 while size <= changesets:
1154 1154 tests, size = tests + 1, size * 2
1155 1155 rev = repo.changelog.rev(node)
1156 1156 summary = cmdutil.format_changeset_summary(ui, repo[rev], b'bisect')
1157 1157 ui.write(
1158 1158 _(
1159 1159 b"Testing changeset %s "
1160 1160 b"(%d changesets remaining, ~%d tests)\n"
1161 1161 )
1162 1162 % (summary, changesets, tests)
1163 1163 )
1164 1164 state[b'current'] = [node]
1165 1165 hbisect.save_state(repo, state)
1166 1166 return mayupdate(repo, node)
1167 1167
1168 1168
1169 1169 @command(
1170 1170 b'bookmarks|bookmark',
1171 1171 [
1172 1172 (b'f', b'force', False, _(b'force')),
1173 1173 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1174 1174 (b'd', b'delete', False, _(b'delete a given bookmark')),
1175 1175 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1176 1176 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1177 1177 (b'l', b'list', False, _(b'list existing bookmarks')),
1178 1178 ]
1179 1179 + formatteropts,
1180 1180 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1181 1181 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1182 1182 )
1183 1183 def bookmark(ui, repo, *names, **opts):
1184 1184 """create a new bookmark or list existing bookmarks
1185 1185
1186 1186 Bookmarks are labels on changesets to help track lines of development.
1187 1187 Bookmarks are unversioned and can be moved, renamed and deleted.
1188 1188 Deleting or moving a bookmark has no effect on the associated changesets.
1189 1189
1190 1190 Creating or updating to a bookmark causes it to be marked as 'active'.
1191 1191 The active bookmark is indicated with a '*'.
1192 1192 When a commit is made, the active bookmark will advance to the new commit.
1193 1193 A plain :hg:`update` will also advance an active bookmark, if possible.
1194 1194 Updating away from a bookmark will cause it to be deactivated.
1195 1195
1196 1196 Bookmarks can be pushed and pulled between repositories (see
1197 1197 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1198 1198 diverged, a new 'divergent bookmark' of the form 'name@path' will
1199 1199 be created. Using :hg:`merge` will resolve the divergence.
1200 1200
1201 1201 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1202 1202 the active bookmark's name.
1203 1203
1204 1204 A bookmark named '@' has the special property that :hg:`clone` will
1205 1205 check it out by default if it exists.
1206 1206
1207 1207 .. container:: verbose
1208 1208
1209 1209 Template:
1210 1210
1211 1211 The following keywords are supported in addition to the common template
1212 1212 keywords and functions such as ``{bookmark}``. See also
1213 1213 :hg:`help templates`.
1214 1214
1215 1215 :active: Boolean. True if the bookmark is active.
1216 1216
1217 1217 Examples:
1218 1218
1219 1219 - create an active bookmark for a new line of development::
1220 1220
1221 1221 hg book new-feature
1222 1222
1223 1223 - create an inactive bookmark as a place marker::
1224 1224
1225 1225 hg book -i reviewed
1226 1226
1227 1227 - create an inactive bookmark on another changeset::
1228 1228
1229 1229 hg book -r .^ tested
1230 1230
1231 1231 - rename bookmark turkey to dinner::
1232 1232
1233 1233 hg book -m turkey dinner
1234 1234
1235 1235 - move the '@' bookmark from another branch::
1236 1236
1237 1237 hg book -f @
1238 1238
1239 1239 - print only the active bookmark name::
1240 1240
1241 1241 hg book -ql .
1242 1242 """
1243 1243 force = opts.get('force')
1244 1244 rev = opts.get('rev')
1245 1245 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1246 1246
1247 1247 action = cmdutil.check_at_most_one_arg(opts, 'delete', 'rename', 'list')
1248 1248 if action:
1249 1249 cmdutil.check_incompatible_arguments(opts, action, ['rev'])
1250 1250 elif names or rev:
1251 1251 action = 'add'
1252 1252 elif inactive:
1253 1253 action = 'inactive' # meaning deactivate
1254 1254 else:
1255 1255 action = 'list'
1256 1256
1257 1257 cmdutil.check_incompatible_arguments(opts, 'inactive', ['delete', 'list'])
1258 1258 if not names and action in {'add', 'delete'}:
1259 1259 raise error.InputError(_(b"bookmark name required"))
1260 1260
1261 1261 if action in {'add', 'delete', 'rename', 'inactive'}:
1262 1262 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1263 1263 if action == 'delete':
1264 1264 names = pycompat.maplist(repo._bookmarks.expandname, names)
1265 1265 bookmarks.delete(repo, tr, names)
1266 1266 elif action == 'rename':
1267 1267 if not names:
1268 1268 raise error.InputError(_(b"new bookmark name required"))
1269 1269 elif len(names) > 1:
1270 1270 raise error.InputError(
1271 1271 _(b"only one new bookmark name allowed")
1272 1272 )
1273 1273 oldname = repo._bookmarks.expandname(opts['rename'])
1274 1274 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1275 1275 elif action == 'add':
1276 1276 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1277 1277 elif action == 'inactive':
1278 1278 if len(repo._bookmarks) == 0:
1279 1279 ui.status(_(b"no bookmarks set\n"))
1280 1280 elif not repo._activebookmark:
1281 1281 ui.status(_(b"no active bookmark\n"))
1282 1282 else:
1283 1283 bookmarks.deactivate(repo)
1284 1284 elif action == 'list':
1285 1285 names = pycompat.maplist(repo._bookmarks.expandname, names)
1286 1286 with ui.formatter(b'bookmarks', pycompat.byteskwargs(opts)) as fm:
1287 1287 bookmarks.printbookmarks(ui, repo, fm, names)
1288 1288 else:
1289 1289 raise error.ProgrammingError(
1290 1290 b'invalid action: %s' % pycompat.sysbytes(action)
1291 1291 )
1292 1292
1293 1293
1294 1294 @command(
1295 1295 b'branch',
1296 1296 [
1297 1297 (
1298 1298 b'f',
1299 1299 b'force',
1300 1300 None,
1301 1301 _(b'set branch name even if it shadows an existing branch'),
1302 1302 ),
1303 1303 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1304 1304 (
1305 1305 b'r',
1306 1306 b'rev',
1307 1307 [],
1308 1308 _(b'change branches of the given revs (EXPERIMENTAL)'),
1309 1309 ),
1310 1310 ],
1311 1311 _(b'[-fC] [NAME]'),
1312 1312 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1313 1313 )
1314 1314 def branch(ui, repo, label=None, **opts):
1315 1315 """set or show the current branch name
1316 1316
1317 1317 .. note::
1318 1318
1319 1319 Branch names are permanent and global. Use :hg:`bookmark` to create a
1320 1320 light-weight bookmark instead. See :hg:`help glossary` for more
1321 1321 information about named branches and bookmarks.
1322 1322
1323 1323 With no argument, show the current branch name. With one argument,
1324 1324 set the working directory branch name (the branch will not exist
1325 1325 in the repository until the next commit). Standard practice
1326 1326 recommends that primary development take place on the 'default'
1327 1327 branch.
1328 1328
1329 1329 Unless -f/--force is specified, branch will not let you set a
1330 1330 branch name that already exists.
1331 1331
1332 1332 Use -C/--clean to reset the working directory branch to that of
1333 1333 the parent of the working directory, negating a previous branch
1334 1334 change.
1335 1335
1336 1336 Use the command :hg:`update` to switch to an existing branch. Use
1337 1337 :hg:`commit --close-branch` to mark this branch head as closed.
1338 1338 When all heads of a branch are closed, the branch will be
1339 1339 considered closed.
1340 1340
1341 1341 Returns 0 on success.
1342 1342 """
1343 1343 revs = opts.get('rev')
1344 1344 if label:
1345 1345 label = label.strip()
1346 1346
1347 1347 if not opts.get('clean') and not label:
1348 1348 if revs:
1349 1349 raise error.InputError(
1350 1350 _(b"no branch name specified for the revisions")
1351 1351 )
1352 1352 ui.write(b"%s\n" % repo.dirstate.branch())
1353 1353 return
1354 1354
1355 1355 with repo.wlock():
1356 1356 if opts.get('clean'):
1357 1357 label = repo[b'.'].branch()
1358 1358 repo.dirstate.setbranch(label, repo.currenttransaction())
1359 1359 ui.status(_(b'reset working directory to branch %s\n') % label)
1360 1360 elif label:
1361 1361
1362 1362 scmutil.checknewlabel(repo, label, b'branch')
1363 1363 if revs:
1364 1364 return cmdutil.changebranch(ui, repo, revs, label, **opts)
1365 1365
1366 1366 if not opts.get('force') and label in repo.branchmap():
1367 1367 if label not in [p.branch() for p in repo[None].parents()]:
1368 1368 raise error.InputError(
1369 1369 _(b'a branch of the same name already exists'),
1370 1370 # i18n: "it" refers to an existing branch
1371 1371 hint=_(b"use 'hg update' to switch to it"),
1372 1372 )
1373 1373
1374 1374 repo.dirstate.setbranch(label, repo.currenttransaction())
1375 1375 ui.status(_(b'marked working directory as branch %s\n') % label)
1376 1376
1377 1377 # find any open named branches aside from default
1378 1378 for n, h, t, c in repo.branchmap().iterbranches():
1379 1379 if n != b"default" and not c:
1380 1380 return 0
1381 1381 ui.status(
1382 1382 _(
1383 1383 b'(branches are permanent and global, '
1384 1384 b'did you want a bookmark?)\n'
1385 1385 )
1386 1386 )
1387 1387
1388 1388
1389 1389 @command(
1390 1390 b'branches',
1391 1391 [
1392 1392 (
1393 1393 b'a',
1394 1394 b'active',
1395 1395 False,
1396 1396 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1397 1397 ),
1398 1398 (b'c', b'closed', False, _(b'show normal and closed branches')),
1399 1399 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1400 1400 ]
1401 1401 + formatteropts,
1402 1402 _(b'[-c]'),
1403 1403 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1404 1404 intents={INTENT_READONLY},
1405 1405 )
1406 1406 def branches(ui, repo, active=False, closed=False, **opts):
1407 1407 """list repository named branches
1408 1408
1409 1409 List the repository's named branches, indicating which ones are
1410 1410 inactive. If -c/--closed is specified, also list branches which have
1411 1411 been marked closed (see :hg:`commit --close-branch`).
1412 1412
1413 1413 Use the command :hg:`update` to switch to an existing branch.
1414 1414
1415 1415 .. container:: verbose
1416 1416
1417 1417 Template:
1418 1418
1419 1419 The following keywords are supported in addition to the common template
1420 1420 keywords and functions such as ``{branch}``. See also
1421 1421 :hg:`help templates`.
1422 1422
1423 1423 :active: Boolean. True if the branch is active.
1424 1424 :closed: Boolean. True if the branch is closed.
1425 1425 :current: Boolean. True if it is the current branch.
1426 1426
1427 1427 Returns 0.
1428 1428 """
1429 1429
1430 1430 revs = opts.get('rev')
1431 1431 selectedbranches = None
1432 1432 if revs:
1433 1433 revs = logcmdutil.revrange(repo, revs)
1434 1434 getbi = repo.revbranchcache().branchinfo
1435 1435 selectedbranches = {getbi(r)[0] for r in revs}
1436 1436
1437 1437 ui.pager(b'branches')
1438 1438 fm = ui.formatter(b'branches', pycompat.byteskwargs(opts))
1439 1439 hexfunc = fm.hexfunc
1440 1440
1441 1441 allheads = set(repo.heads())
1442 1442 branches = []
1443 1443 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1444 1444 if selectedbranches is not None and tag not in selectedbranches:
1445 1445 continue
1446 1446 isactive = False
1447 1447 if not isclosed:
1448 1448 openheads = set(repo.branchmap().iteropen(heads))
1449 1449 isactive = bool(openheads & allheads)
1450 1450 branches.append((tag, repo[tip], isactive, not isclosed))
1451 1451 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1452 1452
1453 1453 for tag, ctx, isactive, isopen in branches:
1454 1454 if active and not isactive:
1455 1455 continue
1456 1456 if isactive:
1457 1457 label = b'branches.active'
1458 1458 notice = b''
1459 1459 elif not isopen:
1460 1460 if not closed:
1461 1461 continue
1462 1462 label = b'branches.closed'
1463 1463 notice = _(b' (closed)')
1464 1464 else:
1465 1465 label = b'branches.inactive'
1466 1466 notice = _(b' (inactive)')
1467 1467 current = tag == repo.dirstate.branch()
1468 1468 if current:
1469 1469 label = b'branches.current'
1470 1470
1471 1471 fm.startitem()
1472 1472 fm.write(b'branch', b'%s', tag, label=label)
1473 1473 rev = ctx.rev()
1474 1474 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1475 1475 fmt = b' ' * padsize + b' %d:%s'
1476 1476 fm.condwrite(
1477 1477 not ui.quiet,
1478 1478 b'rev node',
1479 1479 fmt,
1480 1480 rev,
1481 1481 hexfunc(ctx.node()),
1482 1482 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1483 1483 )
1484 1484 fm.context(ctx=ctx)
1485 1485 fm.data(active=isactive, closed=not isopen, current=current)
1486 1486 if not ui.quiet:
1487 1487 fm.plain(notice)
1488 1488 fm.plain(b'\n')
1489 1489 fm.end()
1490 1490
1491 1491
1492 1492 @command(
1493 1493 b'bundle',
1494 1494 [
1495 1495 (
1496 1496 b'',
1497 1497 b'exact',
1498 1498 None,
1499 1499 _(b'compute the base from the revision specified'),
1500 1500 ),
1501 1501 (
1502 1502 b'f',
1503 1503 b'force',
1504 1504 None,
1505 1505 _(b'run even when the destination is unrelated'),
1506 1506 ),
1507 1507 (
1508 1508 b'r',
1509 1509 b'rev',
1510 1510 [],
1511 1511 _(b'a changeset intended to be added to the destination'),
1512 1512 _(b'REV'),
1513 1513 ),
1514 1514 (
1515 1515 b'b',
1516 1516 b'branch',
1517 1517 [],
1518 1518 _(b'a specific branch you would like to bundle'),
1519 1519 _(b'BRANCH'),
1520 1520 ),
1521 1521 (
1522 1522 b'',
1523 1523 b'base',
1524 1524 [],
1525 1525 _(b'a base changeset assumed to be available at the destination'),
1526 1526 _(b'REV'),
1527 1527 ),
1528 1528 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1529 1529 (
1530 1530 b't',
1531 1531 b'type',
1532 1532 b'bzip2',
1533 1533 _(b'bundle compression type to use'),
1534 1534 _(b'TYPE'),
1535 1535 ),
1536 1536 ]
1537 1537 + remoteopts,
1538 1538 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]...'),
1539 1539 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1540 1540 )
1541 1541 def bundle(ui, repo, fname, *dests, **opts):
1542 1542 """create a bundle file
1543 1543
1544 1544 Generate a bundle file containing data to be transferred to another
1545 1545 repository.
1546 1546
1547 1547 To create a bundle containing all changesets, use -a/--all
1548 1548 (or --base null). Otherwise, hg assumes the destination will have
1549 1549 all the nodes you specify with --base parameters. Otherwise, hg
1550 1550 will assume the repository has all the nodes in destination, or
1551 1551 default-push/default if no destination is specified, where destination
1552 1552 is the repositories you provide through DEST option.
1553 1553
1554 1554 You can change bundle format with the -t/--type option. See
1555 1555 :hg:`help bundlespec` for documentation on this format. By default,
1556 1556 the most appropriate format is used and compression defaults to
1557 1557 bzip2.
1558 1558
1559 1559 The bundle file can then be transferred using conventional means
1560 1560 and applied to another repository with the unbundle or pull
1561 1561 command. This is useful when direct push and pull are not
1562 1562 available or when exporting an entire repository is undesirable.
1563 1563
1564 1564 Applying bundles preserves all changeset contents including
1565 1565 permissions, copy/rename information, and revision history.
1566 1566
1567 1567 Returns 0 on success, 1 if no changes found.
1568 1568 """
1569 1569
1570 1570 revs = None
1571 1571 if 'rev' in opts:
1572 1572 revstrings = opts['rev']
1573 1573 revs = logcmdutil.revrange(repo, revstrings)
1574 1574 if revstrings and not revs:
1575 1575 raise error.InputError(_(b'no commits to bundle'))
1576 1576
1577 1577 bundletype = opts.get('type', b'bzip2').lower()
1578 1578 try:
1579 1579 bundlespec = bundlecaches.parsebundlespec(
1580 1580 repo, bundletype, strict=False
1581 1581 )
1582 1582 except error.UnsupportedBundleSpecification as e:
1583 1583 raise error.InputError(
1584 1584 pycompat.bytestr(e),
1585 1585 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1586 1586 )
1587 1587 cgversion = bundlespec.params[b"cg.version"]
1588 1588
1589 1589 # Packed bundles are a pseudo bundle format for now.
1590 1590 if cgversion == b's1':
1591 1591 raise error.InputError(
1592 1592 _(b'packed bundles cannot be produced by "hg bundle"'),
1593 1593 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1594 1594 )
1595 1595
1596 1596 if opts.get('all'):
1597 1597 if dests:
1598 1598 raise error.InputError(
1599 1599 _(b"--all is incompatible with specifying destinations")
1600 1600 )
1601 1601 if opts.get('base'):
1602 1602 ui.warn(_(b"ignoring --base because --all was specified\n"))
1603 1603 if opts.get('exact'):
1604 1604 ui.warn(_(b"ignoring --exact because --all was specified\n"))
1605 1605 base = [nullrev]
1606 1606 elif opts.get('exact'):
1607 1607 if dests:
1608 1608 raise error.InputError(
1609 1609 _(b"--exact is incompatible with specifying destinations")
1610 1610 )
1611 1611 if opts.get('base'):
1612 1612 ui.warn(_(b"ignoring --base because --exact was specified\n"))
1613 1613 base = repo.revs(b'parents(%ld) - %ld', revs, revs)
1614 1614 if not base:
1615 1615 base = [nullrev]
1616 1616 else:
1617 1617 base = logcmdutil.revrange(repo, opts.get('base'))
1618 1618 if cgversion not in changegroup.supportedoutgoingversions(repo):
1619 1619 raise error.Abort(
1620 1620 _(b"repository does not support bundle version %s") % cgversion
1621 1621 )
1622 1622
1623 1623 if base:
1624 1624 if dests:
1625 1625 raise error.InputError(
1626 1626 _(b"--base is incompatible with specifying destinations")
1627 1627 )
1628 1628 cl = repo.changelog
1629 1629 common = [cl.node(rev) for rev in base]
1630 1630 heads = [cl.node(r) for r in revs] if revs else None
1631 1631 outgoing = discovery.outgoing(repo, common, heads)
1632 1632 missing = outgoing.missing
1633 1633 excluded = outgoing.excluded
1634 1634 else:
1635 1635 missing = set()
1636 1636 excluded = set()
1637 1637 for path in urlutil.get_push_paths(repo, ui, dests):
1638 1638 other = hg.peer(repo, pycompat.byteskwargs(opts), path)
1639 1639 if revs is not None:
1640 1640 hex_revs = [repo[r].hex() for r in revs]
1641 1641 else:
1642 1642 hex_revs = None
1643 1643 branches = (path.branch, [])
1644 1644 head_revs, checkout = hg.addbranchrevs(
1645 1645 repo, repo, branches, hex_revs
1646 1646 )
1647 1647 heads = (
1648 1648 head_revs
1649 1649 and pycompat.maplist(repo.lookup, head_revs)
1650 1650 or head_revs
1651 1651 )
1652 1652 outgoing = discovery.findcommonoutgoing(
1653 1653 repo,
1654 1654 other,
1655 1655 onlyheads=heads,
1656 1656 force=opts.get('force'),
1657 1657 portable=True,
1658 1658 )
1659 1659 missing.update(outgoing.missing)
1660 1660 excluded.update(outgoing.excluded)
1661 1661
1662 1662 if not missing:
1663 1663 scmutil.nochangesfound(ui, repo, not base and excluded)
1664 1664 return 1
1665 1665
1666 1666 # internal changeset are internal implementation details that should not
1667 1667 # leave the repository. Bundling with `hg bundle` create such risk.
1668 1668 bundled_internal = repo.revs(b"%ln and _internal()", missing)
1669 1669 if bundled_internal:
1670 1670 msg = _(b"cannot bundle internal changesets")
1671 1671 hint = _(b"%d internal changesets selected") % len(bundled_internal)
1672 1672 raise error.Abort(msg, hint=hint)
1673 1673
1674 1674 if heads:
1675 1675 outgoing = discovery.outgoing(
1676 1676 repo, missingroots=missing, ancestorsof=heads
1677 1677 )
1678 1678 else:
1679 1679 outgoing = discovery.outgoing(repo, missingroots=missing)
1680 1680 outgoing.excluded = sorted(excluded)
1681 1681
1682 1682 if cgversion == b'01': # bundle1
1683 1683 bversion = b'HG10' + bundlespec.wirecompression
1684 1684 bcompression = None
1685 1685 elif cgversion in (b'02', b'03'):
1686 1686 bversion = b'HG20'
1687 1687 bcompression = bundlespec.wirecompression
1688 1688 else:
1689 1689 raise error.ProgrammingError(
1690 1690 b'bundle: unexpected changegroup version %s' % cgversion
1691 1691 )
1692 1692
1693 1693 # TODO compression options should be derived from bundlespec parsing.
1694 1694 # This is a temporary hack to allow adjusting bundle compression
1695 1695 # level without a) formalizing the bundlespec changes to declare it
1696 1696 # b) introducing a command flag.
1697 1697 compopts = {}
1698 1698 complevel = ui.configint(
1699 1699 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1700 1700 )
1701 1701 if complevel is None:
1702 1702 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1703 1703 if complevel is not None:
1704 1704 compopts[b'level'] = complevel
1705 1705
1706 1706 compthreads = ui.configint(
1707 1707 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1708 1708 )
1709 1709 if compthreads is None:
1710 1710 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1711 1711 if compthreads is not None:
1712 1712 compopts[b'threads'] = compthreads
1713 1713
1714 1714 # Bundling of obsmarker and phases is optional as not all clients
1715 1715 # support the necessary features.
1716 1716 cfg = ui.configbool
1717 1717 obsolescence_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker')
1718 1718 bundlespec.set_param(b'obsolescence', obsolescence_cfg, overwrite=False)
1719 1719 obs_mand_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker:mandatory')
1720 1720 bundlespec.set_param(
1721 1721 b'obsolescence-mandatory', obs_mand_cfg, overwrite=False
1722 1722 )
1723 1723 if not bundlespec.params.get(b'phases', False):
1724 1724 phases_cfg = cfg(b'experimental', b'bundle-phases')
1725 1725 bundlespec.set_param(b'phases', phases_cfg, overwrite=False)
1726 1726
1727 1727 bundle2.writenewbundle(
1728 1728 ui,
1729 1729 repo,
1730 1730 b'bundle',
1731 1731 fname,
1732 1732 bversion,
1733 1733 outgoing,
1734 1734 bundlespec.params,
1735 1735 compression=bcompression,
1736 1736 compopts=compopts,
1737 1737 )
1738 1738
1739 1739
1740 1740 @command(
1741 1741 b'cat',
1742 1742 [
1743 1743 (
1744 1744 b'o',
1745 1745 b'output',
1746 1746 b'',
1747 1747 _(b'print output to file with formatted name'),
1748 1748 _(b'FORMAT'),
1749 1749 ),
1750 1750 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1751 1751 (b'', b'decode', None, _(b'apply any matching decode filter')),
1752 1752 ]
1753 1753 + walkopts
1754 1754 + formatteropts,
1755 1755 _(b'[OPTION]... FILE...'),
1756 1756 helpcategory=command.CATEGORY_FILE_CONTENTS,
1757 1757 inferrepo=True,
1758 1758 intents={INTENT_READONLY},
1759 1759 )
1760 1760 def cat(ui, repo, file1, *pats, **opts):
1761 1761 """output the current or given revision of files
1762 1762
1763 1763 Print the specified files as they were at the given revision. If
1764 1764 no revision is given, the parent of the working directory is used.
1765 1765
1766 1766 Output may be to a file, in which case the name of the file is
1767 1767 given using a template string. See :hg:`help templates`. In addition
1768 1768 to the common template keywords, the following formatting rules are
1769 1769 supported:
1770 1770
1771 1771 :``%%``: literal "%" character
1772 1772 :``%s``: basename of file being printed
1773 1773 :``%d``: dirname of file being printed, or '.' if in repository root
1774 1774 :``%p``: root-relative path name of file being printed
1775 1775 :``%H``: changeset hash (40 hexadecimal digits)
1776 1776 :``%R``: changeset revision number
1777 1777 :``%h``: short-form changeset hash (12 hexadecimal digits)
1778 1778 :``%r``: zero-padded changeset revision number
1779 1779 :``%b``: basename of the exporting repository
1780 1780 :``\\``: literal "\\" character
1781 1781
1782 1782 .. container:: verbose
1783 1783
1784 1784 Template:
1785 1785
1786 1786 The following keywords are supported in addition to the common template
1787 1787 keywords and functions. See also :hg:`help templates`.
1788 1788
1789 1789 :data: String. File content.
1790 1790 :path: String. Repository-absolute path of the file.
1791 1791
1792 1792 Returns 0 on success.
1793 1793 """
1794 1794 rev = opts.get('rev')
1795 1795 if rev:
1796 1796 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1797 1797 ctx = logcmdutil.revsingle(repo, rev)
1798 1798 m = scmutil.match(ctx, (file1,) + pats, pycompat.byteskwargs(opts))
1799 1799 fntemplate = opts.pop('output', b'')
1800 1800 if cmdutil.isstdiofilename(fntemplate):
1801 1801 fntemplate = b''
1802 1802
1803 1803 if fntemplate:
1804 1804 fm = formatter.nullformatter(ui, b'cat', pycompat.byteskwargs(opts))
1805 1805 else:
1806 1806 ui.pager(b'cat')
1807 1807 fm = ui.formatter(b'cat', pycompat.byteskwargs(opts))
1808 1808 with fm:
1809 1809 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, b'', **opts)
1810 1810
1811 1811
1812 1812 @command(
1813 1813 b'clone',
1814 1814 [
1815 1815 (
1816 1816 b'U',
1817 1817 b'noupdate',
1818 1818 None,
1819 1819 _(
1820 1820 b'the clone will include an empty working '
1821 1821 b'directory (only a repository)'
1822 1822 ),
1823 1823 ),
1824 1824 (
1825 1825 b'u',
1826 1826 b'updaterev',
1827 1827 b'',
1828 1828 _(b'revision, tag, or branch to check out'),
1829 1829 _(b'REV'),
1830 1830 ),
1831 1831 (
1832 1832 b'r',
1833 1833 b'rev',
1834 1834 [],
1835 1835 _(
1836 1836 b'do not clone everything, but include this changeset'
1837 1837 b' and its ancestors'
1838 1838 ),
1839 1839 _(b'REV'),
1840 1840 ),
1841 1841 (
1842 1842 b'b',
1843 1843 b'branch',
1844 1844 [],
1845 1845 _(
1846 1846 b'do not clone everything, but include this branch\'s'
1847 1847 b' changesets and their ancestors'
1848 1848 ),
1849 1849 _(b'BRANCH'),
1850 1850 ),
1851 1851 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1852 1852 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1853 1853 (b'', b'stream', None, _(b'clone with minimal data processing')),
1854 1854 ]
1855 1855 + remoteopts,
1856 1856 _(b'[OPTION]... SOURCE [DEST]'),
1857 1857 helpcategory=command.CATEGORY_REPO_CREATION,
1858 1858 helpbasic=True,
1859 1859 norepo=True,
1860 1860 )
1861 1861 def clone(ui, source, dest=None, **opts):
1862 1862 """make a copy of an existing repository
1863 1863
1864 1864 Create a copy of an existing repository in a new directory.
1865 1865
1866 1866 If no destination directory name is specified, it defaults to the
1867 1867 basename of the source.
1868 1868
1869 1869 The location of the source is added to the new repository's
1870 1870 ``.hg/hgrc`` file, as the default to be used for future pulls.
1871 1871
1872 1872 Only local paths and ``ssh://`` URLs are supported as
1873 1873 destinations. For ``ssh://`` destinations, no working directory or
1874 1874 ``.hg/hgrc`` will be created on the remote side.
1875 1875
1876 1876 If the source repository has a bookmark called '@' set, that
1877 1877 revision will be checked out in the new repository by default.
1878 1878
1879 1879 To check out a particular version, use -u/--update, or
1880 1880 -U/--noupdate to create a clone with no working directory.
1881 1881
1882 1882 To pull only a subset of changesets, specify one or more revisions
1883 1883 identifiers with -r/--rev or branches with -b/--branch. The
1884 1884 resulting clone will contain only the specified changesets and
1885 1885 their ancestors. These options (or 'clone src#rev dest') imply
1886 1886 --pull, even for local source repositories.
1887 1887
1888 1888 In normal clone mode, the remote normalizes repository data into a common
1889 1889 exchange format and the receiving end translates this data into its local
1890 1890 storage format. --stream activates a different clone mode that essentially
1891 1891 copies repository files from the remote with minimal data processing. This
1892 1892 significantly reduces the CPU cost of a clone both remotely and locally.
1893 1893 However, it often increases the transferred data size by 30-40%. This can
1894 1894 result in substantially faster clones where I/O throughput is plentiful,
1895 1895 especially for larger repositories. A side-effect of --stream clones is
1896 1896 that storage settings and requirements on the remote are applied locally:
1897 1897 a modern client may inherit legacy or inefficient storage used by the
1898 1898 remote or a legacy Mercurial client may not be able to clone from a
1899 1899 modern Mercurial remote.
1900 1900
1901 1901 .. note::
1902 1902
1903 1903 Specifying a tag will include the tagged changeset but not the
1904 1904 changeset containing the tag.
1905 1905
1906 1906 .. container:: verbose
1907 1907
1908 1908 For efficiency, hardlinks are used for cloning whenever the
1909 1909 source and destination are on the same filesystem (note this
1910 1910 applies only to the repository data, not to the working
1911 1911 directory). Some filesystems, such as AFS, implement hardlinking
1912 1912 incorrectly, but do not report errors. In these cases, use the
1913 1913 --pull option to avoid hardlinking.
1914 1914
1915 1915 Mercurial will update the working directory to the first applicable
1916 1916 revision from this list:
1917 1917
1918 1918 a) null if -U or the source repository has no changesets
1919 1919 b) if -u . and the source repository is local, the first parent of
1920 1920 the source repository's working directory
1921 1921 c) the changeset specified with -u (if a branch name, this means the
1922 1922 latest head of that branch)
1923 1923 d) the changeset specified with -r
1924 1924 e) the tipmost head specified with -b
1925 1925 f) the tipmost head specified with the url#branch source syntax
1926 1926 g) the revision marked with the '@' bookmark, if present
1927 1927 h) the tipmost head of the default branch
1928 1928 i) tip
1929 1929
1930 1930 When cloning from servers that support it, Mercurial may fetch
1931 1931 pre-generated data from a server-advertised URL or inline from the
1932 1932 same stream. When this is done, hooks operating on incoming changesets
1933 1933 and changegroups may fire more than once, once for each pre-generated
1934 1934 bundle and as well as for any additional remaining data. In addition,
1935 1935 if an error occurs, the repository may be rolled back to a partial
1936 1936 clone. This behavior may change in future releases.
1937 1937 See :hg:`help -e clonebundles` for more.
1938 1938
1939 1939 Examples:
1940 1940
1941 1941 - clone a remote repository to a new directory named hg/::
1942 1942
1943 1943 hg clone https://www.mercurial-scm.org/repo/hg/
1944 1944
1945 1945 - create a lightweight local clone::
1946 1946
1947 1947 hg clone project/ project-feature/
1948 1948
1949 1949 - clone from an absolute path on an ssh server (note double-slash)::
1950 1950
1951 1951 hg clone ssh://user@server//home/projects/alpha/
1952 1952
1953 1953 - do a streaming clone while checking out a specified version::
1954 1954
1955 1955 hg clone --stream http://server/repo -u 1.5
1956 1956
1957 1957 - create a repository without changesets after a particular revision::
1958 1958
1959 1959 hg clone -r 04e544 experimental/ good/
1960 1960
1961 1961 - clone (and track) a particular named branch::
1962 1962
1963 1963 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1964 1964
1965 1965 See :hg:`help urls` for details on specifying URLs.
1966 1966
1967 1967 Returns 0 on success.
1968 1968 """
1969 1969 cmdutil.check_at_most_one_arg(opts, 'noupdate', 'updaterev')
1970 1970
1971 1971 # --include/--exclude can come from narrow or sparse.
1972 1972 includepats, excludepats = None, None
1973 1973
1974 1974 # hg.clone() differentiates between None and an empty set. So make sure
1975 1975 # patterns are sets if narrow is requested without patterns.
1976 1976 if opts.get('narrow'):
1977 1977 includepats = set()
1978 1978 excludepats = set()
1979 1979
1980 1980 if opts.get('include'):
1981 1981 includepats = narrowspec.parsepatterns(opts.get('include'))
1982 1982 if opts.get('exclude'):
1983 1983 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
1984 1984
1985 1985 r = hg.clone(
1986 1986 ui,
1987 1987 pycompat.byteskwargs(opts),
1988 1988 source,
1989 1989 dest,
1990 1990 pull=opts.get('pull'),
1991 1991 stream=opts.get('stream') or opts.get('uncompressed'),
1992 1992 revs=opts.get('rev'),
1993 1993 update=opts.get('updaterev') or not opts.get('noupdate'),
1994 1994 branch=opts.get('branch'),
1995 1995 shareopts=opts.get('shareopts'),
1996 1996 storeincludepats=includepats,
1997 1997 storeexcludepats=excludepats,
1998 1998 depth=opts.get('depth') or None,
1999 1999 )
2000 2000
2001 2001 return r is None
2002 2002
2003 2003
2004 2004 @command(
2005 2005 b'commit|ci',
2006 2006 [
2007 2007 (
2008 2008 b'A',
2009 2009 b'addremove',
2010 2010 None,
2011 2011 _(b'mark new/missing files as added/removed before committing'),
2012 2012 ),
2013 2013 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
2014 2014 (b'', b'amend', None, _(b'amend the parent of the working directory')),
2015 2015 (b's', b'secret', None, _(b'use the secret phase for committing')),
2016 2016 (b'', b'draft', None, _(b'use the draft phase for committing')),
2017 2017 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
2018 2018 (
2019 2019 b'',
2020 2020 b'force-close-branch',
2021 2021 None,
2022 2022 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
2023 2023 ),
2024 2024 (b'i', b'interactive', None, _(b'use interactive mode')),
2025 2025 ]
2026 2026 + walkopts
2027 2027 + commitopts
2028 2028 + commitopts2
2029 2029 + subrepoopts,
2030 2030 _(b'[OPTION]... [FILE]...'),
2031 2031 helpcategory=command.CATEGORY_COMMITTING,
2032 2032 helpbasic=True,
2033 2033 inferrepo=True,
2034 2034 )
2035 2035 def commit(ui, repo, *pats, **opts):
2036 2036 """commit the specified files or all outstanding changes
2037 2037
2038 2038 Commit changes to the given files into the repository. Unlike a
2039 2039 centralized SCM, this operation is a local operation. See
2040 2040 :hg:`push` for a way to actively distribute your changes.
2041 2041
2042 2042 If a list of files is omitted, all changes reported by :hg:`status`
2043 2043 will be committed.
2044 2044
2045 2045 If you are committing the result of a merge, do not provide any
2046 2046 filenames or -I/-X filters.
2047 2047
2048 2048 If no commit message is specified, Mercurial starts your
2049 2049 configured editor where you can enter a message. In case your
2050 2050 commit fails, you will find a backup of your message in
2051 2051 ``.hg/last-message.txt``.
2052 2052
2053 2053 The --close-branch flag can be used to mark the current branch
2054 2054 head closed. When all heads of a branch are closed, the branch
2055 2055 will be considered closed and no longer listed.
2056 2056
2057 2057 The --amend flag can be used to amend the parent of the
2058 2058 working directory with a new commit that contains the changes
2059 2059 in the parent in addition to those currently reported by :hg:`status`,
2060 2060 if there are any. The old commit is stored in a backup bundle in
2061 2061 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2062 2062 on how to restore it).
2063 2063
2064 2064 Message, user and date are taken from the amended commit unless
2065 2065 specified. When a message isn't specified on the command line,
2066 2066 the editor will open with the message of the amended commit.
2067 2067
2068 2068 It is not possible to amend public changesets (see :hg:`help phases`)
2069 2069 or changesets that have children.
2070 2070
2071 2071 See :hg:`help dates` for a list of formats valid for -d/--date.
2072 2072
2073 2073 Returns 0 on success, 1 if nothing changed.
2074 2074
2075 2075 .. container:: verbose
2076 2076
2077 2077 Examples:
2078 2078
2079 2079 - commit all files ending in .py::
2080 2080
2081 2081 hg commit --include "set:**.py"
2082 2082
2083 2083 - commit all non-binary files::
2084 2084
2085 2085 hg commit --exclude "set:binary()"
2086 2086
2087 2087 - amend the current commit and set the date to now::
2088 2088
2089 2089 hg commit --amend --date now
2090 2090 """
2091 2091 cmdutil.check_at_most_one_arg(opts, 'draft', 'secret')
2092 2092 cmdutil.check_incompatible_arguments(opts, 'subrepos', ['amend'])
2093 2093 with repo.wlock(), repo.lock():
2094 2094 return _docommit(ui, repo, *pats, **opts)
2095 2095
2096 2096
2097 2097 def _docommit(ui, repo, *pats, **opts):
2098 2098 if opts.get('interactive'):
2099 2099 opts.pop('interactive')
2100 2100 ret = cmdutil.dorecord(
2101 2101 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2102 2102 )
2103 2103 # ret can be 0 (no changes to record) or the value returned by
2104 2104 # commit(), 1 if nothing changed or None on success.
2105 2105 return 1 if ret == 0 else ret
2106 2106
2107 2107 if opts.get('subrepos'):
2108 2108 # Let --subrepos on the command line override config setting.
2109 2109 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2110 2110
2111 2111 cmdutil.checkunfinished(repo, commit=True)
2112 2112
2113 2113 branch = repo[None].branch()
2114 2114 bheads = repo.branchheads(branch)
2115 2115 tip = repo.changelog.tip()
2116 2116
2117 2117 extra = {}
2118 2118 if opts.get('close_branch') or opts.get('force_close_branch'):
2119 2119 extra[b'close'] = b'1'
2120 2120
2121 2121 if repo[b'.'].closesbranch():
2122 2122 # Not ideal, but let us do an extra status early to prevent early
2123 2123 # bail out.
2124 2124 matcher = scmutil.match(
2125 2125 repo[None], pats, pycompat.byteskwargs(opts)
2126 2126 )
2127 2127 s = repo.status(match=matcher)
2128 2128 if s.modified or s.added or s.removed:
2129 2129 bheads = repo.branchheads(branch, closed=True)
2130 2130 else:
2131 2131 msg = _(b'current revision is already a branch closing head')
2132 2132 raise error.InputError(msg)
2133 2133
2134 2134 if not bheads:
2135 2135 raise error.InputError(
2136 2136 _(b'branch "%s" has no heads to close') % branch
2137 2137 )
2138 2138 elif (
2139 2139 branch == repo[b'.'].branch()
2140 2140 and repo[b'.'].node() not in bheads
2141 2141 and not opts.get('force_close_branch')
2142 2142 ):
2143 2143 hint = _(
2144 2144 b'use --force-close-branch to close branch from a non-head'
2145 2145 b' changeset'
2146 2146 )
2147 2147 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2148 2148 elif opts.get('amend'):
2149 2149 if (
2150 2150 repo[b'.'].p1().branch() != branch
2151 2151 and repo[b'.'].p2().branch() != branch
2152 2152 ):
2153 2153 raise error.InputError(_(b'can only close branch heads'))
2154 2154
2155 2155 if opts.get('amend'):
2156 2156 if ui.configbool(b'ui', b'commitsubrepos'):
2157 2157 raise error.InputError(
2158 2158 _(b'cannot amend with ui.commitsubrepos enabled')
2159 2159 )
2160 2160
2161 2161 old = repo[b'.']
2162 2162 rewriteutil.precheck(repo, [old.rev()], b'amend')
2163 2163
2164 2164 # Currently histedit gets confused if an amend happens while histedit
2165 2165 # is in progress. Since we have a checkunfinished command, we are
2166 2166 # temporarily honoring it.
2167 2167 #
2168 2168 # Note: eventually this guard will be removed. Please do not expect
2169 2169 # this behavior to remain.
2170 2170 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2171 2171 cmdutil.checkunfinished(repo)
2172 2172
2173 2173 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2174 2174 if node == old.node():
2175 2175 ui.status(_(b"nothing changed\n"))
2176 2176 return 1
2177 2177 else:
2178 2178
2179 2179 def commitfunc(ui, repo, message, match, opts):
2180 2180 overrides = {}
2181 2181 if opts.get(b'secret'):
2182 2182 overrides[(b'phases', b'new-commit')] = b'secret'
2183 2183 elif opts.get(b'draft'):
2184 2184 overrides[(b'phases', b'new-commit')] = b'draft'
2185 2185
2186 2186 baseui = repo.baseui
2187 2187 with baseui.configoverride(overrides, b'commit'):
2188 2188 with ui.configoverride(overrides, b'commit'):
2189 2189 editform = cmdutil.mergeeditform(
2190 2190 repo[None], b'commit.normal'
2191 2191 )
2192 2192 editor = cmdutil.getcommiteditor(
2193 2193 editform=editform, **pycompat.strkwargs(opts)
2194 2194 )
2195 2195 return repo.commit(
2196 2196 message,
2197 2197 opts.get(b'user'),
2198 2198 opts.get(b'date'),
2199 2199 match,
2200 2200 editor=editor,
2201 2201 extra=extra,
2202 2202 )
2203 2203
2204 2204 node = cmdutil.commit(
2205 2205 ui, repo, commitfunc, pats, pycompat.byteskwargs(opts)
2206 2206 )
2207 2207
2208 2208 if not node:
2209 2209 stat = cmdutil.postcommitstatus(
2210 2210 repo, pats, pycompat.byteskwargs(opts)
2211 2211 )
2212 2212 if stat.deleted:
2213 2213 ui.status(
2214 2214 _(
2215 2215 b"nothing changed (%d missing files, see "
2216 2216 b"'hg status')\n"
2217 2217 )
2218 2218 % len(stat.deleted)
2219 2219 )
2220 2220 else:
2221 2221 ui.status(_(b"nothing changed\n"))
2222 2222 return 1
2223 2223
2224 2224 cmdutil.commitstatus(repo, node, branch, bheads, tip, **opts)
2225 2225
2226 2226 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2227 2227 status(
2228 2228 ui,
2229 2229 repo,
2230 2230 modified=True,
2231 2231 added=True,
2232 2232 removed=True,
2233 2233 deleted=True,
2234 2234 unknown=True,
2235 2235 subrepos=opts.get('subrepos'),
2236 2236 )
2237 2237
2238 2238
2239 2239 @command(
2240 2240 b'config|showconfig|debugconfig',
2241 2241 [
2242 2242 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2243 2243 # This is experimental because we need
2244 2244 # * reasonable behavior around aliases,
2245 2245 # * decide if we display [debug] [experimental] and [devel] section par
2246 2246 # default
2247 2247 # * some way to display "generic" config entry (the one matching
2248 2248 # regexp,
2249 2249 # * proper display of the different value type
2250 2250 # * a better way to handle <DYNAMIC> values (and variable types),
2251 2251 # * maybe some type information ?
2252 2252 (
2253 2253 b'',
2254 2254 b'exp-all-known',
2255 2255 None,
2256 2256 _(b'show all known config option (EXPERIMENTAL)'),
2257 2257 ),
2258 2258 (b'e', b'edit', None, _(b'edit user config')),
2259 2259 (b'l', b'local', None, _(b'edit repository config')),
2260 2260 (b'', b'source', None, _(b'show source of configuration value')),
2261 2261 (
2262 2262 b'',
2263 2263 b'shared',
2264 2264 None,
2265 2265 _(b'edit shared source repository config (EXPERIMENTAL)'),
2266 2266 ),
2267 2267 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2268 2268 (b'g', b'global', None, _(b'edit global config')),
2269 2269 ]
2270 2270 + formatteropts,
2271 2271 _(b'[-u] [NAME]...'),
2272 2272 helpcategory=command.CATEGORY_HELP,
2273 2273 optionalrepo=True,
2274 2274 intents={INTENT_READONLY},
2275 2275 )
2276 2276 def config(ui, repo, *values, **opts):
2277 2277 """show combined config settings from all hgrc files
2278 2278
2279 2279 With no arguments, print names and values of all config items.
2280 2280
2281 2281 With one argument of the form section.name, print just the value
2282 2282 of that config item.
2283 2283
2284 2284 With multiple arguments, print names and values of all config
2285 2285 items with matching section names or section.names.
2286 2286
2287 2287 With --edit, start an editor on the user-level config file. With
2288 2288 --global, edit the system-wide config file. With --local, edit the
2289 2289 repository-level config file.
2290 2290
2291 2291 With --source, the source (filename and line number) is printed
2292 2292 for each config item.
2293 2293
2294 2294 See :hg:`help config` for more information about config files.
2295 2295
2296 2296 .. container:: verbose
2297 2297
2298 2298 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2299 2299 This file is not shared across shares when in share-safe mode.
2300 2300
2301 2301 Template:
2302 2302
2303 2303 The following keywords are supported. See also :hg:`help templates`.
2304 2304
2305 2305 :name: String. Config name.
2306 2306 :source: String. Filename and line number where the item is defined.
2307 2307 :value: String. Config value.
2308 2308
2309 2309 The --shared flag can be used to edit the config file of shared source
2310 2310 repository. It only works when you have shared using the experimental
2311 2311 share safe feature.
2312 2312
2313 2313 Returns 0 on success, 1 if NAME does not exist.
2314 2314
2315 2315 """
2316 2316
2317 2317 editopts = ('edit', 'local', 'global', 'shared', 'non_shared')
2318 2318 if any(opts.get(o) for o in editopts):
2319 2319 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2320 2320 if opts.get('local'):
2321 2321 if not repo:
2322 2322 raise error.InputError(
2323 2323 _(b"can't use --local outside a repository")
2324 2324 )
2325 2325 paths = [repo.vfs.join(b'hgrc')]
2326 2326 elif opts.get('global'):
2327 2327 paths = rcutil.systemrcpath()
2328 2328 elif opts.get('shared'):
2329 2329 if not repo.shared():
2330 2330 raise error.InputError(
2331 2331 _(b"repository is not shared; can't use --shared")
2332 2332 )
2333 2333 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2334 2334 raise error.InputError(
2335 2335 _(
2336 2336 b"share safe feature not enabled; "
2337 2337 b"unable to edit shared source repository config"
2338 2338 )
2339 2339 )
2340 2340 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2341 2341 elif opts.get('non_shared'):
2342 2342 paths = [repo.vfs.join(b'hgrc-not-shared')]
2343 2343 else:
2344 2344 paths = rcutil.userrcpath()
2345 2345
2346 2346 for f in paths:
2347 2347 if os.path.exists(f):
2348 2348 break
2349 2349 else:
2350 2350 if opts.get('global'):
2351 2351 samplehgrc = uimod.samplehgrcs[b'global']
2352 2352 elif opts.get('local'):
2353 2353 samplehgrc = uimod.samplehgrcs[b'local']
2354 2354 else:
2355 2355 samplehgrc = uimod.samplehgrcs[b'user']
2356 2356
2357 2357 f = paths[0]
2358 2358 util.writefile(f, util.tonativeeol(samplehgrc))
2359 2359
2360 2360 editor = ui.geteditor()
2361 2361 ui.system(
2362 2362 b"%s \"%s\"" % (editor, f),
2363 2363 onerr=error.InputError,
2364 2364 errprefix=_(b"edit failed"),
2365 2365 blockedtag=b'config_edit',
2366 2366 )
2367 2367 return
2368 2368 ui.pager(b'config')
2369 2369 fm = ui.formatter(b'config', pycompat.byteskwargs(opts))
2370 2370 for t, f in rcutil.rccomponents():
2371 2371 if t == b'path':
2372 2372 ui.debug(b'read config from: %s\n' % f)
2373 2373 elif t == b'resource':
2374 2374 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2375 2375 elif t == b'items':
2376 2376 # Don't print anything for 'items'.
2377 2377 pass
2378 2378 else:
2379 2379 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2380 2380 untrusted = bool(opts.get('untrusted'))
2381 2381
2382 2382 selsections = selentries = []
2383 2383 if values:
2384 2384 selsections = [v for v in values if b'.' not in v]
2385 2385 selentries = [v for v in values if b'.' in v]
2386 2386 uniquesel = len(selentries) == 1 and not selsections
2387 2387 selsections = set(selsections)
2388 2388 selentries = set(selentries)
2389 2389
2390 2390 matched = False
2391 2391 all_known = opts['exp_all_known']
2392 2392 show_source = ui.debugflag or opts.get('source')
2393 2393 entries = ui.walkconfig(untrusted=untrusted, all_known=all_known)
2394 2394 for section, name, value in entries:
2395 2395 source = ui.configsource(section, name, untrusted)
2396 2396 value = pycompat.bytestr(value)
2397 2397 defaultvalue = ui.configdefault(section, name)
2398 2398 if fm.isplain():
2399 2399 source = source or b'none'
2400 2400 value = value.replace(b'\n', b'\\n')
2401 2401 entryname = section + b'.' + name
2402 2402 if values and not (section in selsections or entryname in selentries):
2403 2403 continue
2404 2404 fm.startitem()
2405 2405 fm.condwrite(show_source, b'source', b'%s: ', source)
2406 2406 if uniquesel:
2407 2407 fm.data(name=entryname)
2408 2408 fm.write(b'value', b'%s\n', value)
2409 2409 else:
2410 2410 fm.write(b'name value', b'%s=%s\n', entryname, value)
2411 2411 if formatter.isprintable(defaultvalue):
2412 2412 fm.data(defaultvalue=defaultvalue)
2413 2413 elif isinstance(defaultvalue, list) and all(
2414 2414 formatter.isprintable(e) for e in defaultvalue
2415 2415 ):
2416 2416 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2417 2417 # TODO: no idea how to process unsupported defaultvalue types
2418 2418 matched = True
2419 2419 fm.end()
2420 2420 if matched:
2421 2421 return 0
2422 2422 return 1
2423 2423
2424 2424
2425 2425 @command(
2426 2426 b'continue',
2427 2427 dryrunopts,
2428 2428 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2429 2429 helpbasic=True,
2430 2430 )
2431 2431 def continuecmd(ui, repo, **opts):
2432 2432 """resumes an interrupted operation (EXPERIMENTAL)
2433 2433
2434 2434 Finishes a multistep operation like graft, histedit, rebase, merge,
2435 2435 and unshelve if they are in an interrupted state.
2436 2436
2437 2437 use --dry-run/-n to dry run the command.
2438 2438 """
2439 2439 dryrun = opts.get('dry_run')
2440 2440 contstate = cmdutil.getunfinishedstate(repo)
2441 2441 if not contstate:
2442 2442 raise error.StateError(_(b'no operation in progress'))
2443 2443 if not contstate.continuefunc:
2444 2444 raise error.StateError(
2445 2445 (
2446 2446 _(b"%s in progress but does not support 'hg continue'")
2447 2447 % (contstate._opname)
2448 2448 ),
2449 2449 hint=contstate.continuemsg(),
2450 2450 )
2451 2451 if dryrun:
2452 2452 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2453 2453 return
2454 2454 return contstate.continuefunc(ui, repo)
2455 2455
2456 2456
2457 2457 @command(
2458 2458 b'copy|cp',
2459 2459 [
2460 2460 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2461 2461 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2462 2462 (
2463 2463 b'',
2464 2464 b'at-rev',
2465 2465 b'',
2466 2466 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2467 2467 _(b'REV'),
2468 2468 ),
2469 2469 (
2470 2470 b'f',
2471 2471 b'force',
2472 2472 None,
2473 2473 _(b'forcibly copy over an existing managed file'),
2474 2474 ),
2475 2475 ]
2476 2476 + walkopts
2477 2477 + dryrunopts,
2478 2478 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2479 2479 helpcategory=command.CATEGORY_FILE_CONTENTS,
2480 2480 )
2481 2481 def copy(ui, repo, *pats, **opts):
2482 2482 """mark files as copied for the next commit
2483 2483
2484 2484 Mark dest as having copies of source files. If dest is a
2485 2485 directory, copies are put in that directory. If dest is a file,
2486 2486 the source must be a single file.
2487 2487
2488 2488 By default, this command copies the contents of files as they
2489 2489 exist in the working directory. If invoked with -A/--after, the
2490 2490 operation is recorded, but no copying is performed.
2491 2491
2492 2492 To undo marking a destination file as copied, use --forget. With that
2493 2493 option, all given (positional) arguments are unmarked as copies. The
2494 2494 destination file(s) will be left in place (still tracked). Note that
2495 2495 :hg:`copy --forget` behaves the same way as :hg:`rename --forget`.
2496 2496
2497 2497 This command takes effect with the next commit by default.
2498 2498
2499 2499 Returns 0 on success, 1 if errors are encountered.
2500 2500 """
2501 2501
2502 2502 context = lambda repo: repo.dirstate.changing_files(repo)
2503 2503 rev = opts.get('at_rev')
2504 2504
2505 2505 if rev:
2506 2506 ctx = logcmdutil.revsingle(repo, rev)
2507 2507 if ctx.rev() is not None:
2508 2508
2509 2509 def context(repo):
2510 2510 return util.nullcontextmanager()
2511 2511
2512 2512 opts['at_rev'] = ctx.rev()
2513 2513 with repo.wlock(), context(repo):
2514 2514 return cmdutil.copy(ui, repo, pats, pycompat.byteskwargs(opts))
2515 2515
2516 2516
2517 2517 @command(
2518 2518 b'debugcommands',
2519 2519 [],
2520 2520 _(b'[COMMAND]'),
2521 2521 helpcategory=command.CATEGORY_HELP,
2522 2522 norepo=True,
2523 2523 )
2524 2524 def debugcommands(ui, cmd=b'', *args):
2525 2525 """list all available commands and options"""
2526 2526 for cmd, vals in sorted(table.items()):
2527 2527 cmd = cmd.split(b'|')[0]
2528 2528 opts = b', '.join([i[1] for i in vals[1]])
2529 2529 ui.write(b'%s: %s\n' % (cmd, opts))
2530 2530
2531 2531
2532 2532 @command(
2533 2533 b'debugcomplete',
2534 2534 [(b'o', b'options', None, _(b'show the command options'))],
2535 2535 _(b'[-o] CMD'),
2536 2536 helpcategory=command.CATEGORY_HELP,
2537 2537 norepo=True,
2538 2538 )
2539 2539 def debugcomplete(ui, cmd=b'', **opts):
2540 2540 """returns the completion list associated with the given command"""
2541 2541
2542 2542 if opts.get('options'):
2543 2543 options = []
2544 2544 otables = [globalopts]
2545 2545 if cmd:
2546 2546 aliases, entry = cmdutil.findcmd(cmd, table, False)
2547 2547 otables.append(entry[1])
2548 2548 for t in otables:
2549 2549 for o in t:
2550 2550 if b"(DEPRECATED)" in o[3]:
2551 2551 continue
2552 2552 if o[0]:
2553 2553 options.append(b'-%s' % o[0])
2554 2554 options.append(b'--%s' % o[1])
2555 2555 ui.write(b"%s\n" % b"\n".join(options))
2556 2556 return
2557 2557
2558 2558 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2559 2559 if ui.verbose:
2560 2560 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2561 2561 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2562 2562
2563 2563
2564 2564 @command(
2565 2565 b'diff',
2566 2566 [
2567 2567 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2568 2568 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2569 2569 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2570 2570 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2571 2571 ]
2572 2572 + diffopts
2573 2573 + diffopts2
2574 2574 + walkopts
2575 2575 + subrepoopts,
2576 2576 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2577 2577 helpcategory=command.CATEGORY_FILE_CONTENTS,
2578 2578 helpbasic=True,
2579 2579 inferrepo=True,
2580 2580 intents={INTENT_READONLY},
2581 2581 )
2582 2582 def diff(ui, repo, *pats, **opts):
2583 2583 """diff repository (or selected files)
2584 2584
2585 2585 Show differences between revisions for the specified files.
2586 2586
2587 2587 Differences between files are shown using the unified diff format.
2588 2588
2589 2589 .. note::
2590 2590
2591 2591 :hg:`diff` may generate unexpected results for merges, as it will
2592 2592 default to comparing against the working directory's first
2593 2593 parent changeset if no revisions are specified. To diff against the
2594 2594 conflict regions, you can use `--config diff.merge=yes`.
2595 2595
2596 2596 By default, the working directory files are compared to its first parent. To
2597 2597 see the differences from another revision, use --from. To see the difference
2598 2598 to another revision, use --to. For example, :hg:`diff --from .^` will show
2599 2599 the differences from the working copy's grandparent to the working copy,
2600 2600 :hg:`diff --to .` will show the diff from the working copy to its parent
2601 2601 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2602 2602 show the diff between those two revisions.
2603 2603
2604 2604 Alternatively you can specify -c/--change with a revision to see the changes
2605 2605 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2606 2606 equivalent to :hg:`diff --from 42^ --to 42`)
2607 2607
2608 2608 Without the -a/--text option, diff will avoid generating diffs of
2609 2609 files it detects as binary. With -a, diff will generate a diff
2610 2610 anyway, probably with undesirable results.
2611 2611
2612 2612 Use the -g/--git option to generate diffs in the git extended diff
2613 2613 format. For more information, read :hg:`help diffs`.
2614 2614
2615 2615 .. container:: verbose
2616 2616
2617 2617 Examples:
2618 2618
2619 2619 - compare a file in the current working directory to its parent::
2620 2620
2621 2621 hg diff foo.c
2622 2622
2623 2623 - compare two historical versions of a directory, with rename info::
2624 2624
2625 2625 hg diff --git --from 1.0 --to 1.2 lib/
2626 2626
2627 2627 - get change stats relative to the last change on some date::
2628 2628
2629 2629 hg diff --stat --from "date('may 2')"
2630 2630
2631 2631 - diff all newly-added files that contain a keyword::
2632 2632
2633 2633 hg diff "set:added() and grep(GNU)"
2634 2634
2635 2635 - compare a revision and its parents::
2636 2636
2637 2637 hg diff -c 9353 # compare against first parent
2638 2638 hg diff --from 9353^ --to 9353 # same using revset syntax
2639 2639 hg diff --from 9353^2 --to 9353 # compare against the second parent
2640 2640
2641 2641 Returns 0 on success.
2642 2642 """
2643 2643
2644 2644 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2645 2645 opts = pycompat.byteskwargs(opts)
2646 2646 revs = opts.get(b'rev')
2647 2647 change = opts.get(b'change')
2648 2648 from_rev = opts.get(b'from')
2649 2649 to_rev = opts.get(b'to')
2650 2650 stat = opts.get(b'stat')
2651 2651 reverse = opts.get(b'reverse')
2652 2652
2653 2653 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2654 2654 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2655 2655 if change:
2656 2656 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2657 2657 ctx2 = logcmdutil.revsingle(repo, change, None)
2658 2658 ctx1 = logcmdutil.diff_parent(ctx2)
2659 2659 elif from_rev or to_rev:
2660 2660 repo = scmutil.unhidehashlikerevs(
2661 2661 repo, [from_rev] + [to_rev], b'nowarn'
2662 2662 )
2663 2663 ctx1 = logcmdutil.revsingle(repo, from_rev, None)
2664 2664 ctx2 = logcmdutil.revsingle(repo, to_rev, None)
2665 2665 else:
2666 2666 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2667 2667 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
2668 2668
2669 2669 if reverse:
2670 2670 ctxleft = ctx2
2671 2671 ctxright = ctx1
2672 2672 else:
2673 2673 ctxleft = ctx1
2674 2674 ctxright = ctx2
2675 2675
2676 2676 diffopts = patch.diffallopts(ui, opts)
2677 2677 m = scmutil.match(ctx2, pats, opts)
2678 2678 m = repo.narrowmatch(m)
2679 2679 ui.pager(b'diff')
2680 2680 logcmdutil.diffordiffstat(
2681 2681 ui,
2682 2682 repo,
2683 2683 diffopts,
2684 2684 ctxleft,
2685 2685 ctxright,
2686 2686 m,
2687 2687 stat=stat,
2688 2688 listsubrepos=opts.get(b'subrepos'),
2689 2689 root=opts.get(b'root'),
2690 2690 )
2691 2691
2692 2692
2693 2693 @command(
2694 2694 b'export',
2695 2695 [
2696 2696 (
2697 2697 b'B',
2698 2698 b'bookmark',
2699 2699 b'',
2700 2700 _(b'export changes only reachable by given bookmark'),
2701 2701 _(b'BOOKMARK'),
2702 2702 ),
2703 2703 (
2704 2704 b'o',
2705 2705 b'output',
2706 2706 b'',
2707 2707 _(b'print output to file with formatted name'),
2708 2708 _(b'FORMAT'),
2709 2709 ),
2710 2710 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2711 2711 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2712 2712 ]
2713 2713 + diffopts
2714 2714 + formatteropts,
2715 2715 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2716 2716 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2717 2717 helpbasic=True,
2718 2718 intents={INTENT_READONLY},
2719 2719 )
2720 2720 def export(ui, repo, *changesets, **opts):
2721 2721 """dump the header and diffs for one or more changesets
2722 2722
2723 2723 Print the changeset header and diffs for one or more revisions.
2724 2724 If no revision is given, the parent of the working directory is used.
2725 2725
2726 2726 The information shown in the changeset header is: author, date,
2727 2727 branch name (if non-default), changeset hash, parent(s) and commit
2728 2728 comment.
2729 2729
2730 2730 .. note::
2731 2731
2732 2732 :hg:`export` may generate unexpected diff output for merge
2733 2733 changesets, as it will compare the merge changeset against its
2734 2734 first parent only.
2735 2735
2736 2736 Output may be to a file, in which case the name of the file is
2737 2737 given using a template string. See :hg:`help templates`. In addition
2738 2738 to the common template keywords, the following formatting rules are
2739 2739 supported:
2740 2740
2741 2741 :``%%``: literal "%" character
2742 2742 :``%H``: changeset hash (40 hexadecimal digits)
2743 2743 :``%N``: number of patches being generated
2744 2744 :``%R``: changeset revision number
2745 2745 :``%b``: basename of the exporting repository
2746 2746 :``%h``: short-form changeset hash (12 hexadecimal digits)
2747 2747 :``%m``: first line of the commit message (only alphanumeric characters)
2748 2748 :``%n``: zero-padded sequence number, starting at 1
2749 2749 :``%r``: zero-padded changeset revision number
2750 2750 :``\\``: literal "\\" character
2751 2751
2752 2752 Without the -a/--text option, export will avoid generating diffs
2753 2753 of files it detects as binary. With -a, export will generate a
2754 2754 diff anyway, probably with undesirable results.
2755 2755
2756 2756 With -B/--bookmark changesets reachable by the given bookmark are
2757 2757 selected.
2758 2758
2759 2759 Use the -g/--git option to generate diffs in the git extended diff
2760 2760 format. See :hg:`help diffs` for more information.
2761 2761
2762 2762 With the --switch-parent option, the diff will be against the
2763 2763 second parent. It can be useful to review a merge.
2764 2764
2765 2765 .. container:: verbose
2766 2766
2767 2767 Template:
2768 2768
2769 2769 The following keywords are supported in addition to the common template
2770 2770 keywords and functions. See also :hg:`help templates`.
2771 2771
2772 2772 :diff: String. Diff content.
2773 2773 :parents: List of strings. Parent nodes of the changeset.
2774 2774
2775 2775 Examples:
2776 2776
2777 2777 - use export and import to transplant a bugfix to the current
2778 2778 branch::
2779 2779
2780 2780 hg export -r 9353 | hg import -
2781 2781
2782 2782 - export all the changesets between two revisions to a file with
2783 2783 rename information::
2784 2784
2785 2785 hg export --git -r 123:150 > changes.txt
2786 2786
2787 2787 - split outgoing changes into a series of patches with
2788 2788 descriptive names::
2789 2789
2790 2790 hg export -r "outgoing()" -o "%n-%m.patch"
2791 2791
2792 2792 Returns 0 on success.
2793 2793 """
2794 2794 opts = pycompat.byteskwargs(opts)
2795 2795 bookmark = opts.get(b'bookmark')
2796 2796 changesets += tuple(opts.get(b'rev', []))
2797 2797
2798 2798 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2799 2799
2800 2800 if bookmark:
2801 2801 if bookmark not in repo._bookmarks:
2802 2802 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2803 2803
2804 2804 revs = scmutil.bookmarkrevs(repo, bookmark)
2805 2805 else:
2806 2806 if not changesets:
2807 2807 changesets = [b'.']
2808 2808
2809 2809 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2810 2810 revs = logcmdutil.revrange(repo, changesets)
2811 2811
2812 2812 if not revs:
2813 2813 raise error.InputError(_(b"export requires at least one changeset"))
2814 2814 if len(revs) > 1:
2815 2815 ui.note(_(b'exporting patches:\n'))
2816 2816 else:
2817 2817 ui.note(_(b'exporting patch:\n'))
2818 2818
2819 2819 fntemplate = opts.get(b'output')
2820 2820 if cmdutil.isstdiofilename(fntemplate):
2821 2821 fntemplate = b''
2822 2822
2823 2823 if fntemplate:
2824 2824 fm = formatter.nullformatter(ui, b'export', opts)
2825 2825 else:
2826 2826 ui.pager(b'export')
2827 2827 fm = ui.formatter(b'export', opts)
2828 2828 with fm:
2829 2829 cmdutil.export(
2830 2830 repo,
2831 2831 revs,
2832 2832 fm,
2833 2833 fntemplate=fntemplate,
2834 2834 switch_parent=opts.get(b'switch_parent'),
2835 2835 opts=patch.diffallopts(ui, opts),
2836 2836 )
2837 2837
2838 2838
2839 2839 @command(
2840 2840 b'files',
2841 2841 [
2842 2842 (
2843 2843 b'r',
2844 2844 b'rev',
2845 2845 b'',
2846 2846 _(b'search the repository as it is in REV'),
2847 2847 _(b'REV'),
2848 2848 ),
2849 2849 (
2850 2850 b'0',
2851 2851 b'print0',
2852 2852 None,
2853 2853 _(b'end filenames with NUL, for use with xargs'),
2854 2854 ),
2855 2855 ]
2856 2856 + walkopts
2857 2857 + formatteropts
2858 2858 + subrepoopts,
2859 2859 _(b'[OPTION]... [FILE]...'),
2860 2860 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2861 2861 intents={INTENT_READONLY},
2862 2862 )
2863 2863 def files(ui, repo, *pats, **opts):
2864 2864 """list tracked files
2865 2865
2866 2866 Print files under Mercurial control in the working directory or
2867 2867 specified revision for given files (excluding removed files).
2868 2868 Files can be specified as filenames or filesets.
2869 2869
2870 2870 If no files are given to match, this command prints the names
2871 2871 of all files under Mercurial control.
2872 2872
2873 2873 .. container:: verbose
2874 2874
2875 2875 Template:
2876 2876
2877 2877 The following keywords are supported in addition to the common template
2878 2878 keywords and functions. See also :hg:`help templates`.
2879 2879
2880 2880 :flags: String. Character denoting file's symlink and executable bits.
2881 2881 :path: String. Repository-absolute path of the file.
2882 2882 :size: Integer. Size of the file in bytes.
2883 2883
2884 2884 Examples:
2885 2885
2886 2886 - list all files under the current directory::
2887 2887
2888 2888 hg files .
2889 2889
2890 2890 - shows sizes and flags for current revision::
2891 2891
2892 2892 hg files -vr .
2893 2893
2894 2894 - list all files named README::
2895 2895
2896 2896 hg files -I "**/README"
2897 2897
2898 2898 - list all binary files::
2899 2899
2900 2900 hg files "set:binary()"
2901 2901
2902 2902 - find files containing a regular expression::
2903 2903
2904 2904 hg files "set:grep('bob')"
2905 2905
2906 2906 - search tracked file contents with xargs and grep::
2907 2907
2908 2908 hg files -0 | xargs -0 grep foo
2909 2909
2910 2910 See :hg:`help patterns` and :hg:`help filesets` for more information
2911 2911 on specifying file patterns.
2912 2912
2913 2913 Returns 0 if a match is found, 1 otherwise.
2914 2914
2915 2915 """
2916 2916
2917 2917 opts = pycompat.byteskwargs(opts)
2918 2918 rev = opts.get(b'rev')
2919 2919 if rev:
2920 2920 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2921 2921 ctx = logcmdutil.revsingle(repo, rev, None)
2922 2922
2923 2923 end = b'\n'
2924 2924 if opts.get(b'print0'):
2925 2925 end = b'\0'
2926 2926 fmt = b'%s' + end
2927 2927
2928 2928 m = scmutil.match(ctx, pats, opts)
2929 2929 ui.pager(b'files')
2930 2930 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2931 2931 with ui.formatter(b'files', opts) as fm:
2932 2932 return cmdutil.files(
2933 2933 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2934 2934 )
2935 2935
2936 2936
2937 2937 @command(
2938 2938 b'forget',
2939 2939 [
2940 2940 (b'i', b'interactive', None, _(b'use interactive mode')),
2941 2941 ]
2942 2942 + walkopts
2943 2943 + dryrunopts,
2944 2944 _(b'[OPTION]... FILE...'),
2945 2945 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2946 2946 helpbasic=True,
2947 2947 inferrepo=True,
2948 2948 )
2949 2949 def forget(ui, repo, *pats, **opts):
2950 2950 """forget the specified files on the next commit
2951 2951
2952 2952 Mark the specified files so they will no longer be tracked
2953 2953 after the next commit.
2954 2954
2955 2955 This only removes files from the current branch, not from the
2956 2956 entire project history, and it does not delete them from the
2957 2957 working directory.
2958 2958
2959 2959 To delete the file from the working directory, see :hg:`remove`.
2960 2960
2961 2961 To undo a forget before the next commit, see :hg:`add`.
2962 2962
2963 2963 .. container:: verbose
2964 2964
2965 2965 Examples:
2966 2966
2967 2967 - forget newly-added binary files::
2968 2968
2969 2969 hg forget "set:added() and binary()"
2970 2970
2971 2971 - forget files that would be excluded by .hgignore::
2972 2972
2973 2973 hg forget "set:hgignore()"
2974 2974
2975 2975 Returns 0 on success.
2976 2976 """
2977 2977
2978 2978 if not pats:
2979 2979 raise error.InputError(_(b'no files specified'))
2980 2980
2981 2981 with repo.wlock(), repo.dirstate.changing_files(repo):
2982 2982 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
2983 2983 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2984 2984 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2985 2985 rejected = cmdutil.forget(
2986 2986 ui,
2987 2987 repo,
2988 2988 m,
2989 2989 prefix=b"",
2990 2990 uipathfn=uipathfn,
2991 2991 explicitonly=False,
2992 2992 dryrun=dryrun,
2993 2993 interactive=interactive,
2994 2994 )[0]
2995 2995 return rejected and 1 or 0
2996 2996
2997 2997
2998 2998 @command(
2999 2999 b'graft',
3000 3000 [
3001 3001 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
3002 3002 (
3003 3003 b'',
3004 3004 b'base',
3005 3005 b'',
3006 3006 _(b'base revision when doing the graft merge (ADVANCED)'),
3007 3007 _(b'REV'),
3008 3008 ),
3009 3009 (b'c', b'continue', False, _(b'resume interrupted graft')),
3010 3010 (b'', b'stop', False, _(b'stop interrupted graft')),
3011 3011 (b'', b'abort', False, _(b'abort interrupted graft')),
3012 3012 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3013 3013 (b'', b'log', None, _(b'append graft info to log message')),
3014 3014 (
3015 3015 b'',
3016 3016 b'no-commit',
3017 3017 None,
3018 3018 _(b"don't commit, just apply the changes in working directory"),
3019 3019 ),
3020 3020 (b'f', b'force', False, _(b'force graft')),
3021 3021 (
3022 3022 b'D',
3023 3023 b'currentdate',
3024 3024 False,
3025 3025 _(b'record the current date as commit date'),
3026 3026 ),
3027 3027 (
3028 3028 b'U',
3029 3029 b'currentuser',
3030 3030 False,
3031 3031 _(b'record the current user as committer'),
3032 3032 ),
3033 3033 ]
3034 3034 + commitopts2
3035 3035 + mergetoolopts
3036 3036 + dryrunopts,
3037 3037 _(b'[OPTION]... [-r REV]... REV...'),
3038 3038 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
3039 3039 )
3040 3040 def graft(ui, repo, *revs, **opts):
3041 3041 """copy changes from other branches onto the current branch
3042 3042
3043 3043 This command uses Mercurial's merge logic to copy individual
3044 3044 changes from other branches without merging branches in the
3045 3045 history graph. This is sometimes known as 'backporting' or
3046 3046 'cherry-picking'. By default, graft will copy user, date, and
3047 3047 description from the source changesets.
3048 3048
3049 3049 Changesets that are ancestors of the current revision, that have
3050 3050 already been grafted, or that are merges will be skipped.
3051 3051
3052 3052 If --log is specified, log messages will have a comment appended
3053 3053 of the form::
3054 3054
3055 3055 (grafted from CHANGESETHASH)
3056 3056
3057 3057 If --force is specified, revisions will be grafted even if they
3058 3058 are already ancestors of, or have been grafted to, the destination.
3059 3059 This is useful when the revisions have since been backed out.
3060 3060
3061 3061 If a graft merge results in conflicts, the graft process is
3062 3062 interrupted so that the current merge can be manually resolved.
3063 3063 Once all conflicts are addressed, the graft process can be
3064 3064 continued with the -c/--continue option.
3065 3065
3066 3066 The -c/--continue option reapplies all the earlier options.
3067 3067
3068 3068 .. container:: verbose
3069 3069
3070 3070 The --base option exposes more of how graft internally uses merge with a
3071 3071 custom base revision. --base can be used to specify another ancestor than
3072 3072 the first and only parent.
3073 3073
3074 3074 The command::
3075 3075
3076 3076 hg graft -r 345 --base 234
3077 3077
3078 3078 is thus pretty much the same as::
3079 3079
3080 3080 hg diff --from 234 --to 345 | hg import
3081 3081
3082 3082 but using merge to resolve conflicts and track moved files.
3083 3083
3084 3084 The result of a merge can thus be backported as a single commit by
3085 3085 specifying one of the merge parents as base, and thus effectively
3086 3086 grafting the changes from the other side.
3087 3087
3088 3088 It is also possible to collapse multiple changesets and clean up history
3089 3089 by specifying another ancestor as base, much like rebase --collapse
3090 3090 --keep.
3091 3091
3092 3092 The commit message can be tweaked after the fact using commit --amend .
3093 3093
3094 3094 For using non-ancestors as the base to backout changes, see the backout
3095 3095 command and the hidden --parent option.
3096 3096
3097 3097 .. container:: verbose
3098 3098
3099 3099 Examples:
3100 3100
3101 3101 - copy a single change to the stable branch and edit its description::
3102 3102
3103 3103 hg update stable
3104 3104 hg graft --edit 9393
3105 3105
3106 3106 - graft a range of changesets with one exception, updating dates::
3107 3107
3108 3108 hg graft -D "2085::2093 and not 2091"
3109 3109
3110 3110 - continue a graft after resolving conflicts::
3111 3111
3112 3112 hg graft -c
3113 3113
3114 3114 - show the source of a grafted changeset::
3115 3115
3116 3116 hg log --debug -r .
3117 3117
3118 3118 - show revisions sorted by date::
3119 3119
3120 3120 hg log -r "sort(all(), date)"
3121 3121
3122 3122 - backport the result of a merge as a single commit::
3123 3123
3124 3124 hg graft -r 123 --base 123^
3125 3125
3126 3126 - land a feature branch as one changeset::
3127 3127
3128 3128 hg up -cr default
3129 3129 hg graft -r featureX --base "ancestor('featureX', 'default')"
3130 3130
3131 3131 See :hg:`help revisions` for more about specifying revisions.
3132 3132
3133 3133 Returns 0 on successful completion, 1 if there are unresolved files.
3134 3134 """
3135 3135 with repo.wlock():
3136 3136 return _dograft(ui, repo, *revs, **opts)
3137 3137
3138 3138
3139 3139 def _dograft(ui, repo, *revs, **opts):
3140 3140 if revs and opts.get('rev'):
3141 3141 ui.warn(
3142 3142 _(
3143 3143 b'warning: inconsistent use of --rev might give unexpected '
3144 3144 b'revision ordering!\n'
3145 3145 )
3146 3146 )
3147 3147
3148 3148 revs = list(revs)
3149 3149 revs.extend(opts.get('rev'))
3150 3150 # a dict of data to be stored in state file
3151 3151 statedata = {}
3152 3152 # list of new nodes created by ongoing graft
3153 3153 statedata[b'newnodes'] = []
3154 3154
3155 3155 cmdutil.resolve_commit_options(ui, opts)
3156 3156
3157 3157 editor = cmdutil.getcommiteditor(editform=b'graft', **opts)
3158 3158
3159 3159 cmdutil.check_at_most_one_arg(opts, 'abort', 'stop', 'continue')
3160 3160
3161 3161 cont = False
3162 3162 if opts.get('no_commit'):
3163 3163 cmdutil.check_incompatible_arguments(
3164 3164 opts,
3165 3165 'no_commit',
3166 3166 ['edit', 'currentuser', 'currentdate', 'log'],
3167 3167 )
3168 3168
3169 3169 graftstate = statemod.cmdstate(repo, b'graftstate')
3170 3170
3171 3171 if opts.get('stop'):
3172 3172 cmdutil.check_incompatible_arguments(
3173 3173 opts,
3174 3174 'stop',
3175 3175 [
3176 3176 'edit',
3177 3177 'log',
3178 3178 'user',
3179 3179 'date',
3180 3180 'currentdate',
3181 3181 'currentuser',
3182 3182 'rev',
3183 3183 ],
3184 3184 )
3185 3185 return _stopgraft(ui, repo, graftstate)
3186 3186 elif opts.get('abort'):
3187 3187 cmdutil.check_incompatible_arguments(
3188 3188 opts,
3189 3189 'abort',
3190 3190 [
3191 3191 'edit',
3192 3192 'log',
3193 3193 'user',
3194 3194 'date',
3195 3195 'currentdate',
3196 3196 'currentuser',
3197 3197 'rev',
3198 3198 ],
3199 3199 )
3200 3200 return cmdutil.abortgraft(ui, repo, graftstate)
3201 3201 elif opts.get('continue'):
3202 3202 cont = True
3203 3203 if revs:
3204 3204 raise error.InputError(_(b"can't specify --continue and revisions"))
3205 3205 # read in unfinished revisions
3206 3206 if graftstate.exists():
3207 3207 statedata = cmdutil.readgraftstate(repo, graftstate)
3208 3208 if statedata.get(b'date'):
3209 3209 opts['date'] = statedata[b'date']
3210 3210 if statedata.get(b'user'):
3211 3211 opts['user'] = statedata[b'user']
3212 3212 if statedata.get(b'log'):
3213 3213 opts['log'] = True
3214 3214 if statedata.get(b'no_commit'):
3215 3215 opts['no_commit'] = statedata.get(b'no_commit')
3216 3216 if statedata.get(b'base'):
3217 3217 opts['base'] = statedata.get(b'base')
3218 3218 nodes = statedata[b'nodes']
3219 3219 revs = [repo[node].rev() for node in nodes]
3220 3220 else:
3221 3221 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3222 3222 else:
3223 3223 if not revs:
3224 3224 raise error.InputError(_(b'no revisions specified'))
3225 3225 cmdutil.checkunfinished(repo)
3226 3226 cmdutil.bailifchanged(repo)
3227 3227 revs = logcmdutil.revrange(repo, revs)
3228 3228
3229 3229 skipped = set()
3230 3230 basectx = None
3231 3231 if opts.get('base'):
3232 3232 basectx = logcmdutil.revsingle(repo, opts['base'], None)
3233 3233 if basectx is None:
3234 3234 # check for merges
3235 3235 for rev in repo.revs(b'%ld and merge()', revs):
3236 3236 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3237 3237 skipped.add(rev)
3238 3238 revs = [r for r in revs if r not in skipped]
3239 3239 if not revs:
3240 3240 return -1
3241 3241 if basectx is not None and len(revs) != 1:
3242 3242 raise error.InputError(_(b'only one revision allowed with --base '))
3243 3243
3244 3244 # Don't check in the --continue case, in effect retaining --force across
3245 3245 # --continues. That's because without --force, any revisions we decided to
3246 3246 # skip would have been filtered out here, so they wouldn't have made their
3247 3247 # way to the graftstate. With --force, any revisions we would have otherwise
3248 3248 # skipped would not have been filtered out, and if they hadn't been applied
3249 3249 # already, they'd have been in the graftstate.
3250 3250 if not (cont or opts.get('force')) and basectx is None:
3251 3251 # check for ancestors of dest branch
3252 3252 ancestors = repo.revs(b'%ld & (::.)', revs)
3253 3253 for rev in ancestors:
3254 3254 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3255 3255
3256 3256 revs = [r for r in revs if r not in ancestors]
3257 3257
3258 3258 if not revs:
3259 3259 return -1
3260 3260
3261 3261 # analyze revs for earlier grafts
3262 3262 ids = {}
3263 3263 for ctx in repo.set(b"%ld", revs):
3264 3264 ids[ctx.hex()] = ctx.rev()
3265 3265 n = ctx.extra().get(b'source')
3266 3266 if n:
3267 3267 ids[n] = ctx.rev()
3268 3268
3269 3269 # check ancestors for earlier grafts
3270 3270 ui.debug(b'scanning for duplicate grafts\n')
3271 3271
3272 3272 # The only changesets we can be sure doesn't contain grafts of any
3273 3273 # revs, are the ones that are common ancestors of *all* revs:
3274 3274 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3275 3275 ctx = repo[rev]
3276 3276 n = ctx.extra().get(b'source')
3277 3277 if n in ids:
3278 3278 try:
3279 3279 r = repo[n].rev()
3280 3280 except error.RepoLookupError:
3281 3281 r = None
3282 3282 if r in revs:
3283 3283 ui.warn(
3284 3284 _(
3285 3285 b'skipping revision %d:%s '
3286 3286 b'(already grafted to %d:%s)\n'
3287 3287 )
3288 3288 % (r, repo[r], rev, ctx)
3289 3289 )
3290 3290 revs.remove(r)
3291 3291 elif ids[n] in revs:
3292 3292 if r is None:
3293 3293 ui.warn(
3294 3294 _(
3295 3295 b'skipping already grafted revision %d:%s '
3296 3296 b'(%d:%s also has unknown origin %s)\n'
3297 3297 )
3298 3298 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3299 3299 )
3300 3300 else:
3301 3301 ui.warn(
3302 3302 _(
3303 3303 b'skipping already grafted revision %d:%s '
3304 3304 b'(%d:%s also has origin %d:%s)\n'
3305 3305 )
3306 3306 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3307 3307 )
3308 3308 revs.remove(ids[n])
3309 3309 elif ctx.hex() in ids:
3310 3310 r = ids[ctx.hex()]
3311 3311 if r in revs:
3312 3312 ui.warn(
3313 3313 _(
3314 3314 b'skipping already grafted revision %d:%s '
3315 3315 b'(was grafted from %d:%s)\n'
3316 3316 )
3317 3317 % (r, repo[r], rev, ctx)
3318 3318 )
3319 3319 revs.remove(r)
3320 3320 if not revs:
3321 3321 return -1
3322 3322
3323 3323 if opts.get('no_commit'):
3324 3324 statedata[b'no_commit'] = True
3325 3325 if opts.get('base'):
3326 3326 statedata[b'base'] = opts['base']
3327 3327 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3328 3328 desc = b'%d:%s "%s"' % (
3329 3329 ctx.rev(),
3330 3330 ctx,
3331 3331 ctx.description().split(b'\n', 1)[0],
3332 3332 )
3333 3333 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3334 3334 if names:
3335 3335 desc += b' (%s)' % b' '.join(names)
3336 3336 ui.status(_(b'grafting %s\n') % desc)
3337 3337 if opts.get('dry_run'):
3338 3338 continue
3339 3339
3340 3340 source = ctx.extra().get(b'source')
3341 3341 extra = {}
3342 3342 if source:
3343 3343 extra[b'source'] = source
3344 3344 extra[b'intermediate-source'] = ctx.hex()
3345 3345 else:
3346 3346 extra[b'source'] = ctx.hex()
3347 3347 user = ctx.user()
3348 3348 if opts.get('user'):
3349 3349 user = opts['user']
3350 3350 statedata[b'user'] = user
3351 3351 date = ctx.date()
3352 3352 if opts.get('date'):
3353 3353 date = opts['date']
3354 3354 statedata[b'date'] = date
3355 3355 message = ctx.description()
3356 3356 if opts.get('log'):
3357 3357 message += b'\n(grafted from %s)' % ctx.hex()
3358 3358 statedata[b'log'] = True
3359 3359
3360 3360 # we don't merge the first commit when continuing
3361 3361 if not cont:
3362 3362 # perform the graft merge with p1(rev) as 'ancestor'
3363 3363 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
3364 3364 base = ctx.p1() if basectx is None else basectx
3365 3365 with ui.configoverride(overrides, b'graft'):
3366 3366 stats = mergemod.graft(
3367 3367 repo, ctx, base, [b'local', b'graft', b'parent of graft']
3368 3368 )
3369 3369 # report any conflicts
3370 3370 if stats.unresolvedcount > 0:
3371 3371 # write out state for --continue
3372 3372 nodes = [repo[rev].hex() for rev in revs[pos:]]
3373 3373 statedata[b'nodes'] = nodes
3374 3374 stateversion = 1
3375 3375 graftstate.save(stateversion, statedata)
3376 3376 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3377 3377 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3378 3378 return 1
3379 3379 else:
3380 3380 cont = False
3381 3381
3382 3382 # commit if --no-commit is false
3383 3383 if not opts.get('no_commit'):
3384 3384 node = repo.commit(
3385 3385 text=message, user=user, date=date, extra=extra, editor=editor
3386 3386 )
3387 3387 if node is None:
3388 3388 ui.warn(
3389 3389 _(b'note: graft of %d:%s created no changes to commit\n')
3390 3390 % (ctx.rev(), ctx)
3391 3391 )
3392 3392 # checking that newnodes exist because old state files won't have it
3393 3393 elif statedata.get(b'newnodes') is not None:
3394 3394 nn = statedata[b'newnodes']
3395 3395 assert isinstance(nn, list) # list of bytes
3396 3396 nn.append(node)
3397 3397
3398 3398 # remove state when we complete successfully
3399 3399 if not opts.get('dry_run'):
3400 3400 graftstate.delete()
3401 3401
3402 3402 return 0
3403 3403
3404 3404
3405 3405 def _stopgraft(ui, repo, graftstate):
3406 3406 """stop the interrupted graft"""
3407 3407 if not graftstate.exists():
3408 3408 raise error.StateError(_(b"no interrupted graft found"))
3409 3409 pctx = repo[b'.']
3410 3410 mergemod.clean_update(pctx)
3411 3411 graftstate.delete()
3412 3412 ui.status(_(b"stopped the interrupted graft\n"))
3413 3413 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3414 3414 return 0
3415 3415
3416 3416
3417 3417 statemod.addunfinished(
3418 3418 b'graft',
3419 3419 fname=b'graftstate',
3420 3420 clearable=True,
3421 3421 stopflag=True,
3422 3422 continueflag=True,
3423 3423 abortfunc=cmdutil.hgabortgraft,
3424 3424 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3425 3425 )
3426 3426
3427 3427
3428 3428 @command(
3429 3429 b'grep',
3430 3430 [
3431 3431 (b'0', b'print0', None, _(b'end fields with NUL')),
3432 3432 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3433 3433 (
3434 3434 b'',
3435 3435 b'diff',
3436 3436 None,
3437 3437 _(
3438 3438 b'search revision differences for when the pattern was added '
3439 3439 b'or removed'
3440 3440 ),
3441 3441 ),
3442 3442 (b'a', b'text', None, _(b'treat all files as text')),
3443 3443 (
3444 3444 b'f',
3445 3445 b'follow',
3446 3446 None,
3447 3447 _(
3448 3448 b'follow changeset history,'
3449 3449 b' or file history across copies and renames'
3450 3450 ),
3451 3451 ),
3452 3452 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3453 3453 (
3454 3454 b'l',
3455 3455 b'files-with-matches',
3456 3456 None,
3457 3457 _(b'print only filenames and revisions that match'),
3458 3458 ),
3459 3459 (b'n', b'line-number', None, _(b'print matching line numbers')),
3460 3460 (
3461 3461 b'r',
3462 3462 b'rev',
3463 3463 [],
3464 3464 _(b'search files changed within revision range'),
3465 3465 _(b'REV'),
3466 3466 ),
3467 3467 (
3468 3468 b'',
3469 3469 b'all-files',
3470 3470 None,
3471 3471 _(
3472 3472 b'include all files in the changeset while grepping (DEPRECATED)'
3473 3473 ),
3474 3474 ),
3475 3475 (b'u', b'user', None, _(b'list the author (long with -v)')),
3476 3476 (b'd', b'date', None, _(b'list the date (short with -q)')),
3477 3477 ]
3478 3478 + formatteropts
3479 3479 + walkopts,
3480 3480 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3481 3481 helpcategory=command.CATEGORY_FILE_CONTENTS,
3482 3482 inferrepo=True,
3483 3483 intents={INTENT_READONLY},
3484 3484 )
3485 3485 def grep(ui, repo, pattern, *pats, **opts):
3486 3486 """search for a pattern in specified files
3487 3487
3488 3488 Search the working directory or revision history for a regular
3489 3489 expression in the specified files for the entire repository.
3490 3490
3491 3491 By default, grep searches the repository files in the working
3492 3492 directory and prints the files where it finds a match. To specify
3493 3493 historical revisions instead of the working directory, use the
3494 3494 --rev flag.
3495 3495
3496 3496 To search instead historical revision differences that contains a
3497 3497 change in match status ("-" for a match that becomes a non-match,
3498 3498 or "+" for a non-match that becomes a match), use the --diff flag.
3499 3499
3500 3500 PATTERN can be any Python (roughly Perl-compatible) regular
3501 3501 expression.
3502 3502
3503 3503 If no FILEs are specified and the --rev flag isn't supplied, all
3504 3504 files in the working directory are searched. When using the --rev
3505 3505 flag and specifying FILEs, use the --follow argument to also
3506 3506 follow the specified FILEs across renames and copies.
3507 3507
3508 3508 .. container:: verbose
3509 3509
3510 3510 Template:
3511 3511
3512 3512 The following keywords are supported in addition to the common template
3513 3513 keywords and functions. See also :hg:`help templates`.
3514 3514
3515 3515 :change: String. Character denoting insertion ``+`` or removal ``-``.
3516 3516 Available if ``--diff`` is specified.
3517 3517 :lineno: Integer. Line number of the match.
3518 3518 :path: String. Repository-absolute path of the file.
3519 3519 :texts: List of text chunks.
3520 3520
3521 3521 And each entry of ``{texts}`` provides the following sub-keywords.
3522 3522
3523 3523 :matched: Boolean. True if the chunk matches the specified pattern.
3524 3524 :text: String. Chunk content.
3525 3525
3526 3526 See :hg:`help templates.operators` for the list expansion syntax.
3527 3527
3528 3528 Returns 0 if a match is found, 1 otherwise.
3529 3529
3530 3530 """
3531 3531 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3532 3532
3533 3533 diff = opts.get('all') or opts.get('diff')
3534 3534 follow = opts.get('follow')
3535 3535 if opts.get('all_files') is None and not diff:
3536 3536 opts['all_files'] = True
3537 3537 plaingrep = (
3538 3538 opts.get('all_files') and not opts.get('rev') and not opts.get('follow')
3539 3539 )
3540 3540 all_files = opts.get('all_files')
3541 3541 if plaingrep:
3542 3542 opts['rev'] = [b'wdir()']
3543 3543
3544 3544 reflags = re.M
3545 3545 if opts.get('ignore_case'):
3546 3546 reflags |= re.I
3547 3547 try:
3548 3548 regexp = util.re.compile(pattern, reflags)
3549 3549 except re.error as inst:
3550 3550 ui.warn(
3551 3551 _(b"grep: invalid match pattern: %s\n")
3552 3552 % stringutil.forcebytestr(inst)
3553 3553 )
3554 3554 return 1
3555 3555 sep, eol = b':', b'\n'
3556 3556 if opts.get('print0'):
3557 3557 sep = eol = b'\0'
3558 3558
3559 3559 searcher = grepmod.grepsearcher(
3560 3560 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3561 3561 )
3562 3562
3563 3563 getfile = searcher._getfile
3564 3564
3565 3565 uipathfn = scmutil.getuipathfn(repo)
3566 3566
3567 3567 def display(fm, fn, ctx, pstates, states):
3568 3568 rev = scmutil.intrev(ctx)
3569 3569 if fm.isplain():
3570 3570 formatuser = ui.shortuser
3571 3571 else:
3572 3572 formatuser = pycompat.bytestr
3573 3573 if ui.quiet:
3574 3574 datefmt = b'%Y-%m-%d'
3575 3575 else:
3576 3576 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3577 3577 found = False
3578 3578
3579 3579 @util.cachefunc
3580 3580 def binary():
3581 3581 flog = getfile(fn)
3582 3582 try:
3583 3583 return stringutil.binary(flog.read(ctx.filenode(fn)))
3584 3584 except error.WdirUnsupported:
3585 3585 return ctx[fn].isbinary()
3586 3586
3587 3587 fieldnamemap = {b'linenumber': b'lineno'}
3588 3588 if diff:
3589 3589 iter = grepmod.difflinestates(pstates, states)
3590 3590 else:
3591 3591 iter = [(b'', l) for l in states]
3592 3592 for change, l in iter:
3593 3593 fm.startitem()
3594 3594 fm.context(ctx=ctx)
3595 3595 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3596 3596 fm.plain(uipathfn(fn), label=b'grep.filename')
3597 3597
3598 3598 cols = [
3599 3599 (b'rev', b'%d', rev, not plaingrep, b''),
3600 3600 (
3601 3601 b'linenumber',
3602 3602 b'%d',
3603 3603 l.linenum,
3604 3604 opts.get('line_number'),
3605 3605 b'',
3606 3606 ),
3607 3607 ]
3608 3608 if diff:
3609 3609 cols.append(
3610 3610 (
3611 3611 b'change',
3612 3612 b'%s',
3613 3613 change,
3614 3614 True,
3615 3615 b'grep.inserted '
3616 3616 if change == b'+'
3617 3617 else b'grep.deleted ',
3618 3618 )
3619 3619 )
3620 3620 cols.extend(
3621 3621 [
3622 3622 (
3623 3623 b'user',
3624 3624 b'%s',
3625 3625 formatuser(ctx.user()),
3626 3626 opts.get('user'),
3627 3627 b'',
3628 3628 ),
3629 3629 (
3630 3630 b'date',
3631 3631 b'%s',
3632 3632 fm.formatdate(ctx.date(), datefmt),
3633 3633 opts.get('date'),
3634 3634 b'',
3635 3635 ),
3636 3636 ]
3637 3637 )
3638 3638 for name, fmt, data, cond, extra_label in cols:
3639 3639 if cond:
3640 3640 fm.plain(sep, label=b'grep.sep')
3641 3641 field = fieldnamemap.get(name, name)
3642 3642 label = extra_label + (b'grep.%s' % name)
3643 3643 fm.condwrite(cond, field, fmt, data, label=label)
3644 3644 if not opts.get('files_with_matches'):
3645 3645 fm.plain(sep, label=b'grep.sep')
3646 3646 if not opts.get('text') and binary():
3647 3647 fm.plain(_(b" Binary file matches"))
3648 3648 else:
3649 3649 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3650 3650 fm.plain(eol)
3651 3651 found = True
3652 3652 if opts.get('files_with_matches'):
3653 3653 break
3654 3654 return found
3655 3655
3656 3656 def displaymatches(fm, l):
3657 3657 p = 0
3658 3658 for s, e in l.findpos(regexp):
3659 3659 if p < s:
3660 3660 fm.startitem()
3661 3661 fm.write(b'text', b'%s', l.line[p:s])
3662 3662 fm.data(matched=False)
3663 3663 fm.startitem()
3664 3664 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3665 3665 fm.data(matched=True)
3666 3666 p = e
3667 3667 if p < len(l.line):
3668 3668 fm.startitem()
3669 3669 fm.write(b'text', b'%s', l.line[p:])
3670 3670 fm.data(matched=False)
3671 3671 fm.end()
3672 3672
3673 3673 found = False
3674 3674
3675 3675 wopts = logcmdutil.walkopts(
3676 3676 pats=pats,
3677 3677 opts=opts,
3678 3678 revspec=opts['rev'],
3679 3679 include_pats=opts['include'],
3680 3680 exclude_pats=opts['exclude'],
3681 3681 follow=follow,
3682 3682 force_changelog_traversal=all_files,
3683 3683 filter_revisions_by_pats=not all_files,
3684 3684 )
3685 3685 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3686 3686
3687 3687 ui.pager(b'grep')
3688 3688 fm = ui.formatter(b'grep', pycompat.byteskwargs(opts))
3689 3689 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3690 3690 r = display(fm, fn, ctx, pstates, states)
3691 3691 found = found or r
3692 3692 if r and not diff and not all_files:
3693 3693 searcher.skipfile(fn, ctx.rev())
3694 3694 fm.end()
3695 3695
3696 3696 return not found
3697 3697
3698 3698
3699 3699 @command(
3700 3700 b'heads',
3701 3701 [
3702 3702 (
3703 3703 b'r',
3704 3704 b'rev',
3705 3705 b'',
3706 3706 _(b'show only heads which are descendants of STARTREV'),
3707 3707 _(b'STARTREV'),
3708 3708 ),
3709 3709 (b't', b'topo', False, _(b'show topological heads only')),
3710 3710 (
3711 3711 b'a',
3712 3712 b'active',
3713 3713 False,
3714 3714 _(b'show active branchheads only (DEPRECATED)'),
3715 3715 ),
3716 3716 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3717 3717 ]
3718 3718 + templateopts,
3719 3719 _(b'[-ct] [-r STARTREV] [REV]...'),
3720 3720 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3721 3721 intents={INTENT_READONLY},
3722 3722 )
3723 3723 def heads(ui, repo, *branchrevs, **opts):
3724 3724 """show branch heads
3725 3725
3726 3726 With no arguments, show all open branch heads in the repository.
3727 3727 Branch heads are changesets that have no descendants on the
3728 3728 same branch. They are where development generally takes place and
3729 3729 are the usual targets for update and merge operations.
3730 3730
3731 3731 If one or more REVs are given, only open branch heads on the
3732 3732 branches associated with the specified changesets are shown. This
3733 3733 means that you can use :hg:`heads .` to see the heads on the
3734 3734 currently checked-out branch.
3735 3735
3736 3736 If -c/--closed is specified, also show branch heads marked closed
3737 3737 (see :hg:`commit --close-branch`).
3738 3738
3739 3739 If STARTREV is specified, only those heads that are descendants of
3740 3740 STARTREV will be displayed.
3741 3741
3742 3742 If -t/--topo is specified, named branch mechanics will be ignored and only
3743 3743 topological heads (changesets with no children) will be shown.
3744 3744
3745 3745 Returns 0 if matching heads are found, 1 if not.
3746 3746 """
3747 3747
3748 3748 start = None
3749 3749 rev = opts.get('rev')
3750 3750 if rev:
3751 3751 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3752 3752 start = logcmdutil.revsingle(repo, rev, None).node()
3753 3753
3754 3754 if opts.get('topo'):
3755 3755 heads = [repo[h] for h in repo.heads(start)]
3756 3756 else:
3757 3757 heads = []
3758 3758 for branch in repo.branchmap():
3759 3759 heads += repo.branchheads(branch, start, opts.get('closed'))
3760 3760 heads = [repo[h] for h in heads]
3761 3761
3762 3762 if branchrevs:
3763 3763 branches = {
3764 3764 repo[r].branch() for r in logcmdutil.revrange(repo, branchrevs)
3765 3765 }
3766 3766 heads = [h for h in heads if h.branch() in branches]
3767 3767
3768 3768 if opts.get('active') and branchrevs:
3769 3769 dagheads = repo.heads(start)
3770 3770 heads = [h for h in heads if h.node() in dagheads]
3771 3771
3772 3772 if branchrevs:
3773 3773 haveheads = {h.branch() for h in heads}
3774 3774 if branches - haveheads:
3775 3775 headless = b', '.join(b for b in branches - haveheads)
3776 3776 msg = _(b'no open branch heads found on branches %s')
3777 3777 if opts.get('rev'):
3778 3778 msg += _(b' (started at %s)') % opts['rev']
3779 3779 ui.warn((msg + b'\n') % headless)
3780 3780
3781 3781 if not heads:
3782 3782 return 1
3783 3783
3784 3784 ui.pager(b'heads')
3785 3785 heads = sorted(heads, key=lambda x: -(x.rev()))
3786 3786 displayer = logcmdutil.changesetdisplayer(
3787 3787 ui, repo, pycompat.byteskwargs(opts)
3788 3788 )
3789 3789 for ctx in heads:
3790 3790 displayer.show(ctx)
3791 3791 displayer.close()
3792 3792
3793 3793
3794 3794 @command(
3795 3795 b'help',
3796 3796 [
3797 3797 (b'e', b'extension', None, _(b'show only help for extensions')),
3798 3798 (b'c', b'command', None, _(b'show only help for commands')),
3799 3799 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3800 3800 (
3801 3801 b's',
3802 3802 b'system',
3803 3803 [],
3804 3804 _(b'show help for specific platform(s)'),
3805 3805 _(b'PLATFORM'),
3806 3806 ),
3807 3807 ],
3808 3808 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3809 3809 helpcategory=command.CATEGORY_HELP,
3810 3810 norepo=True,
3811 3811 intents={INTENT_READONLY},
3812 3812 )
3813 3813 def help_(ui, name=None, **opts):
3814 3814 """show help for a given topic or a help overview
3815 3815
3816 3816 With no arguments, print a list of commands with short help messages.
3817 3817
3818 3818 Given a topic, extension, or command name, print help for that
3819 3819 topic.
3820 3820
3821 3821 Returns 0 if successful.
3822 3822 """
3823 3823
3824 3824 keep = opts.get('system') or []
3825 3825 if len(keep) == 0:
3826 3826 if pycompat.sysplatform.startswith(b'win'):
3827 3827 keep.append(b'windows')
3828 3828 elif pycompat.sysplatform == b'OpenVMS':
3829 3829 keep.append(b'vms')
3830 3830 elif pycompat.sysplatform == b'plan9':
3831 3831 keep.append(b'plan9')
3832 3832 else:
3833 3833 keep.append(b'unix')
3834 3834 keep.append(pycompat.sysplatform.lower())
3835 3835 if ui.verbose:
3836 3836 keep.append(b'verbose')
3837 3837
3838 3838 commands = sys.modules[__name__]
3839 3839 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3840 3840 ui.pager(b'help')
3841 3841 ui.write(formatted)
3842 3842
3843 3843
3844 3844 @command(
3845 3845 b'identify|id',
3846 3846 [
3847 3847 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3848 3848 (b'n', b'num', None, _(b'show local revision number')),
3849 3849 (b'i', b'id', None, _(b'show global revision id')),
3850 3850 (b'b', b'branch', None, _(b'show branch')),
3851 3851 (b't', b'tags', None, _(b'show tags')),
3852 3852 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3853 3853 ]
3854 3854 + remoteopts
3855 3855 + formatteropts,
3856 3856 _(b'[-nibtB] [-r REV] [SOURCE]'),
3857 3857 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3858 3858 optionalrepo=True,
3859 3859 intents={INTENT_READONLY},
3860 3860 )
3861 3861 def identify(
3862 3862 ui,
3863 3863 repo,
3864 3864 source=None,
3865 3865 rev=None,
3866 3866 num=None,
3867 3867 id=None,
3868 3868 branch=None,
3869 3869 tags=None,
3870 3870 bookmarks=None,
3871 3871 **opts
3872 3872 ):
3873 3873 """identify the working directory or specified revision
3874 3874
3875 3875 Print a summary identifying the repository state at REV using one or
3876 3876 two parent hash identifiers, followed by a "+" if the working
3877 3877 directory has uncommitted changes, the branch name (if not default),
3878 3878 a list of tags, and a list of bookmarks.
3879 3879
3880 3880 When REV is not given, print a summary of the current state of the
3881 3881 repository including the working directory. Specify -r. to get information
3882 3882 of the working directory parent without scanning uncommitted changes.
3883 3883
3884 3884 Specifying a path to a repository root or Mercurial bundle will
3885 3885 cause lookup to operate on that repository/bundle.
3886 3886
3887 3887 .. container:: verbose
3888 3888
3889 3889 Template:
3890 3890
3891 3891 The following keywords are supported in addition to the common template
3892 3892 keywords and functions. See also :hg:`help templates`.
3893 3893
3894 3894 :dirty: String. Character ``+`` denoting if the working directory has
3895 3895 uncommitted changes.
3896 3896 :id: String. One or two nodes, optionally followed by ``+``.
3897 3897 :parents: List of strings. Parent nodes of the changeset.
3898 3898
3899 3899 Examples:
3900 3900
3901 3901 - generate a build identifier for the working directory::
3902 3902
3903 3903 hg id --id > build-id.dat
3904 3904
3905 3905 - find the revision corresponding to a tag::
3906 3906
3907 3907 hg id -n -r 1.3
3908 3908
3909 3909 - check the most recent revision of a remote repository::
3910 3910
3911 3911 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3912 3912
3913 3913 See :hg:`log` for generating more information about specific revisions,
3914 3914 including full hash identifiers.
3915 3915
3916 3916 Returns 0 if successful.
3917 3917 """
3918 3918
3919 3919 opts = pycompat.byteskwargs(opts)
3920 3920 if not repo and not source:
3921 3921 raise error.InputError(
3922 3922 _(b"there is no Mercurial repository here (.hg not found)")
3923 3923 )
3924 3924
3925 3925 default = not (num or id or branch or tags or bookmarks)
3926 3926 output = []
3927 3927 revs = []
3928 3928
3929 3929 peer = None
3930 3930 try:
3931 3931 if source:
3932 3932 path = urlutil.get_unique_pull_path_obj(b'identify', ui, source)
3933 3933 # only pass ui when no repo
3934 3934 peer = hg.peer(repo or ui, opts, path)
3935 3935 repo = peer.local()
3936 3936 branches = (path.branch, [])
3937 3937 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3938 3938
3939 3939 fm = ui.formatter(b'identify', opts)
3940 3940 fm.startitem()
3941 3941
3942 3942 if not repo:
3943 3943 if num or branch or tags:
3944 3944 raise error.InputError(
3945 3945 _(b"can't query remote revision number, branch, or tags")
3946 3946 )
3947 3947 if not rev and revs:
3948 3948 rev = revs[0]
3949 3949 if not rev:
3950 3950 rev = b"tip"
3951 3951
3952 3952 remoterev = peer.lookup(rev)
3953 3953 hexrev = fm.hexfunc(remoterev)
3954 3954 if default or id:
3955 3955 output = [hexrev]
3956 3956 fm.data(id=hexrev)
3957 3957
3958 3958 @util.cachefunc
3959 3959 def getbms():
3960 3960 bms = []
3961 3961
3962 3962 if b'bookmarks' in peer.listkeys(b'namespaces'):
3963 3963 hexremoterev = hex(remoterev)
3964 3964 bms = [
3965 3965 bm
3966 3966 for bm, bmr in peer.listkeys(b'bookmarks').items()
3967 3967 if bmr == hexremoterev
3968 3968 ]
3969 3969
3970 3970 return sorted(bms)
3971 3971
3972 3972 if fm.isplain():
3973 3973 if bookmarks:
3974 3974 output.extend(getbms())
3975 3975 elif default and not ui.quiet:
3976 3976 # multiple bookmarks for a single parent separated by '/'
3977 3977 bm = b'/'.join(getbms())
3978 3978 if bm:
3979 3979 output.append(bm)
3980 3980 else:
3981 3981 fm.data(node=hex(remoterev))
3982 3982 if bookmarks or b'bookmarks' in fm.datahint():
3983 3983 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3984 3984 else:
3985 3985 if rev:
3986 3986 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3987 3987 ctx = logcmdutil.revsingle(repo, rev, None)
3988 3988
3989 3989 if ctx.rev() is None:
3990 3990 ctx = repo[None]
3991 3991 parents = ctx.parents()
3992 3992 taglist = []
3993 3993 for p in parents:
3994 3994 taglist.extend(p.tags())
3995 3995
3996 3996 dirty = b""
3997 3997 if ctx.dirty(missing=True, merge=False, branch=False):
3998 3998 dirty = b'+'
3999 3999 fm.data(dirty=dirty)
4000 4000
4001 4001 hexoutput = [fm.hexfunc(p.node()) for p in parents]
4002 4002 if default or id:
4003 4003 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
4004 4004 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
4005 4005
4006 4006 if num:
4007 4007 numoutput = [b"%d" % p.rev() for p in parents]
4008 4008 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
4009 4009
4010 4010 fm.data(
4011 4011 parents=fm.formatlist(
4012 4012 [fm.hexfunc(p.node()) for p in parents], name=b'node'
4013 4013 )
4014 4014 )
4015 4015 else:
4016 4016 hexoutput = fm.hexfunc(ctx.node())
4017 4017 if default or id:
4018 4018 output = [hexoutput]
4019 4019 fm.data(id=hexoutput)
4020 4020
4021 4021 if num:
4022 4022 output.append(pycompat.bytestr(ctx.rev()))
4023 4023 taglist = ctx.tags()
4024 4024
4025 4025 if default and not ui.quiet:
4026 4026 b = ctx.branch()
4027 4027 if b != b'default':
4028 4028 output.append(b"(%s)" % b)
4029 4029
4030 4030 # multiple tags for a single parent separated by '/'
4031 4031 t = b'/'.join(taglist)
4032 4032 if t:
4033 4033 output.append(t)
4034 4034
4035 4035 # multiple bookmarks for a single parent separated by '/'
4036 4036 bm = b'/'.join(ctx.bookmarks())
4037 4037 if bm:
4038 4038 output.append(bm)
4039 4039 else:
4040 4040 if branch:
4041 4041 output.append(ctx.branch())
4042 4042
4043 4043 if tags:
4044 4044 output.extend(taglist)
4045 4045
4046 4046 if bookmarks:
4047 4047 output.extend(ctx.bookmarks())
4048 4048
4049 4049 fm.data(node=ctx.hex())
4050 4050 fm.data(branch=ctx.branch())
4051 4051 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4052 4052 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4053 4053 fm.context(ctx=ctx)
4054 4054
4055 4055 fm.plain(b"%s\n" % b' '.join(output))
4056 4056 fm.end()
4057 4057 finally:
4058 4058 if peer:
4059 4059 peer.close()
4060 4060
4061 4061
4062 4062 @command(
4063 4063 b'import|patch',
4064 4064 [
4065 4065 (
4066 4066 b'p',
4067 4067 b'strip',
4068 4068 1,
4069 4069 _(
4070 4070 b'directory strip option for patch. This has the same '
4071 4071 b'meaning as the corresponding patch option'
4072 4072 ),
4073 4073 _(b'NUM'),
4074 4074 ),
4075 4075 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4076 4076 (b'', b'secret', None, _(b'use the secret phase for committing')),
4077 4077 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4078 4078 (
4079 4079 b'f',
4080 4080 b'force',
4081 4081 None,
4082 4082 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4083 4083 ),
4084 4084 (
4085 4085 b'',
4086 4086 b'no-commit',
4087 4087 None,
4088 4088 _(b"don't commit, just update the working directory"),
4089 4089 ),
4090 4090 (
4091 4091 b'',
4092 4092 b'bypass',
4093 4093 None,
4094 4094 _(b"apply patch without touching the working directory"),
4095 4095 ),
4096 4096 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4097 4097 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4098 4098 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4099 4099 (
4100 4100 b'',
4101 4101 b'import-branch',
4102 4102 None,
4103 4103 _(b'use any branch information in patch (implied by --exact)'),
4104 4104 ),
4105 4105 ]
4106 4106 + commitopts
4107 4107 + commitopts2
4108 4108 + similarityopts,
4109 4109 _(b'[OPTION]... PATCH...'),
4110 4110 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4111 4111 )
4112 4112 def import_(ui, repo, patch1=None, *patches, **opts):
4113 4113 """import an ordered set of patches
4114 4114
4115 4115 Import a list of patches and commit them individually (unless
4116 4116 --no-commit is specified).
4117 4117
4118 4118 To read a patch from standard input (stdin), use "-" as the patch
4119 4119 name. If a URL is specified, the patch will be downloaded from
4120 4120 there.
4121 4121
4122 4122 Import first applies changes to the working directory (unless
4123 4123 --bypass is specified), import will abort if there are outstanding
4124 4124 changes.
4125 4125
4126 4126 Use --bypass to apply and commit patches directly to the
4127 4127 repository, without affecting the working directory. Without
4128 4128 --exact, patches will be applied on top of the working directory
4129 4129 parent revision.
4130 4130
4131 4131 You can import a patch straight from a mail message. Even patches
4132 4132 as attachments work (to use the body part, it must have type
4133 4133 text/plain or text/x-patch). From and Subject headers of email
4134 4134 message are used as default committer and commit message. All
4135 4135 text/plain body parts before first diff are added to the commit
4136 4136 message.
4137 4137
4138 4138 If the imported patch was generated by :hg:`export`, user and
4139 4139 description from patch override values from message headers and
4140 4140 body. Values given on command line with -m/--message and -u/--user
4141 4141 override these.
4142 4142
4143 4143 If --exact is specified, import will set the working directory to
4144 4144 the parent of each patch before applying it, and will abort if the
4145 4145 resulting changeset has a different ID than the one recorded in
4146 4146 the patch. This will guard against various ways that portable
4147 4147 patch formats and mail systems might fail to transfer Mercurial
4148 4148 data or metadata. See :hg:`bundle` for lossless transmission.
4149 4149
4150 4150 Use --partial to ensure a changeset will be created from the patch
4151 4151 even if some hunks fail to apply. Hunks that fail to apply will be
4152 4152 written to a <target-file>.rej file. Conflicts can then be resolved
4153 4153 by hand before :hg:`commit --amend` is run to update the created
4154 4154 changeset. This flag exists to let people import patches that
4155 4155 partially apply without losing the associated metadata (author,
4156 4156 date, description, ...).
4157 4157
4158 4158 .. note::
4159 4159
4160 4160 When no hunks apply cleanly, :hg:`import --partial` will create
4161 4161 an empty changeset, importing only the patch metadata.
4162 4162
4163 4163 With -s/--similarity, hg will attempt to discover renames and
4164 4164 copies in the patch in the same way as :hg:`addremove`.
4165 4165
4166 4166 It is possible to use external patch programs to perform the patch
4167 4167 by setting the ``ui.patch`` configuration option. For the default
4168 4168 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4169 4169 See :hg:`help config` for more information about configuration
4170 4170 files and how to use these options.
4171 4171
4172 4172 See :hg:`help dates` for a list of formats valid for -d/--date.
4173 4173
4174 4174 .. container:: verbose
4175 4175
4176 4176 Examples:
4177 4177
4178 4178 - import a traditional patch from a website and detect renames::
4179 4179
4180 4180 hg import -s 80 http://example.com/bugfix.patch
4181 4181
4182 4182 - import a changeset from an hgweb server::
4183 4183
4184 4184 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4185 4185
4186 4186 - import all the patches in an Unix-style mbox::
4187 4187
4188 4188 hg import incoming-patches.mbox
4189 4189
4190 4190 - import patches from stdin::
4191 4191
4192 4192 hg import -
4193 4193
4194 4194 - attempt to exactly restore an exported changeset (not always
4195 4195 possible)::
4196 4196
4197 4197 hg import --exact proposed-fix.patch
4198 4198
4199 4199 - use an external tool to apply a patch which is too fuzzy for
4200 4200 the default internal tool.
4201 4201
4202 4202 hg import --config ui.patch="patch --merge" fuzzy.patch
4203 4203
4204 4204 - change the default fuzzing from 2 to a less strict 7
4205 4205
4206 4206 hg import --config ui.fuzz=7 fuzz.patch
4207 4207
4208 4208 Returns 0 on success, 1 on partial success (see --partial).
4209 4209 """
4210 4210
4211 4211 cmdutil.check_incompatible_arguments(
4212 4212 opts, 'no_commit', ['bypass', 'secret']
4213 4213 )
4214 4214 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4215 4215
4216 4216 if not patch1:
4217 4217 raise error.InputError(_(b'need at least one patch to import'))
4218 4218
4219 4219 patches = (patch1,) + patches
4220 4220
4221 4221 date = opts.get('date')
4222 4222 if date:
4223 4223 opts['date'] = dateutil.parsedate(date)
4224 4224
4225 4225 exact = opts.get('exact')
4226 4226 update = not opts.get('bypass')
4227 4227 try:
4228 4228 sim = float(opts.get('similarity') or 0)
4229 4229 except ValueError:
4230 4230 raise error.InputError(_(b'similarity must be a number'))
4231 4231 if sim < 0 or sim > 100:
4232 4232 raise error.InputError(_(b'similarity must be between 0 and 100'))
4233 4233 if sim and not update:
4234 4234 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4235 4235
4236 4236 base = opts["base"]
4237 4237 msgs = []
4238 4238 ret = 0
4239 4239
4240 4240 with repo.wlock():
4241 4241 if update:
4242 4242 cmdutil.checkunfinished(repo)
4243 4243 if exact or not opts.get('force'):
4244 4244 cmdutil.bailifchanged(repo)
4245 4245
4246 4246 if not opts.get('no_commit'):
4247 4247 lock = repo.lock
4248 4248 tr = lambda: repo.transaction(b'import')
4249 4249 else:
4250 4250 lock = util.nullcontextmanager
4251 4251 tr = util.nullcontextmanager
4252 4252 with lock(), tr():
4253 4253 parents = repo[None].parents()
4254 4254 for patchurl in patches:
4255 4255 if patchurl == b'-':
4256 4256 ui.status(_(b'applying patch from stdin\n'))
4257 4257 patchfile = ui.fin
4258 4258 patchurl = b'stdin' # for error message
4259 4259 else:
4260 4260 patchurl = os.path.join(base, patchurl)
4261 4261 ui.status(_(b'applying %s\n') % patchurl)
4262 4262 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4263 4263
4264 4264 haspatch = False
4265 4265 for hunk in patch.split(patchfile):
4266 4266 with patch.extract(ui, hunk) as patchdata:
4267 4267 msg, node, rej = cmdutil.tryimportone(
4268 4268 ui,
4269 4269 repo,
4270 4270 patchdata,
4271 4271 parents,
4272 4272 pycompat.byteskwargs(opts),
4273 4273 msgs,
4274 4274 hg.clean,
4275 4275 )
4276 4276 if msg:
4277 4277 haspatch = True
4278 4278 ui.note(msg + b'\n')
4279 4279 if update or exact:
4280 4280 parents = repo[None].parents()
4281 4281 else:
4282 4282 parents = [repo[node]]
4283 4283 if rej:
4284 4284 ui.write_err(_(b"patch applied partially\n"))
4285 4285 ui.write_err(
4286 4286 _(
4287 4287 b"(fix the .rej files and run "
4288 4288 b"`hg commit --amend`)\n"
4289 4289 )
4290 4290 )
4291 4291 ret = 1
4292 4292 break
4293 4293
4294 4294 if not haspatch:
4295 4295 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4296 4296
4297 4297 if msgs:
4298 4298 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4299 4299 return ret
4300 4300
4301 4301
4302 4302 @command(
4303 4303 b'incoming|in',
4304 4304 [
4305 4305 (
4306 4306 b'f',
4307 4307 b'force',
4308 4308 None,
4309 4309 _(b'run even if remote repository is unrelated'),
4310 4310 ),
4311 4311 (b'n', b'newest-first', None, _(b'show newest record first')),
4312 4312 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4313 4313 (
4314 4314 b'r',
4315 4315 b'rev',
4316 4316 [],
4317 4317 _(b'a remote changeset intended to be added'),
4318 4318 _(b'REV'),
4319 4319 ),
4320 4320 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4321 4321 (
4322 4322 b'b',
4323 4323 b'branch',
4324 4324 [],
4325 4325 _(b'a specific branch you would like to pull'),
4326 4326 _(b'BRANCH'),
4327 4327 ),
4328 4328 ]
4329 4329 + logopts
4330 4330 + remoteopts
4331 4331 + subrepoopts,
4332 4332 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4333 4333 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4334 4334 )
4335 4335 def incoming(ui, repo, source=b"default", **opts):
4336 4336 """show new changesets found in source
4337 4337
4338 4338 Show new changesets found in the specified path/URL or the default
4339 4339 pull location. These are the changesets that would have been pulled
4340 4340 by :hg:`pull` at the time you issued this command.
4341 4341
4342 4342 See pull for valid source format details.
4343 4343
4344 4344 .. container:: verbose
4345 4345
4346 4346 With -B/--bookmarks, the result of bookmark comparison between
4347 4347 local and remote repositories is displayed. With -v/--verbose,
4348 4348 status is also displayed for each bookmark like below::
4349 4349
4350 4350 BM1 01234567890a added
4351 4351 BM2 1234567890ab advanced
4352 4352 BM3 234567890abc diverged
4353 4353 BM4 34567890abcd changed
4354 4354
4355 4355 The action taken locally when pulling depends on the
4356 4356 status of each bookmark:
4357 4357
4358 4358 :``added``: pull will create it
4359 4359 :``advanced``: pull will update it
4360 4360 :``diverged``: pull will create a divergent bookmark
4361 4361 :``changed``: result depends on remote changesets
4362 4362
4363 4363 From the point of view of pulling behavior, bookmark
4364 4364 existing only in the remote repository are treated as ``added``,
4365 4365 even if it is in fact locally deleted.
4366 4366
4367 4367 .. container:: verbose
4368 4368
4369 4369 For remote repository, using --bundle avoids downloading the
4370 4370 changesets twice if the incoming is followed by a pull.
4371 4371
4372 4372 Examples:
4373 4373
4374 4374 - show incoming changes with patches and full description::
4375 4375
4376 4376 hg incoming -vp
4377 4377
4378 4378 - show incoming changes excluding merges, store a bundle::
4379 4379
4380 4380 hg in -vpM --bundle incoming.hg
4381 4381 hg pull incoming.hg
4382 4382
4383 4383 - briefly list changes inside a bundle::
4384 4384
4385 4385 hg in changes.hg -T "{desc|firstline}\\n"
4386 4386
4387 4387 Returns 0 if there are incoming changes, 1 otherwise.
4388 4388 """
4389 4389 opts = pycompat.byteskwargs(opts)
4390 4390 if opts.get(b'graph'):
4391 4391 logcmdutil.checkunsupportedgraphflags([], opts)
4392 4392
4393 4393 def display(other, chlist, displayer):
4394 4394 revdag = logcmdutil.graphrevs(other, chlist, opts)
4395 4395 logcmdutil.displaygraph(
4396 4396 ui, repo, revdag, displayer, graphmod.asciiedges
4397 4397 )
4398 4398
4399 4399 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4400 4400 return 0
4401 4401
4402 4402 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4403 4403
4404 4404 if opts.get(b'bookmarks'):
4405 4405 srcs = urlutil.get_pull_paths(repo, ui, [source])
4406 4406 for path in srcs:
4407 4407 # XXX the "branches" options are not used. Should it be used?
4408 4408 other = hg.peer(repo, opts, path)
4409 4409 try:
4410 4410 if b'bookmarks' not in other.listkeys(b'namespaces'):
4411 4411 ui.warn(_(b"remote doesn't support bookmarks\n"))
4412 4412 return 0
4413 4413 ui.pager(b'incoming')
4414 4414 ui.status(
4415 4415 _(b'comparing with %s\n') % urlutil.hidepassword(path.loc)
4416 4416 )
4417 4417 return bookmarks.incoming(
4418 4418 ui, repo, other, mode=path.bookmarks_mode
4419 4419 )
4420 4420 finally:
4421 4421 other.close()
4422 4422
4423 4423 return hg.incoming(ui, repo, source, opts)
4424 4424
4425 4425
4426 4426 @command(
4427 4427 b'init',
4428 4428 remoteopts,
4429 4429 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4430 4430 helpcategory=command.CATEGORY_REPO_CREATION,
4431 4431 helpbasic=True,
4432 4432 norepo=True,
4433 4433 )
4434 4434 def init(ui, dest=b".", **opts):
4435 4435 """create a new repository in the given directory
4436 4436
4437 4437 Initialize a new repository in the given directory. If the given
4438 4438 directory does not exist, it will be created.
4439 4439
4440 4440 If no directory is given, the current directory is used.
4441 4441
4442 4442 It is possible to specify an ``ssh://`` URL as the destination.
4443 4443 See :hg:`help urls` for more information.
4444 4444
4445 4445 Returns 0 on success.
4446 4446 """
4447 4447 opts = pycompat.byteskwargs(opts)
4448 4448 path = urlutil.get_clone_path_obj(ui, dest)
4449 4449 peer = hg.peer(ui, opts, path, create=True)
4450 4450 peer.close()
4451 4451
4452 4452
4453 4453 @command(
4454 4454 b'locate',
4455 4455 [
4456 4456 (
4457 4457 b'r',
4458 4458 b'rev',
4459 4459 b'',
4460 4460 _(b'search the repository as it is in REV'),
4461 4461 _(b'REV'),
4462 4462 ),
4463 4463 (
4464 4464 b'0',
4465 4465 b'print0',
4466 4466 None,
4467 4467 _(b'end filenames with NUL, for use with xargs'),
4468 4468 ),
4469 4469 (
4470 4470 b'f',
4471 4471 b'fullpath',
4472 4472 None,
4473 4473 _(b'print complete paths from the filesystem root'),
4474 4474 ),
4475 4475 ]
4476 4476 + walkopts,
4477 4477 _(b'[OPTION]... [PATTERN]...'),
4478 4478 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4479 4479 )
4480 4480 def locate(ui, repo, *pats, **opts):
4481 4481 """locate files matching specific patterns (DEPRECATED)
4482 4482
4483 4483 Print files under Mercurial control in the working directory whose
4484 4484 names match the given patterns.
4485 4485
4486 4486 By default, this command searches all directories in the working
4487 4487 directory. To search just the current directory and its
4488 4488 subdirectories, use "--include .".
4489 4489
4490 4490 If no patterns are given to match, this command prints the names
4491 4491 of all files under Mercurial control in the working directory.
4492 4492
4493 4493 If you want to feed the output of this command into the "xargs"
4494 4494 command, use the -0 option to both this command and "xargs". This
4495 4495 will avoid the problem of "xargs" treating single filenames that
4496 4496 contain whitespace as multiple filenames.
4497 4497
4498 4498 See :hg:`help files` for a more versatile command.
4499 4499
4500 4500 Returns 0 if a match is found, 1 otherwise.
4501 4501 """
4502 4502 if opts.get('print0'):
4503 4503 end = b'\0'
4504 4504 else:
4505 4505 end = b'\n'
4506 4506 ctx = logcmdutil.revsingle(repo, opts.get('rev'), None)
4507 4507
4508 4508 ret = 1
4509 4509 m = scmutil.match(
4510 4510 ctx,
4511 4511 pats,
4512 4512 pycompat.byteskwargs(opts),
4513 4513 default=b'relglob',
4514 4514 badfn=lambda x, y: False,
4515 4515 )
4516 4516
4517 4517 ui.pager(b'locate')
4518 4518 if ctx.rev() is None:
4519 4519 # When run on the working copy, "locate" includes removed files, so
4520 4520 # we get the list of files from the dirstate.
4521 4521 filesgen = sorted(repo.dirstate.matches(m))
4522 4522 else:
4523 4523 filesgen = ctx.matches(m)
4524 4524 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4525 4525 for abs in filesgen:
4526 4526 if opts.get('fullpath'):
4527 4527 ui.write(repo.wjoin(abs), end)
4528 4528 else:
4529 4529 ui.write(uipathfn(abs), end)
4530 4530 ret = 0
4531 4531
4532 4532 return ret
4533 4533
4534 4534
4535 4535 @command(
4536 4536 b'log|history',
4537 4537 [
4538 4538 (
4539 4539 b'f',
4540 4540 b'follow',
4541 4541 None,
4542 4542 _(
4543 4543 b'follow changeset history, or file history across copies and renames'
4544 4544 ),
4545 4545 ),
4546 4546 (
4547 4547 b'',
4548 4548 b'follow-first',
4549 4549 None,
4550 4550 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4551 4551 ),
4552 4552 (
4553 4553 b'd',
4554 4554 b'date',
4555 4555 b'',
4556 4556 _(b'show revisions matching date spec'),
4557 4557 _(b'DATE'),
4558 4558 ),
4559 4559 (b'C', b'copies', None, _(b'show copied files')),
4560 4560 (
4561 4561 b'k',
4562 4562 b'keyword',
4563 4563 [],
4564 4564 _(b'do case-insensitive search for a given text'),
4565 4565 _(b'TEXT'),
4566 4566 ),
4567 4567 (
4568 4568 b'r',
4569 4569 b'rev',
4570 4570 [],
4571 4571 _(b'revisions to select or follow from'),
4572 4572 _(b'REV'),
4573 4573 ),
4574 4574 (
4575 4575 b'L',
4576 4576 b'line-range',
4577 4577 [],
4578 4578 _(b'follow line range of specified file (EXPERIMENTAL)'),
4579 4579 _(b'FILE,RANGE'),
4580 4580 ),
4581 4581 (
4582 4582 b'',
4583 4583 b'removed',
4584 4584 None,
4585 4585 _(b'include revisions where files were removed'),
4586 4586 ),
4587 4587 (
4588 4588 b'm',
4589 4589 b'only-merges',
4590 4590 None,
4591 4591 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4592 4592 ),
4593 4593 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4594 4594 (
4595 4595 b'',
4596 4596 b'only-branch',
4597 4597 [],
4598 4598 _(
4599 4599 b'show only changesets within the given named branch (DEPRECATED)'
4600 4600 ),
4601 4601 _(b'BRANCH'),
4602 4602 ),
4603 4603 (
4604 4604 b'b',
4605 4605 b'branch',
4606 4606 [],
4607 4607 _(b'show changesets within the given named branch'),
4608 4608 _(b'BRANCH'),
4609 4609 ),
4610 4610 (
4611 4611 b'B',
4612 4612 b'bookmark',
4613 4613 [],
4614 4614 _(b"show changesets within the given bookmark"),
4615 4615 _(b'BOOKMARK'),
4616 4616 ),
4617 4617 (
4618 4618 b'P',
4619 4619 b'prune',
4620 4620 [],
4621 4621 _(b'do not display revision or any of its ancestors'),
4622 4622 _(b'REV'),
4623 4623 ),
4624 4624 ]
4625 4625 + logopts
4626 4626 + walkopts,
4627 4627 _(b'[OPTION]... [FILE]'),
4628 4628 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4629 4629 helpbasic=True,
4630 4630 inferrepo=True,
4631 4631 intents={INTENT_READONLY},
4632 4632 )
4633 4633 def log(ui, repo, *pats, **opts):
4634 4634 """show revision history of entire repository or files
4635 4635
4636 4636 Print the revision history of the specified files or the entire
4637 4637 project.
4638 4638
4639 4639 If no revision range is specified, the default is ``tip:0`` unless
4640 4640 --follow is set.
4641 4641
4642 4642 File history is shown without following rename or copy history of
4643 4643 files. Use -f/--follow with a filename to follow history across
4644 4644 renames and copies. --follow without a filename will only show
4645 4645 ancestors of the starting revisions. The starting revisions can be
4646 4646 specified by -r/--rev, which default to the working directory parent.
4647 4647
4648 4648 By default this command prints revision number and changeset id,
4649 4649 tags, non-trivial parents, user, date and time, and a summary for
4650 4650 each commit. When the -v/--verbose switch is used, the list of
4651 4651 changed files and full commit message are shown.
4652 4652
4653 4653 With --graph the revisions are shown as an ASCII art DAG with the most
4654 4654 recent changeset at the top.
4655 4655 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4656 4656 involved in an unresolved merge conflict, '_' closes a branch,
4657 4657 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4658 4658 changeset from the lines below is a parent of the 'o' merge on the same
4659 4659 line.
4660 4660 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4661 4661 of a '|' indicates one or more revisions in a path are omitted.
4662 4662
4663 4663 .. container:: verbose
4664 4664
4665 4665 Use -L/--line-range FILE,M:N options to follow the history of lines
4666 4666 from M to N in FILE. With -p/--patch only diff hunks affecting
4667 4667 specified line range will be shown. This option requires --follow;
4668 4668 it can be specified multiple times. Currently, this option is not
4669 4669 compatible with --graph. This option is experimental.
4670 4670
4671 4671 .. note::
4672 4672
4673 4673 :hg:`log --patch` may generate unexpected diff output for merge
4674 4674 changesets, as it will only compare the merge changeset against
4675 4675 its first parent. Also, only files different from BOTH parents
4676 4676 will appear in files:.
4677 4677
4678 4678 .. note::
4679 4679
4680 4680 For performance reasons, :hg:`log FILE` may omit duplicate changes
4681 4681 made on branches and will not show removals or mode changes. To
4682 4682 see all such changes, use the --removed switch.
4683 4683
4684 4684 .. container:: verbose
4685 4685
4686 4686 .. note::
4687 4687
4688 4688 The history resulting from -L/--line-range options depends on diff
4689 4689 options; for instance if white-spaces are ignored, respective changes
4690 4690 with only white-spaces in specified line range will not be listed.
4691 4691
4692 4692 .. container:: verbose
4693 4693
4694 4694 Some examples:
4695 4695
4696 4696 - changesets with full descriptions and file lists::
4697 4697
4698 4698 hg log -v
4699 4699
4700 4700 - changesets ancestral to the working directory::
4701 4701
4702 4702 hg log -f
4703 4703
4704 4704 - last 10 commits on the current branch::
4705 4705
4706 4706 hg log -l 10 -b .
4707 4707
4708 4708 - changesets showing all modifications of a file, including removals::
4709 4709
4710 4710 hg log --removed file.c
4711 4711
4712 4712 - all changesets that touch a directory, with diffs, excluding merges::
4713 4713
4714 4714 hg log -Mp lib/
4715 4715
4716 4716 - all revision numbers that match a keyword::
4717 4717
4718 4718 hg log -k bug --template "{rev}\\n"
4719 4719
4720 4720 - the full hash identifier of the working directory parent::
4721 4721
4722 4722 hg log -r . --template "{node}\\n"
4723 4723
4724 4724 - list available log templates::
4725 4725
4726 4726 hg log -T list
4727 4727
4728 4728 - check if a given changeset is included in a tagged release::
4729 4729
4730 4730 hg log -r "a21ccf and ancestor(1.9)"
4731 4731
4732 4732 - find all changesets by some user in a date range::
4733 4733
4734 4734 hg log -k alice -d "may 2008 to jul 2008"
4735 4735
4736 4736 - summary of all changesets after the last tag::
4737 4737
4738 4738 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4739 4739
4740 4740 - changesets touching lines 13 to 23 for file.c::
4741 4741
4742 4742 hg log -L file.c,13:23
4743 4743
4744 4744 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4745 4745 main.c with patch::
4746 4746
4747 4747 hg log -L file.c,13:23 -L main.c,2:6 -p
4748 4748
4749 4749 See :hg:`help dates` for a list of formats valid for -d/--date.
4750 4750
4751 4751 See :hg:`help revisions` for more about specifying and ordering
4752 4752 revisions.
4753 4753
4754 4754 See :hg:`help templates` for more about pre-packaged styles and
4755 4755 specifying custom templates. The default template used by the log
4756 4756 command can be customized via the ``command-templates.log`` configuration
4757 4757 setting.
4758 4758
4759 4759 Returns 0 on success.
4760 4760
4761 4761 """
4762 4762 opts = pycompat.byteskwargs(opts)
4763 4763 linerange = opts.get(b'line_range')
4764 4764
4765 4765 if linerange and not opts.get(b'follow'):
4766 4766 raise error.InputError(_(b'--line-range requires --follow'))
4767 4767
4768 4768 if linerange and pats:
4769 4769 # TODO: take pats as patterns with no line-range filter
4770 4770 raise error.InputError(
4771 4771 _(b'FILE arguments are not compatible with --line-range option')
4772 4772 )
4773 4773
4774 4774 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4775 4775 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4776 4776 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4777 4777 if linerange:
4778 4778 # TODO: should follow file history from logcmdutil._initialrevs(),
4779 4779 # then filter the result by logcmdutil._makerevset() and --limit
4780 4780 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4781 4781
4782 4782 getcopies = None
4783 4783 if opts.get(b'copies'):
4784 4784 endrev = None
4785 4785 if revs:
4786 4786 endrev = revs.max() + 1
4787 4787 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4788 4788
4789 4789 ui.pager(b'log')
4790 4790 displayer = logcmdutil.changesetdisplayer(
4791 4791 ui, repo, opts, differ, buffered=True
4792 4792 )
4793 4793 if opts.get(b'graph'):
4794 4794 displayfn = logcmdutil.displaygraphrevs
4795 4795 else:
4796 4796 displayfn = logcmdutil.displayrevs
4797 4797 displayfn(ui, repo, revs, displayer, getcopies)
4798 4798
4799 4799
4800 4800 @command(
4801 4801 b'manifest',
4802 4802 [
4803 4803 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4804 4804 (b'', b'all', False, _(b"list files from all revisions")),
4805 4805 ]
4806 4806 + formatteropts,
4807 4807 _(b'[-r REV]'),
4808 4808 helpcategory=command.CATEGORY_MAINTENANCE,
4809 4809 intents={INTENT_READONLY},
4810 4810 )
4811 4811 def manifest(ui, repo, node=None, rev=None, **opts):
4812 4812 """output the current or given revision of the project manifest
4813 4813
4814 4814 Print a list of version controlled files for the given revision.
4815 4815 If no revision is given, the first parent of the working directory
4816 4816 is used, or the null revision if no revision is checked out.
4817 4817
4818 4818 With -v, print file permissions, symlink and executable bits.
4819 4819 With --debug, print file revision hashes.
4820 4820
4821 4821 If option --all is specified, the list of all files from all revisions
4822 4822 is printed. This includes deleted and renamed files.
4823 4823
4824 4824 Returns 0 on success.
4825 4825 """
4826 4826 fm = ui.formatter(b'manifest', pycompat.byteskwargs(opts))
4827 4827
4828 4828 if opts.get('all'):
4829 4829 if rev or node:
4830 4830 raise error.InputError(_(b"can't specify a revision with --all"))
4831 4831
4832 4832 res = set()
4833 4833 for rev in repo:
4834 4834 ctx = repo[rev]
4835 4835 res |= set(ctx.files())
4836 4836
4837 4837 ui.pager(b'manifest')
4838 4838 for f in sorted(res):
4839 4839 fm.startitem()
4840 4840 fm.write(b"path", b'%s\n', f)
4841 4841 fm.end()
4842 4842 return
4843 4843
4844 4844 if rev and node:
4845 4845 raise error.InputError(_(b"please specify just one revision"))
4846 4846
4847 4847 if not node:
4848 4848 node = rev
4849 4849
4850 4850 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4851 4851 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4852 4852 if node:
4853 4853 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4854 4854 ctx = logcmdutil.revsingle(repo, node)
4855 4855 mf = ctx.manifest()
4856 4856 ui.pager(b'manifest')
4857 4857 for f in ctx:
4858 4858 fm.startitem()
4859 4859 fm.context(ctx=ctx)
4860 4860 fl = ctx[f].flags()
4861 4861 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4862 4862 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4863 4863 fm.write(b'path', b'%s\n', f)
4864 4864 fm.end()
4865 4865
4866 4866
4867 4867 @command(
4868 4868 b'merge',
4869 4869 [
4870 4870 (
4871 4871 b'f',
4872 4872 b'force',
4873 4873 None,
4874 4874 _(b'force a merge including outstanding changes (DEPRECATED)'),
4875 4875 ),
4876 4876 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4877 4877 (
4878 4878 b'P',
4879 4879 b'preview',
4880 4880 None,
4881 4881 _(b'review revisions to merge (no merge is performed)'),
4882 4882 ),
4883 4883 (b'', b'abort', None, _(b'abort the ongoing merge')),
4884 4884 ]
4885 4885 + mergetoolopts,
4886 4886 _(b'[-P] [[-r] REV]'),
4887 4887 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4888 4888 helpbasic=True,
4889 4889 )
4890 4890 def merge(ui, repo, node=None, **opts):
4891 4891 """merge another revision into working directory
4892 4892
4893 4893 The current working directory is updated with all changes made in
4894 4894 the requested revision since the last common predecessor revision.
4895 4895
4896 4896 Files that changed between either parent are marked as changed for
4897 4897 the next commit and a commit must be performed before any further
4898 4898 updates to the repository are allowed. The next commit will have
4899 4899 two parents.
4900 4900
4901 4901 ``--tool`` can be used to specify the merge tool used for file
4902 4902 merges. It overrides the HGMERGE environment variable and your
4903 4903 configuration files. See :hg:`help merge-tools` for options.
4904 4904
4905 4905 If no revision is specified, the working directory's parent is a
4906 4906 head revision, and the current branch contains exactly one other
4907 4907 head, the other head is merged with by default. Otherwise, an
4908 4908 explicit revision with which to merge must be provided.
4909 4909
4910 4910 See :hg:`help resolve` for information on handling file conflicts.
4911 4911
4912 4912 To undo an uncommitted merge, use :hg:`merge --abort` which
4913 4913 will check out a clean copy of the original merge parent, losing
4914 4914 all changes.
4915 4915
4916 4916 Returns 0 on success, 1 if there are unresolved files.
4917 4917 """
4918 4918
4919 4919 abort = opts.get('abort')
4920 4920 if abort and repo.dirstate.p2() == repo.nullid:
4921 4921 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4922 4922 cmdutil.check_incompatible_arguments(opts, 'abort', ['rev', 'preview'])
4923 4923 if abort:
4924 4924 state = cmdutil.getunfinishedstate(repo)
4925 4925 if state and state._opname != b'merge':
4926 4926 raise error.StateError(
4927 4927 _(b'cannot abort merge with %s in progress') % (state._opname),
4928 4928 hint=state.hint(),
4929 4929 )
4930 4930 if node:
4931 4931 raise error.InputError(_(b"cannot specify a node with --abort"))
4932 4932 return hg.abortmerge(repo.ui, repo)
4933 4933
4934 4934 if opts.get('rev') and node:
4935 4935 raise error.InputError(_(b"please specify just one revision"))
4936 4936 if not node:
4937 4937 node = opts.get('rev')
4938 4938
4939 4939 if node:
4940 4940 ctx = logcmdutil.revsingle(repo, node)
4941 4941 else:
4942 4942 if ui.configbool(b'commands', b'merge.require-rev'):
4943 4943 raise error.InputError(
4944 4944 _(
4945 4945 b'configuration requires specifying revision to merge '
4946 4946 b'with'
4947 4947 )
4948 4948 )
4949 4949 ctx = repo[destutil.destmerge(repo)]
4950 4950
4951 4951 if ctx.node() is None:
4952 4952 raise error.InputError(
4953 4953 _(b'merging with the working copy has no effect')
4954 4954 )
4955 4955
4956 4956 if opts.get('preview'):
4957 4957 # find nodes that are ancestors of p2 but not of p1
4958 4958 p1 = repo[b'.'].node()
4959 4959 p2 = ctx.node()
4960 4960 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4961 4961
4962 4962 displayer = logcmdutil.changesetdisplayer(
4963 4963 ui, repo, pycompat.byteskwargs(opts)
4964 4964 )
4965 4965 for node in nodes:
4966 4966 displayer.show(repo[node])
4967 4967 displayer.close()
4968 4968 return 0
4969 4969
4970 4970 # ui.forcemerge is an internal variable, do not document
4971 4971 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
4972 4972 with ui.configoverride(overrides, b'merge'):
4973 4973 force = opts.get('force')
4974 4974 labels = [b'working copy', b'merge rev', b'common ancestor']
4975 4975 return hg.merge(ctx, force=force, labels=labels)
4976 4976
4977 4977
4978 4978 statemod.addunfinished(
4979 4979 b'merge',
4980 4980 fname=None,
4981 4981 clearable=True,
4982 4982 allowcommit=True,
4983 4983 cmdmsg=_(b'outstanding uncommitted merge'),
4984 4984 abortfunc=hg.abortmerge,
4985 4985 statushint=_(
4986 4986 b'To continue: hg commit\nTo abort: hg merge --abort'
4987 4987 ),
4988 4988 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4989 4989 )
4990 4990
4991 4991
4992 4992 @command(
4993 4993 b'outgoing|out',
4994 4994 [
4995 4995 (
4996 4996 b'f',
4997 4997 b'force',
4998 4998 None,
4999 4999 _(b'run even when the destination is unrelated'),
5000 5000 ),
5001 5001 (
5002 5002 b'r',
5003 5003 b'rev',
5004 5004 [],
5005 5005 _(b'a changeset intended to be included in the destination'),
5006 5006 _(b'REV'),
5007 5007 ),
5008 5008 (b'n', b'newest-first', None, _(b'show newest record first')),
5009 5009 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
5010 5010 (
5011 5011 b'b',
5012 5012 b'branch',
5013 5013 [],
5014 5014 _(b'a specific branch you would like to push'),
5015 5015 _(b'BRANCH'),
5016 5016 ),
5017 5017 ]
5018 5018 + logopts
5019 5019 + remoteopts
5020 5020 + subrepoopts,
5021 5021 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]...'),
5022 5022 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5023 5023 )
5024 5024 def outgoing(ui, repo, *dests, **opts):
5025 5025 """show changesets not found in the destination
5026 5026
5027 5027 Show changesets not found in the specified destination repository
5028 5028 or the default push location. These are the changesets that would
5029 5029 be pushed if a push was requested.
5030 5030
5031 5031 See pull for details of valid destination formats.
5032 5032
5033 5033 .. container:: verbose
5034 5034
5035 5035 With -B/--bookmarks, the result of bookmark comparison between
5036 5036 local and remote repositories is displayed. With -v/--verbose,
5037 5037 status is also displayed for each bookmark like below::
5038 5038
5039 5039 BM1 01234567890a added
5040 5040 BM2 deleted
5041 5041 BM3 234567890abc advanced
5042 5042 BM4 34567890abcd diverged
5043 5043 BM5 4567890abcde changed
5044 5044
5045 5045 The action taken when pushing depends on the
5046 5046 status of each bookmark:
5047 5047
5048 5048 :``added``: push with ``-B`` will create it
5049 5049 :``deleted``: push with ``-B`` will delete it
5050 5050 :``advanced``: push will update it
5051 5051 :``diverged``: push with ``-B`` will update it
5052 5052 :``changed``: push with ``-B`` will update it
5053 5053
5054 5054 From the point of view of pushing behavior, bookmarks
5055 5055 existing only in the remote repository are treated as
5056 5056 ``deleted``, even if it is in fact added remotely.
5057 5057
5058 5058 Returns 0 if there are outgoing changes, 1 otherwise.
5059 5059 """
5060 5060 opts = pycompat.byteskwargs(opts)
5061 5061 if opts.get(b'bookmarks'):
5062 5062 for path in urlutil.get_push_paths(repo, ui, dests):
5063 5063 other = hg.peer(repo, opts, path)
5064 5064 try:
5065 5065 if b'bookmarks' not in other.listkeys(b'namespaces'):
5066 5066 ui.warn(_(b"remote doesn't support bookmarks\n"))
5067 5067 return 0
5068 5068 ui.status(
5069 5069 _(b'comparing with %s\n') % urlutil.hidepassword(path.loc)
5070 5070 )
5071 5071 ui.pager(b'outgoing')
5072 5072 return bookmarks.outgoing(ui, repo, other)
5073 5073 finally:
5074 5074 other.close()
5075 5075
5076 5076 return hg.outgoing(ui, repo, dests, opts)
5077 5077
5078 5078
5079 5079 @command(
5080 5080 b'parents',
5081 5081 [
5082 5082 (
5083 5083 b'r',
5084 5084 b'rev',
5085 5085 b'',
5086 5086 _(b'show parents of the specified revision'),
5087 5087 _(b'REV'),
5088 5088 ),
5089 5089 ]
5090 5090 + templateopts,
5091 5091 _(b'[-r REV] [FILE]'),
5092 5092 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5093 5093 inferrepo=True,
5094 5094 )
5095 5095 def parents(ui, repo, file_=None, **opts):
5096 5096 """show the parents of the working directory or revision (DEPRECATED)
5097 5097
5098 5098 Print the working directory's parent revisions. If a revision is
5099 5099 given via -r/--rev, the parent of that revision will be printed.
5100 5100 If a file argument is given, the revision in which the file was
5101 5101 last changed (before the working directory revision or the
5102 5102 argument to --rev if given) is printed.
5103 5103
5104 5104 This command is equivalent to::
5105 5105
5106 5106 hg log -r "p1()+p2()" or
5107 5107 hg log -r "p1(REV)+p2(REV)" or
5108 5108 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5109 5109 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5110 5110
5111 5111 See :hg:`summary` and :hg:`help revsets` for related information.
5112 5112
5113 5113 Returns 0 on success.
5114 5114 """
5115 5115
5116 5116 opts = pycompat.byteskwargs(opts)
5117 5117 rev = opts.get(b'rev')
5118 5118 if rev:
5119 5119 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5120 5120 ctx = logcmdutil.revsingle(repo, rev, None)
5121 5121
5122 5122 if file_:
5123 5123 m = scmutil.match(ctx, (file_,), opts)
5124 5124 if m.anypats() or len(m.files()) != 1:
5125 5125 raise error.InputError(_(b'can only specify an explicit filename'))
5126 5126 file_ = m.files()[0]
5127 5127 filenodes = []
5128 5128 for cp in ctx.parents():
5129 5129 if not cp:
5130 5130 continue
5131 5131 try:
5132 5132 filenodes.append(cp.filenode(file_))
5133 5133 except error.LookupError:
5134 5134 pass
5135 5135 if not filenodes:
5136 5136 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5137 5137 p = []
5138 5138 for fn in filenodes:
5139 5139 fctx = repo.filectx(file_, fileid=fn)
5140 5140 p.append(fctx.node())
5141 5141 else:
5142 5142 p = [cp.node() for cp in ctx.parents()]
5143 5143
5144 5144 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5145 5145 for n in p:
5146 5146 if n != repo.nullid:
5147 5147 displayer.show(repo[n])
5148 5148 displayer.close()
5149 5149
5150 5150
5151 5151 @command(
5152 5152 b'paths',
5153 5153 formatteropts,
5154 5154 _(b'[NAME]'),
5155 5155 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5156 5156 optionalrepo=True,
5157 5157 intents={INTENT_READONLY},
5158 5158 )
5159 5159 def paths(ui, repo, search=None, **opts):
5160 5160 """show aliases for remote repositories
5161 5161
5162 5162 Show definition of symbolic path name NAME. If no name is given,
5163 5163 show definition of all available names.
5164 5164
5165 5165 Option -q/--quiet suppresses all output when searching for NAME
5166 5166 and shows only the path names when listing all definitions.
5167 5167
5168 5168 Path names are defined in the [paths] section of your
5169 5169 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5170 5170 repository, ``.hg/hgrc`` is used, too.
5171 5171
5172 5172 The path names ``default`` and ``default-push`` have a special
5173 5173 meaning. When performing a push or pull operation, they are used
5174 5174 as fallbacks if no location is specified on the command-line.
5175 5175 When ``default-push`` is set, it will be used for push and
5176 5176 ``default`` will be used for pull; otherwise ``default`` is used
5177 5177 as the fallback for both. When cloning a repository, the clone
5178 5178 source is written as ``default`` in ``.hg/hgrc``.
5179 5179
5180 5180 .. note::
5181 5181
5182 5182 ``default`` and ``default-push`` apply to all inbound (e.g.
5183 5183 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5184 5184 and :hg:`bundle`) operations.
5185 5185
5186 5186 See :hg:`help urls` for more information.
5187 5187
5188 5188 .. container:: verbose
5189 5189
5190 5190 Template:
5191 5191
5192 5192 The following keywords are supported. See also :hg:`help templates`.
5193 5193
5194 5194 :name: String. Symbolic name of the path alias.
5195 5195 :pushurl: String. URL for push operations.
5196 5196 :url: String. URL or directory path for the other operations.
5197 5197
5198 5198 Returns 0 on success.
5199 5199 """
5200 5200
5201 5201 pathitems = urlutil.list_paths(ui, search)
5202 5202 ui.pager(b'paths')
5203 5203
5204 5204 fm = ui.formatter(b'paths', pycompat.byteskwargs(opts))
5205 5205 if fm.isplain():
5206 5206 hidepassword = urlutil.hidepassword
5207 5207 else:
5208 5208 hidepassword = bytes
5209 5209 if ui.quiet:
5210 5210 namefmt = b'%s\n'
5211 5211 else:
5212 5212 namefmt = b'%s = '
5213 5213 showsubopts = not search and not ui.quiet
5214 5214
5215 5215 for name, path in pathitems:
5216 5216 fm.startitem()
5217 5217 fm.condwrite(not search, b'name', namefmt, name)
5218 5218 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5219 5219 for subopt, value in sorted(path.suboptions.items()):
5220 5220 assert subopt not in (b'name', b'url')
5221 5221 if showsubopts:
5222 5222 fm.plain(b'%s:%s = ' % (name, subopt))
5223 5223 display = urlutil.path_suboptions_display[subopt]
5224 5224 value = display(value)
5225 5225 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5226 5226
5227 5227 fm.end()
5228 5228
5229 5229 if search and not pathitems:
5230 5230 if not ui.quiet:
5231 5231 ui.warn(_(b"not found!\n"))
5232 5232 return 1
5233 5233 else:
5234 5234 return 0
5235 5235
5236 5236
5237 5237 @command(
5238 5238 b'phase',
5239 5239 [
5240 5240 (b'p', b'public', False, _(b'set changeset phase to public')),
5241 5241 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5242 5242 (b's', b'secret', False, _(b'set changeset phase to secret')),
5243 5243 (b'f', b'force', False, _(b'allow to move boundary backward')),
5244 5244 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5245 5245 ],
5246 5246 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5247 5247 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5248 5248 )
5249 5249 def phase(ui, repo, *revs, **opts):
5250 5250 """set or show the current phase name
5251 5251
5252 5252 With no argument, show the phase name of the current revision(s).
5253 5253
5254 5254 With one of -p/--public, -d/--draft or -s/--secret, change the
5255 5255 phase value of the specified revisions.
5256 5256
5257 5257 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5258 5258 lower phase to a higher phase. Phases are ordered as follows::
5259 5259
5260 5260 public < draft < secret
5261 5261
5262 5262 Returns 0 on success, 1 if some phases could not be changed.
5263 5263
5264 5264 (For more information about the phases concept, see :hg:`help phases`.)
5265 5265 """
5266 5266 opts = pycompat.byteskwargs(opts)
5267 5267 # search for a unique phase argument
5268 5268 targetphase = None
5269 5269 for idx, name in enumerate(phases.cmdphasenames):
5270 5270 if opts[name]:
5271 5271 if targetphase is not None:
5272 5272 raise error.InputError(_(b'only one phase can be specified'))
5273 5273 targetphase = idx
5274 5274
5275 5275 # look for specified revision
5276 5276 revs = list(revs)
5277 5277 revs.extend(opts[b'rev'])
5278 5278 if revs:
5279 5279 revs = logcmdutil.revrange(repo, revs)
5280 5280 else:
5281 5281 # display both parents as the second parent phase can influence
5282 5282 # the phase of a merge commit
5283 5283 revs = [c.rev() for c in repo[None].parents()]
5284 5284
5285 5285 ret = 0
5286 5286 if targetphase is None:
5287 5287 # display
5288 5288 for r in revs:
5289 5289 ctx = repo[r]
5290 5290 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5291 5291 else:
5292 5292 with repo.lock(), repo.transaction(b"phase") as tr:
5293 5293 # set phase
5294 5294 if not revs:
5295 5295 raise error.InputError(_(b'empty revision set'))
5296 5296 nodes = [repo[r].node() for r in revs]
5297 5297 # moving revision from public to draft may hide them
5298 5298 # We have to check result on an unfiltered repository
5299 5299 unfi = repo.unfiltered()
5300 5300 getphase = unfi._phasecache.phase
5301 5301 olddata = [getphase(unfi, r) for r in unfi]
5302 5302 phases.advanceboundary(repo, tr, targetphase, nodes)
5303 5303 if opts[b'force']:
5304 5304 phases.retractboundary(repo, tr, targetphase, nodes)
5305 5305 getphase = unfi._phasecache.phase
5306 5306 newdata = [getphase(unfi, r) for r in unfi]
5307 5307 changes = sum(newdata[r] != olddata[r] for r in unfi)
5308 5308 cl = unfi.changelog
5309 5309 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5310 5310 if rejected:
5311 5311 ui.warn(
5312 5312 _(
5313 5313 b'cannot move %i changesets to a higher '
5314 5314 b'phase, use --force\n'
5315 5315 )
5316 5316 % len(rejected)
5317 5317 )
5318 5318 ret = 1
5319 5319 if changes:
5320 5320 msg = _(b'phase changed for %i changesets\n') % changes
5321 5321 if ret:
5322 5322 ui.status(msg)
5323 5323 else:
5324 5324 ui.note(msg)
5325 5325 else:
5326 5326 ui.warn(_(b'no phases changed\n'))
5327 5327 return ret
5328 5328
5329 5329
5330 5330 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5331 5331 """Run after a changegroup has been added via pull/unbundle
5332 5332
5333 5333 This takes arguments below:
5334 5334
5335 5335 :modheads: change of heads by pull/unbundle
5336 5336 :optupdate: updating working directory is needed or not
5337 5337 :checkout: update destination revision (or None to default destination)
5338 5338 :brev: a name, which might be a bookmark to be activated after updating
5339 5339
5340 5340 return True if update raise any conflict, False otherwise.
5341 5341 """
5342 5342 if modheads == 0:
5343 5343 return False
5344 5344 if optupdate:
5345 5345 try:
5346 5346 return hg.updatetotally(ui, repo, checkout, brev)
5347 5347 except error.UpdateAbort as inst:
5348 5348 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5349 5349 hint = inst.hint
5350 5350 raise error.UpdateAbort(msg, hint=hint)
5351 5351 if modheads is not None and modheads > 1:
5352 5352 currentbranchheads = len(repo.branchheads())
5353 5353 if currentbranchheads == modheads:
5354 5354 ui.status(
5355 5355 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5356 5356 )
5357 5357 elif currentbranchheads > 1:
5358 5358 ui.status(
5359 5359 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5360 5360 )
5361 5361 else:
5362 5362 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5363 5363 elif not ui.configbool(b'commands', b'update.requiredest'):
5364 5364 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5365 5365 return False
5366 5366
5367 5367
5368 5368 @command(
5369 5369 b'pull',
5370 5370 [
5371 5371 (
5372 5372 b'u',
5373 5373 b'update',
5374 5374 None,
5375 5375 _(b'update to new branch head if new descendants were pulled'),
5376 5376 ),
5377 5377 (
5378 5378 b'f',
5379 5379 b'force',
5380 5380 None,
5381 5381 _(b'run even when remote repository is unrelated'),
5382 5382 ),
5383 5383 (
5384 5384 b'',
5385 5385 b'confirm',
5386 5386 None,
5387 5387 _(b'confirm pull before applying changes'),
5388 5388 ),
5389 5389 (
5390 5390 b'r',
5391 5391 b'rev',
5392 5392 [],
5393 5393 _(b'a remote changeset intended to be added'),
5394 5394 _(b'REV'),
5395 5395 ),
5396 5396 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5397 5397 (
5398 5398 b'b',
5399 5399 b'branch',
5400 5400 [],
5401 5401 _(b'a specific branch you would like to pull'),
5402 5402 _(b'BRANCH'),
5403 5403 ),
5404 5404 (
5405 5405 b'',
5406 5406 b'remote-hidden',
5407 5407 False,
5408 5408 _(b"include changesets hidden on the remote (EXPERIMENTAL)"),
5409 5409 ),
5410 5410 ]
5411 5411 + remoteopts,
5412 5412 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5413 5413 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5414 5414 helpbasic=True,
5415 5415 )
5416 5416 def pull(ui, repo, *sources, **opts):
5417 5417 """pull changes from the specified source
5418 5418
5419 5419 Pull changes from a remote repository to a local one.
5420 5420
5421 5421 This finds all changes from the repository at the specified path
5422 5422 or URL and adds them to a local repository (the current one unless
5423 5423 -R is specified). By default, this does not update the copy of the
5424 5424 project in the working directory.
5425 5425
5426 5426 When cloning from servers that support it, Mercurial may fetch
5427 5427 pre-generated data. When this is done, hooks operating on incoming
5428 5428 changesets and changegroups may fire more than once, once for each
5429 5429 pre-generated bundle and as well as for any additional remaining
5430 5430 data. See :hg:`help -e clonebundles` for more.
5431 5431
5432 5432 Use :hg:`incoming` if you want to see what would have been added
5433 5433 by a pull at the time you issued this command. If you then decide
5434 5434 to add those changes to the repository, you should use :hg:`pull
5435 5435 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5436 5436
5437 5437 If SOURCE is omitted, the 'default' path will be used.
5438 5438 See :hg:`help urls` for more information.
5439 5439
5440 5440 If multiple sources are specified, they will be pulled sequentially as if
5441 5441 the command was run multiple time. If --update is specify and the command
5442 5442 will stop at the first failed --update.
5443 5443
5444 5444 Specifying bookmark as ``.`` is equivalent to specifying the active
5445 5445 bookmark's name.
5446 5446
5447 5447 .. container:: verbose
5448 5448
5449 5449 One can use the `--remote-hidden` flag to pull changesets
5450 5450 hidden on the remote. This flag is "best effort", and will only
5451 5451 work if the server supports the feature and is configured to
5452 5452 allow the user to access hidden changesets. This option is
5453 5453 experimental and backwards compatibility is not garanteed.
5454 5454
5455 5455 Returns 0 on success, 1 if an update had unresolved files.
5456 5456 """
5457 5457
5458 5458 if ui.configbool(b'commands', b'update.requiredest') and opts.get('update'):
5459 5459 msg = _(b'update destination required by configuration')
5460 5460 hint = _(b'use hg pull followed by hg update DEST')
5461 5461 raise error.InputError(msg, hint=hint)
5462 5462
5463 5463 update_conflict = None
5464 5464
5465 5465 for path in urlutil.get_pull_paths(repo, ui, sources):
5466 5466 ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(path.loc))
5467 5467 ui.flush()
5468 5468 other = hg.peer(
5469 5469 repo,
5470 5470 pycompat.byteskwargs(opts),
5471 5471 path,
5472 5472 remotehidden=opts['remote_hidden'],
5473 5473 )
5474 5474 update_conflict = None
5475 5475 try:
5476 5476 branches = (path.branch, opts.get('branch', []))
5477 5477 revs, checkout = hg.addbranchrevs(
5478 5478 repo,
5479 5479 other,
5480 5480 branches,
5481 5481 opts.get('rev'),
5482 5482 remotehidden=opts['remote_hidden'],
5483 5483 )
5484 5484
5485 5485 pullopargs = {}
5486 5486
5487 5487 nodes = None
5488 5488 if opts.get('bookmark') or revs:
5489 5489 # The list of bookmark used here is the same used to actually update
5490 5490 # the bookmark names, to avoid the race from issue 4689 and we do
5491 5491 # all lookup and bookmark queries in one go so they see the same
5492 5492 # version of the server state (issue 4700).
5493 5493 nodes = []
5494 5494 fnodes = []
5495 5495 revs = revs or []
5496 5496 if revs and not other.capable(b'lookup'):
5497 5497 err = _(
5498 5498 b"other repository doesn't support revision lookup, "
5499 5499 b"so a rev cannot be specified."
5500 5500 )
5501 5501 raise error.Abort(err)
5502 5502 with other.commandexecutor() as e:
5503 5503 fremotebookmarks = e.callcommand(
5504 5504 b'listkeys', {b'namespace': b'bookmarks'}
5505 5505 )
5506 5506 for r in revs:
5507 5507 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5508 5508 remotebookmarks = fremotebookmarks.result()
5509 5509 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5510 5510 pullopargs[b'remotebookmarks'] = remotebookmarks
5511 5511 for b in opts.get('bookmark', []):
5512 5512 b = repo._bookmarks.expandname(b)
5513 5513 if b not in remotebookmarks:
5514 5514 raise error.InputError(
5515 5515 _(b'remote bookmark %s not found!') % b
5516 5516 )
5517 5517 nodes.append(remotebookmarks[b])
5518 5518 for i, rev in enumerate(revs):
5519 5519 node = fnodes[i].result()
5520 5520 nodes.append(node)
5521 5521 if rev == checkout:
5522 5522 checkout = node
5523 5523
5524 5524 wlock = util.nullcontextmanager()
5525 5525 if opts.get('update'):
5526 5526 wlock = repo.wlock()
5527 5527 with wlock:
5528 5528 pullopargs.update(opts.get('opargs', {}))
5529 5529 modheads = exchange.pull(
5530 5530 repo,
5531 5531 other,
5532 5532 path=path,
5533 5533 heads=nodes,
5534 5534 force=opts.get('force'),
5535 5535 bookmarks=opts.get('bookmark', ()),
5536 5536 opargs=pullopargs,
5537 5537 confirm=opts.get('confirm'),
5538 5538 ).cgresult
5539 5539
5540 5540 # brev is a name, which might be a bookmark to be activated at
5541 5541 # the end of the update. In other words, it is an explicit
5542 5542 # destination of the update
5543 5543 brev = None
5544 5544
5545 5545 if checkout:
5546 5546 checkout = repo.unfiltered().changelog.rev(checkout)
5547 5547
5548 5548 # order below depends on implementation of
5549 5549 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5550 5550 # because 'checkout' is determined without it.
5551 5551 if opts.get('rev'):
5552 5552 brev = opts['rev'][0]
5553 5553 elif opts.get('branch'):
5554 5554 brev = opts['branch'][0]
5555 5555 else:
5556 5556 brev = path.branch
5557 5557
5558 5558 # XXX path: we are losing the `path` object here. Keeping it
5559 5559 # would be valuable. For example as a "variant" as we do
5560 5560 # for pushes.
5561 5561 repo._subtoppath = path.loc
5562 5562 try:
5563 5563 update_conflict = postincoming(
5564 5564 ui, repo, modheads, opts.get('update'), checkout, brev
5565 5565 )
5566 5566 except error.FilteredRepoLookupError as exc:
5567 5567 msg = _(b'cannot update to target: %s') % exc.args[0]
5568 5568 exc.args = (msg,) + exc.args[1:]
5569 5569 raise
5570 5570 finally:
5571 5571 del repo._subtoppath
5572 5572
5573 5573 finally:
5574 5574 other.close()
5575 5575 # skip the remaining pull source if they are some conflict.
5576 5576 if update_conflict:
5577 5577 break
5578 5578 if update_conflict:
5579 5579 return 1
5580 5580 else:
5581 5581 return 0
5582 5582
5583 5583
5584 5584 @command(
5585 5585 b'purge|clean',
5586 5586 [
5587 5587 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5588 5588 (b'', b'all', None, _(b'purge ignored files too')),
5589 5589 (b'i', b'ignored', None, _(b'purge only ignored files')),
5590 5590 (b'', b'dirs', None, _(b'purge empty directories')),
5591 5591 (b'', b'files', None, _(b'purge files')),
5592 5592 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5593 5593 (
5594 5594 b'0',
5595 5595 b'print0',
5596 5596 None,
5597 5597 _(
5598 5598 b'end filenames with NUL, for use with xargs'
5599 5599 b' (implies -p/--print)'
5600 5600 ),
5601 5601 ),
5602 5602 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5603 5603 ]
5604 5604 + cmdutil.walkopts,
5605 5605 _(b'hg purge [OPTION]... [DIR]...'),
5606 5606 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5607 5607 )
5608 5608 def purge(ui, repo, *dirs, **opts):
5609 5609 """removes files not tracked by Mercurial
5610 5610
5611 5611 Delete files not known to Mercurial. This is useful to test local
5612 5612 and uncommitted changes in an otherwise-clean source tree.
5613 5613
5614 5614 This means that purge will delete the following by default:
5615 5615
5616 5616 - Unknown files: files marked with "?" by :hg:`status`
5617 5617 - Empty directories: in fact Mercurial ignores directories unless
5618 5618 they contain files under source control management
5619 5619
5620 5620 But it will leave untouched:
5621 5621
5622 5622 - Modified and unmodified tracked files
5623 5623 - Ignored files (unless -i or --all is specified)
5624 5624 - New files added to the repository (with :hg:`add`)
5625 5625
5626 5626 The --files and --dirs options can be used to direct purge to delete
5627 5627 only files, only directories, or both. If neither option is given,
5628 5628 both will be deleted.
5629 5629
5630 5630 If directories are given on the command line, only files in these
5631 5631 directories are considered.
5632 5632
5633 5633 Be careful with purge, as you could irreversibly delete some files
5634 5634 you forgot to add to the repository. If you only want to print the
5635 5635 list of files that this program would delete, use the --print
5636 5636 option.
5637 5637 """
5638 5638 cmdutil.check_at_most_one_arg(opts, 'all', 'ignored')
5639 5639
5640 5640 act = not opts.get('print')
5641 5641 eol = b'\n'
5642 5642 if opts.get('print0'):
5643 5643 eol = b'\0'
5644 5644 act = False # --print0 implies --print
5645 5645 if opts.get('all', False):
5646 5646 ignored = True
5647 5647 unknown = True
5648 5648 else:
5649 5649 ignored = opts.get('ignored', False)
5650 5650 unknown = not ignored
5651 5651
5652 5652 removefiles = opts.get('files')
5653 5653 removedirs = opts.get('dirs')
5654 5654 confirm = opts.get('confirm')
5655 5655 if confirm is None:
5656 5656 try:
5657 5657 extensions.find(b'purge')
5658 5658 confirm = False
5659 5659 except KeyError:
5660 5660 confirm = True
5661 5661
5662 5662 if not removefiles and not removedirs:
5663 5663 removefiles = True
5664 5664 removedirs = True
5665 5665
5666 5666 match = scmutil.match(repo[None], dirs, pycompat.byteskwargs(opts))
5667 5667
5668 5668 paths = mergemod.purge(
5669 5669 repo,
5670 5670 match,
5671 5671 unknown=unknown,
5672 5672 ignored=ignored,
5673 5673 removeemptydirs=removedirs,
5674 5674 removefiles=removefiles,
5675 5675 abortonerror=opts.get('abort_on_err'),
5676 5676 noop=not act,
5677 5677 confirm=confirm,
5678 5678 )
5679 5679
5680 5680 for path in paths:
5681 5681 if not act:
5682 5682 ui.write(b'%s%s' % (path, eol))
5683 5683
5684 5684
5685 5685 @command(
5686 5686 b'push',
5687 5687 [
5688 5688 (b'f', b'force', None, _(b'force push')),
5689 5689 (
5690 5690 b'r',
5691 5691 b'rev',
5692 5692 [],
5693 5693 _(b'a changeset intended to be included in the destination'),
5694 5694 _(b'REV'),
5695 5695 ),
5696 5696 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5697 5697 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5698 5698 (
5699 5699 b'b',
5700 5700 b'branch',
5701 5701 [],
5702 5702 _(b'a specific branch you would like to push'),
5703 5703 _(b'BRANCH'),
5704 5704 ),
5705 5705 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5706 5706 (
5707 5707 b'',
5708 5708 b'pushvars',
5709 5709 [],
5710 5710 _(b'variables that can be sent to server (ADVANCED)'),
5711 5711 ),
5712 5712 (
5713 5713 b'',
5714 5714 b'publish',
5715 5715 False,
5716 5716 _(b'push the changeset as public (EXPERIMENTAL)'),
5717 5717 ),
5718 5718 ]
5719 5719 + remoteopts,
5720 5720 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5721 5721 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5722 5722 helpbasic=True,
5723 5723 )
5724 5724 def push(ui, repo, *dests, **opts):
5725 5725 """push changes to the specified destination
5726 5726
5727 5727 Push changesets from the local repository to the specified
5728 5728 destination.
5729 5729
5730 5730 This operation is symmetrical to pull: it is identical to a pull
5731 5731 in the destination repository from the current one.
5732 5732
5733 5733 By default, push will not allow creation of new heads at the
5734 5734 destination, since multiple heads would make it unclear which head
5735 5735 to use. In this situation, it is recommended to pull and merge
5736 5736 before pushing.
5737 5737
5738 5738 Use --new-branch if you want to allow push to create a new named
5739 5739 branch that is not present at the destination. This allows you to
5740 5740 only create a new branch without forcing other changes.
5741 5741
5742 5742 .. note::
5743 5743
5744 5744 Extra care should be taken with the -f/--force option,
5745 5745 which will push all new heads on all branches, an action which will
5746 5746 almost always cause confusion for collaborators.
5747 5747
5748 5748 If -r/--rev is used, the specified revision and all its ancestors
5749 5749 will be pushed to the remote repository.
5750 5750
5751 5751 If -B/--bookmark is used, the specified bookmarked revision, its
5752 5752 ancestors, and the bookmark will be pushed to the remote
5753 5753 repository. Specifying ``.`` is equivalent to specifying the active
5754 5754 bookmark's name. Use the --all-bookmarks option for pushing all
5755 5755 current bookmarks.
5756 5756
5757 5757 Please see :hg:`help urls` for important details about ``ssh://``
5758 5758 URLs. If DESTINATION is omitted, a default path will be used.
5759 5759
5760 5760 When passed multiple destinations, push will process them one after the
5761 5761 other, but stop should an error occur.
5762 5762
5763 5763 .. container:: verbose
5764 5764
5765 5765 The --pushvars option sends strings to the server that become
5766 5766 environment variables prepended with ``HG_USERVAR_``. For example,
5767 5767 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5768 5768 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5769 5769
5770 5770 pushvars can provide for user-overridable hooks as well as set debug
5771 5771 levels. One example is having a hook that blocks commits containing
5772 5772 conflict markers, but enables the user to override the hook if the file
5773 5773 is using conflict markers for testing purposes or the file format has
5774 5774 strings that look like conflict markers.
5775 5775
5776 5776 By default, servers will ignore `--pushvars`. To enable it add the
5777 5777 following to your configuration file::
5778 5778
5779 5779 [push]
5780 5780 pushvars.server = true
5781 5781
5782 5782 Returns 0 if push was successful, 1 if nothing to push.
5783 5783 """
5784 5784
5785 5785 opts = pycompat.byteskwargs(opts)
5786 5786
5787 5787 if opts.get(b'all_bookmarks'):
5788 5788 cmdutil.check_incompatible_arguments(
5789 5789 opts,
5790 5790 b'all_bookmarks',
5791 5791 [b'bookmark', b'rev'],
5792 5792 )
5793 5793 opts[b'bookmark'] = list(repo._bookmarks)
5794 5794
5795 5795 if opts.get(b'bookmark'):
5796 5796 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5797 5797 for b in opts[b'bookmark']:
5798 5798 # translate -B options to -r so changesets get pushed
5799 5799 b = repo._bookmarks.expandname(b)
5800 5800 if b in repo._bookmarks:
5801 5801 opts.setdefault(b'rev', []).append(b)
5802 5802 else:
5803 5803 # if we try to push a deleted bookmark, translate it to null
5804 5804 # this lets simultaneous -r, -b options continue working
5805 5805 opts.setdefault(b'rev', []).append(b"null")
5806 5806
5807 5807 some_pushed = False
5808 5808 result = 0
5809 5809 for path in urlutil.get_push_paths(repo, ui, dests):
5810 5810 dest = path.loc
5811 5811 branches = (path.branch, opts.get(b'branch') or [])
5812 5812 ui.status(_(b'pushing to %s\n') % urlutil.hidepassword(dest))
5813 5813 revs, checkout = hg.addbranchrevs(
5814 5814 repo, repo, branches, opts.get(b'rev')
5815 5815 )
5816 5816 other = hg.peer(repo, opts, dest)
5817 5817
5818 5818 try:
5819 5819 if revs:
5820 5820 revs = [repo[r].node() for r in logcmdutil.revrange(repo, revs)]
5821 5821 if not revs:
5822 5822 raise error.InputError(
5823 5823 _(b"specified revisions evaluate to an empty set"),
5824 5824 hint=_(b"use different revision arguments"),
5825 5825 )
5826 5826 elif path.pushrev:
5827 5827 # It doesn't make any sense to specify ancestor revisions. So limit
5828 5828 # to DAG heads to make discovery simpler.
5829 5829 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5830 5830 revs = scmutil.revrange(repo, [expr])
5831 5831 revs = [repo[rev].node() for rev in revs]
5832 5832 if not revs:
5833 5833 raise error.InputError(
5834 5834 _(
5835 5835 b'default push revset for path evaluates to an empty set'
5836 5836 )
5837 5837 )
5838 5838 elif ui.configbool(b'commands', b'push.require-revs'):
5839 5839 raise error.InputError(
5840 5840 _(b'no revisions specified to push'),
5841 5841 hint=_(b'did you mean "hg push -r ."?'),
5842 5842 )
5843 5843
5844 5844 repo._subtoppath = dest
5845 5845 try:
5846 5846 # push subrepos depth-first for coherent ordering
5847 5847 c = repo[b'.']
5848 5848 subs = c.substate # only repos that are committed
5849 5849 for s in sorted(subs):
5850 5850 sub_result = c.sub(s).push(opts)
5851 5851 if sub_result == 0:
5852 5852 return 1
5853 5853 finally:
5854 5854 del repo._subtoppath
5855 5855
5856 5856 opargs = dict(
5857 5857 opts.get(b'opargs', {})
5858 5858 ) # copy opargs since we may mutate it
5859 5859 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5860 5860
5861 5861 pushop = exchange.push(
5862 5862 repo,
5863 5863 other,
5864 5864 opts.get(b'force'),
5865 5865 revs=revs,
5866 5866 newbranch=opts.get(b'new_branch'),
5867 5867 bookmarks=opts.get(b'bookmark', ()),
5868 5868 publish=opts.get(b'publish'),
5869 5869 opargs=opargs,
5870 5870 )
5871 5871
5872 5872 if pushop.cgresult == 0:
5873 5873 result = 1
5874 5874 elif pushop.cgresult is not None:
5875 5875 some_pushed = True
5876 5876
5877 5877 if pushop.bkresult is not None:
5878 5878 if pushop.bkresult == 2:
5879 5879 result = 2
5880 5880 elif not result and pushop.bkresult:
5881 5881 result = 2
5882 5882
5883 5883 if result:
5884 5884 break
5885 5885
5886 5886 finally:
5887 5887 other.close()
5888 5888 if result == 0 and not some_pushed:
5889 5889 result = 1
5890 5890 return result
5891 5891
5892 5892
5893 5893 @command(
5894 5894 b'recover',
5895 5895 [
5896 5896 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5897 5897 ],
5898 5898 helpcategory=command.CATEGORY_MAINTENANCE,
5899 5899 )
5900 5900 def recover(ui, repo, **opts):
5901 5901 """roll back an interrupted transaction
5902 5902
5903 5903 Recover from an interrupted commit or pull.
5904 5904
5905 5905 This command tries to fix the repository status after an
5906 5906 interrupted operation. It should only be necessary when Mercurial
5907 5907 suggests it.
5908 5908
5909 5909 Returns 0 if successful, 1 if nothing to recover or verify fails.
5910 5910 """
5911 5911 ret = repo.recover()
5912 5912 if ret:
5913 5913 if opts['verify']:
5914 5914 return hg.verify(repo)
5915 5915 else:
5916 5916 msg = _(
5917 5917 b"(verify step skipped, run `hg verify` to check your "
5918 5918 b"repository content)\n"
5919 5919 )
5920 5920 ui.warn(msg)
5921 5921 return 0
5922 5922 return 1
5923 5923
5924 5924
5925 5925 @command(
5926 5926 b'remove|rm',
5927 5927 [
5928 5928 (b'A', b'after', None, _(b'record delete for missing files')),
5929 5929 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5930 5930 ]
5931 5931 + subrepoopts
5932 5932 + walkopts
5933 5933 + dryrunopts,
5934 5934 _(b'[OPTION]... FILE...'),
5935 5935 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5936 5936 helpbasic=True,
5937 5937 inferrepo=True,
5938 5938 )
5939 5939 def remove(ui, repo, *pats, **opts):
5940 5940 """remove the specified files on the next commit
5941 5941
5942 5942 Schedule the indicated files for removal from the current branch.
5943 5943
5944 5944 This command schedules the files to be removed at the next commit.
5945 5945 To undo a remove before that, see :hg:`revert`. To undo added
5946 5946 files, see :hg:`forget`.
5947 5947
5948 5948 .. container:: verbose
5949 5949
5950 5950 -A/--after can be used to remove only files that have already
5951 5951 been deleted, -f/--force can be used to force deletion, and -Af
5952 5952 can be used to remove files from the next revision without
5953 5953 deleting them from the working directory.
5954 5954
5955 5955 The following table details the behavior of remove for different
5956 5956 file states (columns) and option combinations (rows). The file
5957 5957 states are Added [A], Clean [C], Modified [M] and Missing [!]
5958 5958 (as reported by :hg:`status`). The actions are Warn, Remove
5959 5959 (from branch) and Delete (from disk):
5960 5960
5961 5961 ========= == == == ==
5962 5962 opt/state A C M !
5963 5963 ========= == == == ==
5964 5964 none W RD W R
5965 5965 -f R RD RD R
5966 5966 -A W W W R
5967 5967 -Af R R R R
5968 5968 ========= == == == ==
5969 5969
5970 5970 .. note::
5971 5971
5972 5972 :hg:`remove` never deletes files in Added [A] state from the
5973 5973 working directory, not even if ``--force`` is specified.
5974 5974
5975 5975 Returns 0 on success, 1 if any warnings encountered.
5976 5976 """
5977 5977
5978 5978 after, force = opts.get('after'), opts.get('force')
5979 5979 dryrun = opts.get('dry_run')
5980 5980 if not pats and not after:
5981 5981 raise error.InputError(_(b'no files specified'))
5982 5982
5983 5983 with repo.wlock(), repo.dirstate.changing_files(repo):
5984 5984 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
5985 5985 subrepos = opts.get('subrepos')
5986 5986 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5987 5987 return cmdutil.remove(
5988 5988 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5989 5989 )
5990 5990
5991 5991
5992 5992 @command(
5993 5993 b'rename|move|mv',
5994 5994 [
5995 5995 (b'', b'forget', None, _(b'unmark a destination file as renamed')),
5996 5996 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5997 5997 (
5998 5998 b'',
5999 5999 b'at-rev',
6000 6000 b'',
6001 6001 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
6002 6002 _(b'REV'),
6003 6003 ),
6004 6004 (
6005 6005 b'f',
6006 6006 b'force',
6007 6007 None,
6008 6008 _(b'forcibly move over an existing managed file'),
6009 6009 ),
6010 6010 ]
6011 6011 + walkopts
6012 6012 + dryrunopts,
6013 6013 _(b'[OPTION]... SOURCE... DEST'),
6014 6014 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6015 6015 )
6016 6016 def rename(ui, repo, *pats, **opts):
6017 6017 """rename files; equivalent of copy + remove
6018 6018
6019 6019 Mark dest as copies of sources; mark sources for deletion. If dest
6020 6020 is a directory, copies are put in that directory. If dest is a
6021 6021 file, there can only be one source.
6022 6022
6023 6023 By default, this command copies the contents of files as they
6024 6024 exist in the working directory. If invoked with -A/--after, the
6025 6025 operation is recorded, but no copying is performed.
6026 6026
6027 6027 To undo marking a destination file as renamed, use --forget. With that
6028 6028 option, all given (positional) arguments are unmarked as renames. The
6029 6029 destination file(s) will be left in place (still tracked). The source
6030 6030 file(s) will not be restored. Note that :hg:`rename --forget` behaves
6031 6031 the same way as :hg:`copy --forget`.
6032 6032
6033 6033 This command takes effect with the next commit by default.
6034 6034
6035 6035 Returns 0 on success, 1 if errors are encountered.
6036 6036 """
6037 6037 context = lambda repo: repo.dirstate.changing_files(repo)
6038 6038 rev = opts.get('at_rev')
6039 6039
6040 6040 if rev:
6041 6041 ctx = logcmdutil.revsingle(repo, rev)
6042 6042 if ctx.rev() is not None:
6043 6043
6044 6044 def context(repo):
6045 6045 return util.nullcontextmanager()
6046 6046
6047 6047 opts['at_rev'] = ctx.rev()
6048 6048 with repo.wlock(), context(repo):
6049 6049 return cmdutil.copy(
6050 6050 ui, repo, pats, pycompat.byteskwargs(opts), rename=True
6051 6051 )
6052 6052
6053 6053
6054 6054 @command(
6055 6055 b'resolve',
6056 6056 [
6057 6057 (b'a', b'all', None, _(b'select all unresolved files')),
6058 6058 (b'l', b'list', None, _(b'list state of files needing merge')),
6059 6059 (b'm', b'mark', None, _(b'mark files as resolved')),
6060 6060 (b'u', b'unmark', None, _(b'mark files as unresolved')),
6061 6061 (b'n', b'no-status', None, _(b'hide status prefix')),
6062 6062 (b'', b're-merge', None, _(b're-merge files')),
6063 6063 ]
6064 6064 + mergetoolopts
6065 6065 + walkopts
6066 6066 + formatteropts,
6067 6067 _(b'[OPTION]... [FILE]...'),
6068 6068 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6069 6069 inferrepo=True,
6070 6070 )
6071 6071 def resolve(ui, repo, *pats, **opts):
6072 6072 """redo merges or set/view the merge status of files
6073 6073
6074 6074 Merges with unresolved conflicts are often the result of
6075 6075 non-interactive merging using the ``internal:merge`` configuration
6076 6076 setting, or a command-line merge tool like ``diff3``. The resolve
6077 6077 command is used to manage the files involved in a merge, after
6078 6078 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6079 6079 working directory must have two parents). See :hg:`help
6080 6080 merge-tools` for information on configuring merge tools.
6081 6081
6082 6082 The resolve command can be used in the following ways:
6083 6083
6084 6084 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
6085 6085 the specified files, discarding any previous merge attempts. Re-merging
6086 6086 is not performed for files already marked as resolved. Use ``--all/-a``
6087 6087 to select all unresolved files. ``--tool`` can be used to specify
6088 6088 the merge tool used for the given files. It overrides the HGMERGE
6089 6089 environment variable and your configuration files. Previous file
6090 6090 contents are saved with a ``.orig`` suffix.
6091 6091
6092 6092 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6093 6093 (e.g. after having manually fixed-up the files). The default is
6094 6094 to mark all unresolved files.
6095 6095
6096 6096 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6097 6097 default is to mark all resolved files.
6098 6098
6099 6099 - :hg:`resolve -l`: list files which had or still have conflicts.
6100 6100 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6101 6101 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
6102 6102 the list. See :hg:`help filesets` for details.
6103 6103
6104 6104 .. note::
6105 6105
6106 6106 Mercurial will not let you commit files with unresolved merge
6107 6107 conflicts. You must use :hg:`resolve -m ...` before you can
6108 6108 commit after a conflicting merge.
6109 6109
6110 6110 .. container:: verbose
6111 6111
6112 6112 Template:
6113 6113
6114 6114 The following keywords are supported in addition to the common template
6115 6115 keywords and functions. See also :hg:`help templates`.
6116 6116
6117 6117 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6118 6118 :path: String. Repository-absolute path of the file.
6119 6119
6120 6120 Returns 0 on success, 1 if any files fail a resolve attempt.
6121 6121 """
6122 6122
6123 6123 opts = pycompat.byteskwargs(opts)
6124 6124 confirm = ui.configbool(b'commands', b'resolve.confirm')
6125 6125 flaglist = b'all mark unmark list no_status re_merge'.split()
6126 6126 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6127 6127
6128 6128 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6129 6129 if actioncount > 1:
6130 6130 raise error.InputError(_(b"too many actions specified"))
6131 6131 elif actioncount == 0 and ui.configbool(
6132 6132 b'commands', b'resolve.explicit-re-merge'
6133 6133 ):
6134 6134 hint = _(b'use --mark, --unmark, --list or --re-merge')
6135 6135 raise error.InputError(_(b'no action specified'), hint=hint)
6136 6136 if pats and all:
6137 6137 raise error.InputError(_(b"can't specify --all and patterns"))
6138 6138 if not (all or pats or show or mark or unmark):
6139 6139 raise error.InputError(
6140 6140 _(b'no files or directories specified'),
6141 6141 hint=b'use --all to re-merge all unresolved files',
6142 6142 )
6143 6143
6144 6144 if confirm:
6145 6145 if all:
6146 6146 if ui.promptchoice(
6147 6147 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6148 6148 ):
6149 6149 raise error.CanceledError(_(b'user quit'))
6150 6150 if mark and not pats:
6151 6151 if ui.promptchoice(
6152 6152 _(
6153 6153 b'mark all unresolved files as resolved (yn)?'
6154 6154 b'$$ &Yes $$ &No'
6155 6155 )
6156 6156 ):
6157 6157 raise error.CanceledError(_(b'user quit'))
6158 6158 if unmark and not pats:
6159 6159 if ui.promptchoice(
6160 6160 _(
6161 6161 b'mark all resolved files as unresolved (yn)?'
6162 6162 b'$$ &Yes $$ &No'
6163 6163 )
6164 6164 ):
6165 6165 raise error.CanceledError(_(b'user quit'))
6166 6166
6167 6167 uipathfn = scmutil.getuipathfn(repo)
6168 6168
6169 6169 if show:
6170 6170 ui.pager(b'resolve')
6171 6171 fm = ui.formatter(b'resolve', opts)
6172 6172 ms = mergestatemod.mergestate.read(repo)
6173 6173 wctx = repo[None]
6174 6174 m = scmutil.match(wctx, pats, opts)
6175 6175
6176 6176 # Labels and keys based on merge state. Unresolved path conflicts show
6177 6177 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6178 6178 # resolved conflicts.
6179 6179 mergestateinfo = {
6180 6180 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6181 6181 b'resolve.unresolved',
6182 6182 b'U',
6183 6183 ),
6184 6184 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6185 6185 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6186 6186 b'resolve.unresolved',
6187 6187 b'P',
6188 6188 ),
6189 6189 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6190 6190 b'resolve.resolved',
6191 6191 b'R',
6192 6192 ),
6193 6193 }
6194 6194
6195 6195 for f in ms:
6196 6196 if not m(f):
6197 6197 continue
6198 6198
6199 6199 label, key = mergestateinfo[ms[f]]
6200 6200 fm.startitem()
6201 6201 fm.context(ctx=wctx)
6202 6202 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6203 6203 fm.data(path=f)
6204 6204 fm.plain(b'%s\n' % uipathfn(f), label=label)
6205 6205 fm.end()
6206 6206 return 0
6207 6207
6208 6208 with repo.wlock():
6209 6209 ms = mergestatemod.mergestate.read(repo)
6210 6210
6211 6211 if not (ms.active() or repo.dirstate.p2() != repo.nullid):
6212 6212 raise error.StateError(
6213 6213 _(b'resolve command not applicable when not merging')
6214 6214 )
6215 6215
6216 6216 wctx = repo[None]
6217 6217 m = scmutil.match(wctx, pats, opts)
6218 6218 ret = 0
6219 6219 didwork = False
6220 6220
6221 6221 hasconflictmarkers = []
6222 6222 if mark:
6223 6223 markcheck = ui.config(b'commands', b'resolve.mark-check')
6224 6224 if markcheck not in [b'warn', b'abort']:
6225 6225 # Treat all invalid / unrecognized values as 'none'.
6226 6226 markcheck = False
6227 6227 for f in ms:
6228 6228 if not m(f):
6229 6229 continue
6230 6230
6231 6231 didwork = True
6232 6232
6233 6233 # path conflicts must be resolved manually
6234 6234 if ms[f] in (
6235 6235 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6236 6236 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6237 6237 ):
6238 6238 if mark:
6239 6239 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6240 6240 elif unmark:
6241 6241 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6242 6242 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6243 6243 ui.warn(
6244 6244 _(b'%s: path conflict must be resolved manually\n')
6245 6245 % uipathfn(f)
6246 6246 )
6247 6247 continue
6248 6248
6249 6249 if mark:
6250 6250 if markcheck:
6251 6251 fdata = repo.wvfs.tryread(f)
6252 6252 if (
6253 6253 filemerge.hasconflictmarkers(fdata)
6254 6254 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6255 6255 ):
6256 6256 hasconflictmarkers.append(f)
6257 6257 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6258 6258 elif unmark:
6259 6259 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6260 6260 else:
6261 6261 # backup pre-resolve (merge uses .orig for its own purposes)
6262 6262 a = repo.wjoin(f)
6263 6263 try:
6264 6264 util.copyfile(a, a + b".resolve")
6265 6265 except FileNotFoundError:
6266 6266 pass
6267 6267
6268 6268 try:
6269 6269 # preresolve file
6270 6270 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6271 6271 with ui.configoverride(overrides, b'resolve'):
6272 6272 r = ms.resolve(f, wctx)
6273 6273 if r:
6274 6274 ret = 1
6275 6275 finally:
6276 6276 ms.commit()
6277 6277
6278 6278 # replace filemerge's .orig file with our resolve file
6279 6279 try:
6280 6280 util.rename(
6281 6281 a + b".resolve", scmutil.backuppath(ui, repo, f)
6282 6282 )
6283 6283 except FileNotFoundError:
6284 6284 pass
6285 6285
6286 6286 if hasconflictmarkers:
6287 6287 ui.warn(
6288 6288 _(
6289 6289 b'warning: the following files still have conflict '
6290 6290 b'markers:\n'
6291 6291 )
6292 6292 + b''.join(
6293 6293 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6294 6294 )
6295 6295 )
6296 6296 if markcheck == b'abort' and not all and not pats:
6297 6297 raise error.StateError(
6298 6298 _(b'conflict markers detected'),
6299 6299 hint=_(b'use --all to mark anyway'),
6300 6300 )
6301 6301
6302 6302 ms.commit()
6303 6303 branchmerge = repo.dirstate.p2() != repo.nullid
6304 6304 # resolve is not doing a parent change here, however, `record updates`
6305 6305 # will call some dirstate API that at intended for parent changes call.
6306 6306 # Ideally we would not need this and could implement a lighter version
6307 6307 # of the recordupdateslogic that will not have to deal with the part
6308 6308 # related to parent changes. However this would requires that:
6309 6309 # - we are sure we passed around enough information at update/merge
6310 6310 # time to no longer needs it at `hg resolve time`
6311 6311 # - we are sure we store that information well enough to be able to reuse it
6312 6312 # - we are the necessary logic to reuse it right.
6313 6313 #
6314 6314 # All this should eventually happens, but in the mean time, we use this
6315 6315 # context manager slightly out of the context it should be.
6316 6316 with repo.dirstate.changing_parents(repo):
6317 6317 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6318 6318
6319 6319 if not didwork and pats:
6320 6320 hint = None
6321 6321 if not any([p for p in pats if p.find(b':') >= 0]):
6322 6322 pats = [b'path:%s' % p for p in pats]
6323 6323 m = scmutil.match(wctx, pats, opts)
6324 6324 for f in ms:
6325 6325 if not m(f):
6326 6326 continue
6327 6327
6328 6328 def flag(o):
6329 6329 if o == b're_merge':
6330 6330 return b'--re-merge '
6331 6331 return b'-%s ' % o[0:1]
6332 6332
6333 6333 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6334 6334 hint = _(b"(try: hg resolve %s%s)\n") % (
6335 6335 flags,
6336 6336 b' '.join(pats),
6337 6337 )
6338 6338 break
6339 6339 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6340 6340 if hint:
6341 6341 ui.warn(hint)
6342 6342
6343 6343 unresolvedf = ms.unresolvedcount()
6344 6344 if not unresolvedf:
6345 6345 ui.status(_(b'(no more unresolved files)\n'))
6346 6346 cmdutil.checkafterresolved(repo)
6347 6347
6348 6348 return ret
6349 6349
6350 6350
6351 6351 @command(
6352 6352 b'revert',
6353 6353 [
6354 6354 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6355 6355 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6356 6356 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6357 6357 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6358 6358 (b'i', b'interactive', None, _(b'interactively select the changes')),
6359 6359 ]
6360 6360 + walkopts
6361 6361 + dryrunopts,
6362 6362 _(b'[OPTION]... [-r REV] [NAME]...'),
6363 6363 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6364 6364 )
6365 6365 def revert(ui, repo, *pats, **opts):
6366 6366 """restore files to their checkout state
6367 6367
6368 6368 .. note::
6369 6369
6370 6370 To check out earlier revisions, you should use :hg:`update REV`.
6371 6371 To cancel an uncommitted merge (and lose your changes),
6372 6372 use :hg:`merge --abort`.
6373 6373
6374 6374 With no revision specified, revert the specified files or directories
6375 6375 to the contents they had in the parent of the working directory.
6376 6376 This restores the contents of files to an unmodified
6377 6377 state and unschedules adds, removes, copies, and renames. If the
6378 6378 working directory has two parents, you must explicitly specify a
6379 6379 revision.
6380 6380
6381 6381 Using the -r/--rev or -d/--date options, revert the given files or
6382 6382 directories to their states as of a specific revision. Because
6383 6383 revert does not change the working directory parents, this will
6384 6384 cause these files to appear modified. This can be helpful to "back
6385 6385 out" some or all of an earlier change. See :hg:`backout` for a
6386 6386 related method.
6387 6387
6388 6388 Modified files are saved with a .orig suffix before reverting.
6389 6389 To disable these backups, use --no-backup. It is possible to store
6390 6390 the backup files in a custom directory relative to the root of the
6391 6391 repository by setting the ``ui.origbackuppath`` configuration
6392 6392 option.
6393 6393
6394 6394 See :hg:`help dates` for a list of formats valid for -d/--date.
6395 6395
6396 6396 See :hg:`help backout` for a way to reverse the effect of an
6397 6397 earlier changeset.
6398 6398
6399 6399 Returns 0 on success.
6400 6400 """
6401 6401
6402 6402 if opts.get("date"):
6403 6403 cmdutil.check_incompatible_arguments(opts, 'date', ['rev'])
6404 6404 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6405 6405
6406 6406 parent, p2 = repo.dirstate.parents()
6407 6407 if not opts.get('rev') and p2 != repo.nullid:
6408 6408 # revert after merge is a trap for new users (issue2915)
6409 6409 raise error.InputError(
6410 6410 _(b'uncommitted merge with no revision specified'),
6411 6411 hint=_(b"use 'hg update' or see 'hg help revert'"),
6412 6412 )
6413 6413
6414 6414 rev = opts.get('rev')
6415 6415 if rev:
6416 6416 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6417 6417 ctx = logcmdutil.revsingle(repo, rev)
6418 6418
6419 6419 if not (
6420 6420 pats
6421 6421 or opts.get('include')
6422 6422 or opts.get('exclude')
6423 6423 or opts.get('all')
6424 6424 or opts.get('interactive')
6425 6425 ):
6426 6426 msg = _(b"no files or directories specified")
6427 6427 if p2 != repo.nullid:
6428 6428 hint = _(
6429 6429 b"uncommitted merge, use --all to discard all changes,"
6430 6430 b" or 'hg update -C .' to abort the merge"
6431 6431 )
6432 6432 raise error.InputError(msg, hint=hint)
6433 6433 dirty = any(repo.status())
6434 6434 node = ctx.node()
6435 6435 if node != parent:
6436 6436 if dirty:
6437 6437 hint = (
6438 6438 _(
6439 6439 b"uncommitted changes, use --all to discard all"
6440 6440 b" changes, or 'hg update %d' to update"
6441 6441 )
6442 6442 % ctx.rev()
6443 6443 )
6444 6444 else:
6445 6445 hint = (
6446 6446 _(
6447 6447 b"use --all to revert all files,"
6448 6448 b" or 'hg update %d' to update"
6449 6449 )
6450 6450 % ctx.rev()
6451 6451 )
6452 6452 elif dirty:
6453 6453 hint = _(b"uncommitted changes, use --all to discard all changes")
6454 6454 else:
6455 6455 hint = _(b"use --all to revert all files")
6456 6456 raise error.InputError(msg, hint=hint)
6457 6457
6458 6458 return cmdutil.revert(ui, repo, ctx, *pats, **opts)
6459 6459
6460 6460
6461 6461 @command(
6462 6462 b'rollback',
6463 6463 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6464 6464 helpcategory=command.CATEGORY_MAINTENANCE,
6465 6465 )
6466 6466 def rollback(ui, repo, **opts):
6467 6467 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6468 6468
6469 6469 Please use :hg:`commit --amend` instead of rollback to correct
6470 6470 mistakes in the last commit.
6471 6471
6472 6472 This command should be used with care. There is only one level of
6473 6473 rollback, and there is no way to undo a rollback. It will also
6474 6474 restore the dirstate at the time of the last transaction, losing
6475 6475 any dirstate changes since that time. This command does not alter
6476 6476 the working directory.
6477 6477
6478 6478 Transactions are used to encapsulate the effects of all commands
6479 6479 that create new changesets or propagate existing changesets into a
6480 6480 repository.
6481 6481
6482 6482 .. container:: verbose
6483 6483
6484 6484 For example, the following commands are transactional, and their
6485 6485 effects can be rolled back:
6486 6486
6487 6487 - commit
6488 6488 - import
6489 6489 - pull
6490 6490 - push (with this repository as the destination)
6491 6491 - unbundle
6492 6492
6493 6493 To avoid permanent data loss, rollback will refuse to rollback a
6494 6494 commit transaction if it isn't checked out. Use --force to
6495 6495 override this protection.
6496 6496
6497 6497 The rollback command can be entirely disabled by setting the
6498 6498 ``ui.rollback`` configuration setting to false. If you're here
6499 6499 because you want to use rollback and it's disabled, you can
6500 6500 re-enable the command by setting ``ui.rollback`` to true.
6501 6501
6502 6502 This command is not intended for use on public repositories. Once
6503 6503 changes are visible for pull by other users, rolling a transaction
6504 6504 back locally is ineffective (someone else may already have pulled
6505 6505 the changes). Furthermore, a race is possible with readers of the
6506 6506 repository; for example an in-progress pull from the repository
6507 6507 may fail if a rollback is performed.
6508 6508
6509 6509 Returns 0 on success, 1 if no rollback data is available.
6510 6510 """
6511 6511 if not ui.configbool(b'ui', b'rollback'):
6512 6512 raise error.Abort(
6513 6513 _(b'rollback is disabled because it is unsafe'),
6514 6514 hint=b'see `hg help -v rollback` for information',
6515 6515 )
6516 6516 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6517 6517
6518 6518
6519 6519 @command(
6520 6520 b'root',
6521 6521 [] + formatteropts,
6522 6522 intents={INTENT_READONLY},
6523 6523 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6524 6524 )
6525 6525 def root(ui, repo, **opts):
6526 6526 """print the root (top) of the current working directory
6527 6527
6528 6528 Print the root directory of the current repository.
6529 6529
6530 6530 .. container:: verbose
6531 6531
6532 6532 Template:
6533 6533
6534 6534 The following keywords are supported in addition to the common template
6535 6535 keywords and functions. See also :hg:`help templates`.
6536 6536
6537 6537 :hgpath: String. Path to the .hg directory.
6538 6538 :storepath: String. Path to the directory holding versioned data.
6539 6539
6540 6540 Returns 0 on success.
6541 6541 """
6542 6542 opts = pycompat.byteskwargs(opts)
6543 6543 with ui.formatter(b'root', opts) as fm:
6544 6544 fm.startitem()
6545 6545 fm.write(b'reporoot', b'%s\n', repo.root)
6546 6546 fm.data(hgpath=repo.path, storepath=repo.spath)
6547 6547
6548 6548
6549 6549 @command(
6550 6550 b'serve',
6551 6551 [
6552 6552 (
6553 6553 b'A',
6554 6554 b'accesslog',
6555 6555 b'',
6556 6556 _(b'name of access log file to write to'),
6557 6557 _(b'FILE'),
6558 6558 ),
6559 6559 (b'd', b'daemon', None, _(b'run server in background')),
6560 6560 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6561 6561 (
6562 6562 b'E',
6563 6563 b'errorlog',
6564 6564 b'',
6565 6565 _(b'name of error log file to write to'),
6566 6566 _(b'FILE'),
6567 6567 ),
6568 6568 # use string type, then we can check if something was passed
6569 6569 (
6570 6570 b'p',
6571 6571 b'port',
6572 6572 b'',
6573 6573 _(b'port to listen on (default: 8000)'),
6574 6574 _(b'PORT'),
6575 6575 ),
6576 6576 (
6577 6577 b'a',
6578 6578 b'address',
6579 6579 b'',
6580 6580 _(b'address to listen on (default: all interfaces)'),
6581 6581 _(b'ADDR'),
6582 6582 ),
6583 6583 (
6584 6584 b'',
6585 6585 b'prefix',
6586 6586 b'',
6587 6587 _(b'prefix path to serve from (default: server root)'),
6588 6588 _(b'PREFIX'),
6589 6589 ),
6590 6590 (
6591 6591 b'n',
6592 6592 b'name',
6593 6593 b'',
6594 6594 _(b'name to show in web pages (default: working directory)'),
6595 6595 _(b'NAME'),
6596 6596 ),
6597 6597 (
6598 6598 b'',
6599 6599 b'web-conf',
6600 6600 b'',
6601 6601 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6602 6602 _(b'FILE'),
6603 6603 ),
6604 6604 (
6605 6605 b'',
6606 6606 b'webdir-conf',
6607 6607 b'',
6608 6608 _(b'name of the hgweb config file (DEPRECATED)'),
6609 6609 _(b'FILE'),
6610 6610 ),
6611 6611 (
6612 6612 b'',
6613 6613 b'pid-file',
6614 6614 b'',
6615 6615 _(b'name of file to write process ID to'),
6616 6616 _(b'FILE'),
6617 6617 ),
6618 6618 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6619 6619 (
6620 6620 b'',
6621 6621 b'cmdserver',
6622 6622 b'',
6623 6623 _(b'for remote clients (ADVANCED)'),
6624 6624 _(b'MODE'),
6625 6625 ),
6626 6626 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6627 6627 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6628 6628 (b'6', b'ipv6', None, _(b'use IPv6 instead of IPv4')),
6629 6629 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6630 6630 (b'', b'print-url', None, _(b'start and print only the URL')),
6631 6631 ]
6632 6632 + subrepoopts,
6633 6633 _(b'[OPTION]...'),
6634 6634 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6635 6635 helpbasic=True,
6636 6636 optionalrepo=True,
6637 6637 )
6638 6638 def serve(ui, repo, **opts):
6639 6639 """start stand-alone webserver
6640 6640
6641 6641 Start a local HTTP repository browser and pull server. You can use
6642 6642 this for ad-hoc sharing and browsing of repositories. It is
6643 6643 recommended to use a real web server to serve a repository for
6644 6644 longer periods of time.
6645 6645
6646 6646 Please note that the server does not implement access control.
6647 6647 This means that, by default, anybody can read from the server and
6648 6648 nobody can write to it by default. Set the ``web.allow-push``
6649 6649 option to ``*`` to allow everybody to push to the server. You
6650 6650 should use a real web server if you need to authenticate users.
6651 6651
6652 6652 By default, the server logs accesses to stdout and errors to
6653 6653 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6654 6654 files.
6655 6655
6656 6656 To have the server choose a free port number to listen on, specify
6657 6657 a port number of 0; in this case, the server will print the port
6658 6658 number it uses.
6659 6659
6660 6660 Returns 0 on success.
6661 6661 """
6662 6662
6663 6663 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6664 6664 opts = pycompat.byteskwargs(opts)
6665 6665 if opts[b"print_url"] and ui.verbose:
6666 6666 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6667 6667
6668 6668 if opts[b"stdio"]:
6669 6669 if repo is None:
6670 6670 raise error.RepoError(
6671 6671 _(b"there is no Mercurial repository here (.hg not found)")
6672 6672 )
6673 6673 accesshidden = False
6674 6674 if repo.filtername is None:
6675 6675 allow = ui.configlist(
6676 6676 b'experimental', b'server.allow-hidden-access'
6677 6677 )
6678 6678 user = procutil.getuser()
6679 6679 if allow and scmutil.ismember(ui, user, allow):
6680 6680 accesshidden = True
6681 6681 else:
6682 6682 msg = (
6683 6683 _(
6684 6684 b'ignoring request to access hidden changeset by '
6685 6685 b'unauthorized user: %s\n'
6686 6686 )
6687 6687 % user
6688 6688 )
6689 6689 ui.warn(msg)
6690 6690
6691 6691 s = wireprotoserver.sshserver(ui, repo, accesshidden=accesshidden)
6692 6692 s.serve_forever()
6693 6693 return
6694 6694
6695 6695 service = server.createservice(ui, repo, opts)
6696 6696 return server.runservice(opts, initfn=service.init, runfn=service.run)
6697 6697
6698 6698
6699 6699 @command(
6700 6700 b'shelve',
6701 6701 [
6702 6702 (
6703 6703 b'A',
6704 6704 b'addremove',
6705 6705 None,
6706 6706 _(b'mark new/missing files as added/removed before shelving'),
6707 6707 ),
6708 6708 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6709 6709 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6710 6710 (
6711 6711 b'',
6712 6712 b'date',
6713 6713 b'',
6714 6714 _(b'shelve with the specified commit date'),
6715 6715 _(b'DATE'),
6716 6716 ),
6717 6717 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6718 6718 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6719 6719 (
6720 6720 b'k',
6721 6721 b'keep',
6722 6722 False,
6723 6723 _(b'shelve, but keep changes in the working directory'),
6724 6724 ),
6725 6725 (b'l', b'list', None, _(b'list current shelves')),
6726 6726 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6727 6727 (
6728 6728 b'n',
6729 6729 b'name',
6730 6730 b'',
6731 6731 _(b'use the given name for the shelved commit'),
6732 6732 _(b'NAME'),
6733 6733 ),
6734 6734 (
6735 6735 b'p',
6736 6736 b'patch',
6737 6737 None,
6738 6738 _(
6739 6739 b'output patches for changes (provide the names of the shelved '
6740 6740 b'changes as positional arguments)'
6741 6741 ),
6742 6742 ),
6743 6743 (b'i', b'interactive', None, _(b'interactive mode')),
6744 6744 (
6745 6745 b'',
6746 6746 b'stat',
6747 6747 None,
6748 6748 _(
6749 6749 b'output diffstat-style summary of changes (provide the names of '
6750 6750 b'the shelved changes as positional arguments)'
6751 6751 ),
6752 6752 ),
6753 6753 ]
6754 6754 + cmdutil.walkopts,
6755 6755 _(b'hg shelve [OPTION]... [FILE]...'),
6756 6756 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6757 6757 )
6758 6758 def shelve(ui, repo, *pats, **opts):
6759 6759 """save and set aside changes from the working directory
6760 6760
6761 6761 Shelving takes files that "hg status" reports as not clean, saves
6762 6762 the modifications to a bundle (a shelved change), and reverts the
6763 6763 files so that their state in the working directory becomes clean.
6764 6764
6765 6765 To restore these changes to the working directory, using "hg
6766 6766 unshelve"; this will work even if you switch to a different
6767 6767 commit.
6768 6768
6769 6769 When no files are specified, "hg shelve" saves all not-clean
6770 6770 files. If specific files or directories are named, only changes to
6771 6771 those files are shelved.
6772 6772
6773 6773 In bare shelve (when no files are specified, without interactive,
6774 6774 include and exclude option), shelving remembers information if the
6775 6775 working directory was on newly created branch, in other words working
6776 6776 directory was on different branch than its first parent. In this
6777 6777 situation unshelving restores branch information to the working directory.
6778 6778
6779 6779 Each shelved change has a name that makes it easier to find later.
6780 6780 The name of a shelved change defaults to being based on the active
6781 6781 bookmark, or if there is no active bookmark, the current named
6782 6782 branch. To specify a different name, use ``--name``.
6783 6783
6784 6784 To see a list of existing shelved changes, use the ``--list``
6785 6785 option. For each shelved change, this will print its name, age,
6786 6786 and description; use ``--patch`` or ``--stat`` for more details.
6787 6787
6788 6788 To delete specific shelved changes, use ``--delete``. To delete
6789 6789 all shelved changes, use ``--cleanup``.
6790 6790 """
6791 6791 opts = pycompat.byteskwargs(opts)
6792 6792 allowables = [
6793 6793 (b'addremove', {b'create'}), # 'create' is pseudo action
6794 6794 (b'unknown', {b'create'}),
6795 6795 (b'cleanup', {b'cleanup'}),
6796 6796 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6797 6797 (b'delete', {b'delete'}),
6798 6798 (b'edit', {b'create'}),
6799 6799 (b'keep', {b'create'}),
6800 6800 (b'list', {b'list'}),
6801 6801 (b'message', {b'create'}),
6802 6802 (b'name', {b'create'}),
6803 6803 (b'patch', {b'patch', b'list'}),
6804 6804 (b'stat', {b'stat', b'list'}),
6805 6805 ]
6806 6806
6807 6807 def checkopt(opt):
6808 6808 if opts.get(opt):
6809 6809 for i, allowable in allowables:
6810 6810 if opts[i] and opt not in allowable:
6811 6811 raise error.InputError(
6812 6812 _(
6813 6813 b"options '--%s' and '--%s' may not be "
6814 6814 b"used together"
6815 6815 )
6816 6816 % (opt, i)
6817 6817 )
6818 6818 return True
6819 6819
6820 6820 if checkopt(b'cleanup'):
6821 6821 if pats:
6822 6822 raise error.InputError(
6823 6823 _(b"cannot specify names when using '--cleanup'")
6824 6824 )
6825 6825 return shelvemod.cleanupcmd(ui, repo)
6826 6826 elif checkopt(b'delete'):
6827 6827 return shelvemod.deletecmd(ui, repo, pats)
6828 6828 elif checkopt(b'list'):
6829 6829 return shelvemod.listcmd(ui, repo, pats, opts)
6830 6830 elif checkopt(b'patch') or checkopt(b'stat'):
6831 6831 return shelvemod.patchcmds(ui, repo, pats, opts)
6832 6832 else:
6833 6833 return shelvemod.createcmd(ui, repo, pats, opts)
6834 6834
6835 6835
6836 6836 _NOTTERSE = b'nothing'
6837 6837
6838 6838
6839 6839 @command(
6840 6840 b'status|st',
6841 6841 [
6842 6842 (b'A', b'all', None, _(b'show status of all files')),
6843 6843 (b'm', b'modified', None, _(b'show only modified files')),
6844 6844 (b'a', b'added', None, _(b'show only added files')),
6845 6845 (b'r', b'removed', None, _(b'show only removed files')),
6846 6846 (b'd', b'deleted', None, _(b'show only missing files')),
6847 6847 (b'c', b'clean', None, _(b'show only files without changes')),
6848 6848 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6849 6849 (b'i', b'ignored', None, _(b'show only ignored files')),
6850 6850 (b'n', b'no-status', None, _(b'hide status prefix')),
6851 6851 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6852 6852 (
6853 6853 b'C',
6854 6854 b'copies',
6855 6855 None,
6856 6856 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6857 6857 ),
6858 6858 (
6859 6859 b'0',
6860 6860 b'print0',
6861 6861 None,
6862 6862 _(b'end filenames with NUL, for use with xargs'),
6863 6863 ),
6864 6864 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6865 6865 (
6866 6866 b'',
6867 6867 b'change',
6868 6868 b'',
6869 6869 _(b'list the changed files of a revision'),
6870 6870 _(b'REV'),
6871 6871 ),
6872 6872 ]
6873 6873 + walkopts
6874 6874 + subrepoopts
6875 6875 + formatteropts,
6876 6876 _(b'[OPTION]... [FILE]...'),
6877 6877 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6878 6878 helpbasic=True,
6879 6879 inferrepo=True,
6880 6880 intents={INTENT_READONLY},
6881 6881 )
6882 6882 def status(ui, repo, *pats, **opts):
6883 6883 """show changed files in the working directory
6884 6884
6885 6885 Show status of files in the repository. If names are given, only
6886 6886 files that match are shown. Files that are clean or ignored or
6887 6887 the source of a copy/move operation, are not listed unless
6888 6888 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6889 6889 Unless options described with "show only ..." are given, the
6890 6890 options -mardu are used.
6891 6891
6892 6892 Option -q/--quiet hides untracked (unknown and ignored) files
6893 6893 unless explicitly requested with -u/--unknown or -i/--ignored.
6894 6894
6895 6895 .. note::
6896 6896
6897 6897 :hg:`status` may appear to disagree with diff if permissions have
6898 6898 changed or a merge has occurred. The standard diff format does
6899 6899 not report permission changes and diff only reports changes
6900 6900 relative to one merge parent.
6901 6901
6902 6902 If one revision is given, it is used as the base revision.
6903 6903 If two revisions are given, the differences between them are
6904 6904 shown. The --change option can also be used as a shortcut to list
6905 6905 the changed files of a revision from its first parent.
6906 6906
6907 6907 The codes used to show the status of files are::
6908 6908
6909 6909 M = modified
6910 6910 A = added
6911 6911 R = removed
6912 6912 C = clean
6913 6913 ! = missing (deleted by non-hg command, but still tracked)
6914 6914 ? = not tracked
6915 6915 I = ignored
6916 6916 = origin of the previous file (with --copies)
6917 6917
6918 6918 .. container:: verbose
6919 6919
6920 6920 The -t/--terse option abbreviates the output by showing only the directory
6921 6921 name if all the files in it share the same status. The option takes an
6922 6922 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6923 6923 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6924 6924 for 'ignored' and 'c' for clean.
6925 6925
6926 6926 It abbreviates only those statuses which are passed. Note that clean and
6927 6927 ignored files are not displayed with '--terse ic' unless the -c/--clean
6928 6928 and -i/--ignored options are also used.
6929 6929
6930 6930 The -v/--verbose option shows information when the repository is in an
6931 6931 unfinished merge, shelve, rebase state etc. You can have this behavior
6932 6932 turned on by default by enabling the ``commands.status.verbose`` option.
6933 6933
6934 6934 You can skip displaying some of these states by setting
6935 6935 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6936 6936 'histedit', 'merge', 'rebase', or 'unshelve'.
6937 6937
6938 6938 Template:
6939 6939
6940 6940 The following keywords are supported in addition to the common template
6941 6941 keywords and functions. See also :hg:`help templates`.
6942 6942
6943 6943 :path: String. Repository-absolute path of the file.
6944 6944 :source: String. Repository-absolute path of the file originated from.
6945 6945 Available if ``--copies`` is specified.
6946 6946 :status: String. Character denoting file's status.
6947 6947
6948 6948 Examples:
6949 6949
6950 6950 - show changes in the working directory relative to a
6951 6951 changeset::
6952 6952
6953 6953 hg status --rev 9353
6954 6954
6955 6955 - show changes in the working directory relative to the
6956 6956 current directory (see :hg:`help patterns` for more information)::
6957 6957
6958 6958 hg status re:
6959 6959
6960 6960 - show all changes including copies in an existing changeset::
6961 6961
6962 6962 hg status --copies --change 9353
6963 6963
6964 6964 - get a NUL separated list of added files, suitable for xargs::
6965 6965
6966 6966 hg status -an0
6967 6967
6968 6968 - show more information about the repository status, abbreviating
6969 6969 added, removed, modified, deleted, and untracked paths::
6970 6970
6971 6971 hg status -v -t mardu
6972 6972
6973 6973 Returns 0 on success.
6974 6974
6975 6975 """
6976 6976
6977 6977 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6978 6978 opts = pycompat.byteskwargs(opts)
6979 6979 revs = opts.get(b'rev', [])
6980 6980 change = opts.get(b'change', b'')
6981 6981 terse = opts.get(b'terse', _NOTTERSE)
6982 6982 if terse is _NOTTERSE:
6983 6983 if revs:
6984 6984 terse = b''
6985 6985 else:
6986 6986 terse = ui.config(b'commands', b'status.terse')
6987 6987
6988 6988 if revs and terse:
6989 6989 msg = _(b'cannot use --terse with --rev')
6990 6990 raise error.InputError(msg)
6991 6991 elif change:
6992 6992 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6993 6993 ctx2 = logcmdutil.revsingle(repo, change, None)
6994 6994 ctx1 = ctx2.p1()
6995 6995 else:
6996 6996 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6997 6997 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
6998 6998
6999 6999 forcerelativevalue = None
7000 7000 if ui.hasconfig(b'commands', b'status.relative'):
7001 7001 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
7002 7002 uipathfn = scmutil.getuipathfn(
7003 7003 repo,
7004 7004 legacyrelativevalue=bool(pats),
7005 7005 forcerelativevalue=forcerelativevalue,
7006 7006 )
7007 7007
7008 7008 if opts.get(b'print0'):
7009 7009 end = b'\0'
7010 7010 else:
7011 7011 end = b'\n'
7012 7012 states = b'modified added removed deleted unknown ignored clean'.split()
7013 7013 show = [k for k in states if opts.get(k)]
7014 7014 if opts.get(b'all'):
7015 7015 show += ui.quiet and (states[:4] + [b'clean']) or states
7016 7016
7017 7017 if not show:
7018 7018 if ui.quiet:
7019 7019 show = states[:4]
7020 7020 else:
7021 7021 show = states[:5]
7022 7022
7023 7023 m = scmutil.match(ctx2, pats, opts)
7024 7024 if terse:
7025 7025 # we need to compute clean and unknown to terse
7026 7026 stat = repo.status(
7027 7027 ctx1.node(),
7028 7028 ctx2.node(),
7029 7029 m,
7030 7030 b'ignored' in show or b'i' in terse,
7031 7031 clean=True,
7032 7032 unknown=True,
7033 7033 listsubrepos=opts.get(b'subrepos'),
7034 7034 )
7035 7035
7036 7036 stat = cmdutil.tersedir(stat, terse)
7037 7037 else:
7038 7038 stat = repo.status(
7039 7039 ctx1.node(),
7040 7040 ctx2.node(),
7041 7041 m,
7042 7042 b'ignored' in show,
7043 7043 b'clean' in show,
7044 7044 b'unknown' in show,
7045 7045 opts.get(b'subrepos'),
7046 7046 )
7047 7047
7048 7048 changestates = zip(
7049 7049 states,
7050 7050 pycompat.iterbytestr(b'MAR!?IC'),
7051 7051 [getattr(stat, s.decode('utf8')) for s in states],
7052 7052 )
7053 7053
7054 7054 copy = {}
7055 7055 show_copies = ui.configbool(b'ui', b'statuscopies')
7056 7056 if opts.get(b'copies') is not None:
7057 7057 show_copies = opts.get(b'copies')
7058 7058 show_copies = (show_copies or opts.get(b'all')) and not opts.get(
7059 7059 b'no_status'
7060 7060 )
7061 7061 if show_copies:
7062 7062 copy = copies.pathcopies(ctx1, ctx2, m)
7063 7063
7064 7064 morestatus = None
7065 7065 if (
7066 7066 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
7067 7067 and not ui.plain()
7068 7068 and not opts.get(b'print0')
7069 7069 ):
7070 7070 morestatus = cmdutil.readmorestatus(repo)
7071 7071
7072 7072 ui.pager(b'status')
7073 7073 fm = ui.formatter(b'status', opts)
7074 7074 fmt = b'%s' + end
7075 7075 showchar = not opts.get(b'no_status')
7076 7076
7077 7077 for state, char, files in changestates:
7078 7078 if state in show:
7079 7079 label = b'status.' + state
7080 7080 for f in files:
7081 7081 fm.startitem()
7082 7082 fm.context(ctx=ctx2)
7083 7083 fm.data(itemtype=b'file', path=f)
7084 7084 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
7085 7085 fm.plain(fmt % uipathfn(f), label=label)
7086 7086 if f in copy:
7087 7087 fm.data(source=copy[f])
7088 7088 fm.plain(
7089 7089 (b' %s' + end) % uipathfn(copy[f]),
7090 7090 label=b'status.copied',
7091 7091 )
7092 7092 if morestatus:
7093 7093 morestatus.formatfile(f, fm)
7094 7094
7095 7095 if morestatus:
7096 7096 morestatus.formatfooter(fm)
7097 7097 fm.end()
7098 7098
7099 7099
7100 7100 @command(
7101 7101 b'summary|sum',
7102 7102 [(b'', b'remote', None, _(b'check for push and pull'))],
7103 7103 b'[--remote]',
7104 7104 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7105 7105 helpbasic=True,
7106 7106 intents={INTENT_READONLY},
7107 7107 )
7108 7108 def summary(ui, repo, **opts):
7109 7109 """summarize working directory state
7110 7110
7111 7111 This generates a brief summary of the working directory state,
7112 7112 including parents, branch, commit status, phase and available updates.
7113 7113
7114 7114 With the --remote option, this will check the default paths for
7115 7115 incoming and outgoing changes. This can be time-consuming.
7116 7116
7117 7117 Returns 0 on success.
7118 7118 """
7119 7119
7120 7120 ui.pager(b'summary')
7121 7121 ctx = repo[None]
7122 7122 parents = ctx.parents()
7123 7123 pnode = parents[0].node()
7124 7124 marks = []
7125 7125
7126 7126 try:
7127 7127 ms = mergestatemod.mergestate.read(repo)
7128 7128 except error.UnsupportedMergeRecords as e:
7129 7129 s = b' '.join(e.recordtypes)
7130 7130 ui.warn(
7131 7131 _(b'warning: merge state has unsupported record types: %s\n') % s
7132 7132 )
7133 7133 unresolved = []
7134 7134 else:
7135 7135 unresolved = list(ms.unresolved())
7136 7136
7137 7137 for p in parents:
7138 7138 # label with log.changeset (instead of log.parent) since this
7139 7139 # shows a working directory parent *changeset*:
7140 7140 # i18n: column positioning for "hg summary"
7141 7141 ui.write(
7142 7142 _(b'parent: %d:%s ') % (p.rev(), p),
7143 7143 label=logcmdutil.changesetlabels(p),
7144 7144 )
7145 7145 ui.write(b' '.join(p.tags()), label=b'log.tag')
7146 7146 if p.bookmarks():
7147 7147 marks.extend(p.bookmarks())
7148 7148 if p.rev() == -1:
7149 7149 if not len(repo):
7150 7150 ui.write(_(b' (empty repository)'))
7151 7151 else:
7152 7152 ui.write(_(b' (no revision checked out)'))
7153 7153 if p.obsolete():
7154 7154 ui.write(_(b' (obsolete)'))
7155 7155 if p.isunstable():
7156 7156 instabilities = (
7157 7157 ui.label(instability, b'trouble.%s' % instability)
7158 7158 for instability in p.instabilities()
7159 7159 )
7160 7160 ui.write(b' (' + b', '.join(instabilities) + b')')
7161 7161 ui.write(b'\n')
7162 7162 if p.description():
7163 7163 ui.status(
7164 7164 b' ' + p.description().splitlines()[0].strip() + b'\n',
7165 7165 label=b'log.summary',
7166 7166 )
7167 7167
7168 7168 branch = ctx.branch()
7169 7169 bheads = repo.branchheads(branch)
7170 7170 # i18n: column positioning for "hg summary"
7171 7171 m = _(b'branch: %s\n') % branch
7172 7172 if branch != b'default':
7173 7173 ui.write(m, label=b'log.branch')
7174 7174 else:
7175 7175 ui.status(m, label=b'log.branch')
7176 7176
7177 7177 if marks:
7178 7178 active = repo._activebookmark
7179 7179 # i18n: column positioning for "hg summary"
7180 7180 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7181 7181 if active is not None:
7182 7182 if active in marks:
7183 7183 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7184 7184 marks.remove(active)
7185 7185 else:
7186 7186 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7187 7187 for m in marks:
7188 7188 ui.write(b' ' + m, label=b'log.bookmark')
7189 7189 ui.write(b'\n', label=b'log.bookmark')
7190 7190
7191 7191 status = repo.status(unknown=True)
7192 7192
7193 7193 c = repo.dirstate.copies()
7194 7194 copied, renamed = [], []
7195 7195 for d, s in c.items():
7196 7196 if s in status.removed:
7197 7197 status.removed.remove(s)
7198 7198 renamed.append(d)
7199 7199 else:
7200 7200 copied.append(d)
7201 7201 if d in status.added:
7202 7202 status.added.remove(d)
7203 7203
7204 7204 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7205 7205
7206 7206 labels = [
7207 7207 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7208 7208 (ui.label(_(b'%d added'), b'status.added'), status.added),
7209 7209 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7210 7210 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7211 7211 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7212 7212 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7213 7213 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7214 7214 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7215 7215 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7216 7216 ]
7217 7217 t = []
7218 7218 for l, s in labels:
7219 7219 if s:
7220 7220 t.append(l % len(s))
7221 7221
7222 7222 t = b', '.join(t)
7223 7223 cleanworkdir = False
7224 7224
7225 7225 if repo.vfs.exists(b'graftstate'):
7226 7226 t += _(b' (graft in progress)')
7227 7227 if repo.vfs.exists(b'updatestate'):
7228 7228 t += _(b' (interrupted update)')
7229 7229 elif len(parents) > 1:
7230 7230 t += _(b' (merge)')
7231 7231 elif branch != parents[0].branch():
7232 7232 t += _(b' (new branch)')
7233 7233 elif parents[0].closesbranch() and pnode in repo.branchheads(
7234 7234 branch, closed=True
7235 7235 ):
7236 7236 t += _(b' (head closed)')
7237 7237 elif not (
7238 7238 status.modified
7239 7239 or status.added
7240 7240 or status.removed
7241 7241 or renamed
7242 7242 or copied
7243 7243 or subs
7244 7244 ):
7245 7245 t += _(b' (clean)')
7246 7246 cleanworkdir = True
7247 7247 elif pnode not in bheads:
7248 7248 t += _(b' (new branch head)')
7249 7249
7250 7250 if parents:
7251 7251 pendingphase = max(p.phase() for p in parents)
7252 7252 else:
7253 7253 pendingphase = phases.public
7254 7254
7255 7255 if pendingphase > phases.newcommitphase(ui):
7256 7256 t += b' (%s)' % phases.phasenames[pendingphase]
7257 7257
7258 7258 if cleanworkdir:
7259 7259 # i18n: column positioning for "hg summary"
7260 7260 ui.status(_(b'commit: %s\n') % t.strip())
7261 7261 else:
7262 7262 # i18n: column positioning for "hg summary"
7263 7263 ui.write(_(b'commit: %s\n') % t.strip())
7264 7264
7265 7265 # all ancestors of branch heads - all ancestors of parent = new csets
7266 7266 new = len(
7267 7267 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7268 7268 )
7269 7269
7270 7270 if new == 0:
7271 7271 # i18n: column positioning for "hg summary"
7272 7272 ui.status(_(b'update: (current)\n'))
7273 7273 elif pnode not in bheads:
7274 7274 # i18n: column positioning for "hg summary"
7275 7275 ui.write(_(b'update: %d new changesets (update)\n') % new)
7276 7276 else:
7277 7277 # i18n: column positioning for "hg summary"
7278 7278 ui.write(
7279 7279 _(b'update: %d new changesets, %d branch heads (merge)\n')
7280 7280 % (new, len(bheads))
7281 7281 )
7282 7282
7283 7283 t = []
7284 7284 draft = len(repo.revs(b'draft()'))
7285 7285 if draft:
7286 7286 t.append(_(b'%d draft') % draft)
7287 7287 secret = len(repo.revs(b'secret()'))
7288 7288 if secret:
7289 7289 t.append(_(b'%d secret') % secret)
7290 7290
7291 7291 if draft or secret:
7292 7292 ui.status(_(b'phases: %s\n') % b', '.join(t))
7293 7293
7294 7294 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7295 7295 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7296 7296 numtrouble = len(repo.revs(trouble + b"()"))
7297 7297 # We write all the possibilities to ease translation
7298 7298 troublemsg = {
7299 7299 b"orphan": _(b"orphan: %d changesets"),
7300 7300 b"contentdivergent": _(b"content-divergent: %d changesets"),
7301 7301 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7302 7302 }
7303 7303 if numtrouble > 0:
7304 7304 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7305 7305
7306 7306 cmdutil.summaryhooks(ui, repo)
7307 7307
7308 7308 if opts.get('remote'):
7309 7309 needsincoming, needsoutgoing = True, True
7310 7310 else:
7311 7311 needsincoming, needsoutgoing = False, False
7312 7312 for i, o in cmdutil.summaryremotehooks(
7313 7313 ui, repo, pycompat.byteskwargs(opts), None
7314 7314 ):
7315 7315 if i:
7316 7316 needsincoming = True
7317 7317 if o:
7318 7318 needsoutgoing = True
7319 7319 if not needsincoming and not needsoutgoing:
7320 7320 return
7321 7321
7322 7322 def getincoming():
7323 7323 # XXX We should actually skip this if no default is specified, instead
7324 7324 # of passing "default" which will resolve as "./default/" if no default
7325 7325 # path is defined.
7326 7326 path = urlutil.get_unique_pull_path_obj(b'summary', ui, b'default')
7327 7327 sbranch = path.branch
7328 7328 try:
7329 7329 other = hg.peer(repo, {}, path)
7330 7330 except error.RepoError:
7331 7331 if opts.get('remote'):
7332 7332 raise
7333 7333 return path.loc, sbranch, None, None, None
7334 7334 branches = (path.branch, [])
7335 7335 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7336 7336 if revs:
7337 7337 revs = [other.lookup(rev) for rev in revs]
7338 7338 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(path.loc))
7339 7339 with repo.ui.silent():
7340 7340 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7341 7341 return path.loc, sbranch, other, commoninc, commoninc[1]
7342 7342
7343 7343 if needsincoming:
7344 7344 source, sbranch, sother, commoninc, incoming = getincoming()
7345 7345 else:
7346 7346 source = sbranch = sother = commoninc = incoming = None
7347 7347
7348 7348 def getoutgoing():
7349 7349 # XXX We should actually skip this if no default is specified, instead
7350 7350 # of passing "default" which will resolve as "./default/" if no default
7351 7351 # path is defined.
7352 7352 d = None
7353 7353 if b'default-push' in ui.paths:
7354 7354 d = b'default-push'
7355 7355 elif b'default' in ui.paths:
7356 7356 d = b'default'
7357 7357 path = None
7358 7358 if d is not None:
7359 7359 path = urlutil.get_unique_push_path(b'summary', repo, ui, d)
7360 7360 dest = path.loc
7361 7361 dbranch = path.branch
7362 7362 else:
7363 7363 dest = b'default'
7364 7364 dbranch = None
7365 7365 revs, checkout = hg.addbranchrevs(repo, repo, (dbranch, []), None)
7366 7366 if source != dest:
7367 7367 try:
7368 7368 dother = hg.peer(repo, {}, path if path is not None else dest)
7369 7369 except error.RepoError:
7370 7370 if opts.get('remote'):
7371 7371 raise
7372 7372 return dest, dbranch, None, None
7373 7373 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(dest))
7374 7374 elif sother is None:
7375 7375 # there is no explicit destination peer, but source one is invalid
7376 7376 return dest, dbranch, None, None
7377 7377 else:
7378 7378 dother = sother
7379 7379 if source != dest or (sbranch is not None and sbranch != dbranch):
7380 7380 common = None
7381 7381 else:
7382 7382 common = commoninc
7383 7383 if revs:
7384 7384 revs = [repo.lookup(rev) for rev in revs]
7385 7385 with repo.ui.silent():
7386 7386 outgoing = discovery.findcommonoutgoing(
7387 7387 repo, dother, onlyheads=revs, commoninc=common
7388 7388 )
7389 7389 return dest, dbranch, dother, outgoing
7390 7390
7391 7391 if needsoutgoing:
7392 7392 dest, dbranch, dother, outgoing = getoutgoing()
7393 7393 else:
7394 7394 dest = dbranch = dother = outgoing = None
7395 7395
7396 7396 if opts.get('remote'):
7397 7397 # Help pytype. --remote sets both `needsincoming` and `needsoutgoing`.
7398 7398 # The former always sets `sother` (or raises an exception if it can't);
7399 7399 # the latter always sets `outgoing`.
7400 7400 assert sother is not None
7401 7401 assert outgoing is not None
7402 7402
7403 7403 t = []
7404 7404 if incoming:
7405 7405 t.append(_(b'1 or more incoming'))
7406 7406 o = outgoing.missing
7407 7407 if o:
7408 7408 t.append(_(b'%d outgoing') % len(o))
7409 7409 other = dother or sother
7410 7410 if b'bookmarks' in other.listkeys(b'namespaces'):
7411 7411 counts = bookmarks.summary(repo, other)
7412 7412 if counts[0] > 0:
7413 7413 t.append(_(b'%d incoming bookmarks') % counts[0])
7414 7414 if counts[1] > 0:
7415 7415 t.append(_(b'%d outgoing bookmarks') % counts[1])
7416 7416
7417 7417 if t:
7418 7418 # i18n: column positioning for "hg summary"
7419 7419 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7420 7420 else:
7421 7421 # i18n: column positioning for "hg summary"
7422 7422 ui.status(_(b'remote: (synced)\n'))
7423 7423
7424 7424 cmdutil.summaryremotehooks(
7425 7425 ui,
7426 7426 repo,
7427 7427 pycompat.byteskwargs(opts),
7428 7428 (
7429 7429 (source, sbranch, sother, commoninc),
7430 7430 (dest, dbranch, dother, outgoing),
7431 7431 ),
7432 7432 )
7433 7433
7434 7434
7435 7435 @command(
7436 7436 b'tag',
7437 7437 [
7438 7438 (b'f', b'force', None, _(b'force tag')),
7439 7439 (b'l', b'local', None, _(b'make the tag local')),
7440 7440 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7441 7441 (b'', b'remove', None, _(b'remove a tag')),
7442 7442 # -l/--local is already there, commitopts cannot be used
7443 7443 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7444 7444 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7445 7445 ]
7446 7446 + commitopts2,
7447 7447 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7448 7448 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7449 7449 )
7450 7450 def tag(ui, repo, name1, *names, **opts):
7451 7451 """add one or more tags for the current or given revision
7452 7452
7453 7453 Name a particular revision using <name>.
7454 7454
7455 7455 Tags are used to name particular revisions of the repository and are
7456 7456 very useful to compare different revisions, to go back to significant
7457 7457 earlier versions or to mark branch points as releases, etc. Changing
7458 7458 an existing tag is normally disallowed; use -f/--force to override.
7459 7459
7460 7460 If no revision is given, the parent of the working directory is
7461 7461 used.
7462 7462
7463 7463 To facilitate version control, distribution, and merging of tags,
7464 7464 they are stored as a file named ".hgtags" which is managed similarly
7465 7465 to other project files and can be hand-edited if necessary. This
7466 7466 also means that tagging creates a new commit. The file
7467 7467 ".hg/localtags" is used for local tags (not shared among
7468 7468 repositories).
7469 7469
7470 7470 Tag commits are usually made at the head of a branch. If the parent
7471 7471 of the working directory is not a branch head, :hg:`tag` aborts; use
7472 7472 -f/--force to force the tag commit to be based on a non-head
7473 7473 changeset.
7474 7474
7475 7475 See :hg:`help dates` for a list of formats valid for -d/--date.
7476 7476
7477 7477 Since tag names have priority over branch names during revision
7478 7478 lookup, using an existing branch name as a tag name is discouraged.
7479 7479
7480 7480 Returns 0 on success.
7481 7481 """
7482 7482 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7483 7483
7484 7484 with repo.wlock(), repo.lock():
7485 7485 rev_ = b"."
7486 7486 names = [t.strip() for t in (name1,) + names]
7487 7487 if len(names) != len(set(names)):
7488 7488 raise error.InputError(_(b'tag names must be unique'))
7489 7489 for n in names:
7490 7490 scmutil.checknewlabel(repo, n, b'tag')
7491 7491 if not n:
7492 7492 raise error.InputError(
7493 7493 _(b'tag names cannot consist entirely of whitespace')
7494 7494 )
7495 7495 if opts.get('rev'):
7496 7496 rev_ = opts['rev']
7497 7497 message = opts.get('message')
7498 7498 if opts.get('remove'):
7499 7499 if opts.get('local'):
7500 7500 expectedtype = b'local'
7501 7501 else:
7502 7502 expectedtype = b'global'
7503 7503
7504 7504 for n in names:
7505 7505 if repo.tagtype(n) == b'global':
7506 7506 alltags = tagsmod.findglobaltags(ui, repo)
7507 7507 if alltags[n][0] == repo.nullid:
7508 7508 raise error.InputError(
7509 7509 _(b"tag '%s' is already removed") % n
7510 7510 )
7511 7511 if not repo.tagtype(n):
7512 7512 raise error.InputError(_(b"tag '%s' does not exist") % n)
7513 7513 if repo.tagtype(n) != expectedtype:
7514 7514 if expectedtype == b'global':
7515 7515 raise error.InputError(
7516 7516 _(b"tag '%s' is not a global tag") % n
7517 7517 )
7518 7518 else:
7519 7519 raise error.InputError(
7520 7520 _(b"tag '%s' is not a local tag") % n
7521 7521 )
7522 7522 rev_ = b'null'
7523 7523 if not message:
7524 7524 # we don't translate commit messages
7525 7525 message = b'Removed tag %s' % b', '.join(names)
7526 7526 elif not opts.get('force'):
7527 7527 for n in names:
7528 7528 if n in repo.tags():
7529 7529 raise error.InputError(
7530 7530 _(b"tag '%s' already exists (use -f to force)") % n
7531 7531 )
7532 7532 if not opts.get('local'):
7533 7533 p1, p2 = repo.dirstate.parents()
7534 7534 if p2 != repo.nullid:
7535 7535 raise error.StateError(_(b'uncommitted merge'))
7536 7536 bheads = repo.branchheads()
7537 7537 if not opts.get('force') and bheads and p1 not in bheads:
7538 7538 raise error.InputError(
7539 7539 _(
7540 7540 b'working directory is not at a branch head '
7541 7541 b'(use -f to force)'
7542 7542 )
7543 7543 )
7544 7544 node = logcmdutil.revsingle(repo, rev_).node()
7545 7545
7546 7546 # don't allow tagging the null rev or the working directory
7547 7547 if node is None:
7548 7548 raise error.InputError(_(b"cannot tag working directory"))
7549 7549 elif not opts.get('remove') and node == nullid:
7550 7550 raise error.InputError(_(b"cannot tag null revision"))
7551 7551
7552 7552 if not message:
7553 7553 # we don't translate commit messages
7554 7554 message = b'Added tag %s for changeset %s' % (
7555 7555 b', '.join(names),
7556 7556 short(node),
7557 7557 )
7558 7558
7559 7559 date = opts.get('date')
7560 7560 if date:
7561 7561 date = dateutil.parsedate(date)
7562 7562
7563 7563 if opts.get('remove'):
7564 7564 editform = b'tag.remove'
7565 7565 else:
7566 7566 editform = b'tag.add'
7567 7567 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7568 7568
7569 7569 tagsmod.tag(
7570 7570 repo,
7571 7571 names,
7572 7572 node,
7573 7573 message,
7574 7574 opts.get('local'),
7575 7575 opts.get('user'),
7576 7576 date,
7577 7577 editor=editor,
7578 7578 )
7579 7579
7580 7580
7581 7581 @command(
7582 7582 b'tags',
7583 7583 formatteropts,
7584 7584 b'',
7585 7585 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7586 7586 intents={INTENT_READONLY},
7587 7587 )
7588 7588 def tags(ui, repo, **opts):
7589 7589 """list repository tags
7590 7590
7591 7591 This lists both regular and local tags. When the -v/--verbose
7592 7592 switch is used, a third column "local" is printed for local tags.
7593 7593 When the -q/--quiet switch is used, only the tag name is printed.
7594 7594
7595 7595 .. container:: verbose
7596 7596
7597 7597 Template:
7598 7598
7599 7599 The following keywords are supported in addition to the common template
7600 7600 keywords and functions such as ``{tag}``. See also
7601 7601 :hg:`help templates`.
7602 7602
7603 7603 :type: String. ``local`` for local tags.
7604 7604
7605 7605 Returns 0 on success.
7606 7606 """
7607 7607
7608 7608 ui.pager(b'tags')
7609 7609 fm = ui.formatter(b'tags', pycompat.byteskwargs(opts))
7610 7610 hexfunc = fm.hexfunc
7611 7611
7612 7612 for t, n in reversed(repo.tagslist()):
7613 7613 hn = hexfunc(n)
7614 7614 label = b'tags.normal'
7615 7615 tagtype = repo.tagtype(t)
7616 7616 if not tagtype or tagtype == b'global':
7617 7617 tagtype = b''
7618 7618 else:
7619 7619 label = b'tags.' + tagtype
7620 7620
7621 7621 fm.startitem()
7622 7622 fm.context(repo=repo)
7623 7623 fm.write(b'tag', b'%s', t, label=label)
7624 7624 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7625 7625 fm.condwrite(
7626 7626 not ui.quiet,
7627 7627 b'rev node',
7628 7628 fmt,
7629 7629 repo.changelog.rev(n),
7630 7630 hn,
7631 7631 label=label,
7632 7632 )
7633 7633 fm.condwrite(
7634 7634 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7635 7635 )
7636 7636 fm.plain(b'\n')
7637 7637 fm.end()
7638 7638
7639 7639
7640 7640 @command(
7641 7641 b'tip',
7642 7642 [
7643 7643 (b'p', b'patch', None, _(b'show patch')),
7644 7644 (b'g', b'git', None, _(b'use git extended diff format')),
7645 7645 ]
7646 7646 + templateopts,
7647 7647 _(b'[-p] [-g]'),
7648 7648 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7649 7649 )
7650 7650 def tip(ui, repo, **opts):
7651 7651 """show the tip revision (DEPRECATED)
7652 7652
7653 7653 The tip revision (usually just called the tip) is the changeset
7654 7654 most recently added to the repository (and therefore the most
7655 7655 recently changed head).
7656 7656
7657 7657 If you have just made a commit, that commit will be the tip. If
7658 7658 you have just pulled changes from another repository, the tip of
7659 7659 that repository becomes the current tip. The "tip" tag is special
7660 7660 and cannot be renamed or assigned to a different changeset.
7661 7661
7662 7662 This command is deprecated, please use :hg:`heads` instead.
7663 7663
7664 7664 Returns 0 on success.
7665 7665 """
7666 7666 opts = pycompat.byteskwargs(opts)
7667 7667 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7668 7668 displayer.show(repo[b'tip'])
7669 7669 displayer.close()
7670 7670
7671 7671
7672 7672 @command(
7673 7673 b'unbundle',
7674 7674 [
7675 7675 (
7676 7676 b'u',
7677 7677 b'update',
7678 7678 None,
7679 7679 _(b'update to new branch head if changesets were unbundled'),
7680 7680 )
7681 7681 ],
7682 7682 _(b'[-u] FILE...'),
7683 7683 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7684 7684 )
7685 7685 def unbundle(ui, repo, fname1, *fnames, **opts):
7686 7686 """apply one or more bundle files
7687 7687
7688 7688 Apply one or more bundle files generated by :hg:`bundle`.
7689 7689
7690 7690 Returns 0 on success, 1 if an update has unresolved files.
7691 7691 """
7692 7692 fnames = (fname1,) + fnames
7693 7693
7694 7694 with repo.lock():
7695 7695 for fname in fnames:
7696 7696 f = hg.openpath(ui, fname)
7697 7697 gen = exchange.readbundle(ui, f, fname)
7698 7698 if isinstance(gen, streamclone.streamcloneapplier):
7699 7699 raise error.InputError(
7700 7700 _(
7701 7701 b'packed bundles cannot be applied with '
7702 7702 b'"hg unbundle"'
7703 7703 ),
7704 7704 hint=_(b'use "hg debugapplystreamclonebundle"'),
7705 7705 )
7706 7706 url = b'bundle:' + fname
7707 7707 try:
7708 7708 txnname = b'unbundle'
7709 7709 if not isinstance(gen, bundle2.unbundle20):
7710 7710 txnname = b'unbundle\n%s' % urlutil.hidepassword(url)
7711 7711 with repo.transaction(txnname) as tr:
7712 7712 op = bundle2.applybundle(
7713 7713 repo, gen, tr, source=b'unbundle', url=url
7714 7714 )
7715 7715 except error.BundleUnknownFeatureError as exc:
7716 7716 raise error.Abort(
7717 7717 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7718 7718 hint=_(
7719 7719 b"see https://mercurial-scm.org/"
7720 7720 b"wiki/BundleFeature for more "
7721 7721 b"information"
7722 7722 ),
7723 7723 )
7724 7724 modheads = bundle2.combinechangegroupresults(op)
7725 7725
7726 7726 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7727 7727 return 1
7728 7728 else:
7729 7729 return 0
7730 7730
7731 7731
7732 7732 @command(
7733 7733 b'unshelve',
7734 7734 [
7735 7735 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7736 7736 (
7737 7737 b'c',
7738 7738 b'continue',
7739 7739 None,
7740 7740 _(b'continue an incomplete unshelve operation'),
7741 7741 ),
7742 7742 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7743 7743 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7744 7744 (
7745 7745 b'n',
7746 7746 b'name',
7747 7747 b'',
7748 7748 _(b'restore shelved change with given name'),
7749 7749 _(b'NAME'),
7750 7750 ),
7751 7751 (b't', b'tool', b'', _(b'specify merge tool')),
7752 7752 (
7753 7753 b'',
7754 7754 b'date',
7755 7755 b'',
7756 7756 _(b'set date for temporary commits (DEPRECATED)'),
7757 7757 _(b'DATE'),
7758 7758 ),
7759 7759 ],
7760 7760 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7761 7761 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7762 7762 )
7763 7763 def unshelve(ui, repo, *shelved, **opts):
7764 7764 """restore a shelved change to the working directory
7765 7765
7766 7766 This command accepts an optional name of a shelved change to
7767 7767 restore. If none is given, the most recent shelved change is used.
7768 7768
7769 7769 If a shelved change is applied successfully, the bundle that
7770 7770 contains the shelved changes is moved to a backup location
7771 7771 (.hg/shelve-backup).
7772 7772
7773 7773 Since you can restore a shelved change on top of an arbitrary
7774 7774 commit, it is possible that unshelving will result in a conflict
7775 7775 between your changes and the commits you are unshelving onto. If
7776 7776 this occurs, you must resolve the conflict, then use
7777 7777 ``--continue`` to complete the unshelve operation. (The bundle
7778 7778 will not be moved until you successfully complete the unshelve.)
7779 7779
7780 7780 (Alternatively, you can use ``--abort`` to abandon an unshelve
7781 7781 that causes a conflict. This reverts the unshelved changes, and
7782 7782 leaves the bundle in place.)
7783 7783
7784 7784 If bare shelved change (without interactive, include and exclude
7785 7785 option) was done on newly created branch it would restore branch
7786 7786 information to the working directory.
7787 7787
7788 7788 After a successful unshelve, the shelved changes are stored in a
7789 7789 backup directory. Only the N most recent backups are kept. N
7790 7790 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7791 7791 configuration option.
7792 7792
7793 7793 .. container:: verbose
7794 7794
7795 7795 Timestamp in seconds is used to decide order of backups. More
7796 7796 than ``maxbackups`` backups are kept, if same timestamp
7797 7797 prevents from deciding exact order of them, for safety.
7798 7798
7799 7799 Selected changes can be unshelved with ``--interactive`` flag.
7800 7800 The working directory is updated with the selected changes, and
7801 7801 only the unselected changes remain shelved.
7802 7802 Note: The whole shelve is applied to working directory first before
7803 7803 running interactively. So, this will bring up all the conflicts between
7804 7804 working directory and the shelve, irrespective of which changes will be
7805 7805 unshelved.
7806 7806 """
7807 7807 with repo.wlock():
7808 7808 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7809 7809
7810 7810
7811 7811 statemod.addunfinished(
7812 7812 b'unshelve',
7813 7813 fname=b'shelvedstate',
7814 7814 continueflag=True,
7815 7815 abortfunc=shelvemod.hgabortunshelve,
7816 7816 continuefunc=shelvemod.hgcontinueunshelve,
7817 7817 cmdmsg=_(b'unshelve already in progress'),
7818 7818 )
7819 7819
7820 7820
7821 7821 @command(
7822 7822 b'update|up|checkout|co',
7823 7823 [
7824 7824 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7825 7825 (b'c', b'check', None, _(b'require clean working directory')),
7826 7826 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7827 7827 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7828 7828 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7829 7829 ]
7830 7830 + mergetoolopts,
7831 7831 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7832 7832 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7833 7833 helpbasic=True,
7834 7834 )
7835 7835 def update(ui, repo, node=None, **opts):
7836 7836 """update working directory (or switch revisions)
7837 7837
7838 7838 Update the repository's working directory to the specified
7839 7839 changeset. If no changeset is specified, update to the tip of the
7840 7840 current named branch and move the active bookmark (see :hg:`help
7841 7841 bookmarks`).
7842 7842
7843 7843 Update sets the working directory's parent revision to the specified
7844 7844 changeset (see :hg:`help parents`).
7845 7845
7846 7846 If the changeset is not a descendant or ancestor of the working
7847 7847 directory's parent and there are uncommitted changes, the update is
7848 7848 aborted. With the -c/--check option, the working directory is checked
7849 7849 for uncommitted changes; if none are found, the working directory is
7850 7850 updated to the specified changeset.
7851 7851
7852 7852 .. container:: verbose
7853 7853
7854 7854 The -C/--clean, -c/--check, and -m/--merge options control what
7855 7855 happens if the working directory contains uncommitted changes.
7856 7856 At most of one of them can be specified.
7857 7857
7858 7858 1. If no option is specified, and if
7859 7859 the requested changeset is an ancestor or descendant of
7860 7860 the working directory's parent, the uncommitted changes
7861 7861 are merged into the requested changeset and the merged
7862 7862 result is left uncommitted. If the requested changeset is
7863 7863 not an ancestor or descendant (that is, it is on another
7864 7864 branch), the update is aborted and the uncommitted changes
7865 7865 are preserved.
7866 7866
7867 7867 2. With the -m/--merge option, the update is allowed even if the
7868 7868 requested changeset is not an ancestor or descendant of
7869 7869 the working directory's parent.
7870 7870
7871 7871 3. With the -c/--check option, the update is aborted and the
7872 7872 uncommitted changes are preserved.
7873 7873
7874 7874 4. With the -C/--clean option, uncommitted changes are discarded and
7875 7875 the working directory is updated to the requested changeset.
7876 7876
7877 7877 To cancel an uncommitted merge (and lose your changes), use
7878 7878 :hg:`merge --abort`.
7879 7879
7880 7880 Use null as the changeset to remove the working directory (like
7881 7881 :hg:`clone -U`).
7882 7882
7883 7883 If you want to revert just one file to an older revision, use
7884 7884 :hg:`revert [-r REV] NAME`.
7885 7885
7886 7886 See :hg:`help dates` for a list of formats valid for -d/--date.
7887 7887
7888 7888 Returns 0 on success, 1 if there are unresolved files.
7889 7889 """
7890 7890 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7891 7891 rev = opts.get('rev')
7892 7892 date = opts.get('date')
7893 7893 clean = opts.get('clean')
7894 7894 check = opts.get('check')
7895 7895 merge = opts.get('merge')
7896 7896 if rev and node:
7897 7897 raise error.InputError(_(b"please specify just one revision"))
7898 7898
7899 7899 if ui.configbool(b'commands', b'update.requiredest'):
7900 7900 if not node and not rev and not date:
7901 7901 raise error.InputError(
7902 7902 _(b'you must specify a destination'),
7903 7903 hint=_(b'for example: hg update ".::"'),
7904 7904 )
7905 7905
7906 7906 if rev is None or rev == b'':
7907 7907 rev = node
7908 7908
7909 7909 if date and rev is not None:
7910 7910 raise error.InputError(_(b"you can't specify a revision and a date"))
7911 7911
7912 7912 updatecheck = None
7913 7913 if check or merge is not None and not merge:
7914 7914 updatecheck = b'abort'
7915 7915 elif merge or check is not None and not check:
7916 7916 updatecheck = b'none'
7917 7917
7918 7918 with repo.wlock():
7919 7919 cmdutil.clearunfinished(repo)
7920 7920 if date:
7921 7921 rev = cmdutil.finddate(ui, repo, date)
7922 7922
7923 7923 # if we defined a bookmark, we have to remember the original name
7924 7924 brev = rev
7925 7925 if rev:
7926 7926 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7927 7927 ctx = logcmdutil.revsingle(repo, rev, default=None)
7928 7928 rev = ctx.rev()
7929 7929 hidden = ctx.hidden()
7930 7930 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7931 7931 with ui.configoverride(overrides, b'update'):
7932 7932 ret = hg.updatetotally(
7933 7933 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7934 7934 )
7935 7935 if hidden:
7936 7936 ctxstr = ctx.hex()[:12]
7937 7937 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7938 7938
7939 7939 if ctx.obsolete():
7940 7940 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7941 7941 ui.warn(b"(%s)\n" % obsfatemsg)
7942 7942 return ret
7943 7943
7944 7944
7945 7945 @command(
7946 7946 b'verify',
7947 7947 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7948 7948 helpcategory=command.CATEGORY_MAINTENANCE,
7949 7949 )
7950 7950 def verify(ui, repo, **opts):
7951 7951 """verify the integrity of the repository
7952 7952
7953 7953 Verify the integrity of the current repository.
7954 7954
7955 7955 This will perform an extensive check of the repository's
7956 7956 integrity, validating the hashes and checksums of each entry in
7957 7957 the changelog, manifest, and tracked files, as well as the
7958 7958 integrity of their crosslinks and indices.
7959 7959
7960 7960 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7961 7961 for more information about recovery from corruption of the
7962 7962 repository.
7963 7963
7964 For an alternative UI with a lot more control over the verification
7965 process and better error reporting, try `hg help admin::verify`.
7966
7964 7967 Returns 0 on success, 1 if errors are encountered.
7965 7968 """
7966 7969 level = None
7967 7970 if opts['full']:
7968 7971 level = verifymod.VERIFY_FULL
7969 7972 return hg.verify(repo, level)
7970 7973
7971 7974
7972 7975 @command(
7973 7976 b'version',
7974 7977 [] + formatteropts,
7975 7978 helpcategory=command.CATEGORY_HELP,
7976 7979 norepo=True,
7977 7980 intents={INTENT_READONLY},
7978 7981 )
7979 7982 def version_(ui, **opts):
7980 7983 """output version and copyright information
7981 7984
7982 7985 .. container:: verbose
7983 7986
7984 7987 Template:
7985 7988
7986 7989 The following keywords are supported. See also :hg:`help templates`.
7987 7990
7988 7991 :extensions: List of extensions.
7989 7992 :ver: String. Version number.
7990 7993
7991 7994 And each entry of ``{extensions}`` provides the following sub-keywords
7992 7995 in addition to ``{ver}``.
7993 7996
7994 7997 :bundled: Boolean. True if included in the release.
7995 7998 :name: String. Extension name.
7996 7999 """
7997 8000 if ui.verbose:
7998 8001 ui.pager(b'version')
7999 8002 fm = ui.formatter(b"version", pycompat.byteskwargs(opts))
8000 8003 fm.startitem()
8001 8004 fm.write(
8002 8005 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
8003 8006 )
8004 8007 license = _(
8005 8008 b"(see https://mercurial-scm.org for more information)\n"
8006 8009 b"\nCopyright (C) 2005-2023 Olivia Mackall and others\n"
8007 8010 b"This is free software; see the source for copying conditions. "
8008 8011 b"There is NO\nwarranty; "
8009 8012 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
8010 8013 )
8011 8014 if not ui.quiet:
8012 8015 fm.plain(license)
8013 8016
8014 8017 if ui.verbose:
8015 8018 fm.plain(_(b"\nEnabled extensions:\n\n"))
8016 8019 # format names and versions into columns
8017 8020 names = []
8018 8021 vers = []
8019 8022 isinternals = []
8020 8023 for name, module in sorted(extensions.extensions()):
8021 8024 names.append(name)
8022 8025 vers.append(extensions.moduleversion(module) or None)
8023 8026 isinternals.append(extensions.ismoduleinternal(module))
8024 8027 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
8025 8028 if names:
8026 8029 namefmt = b" %%-%ds " % max(len(n) for n in names)
8027 8030 places = [_(b"external"), _(b"internal")]
8028 8031 for n, v, p in zip(names, vers, isinternals):
8029 8032 fn.startitem()
8030 8033 fn.condwrite(ui.verbose, b"name", namefmt, n)
8031 8034 if ui.verbose:
8032 8035 fn.plain(b"%s " % places[p])
8033 8036 fn.data(bundled=p)
8034 8037 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
8035 8038 if ui.verbose:
8036 8039 fn.plain(b"\n")
8037 8040 fn.end()
8038 8041 fm.end()
8039 8042
8040 8043
8041 8044 def loadcmdtable(ui, name, cmdtable):
8042 8045 """Load command functions from specified cmdtable"""
8043 8046 overrides = [cmd for cmd in cmdtable if cmd in table]
8044 8047 if overrides:
8045 8048 ui.warn(
8046 8049 _(b"extension '%s' overrides commands: %s\n")
8047 8050 % (name, b" ".join(overrides))
8048 8051 )
8049 8052 table.update(cmdtable)
@@ -1,535 +1,563 b''
1 1 # registrar.py - utilities to register function for specific purpose
2 2 #
3 3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8
9 from typing import Any, List, Optional, Tuple
9 10 from . import (
10 11 configitems,
11 12 error,
12 13 pycompat,
13 14 )
14 15
15 16 # unlike the other registered items, config options are neither functions or
16 17 # classes. Registering the option is just small function call.
17 18 #
18 19 # We still add the official API to the registrar module for consistency with
19 20 # the other items extensions want might to register.
20 21 configitem = configitems.getitemregister
21 22
22 23
23 24 class _funcregistrarbase:
24 25 """Base of decorator to register a function for specific purpose
25 26
26 27 This decorator stores decorated functions into own dict 'table'.
27 28
28 29 The least derived class can be defined by overriding 'formatdoc',
29 30 for example::
30 31
31 32 class keyword(_funcregistrarbase):
32 33 _docformat = ":%s: %s"
33 34
34 35 This should be used as below:
35 36
36 37 keyword = registrar.keyword()
37 38
38 39 @keyword(b'bar')
39 40 def barfunc(*args, **kwargs):
40 41 '''Explanation of bar keyword ....
41 42 '''
42 43 pass
43 44
44 45 In this case:
45 46
46 47 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
47 48 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
48 49 """
49 50
50 51 def __init__(self, table=None):
51 52 if table is None:
52 53 self._table = {}
53 54 else:
54 55 self._table = table
55 56
56 57 def __call__(self, decl, *args, **kwargs):
57 58 return lambda func: self._doregister(func, decl, *args, **kwargs)
58 59
59 60 def _doregister(self, func, decl, *args, **kwargs):
60 61 name = self._getname(decl)
61 62
62 63 if name in self._table:
63 64 msg = b'duplicate registration for name: "%s"' % name
64 65 raise error.ProgrammingError(msg)
65 66
66 67 if func.__doc__ and not hasattr(func, '_origdoc'):
67 68 func._origdoc = func.__doc__.strip()
68 69 doc = pycompat.sysbytes(func._origdoc)
69 70 func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc))
70 71
71 72 self._table[name] = func
72 73 self._extrasetup(name, func, *args, **kwargs)
73 74
74 75 return func
75 76
76 77 def _merge(self, registrarbase):
77 78 """Merge the entries of the given registrar object into this one.
78 79
79 80 The other registrar object must not contain any entries already in the
80 81 current one, or a ProgrammmingError is raised. Additionally, the types
81 82 of the two registrars must match.
82 83 """
83 84 if not isinstance(registrarbase, type(self)):
84 85 msg = b"cannot merge different types of registrar"
85 86 raise error.ProgrammingError(msg)
86 87
87 88 dups = set(registrarbase._table).intersection(self._table)
88 89
89 90 if dups:
90 91 msg = b'duplicate registration for names: "%s"' % b'", "'.join(dups)
91 92 raise error.ProgrammingError(msg)
92 93
93 94 self._table.update(registrarbase._table)
94 95
95 96 def _parsefuncdecl(self, decl):
96 97 """Parse function declaration and return the name of function in it"""
97 98 i = decl.find(b'(')
98 99 if i >= 0:
99 100 return decl[:i]
100 101 else:
101 102 return decl
102 103
103 104 def _getname(self, decl):
104 105 """Return the name of the registered function from decl
105 106
106 107 Derived class should override this, if it allows more
107 108 descriptive 'decl' string than just a name.
108 109 """
109 110 return decl
110 111
111 112 _docformat = None
112 113
113 114 def _formatdoc(self, decl, doc):
114 115 """Return formatted document of the registered function for help
115 116
116 117 'doc' is '__doc__.strip()' of the registered function.
117 118 """
118 119 return self._docformat % (decl, doc)
119 120
120 121 def _extrasetup(self, name, func):
121 122 """Execute extra setup for registered function, if needed"""
122 123
123 124
124 125 class command(_funcregistrarbase):
125 126 """Decorator to register a command function to table
126 127
127 128 This class receives a command table as its argument. The table should
128 129 be a dict.
129 130
130 131 The created object can be used as a decorator for adding commands to
131 132 that command table. This accepts multiple arguments to define a command.
132 133
133 134 The first argument is the command name (as bytes).
134 135
135 136 The `options` keyword argument is an iterable of tuples defining command
136 137 arguments. See ``mercurial.fancyopts.fancyopts()`` for the format of each
137 138 tuple.
138 139
139 140 The `synopsis` argument defines a short, one line summary of how to use the
140 141 command. This shows up in the help output.
141 142
142 143 There are three arguments that control what repository (if any) is found
143 144 and passed to the decorated function: `norepo`, `optionalrepo`, and
144 145 `inferrepo`.
145 146
146 147 The `norepo` argument defines whether the command does not require a
147 148 local repository. Most commands operate against a repository, thus the
148 149 default is False. When True, no repository will be passed.
149 150
150 151 The `optionalrepo` argument defines whether the command optionally requires
151 152 a local repository. If no repository can be found, None will be passed
152 153 to the decorated function.
153 154
154 155 The `inferrepo` argument defines whether to try to find a repository from
155 156 the command line arguments. If True, arguments will be examined for
156 157 potential repository locations. See ``findrepo()``. If a repository is
157 158 found, it will be used and passed to the decorated function.
158 159
159 160 The `intents` argument defines a set of intended actions or capabilities
160 161 the command is taking. These intents can be used to affect the construction
161 162 of the repository object passed to the command. For example, commands
162 163 declaring that they are read-only could receive a repository that doesn't
163 164 have any methods allowing repository mutation. Other intents could be used
164 165 to prevent the command from running if the requested intent could not be
165 166 fulfilled.
166 167
167 168 If `helpcategory` is set (usually to one of the constants in the help
168 169 module), the command will be displayed under that category in the help's
169 170 list of commands.
170 171
171 172 The following intents are defined:
172 173
173 174 readonly
174 175 The command is read-only
175 176
176 177 The signature of the decorated function looks like this:
177 178 def cmd(ui[, repo] [, <args>] [, <options>])
178 179
179 180 `repo` is required if `norepo` is False.
180 181 `<args>` are positional args (or `*args`) arguments, of non-option
181 182 arguments from the command line.
182 183 `<options>` are keyword arguments (or `**options`) of option arguments
183 184 from the command line.
184 185
185 186 See the WritingExtensions and MercurialApi documentation for more exhaustive
186 187 descriptions and examples.
187 188 """
188 189
189 190 # Command categories for grouping them in help output.
190 191 # These can also be specified for aliases, like:
191 192 # [alias]
192 193 # myalias = something
193 194 # myalias:category = repo
194 195 CATEGORY_REPO_CREATION = b'repo'
195 196 CATEGORY_REMOTE_REPO_MANAGEMENT = b'remote'
196 197 CATEGORY_COMMITTING = b'commit'
197 198 CATEGORY_CHANGE_MANAGEMENT = b'management'
198 199 CATEGORY_CHANGE_ORGANIZATION = b'organization'
199 200 CATEGORY_FILE_CONTENTS = b'files'
200 201 CATEGORY_CHANGE_NAVIGATION = b'navigation'
201 202 CATEGORY_WORKING_DIRECTORY = b'wdir'
202 203 CATEGORY_IMPORT_EXPORT = b'import'
203 204 CATEGORY_MAINTENANCE = b'maintenance'
204 205 CATEGORY_HELP = b'help'
205 206 CATEGORY_MISC = b'misc'
206 207 CATEGORY_NONE = b'none'
207 208
208 209 def _doregister(
209 210 self,
210 211 func,
211 212 name,
212 213 options=(),
213 214 synopsis=None,
214 215 norepo=False,
215 216 optionalrepo=False,
216 217 inferrepo=False,
217 218 intents=None,
218 219 helpcategory=None,
219 220 helpbasic=False,
220 221 ):
221 222 func.norepo = norepo
222 223 func.optionalrepo = optionalrepo
223 224 func.inferrepo = inferrepo
224 225 func.intents = intents or set()
225 226 func.helpcategory = helpcategory
226 227 func.helpbasic = helpbasic
227 228 if synopsis:
228 229 self._table[name] = func, list(options), synopsis
229 230 else:
230 231 self._table[name] = func, list(options)
231 232 return func
232 233
233 234 def rename(self, old, new):
234 235 """rename a command. Used to add aliases, debugstrip ->
235 236 debugstrip|strip
236 237 """
237 238 self._table[new] = self._table.pop(old)
238 239
239 240
240 241 INTENT_READONLY = b'readonly'
241 242
242 243
243 244 class revsetpredicate(_funcregistrarbase):
244 245 """Decorator to register revset predicate
245 246
246 247 Usage::
247 248
248 249 revsetpredicate = registrar.revsetpredicate()
249 250
250 251 @revsetpredicate(b'mypredicate(arg1, arg2[, arg3])')
251 252 def mypredicatefunc(repo, subset, x):
252 253 '''Explanation of this revset predicate ....
253 254 '''
254 255 pass
255 256
256 257 The first string argument is used also in online help.
257 258
258 259 Optional argument 'safe' indicates whether a predicate is safe for
259 260 DoS attack (False by default).
260 261
261 262 Optional argument 'takeorder' indicates whether a predicate function
262 263 takes ordering policy as the last argument.
263 264
264 265 Optional argument 'weight' indicates the estimated run-time cost, useful
265 266 for static optimization, default is 1. Higher weight means more expensive.
266 267 Usually, revsets that are fast and return only one revision has a weight of
267 268 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
268 269 changelog have weight 10 (ex. author); revsets reading manifest deltas have
269 270 weight 30 (ex. adds); revset reading manifest contents have weight 100
270 271 (ex. contains). Note: those values are flexible. If the revset has a
271 272 same big-O time complexity as 'contains', but with a smaller constant, it
272 273 might have a weight of 90.
273 274
274 275 'revsetpredicate' instance in example above can be used to
275 276 decorate multiple functions.
276 277
277 278 Decorated functions are registered automatically at loading
278 279 extension, if an instance named as 'revsetpredicate' is used for
279 280 decorating in extension.
280 281
281 282 Otherwise, explicit 'revset.loadpredicate()' is needed.
282 283 """
283 284
284 285 _getname = _funcregistrarbase._parsefuncdecl
285 286 _docformat = b"``%s``\n %s"
286 287
287 288 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
288 289 func._safe = safe
289 290 func._takeorder = takeorder
290 291 func._weight = weight
291 292
292 293
293 294 class filesetpredicate(_funcregistrarbase):
294 295 """Decorator to register fileset predicate
295 296
296 297 Usage::
297 298
298 299 filesetpredicate = registrar.filesetpredicate()
299 300
300 301 @filesetpredicate(b'mypredicate()')
301 302 def mypredicatefunc(mctx, x):
302 303 '''Explanation of this fileset predicate ....
303 304 '''
304 305 pass
305 306
306 307 The first string argument is used also in online help.
307 308
308 309 Optional argument 'callstatus' indicates whether a predicate
309 310 implies 'matchctx.status()' at runtime or not (False, by
310 311 default).
311 312
312 313 Optional argument 'weight' indicates the estimated run-time cost, useful
313 314 for static optimization, default is 1. Higher weight means more expensive.
314 315 There are predefined weights in the 'filesetlang' module.
315 316
316 317 ====== =============================================================
317 318 Weight Description and examples
318 319 ====== =============================================================
319 320 0.5 basic match patterns (e.g. a symbol)
320 321 10 computing status (e.g. added()) or accessing a few files
321 322 30 reading file content for each (e.g. grep())
322 323 50 scanning working directory (ignored())
323 324 ====== =============================================================
324 325
325 326 'filesetpredicate' instance in example above can be used to
326 327 decorate multiple functions.
327 328
328 329 Decorated functions are registered automatically at loading
329 330 extension, if an instance named as 'filesetpredicate' is used for
330 331 decorating in extension.
331 332
332 333 Otherwise, explicit 'fileset.loadpredicate()' is needed.
333 334 """
334 335
335 336 _getname = _funcregistrarbase._parsefuncdecl
336 337 _docformat = b"``%s``\n %s"
337 338
338 339 def _extrasetup(self, name, func, callstatus=False, weight=1):
339 340 func._callstatus = callstatus
340 341 func._weight = weight
341 342
342 343
343 344 class _templateregistrarbase(_funcregistrarbase):
344 345 """Base of decorator to register functions as template specific one"""
345 346
346 347 _docformat = b":%s: %s"
347 348
348 349
349 350 class templatekeyword(_templateregistrarbase):
350 351 """Decorator to register template keyword
351 352
352 353 Usage::
353 354
354 355 templatekeyword = registrar.templatekeyword()
355 356
356 357 # new API (since Mercurial 4.6)
357 358 @templatekeyword(b'mykeyword', requires={b'repo', b'ctx'})
358 359 def mykeywordfunc(context, mapping):
359 360 '''Explanation of this template keyword ....
360 361 '''
361 362 pass
362 363
363 364 The first string argument is used also in online help.
364 365
365 366 Optional argument 'requires' should be a collection of resource names
366 367 which the template keyword depends on.
367 368
368 369 'templatekeyword' instance in example above can be used to
369 370 decorate multiple functions.
370 371
371 372 Decorated functions are registered automatically at loading
372 373 extension, if an instance named as 'templatekeyword' is used for
373 374 decorating in extension.
374 375
375 376 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
376 377 """
377 378
378 379 def _extrasetup(self, name, func, requires=()):
379 380 func._requires = requires
380 381
381 382
382 383 class templatefilter(_templateregistrarbase):
383 384 """Decorator to register template filer
384 385
385 386 Usage::
386 387
387 388 templatefilter = registrar.templatefilter()
388 389
389 390 @templatefilter(b'myfilter', intype=bytes)
390 391 def myfilterfunc(text):
391 392 '''Explanation of this template filter ....
392 393 '''
393 394 pass
394 395
395 396 The first string argument is used also in online help.
396 397
397 398 Optional argument 'intype' defines the type of the input argument,
398 399 which should be (bytes, int, templateutil.date, or None for any.)
399 400
400 401 'templatefilter' instance in example above can be used to
401 402 decorate multiple functions.
402 403
403 404 Decorated functions are registered automatically at loading
404 405 extension, if an instance named as 'templatefilter' is used for
405 406 decorating in extension.
406 407
407 408 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
408 409 """
409 410
410 411 def _extrasetup(self, name, func, intype=None):
411 412 func._intype = intype
412 413
413 414
414 415 class templatefunc(_templateregistrarbase):
415 416 """Decorator to register template function
416 417
417 418 Usage::
418 419
419 420 templatefunc = registrar.templatefunc()
420 421
421 422 @templatefunc(b'myfunc(arg1, arg2[, arg3])', argspec=b'arg1 arg2 arg3',
422 423 requires={b'ctx'})
423 424 def myfuncfunc(context, mapping, args):
424 425 '''Explanation of this template function ....
425 426 '''
426 427 pass
427 428
428 429 The first string argument is used also in online help.
429 430
430 431 If optional 'argspec' is defined, the function will receive 'args' as
431 432 a dict of named arguments. Otherwise 'args' is a list of positional
432 433 arguments.
433 434
434 435 Optional argument 'requires' should be a collection of resource names
435 436 which the template function depends on.
436 437
437 438 'templatefunc' instance in example above can be used to
438 439 decorate multiple functions.
439 440
440 441 Decorated functions are registered automatically at loading
441 442 extension, if an instance named as 'templatefunc' is used for
442 443 decorating in extension.
443 444
444 445 Otherwise, explicit 'templatefuncs.loadfunction()' is needed.
445 446 """
446 447
447 448 _getname = _funcregistrarbase._parsefuncdecl
448 449
449 450 def _extrasetup(self, name, func, argspec=None, requires=()):
450 451 func._argspec = argspec
451 452 func._requires = requires
452 453
453 454
454 455 class internalmerge(_funcregistrarbase):
455 456 """Decorator to register in-process merge tool
456 457
457 458 Usage::
458 459
459 460 internalmerge = registrar.internalmerge()
460 461
461 462 @internalmerge(b'mymerge', internalmerge.mergeonly,
462 463 onfailure=None, precheck=None,
463 464 binary=False, symlink=False):
464 465 def mymergefunc(repo, mynode, orig, fcd, fco, fca,
465 466 toolconf, files, labels=None):
466 467 '''Explanation of this internal merge tool ....
467 468 '''
468 469 return 1, False # means "conflicted", "no deletion needed"
469 470
470 471 The first string argument is used to compose actual merge tool name,
471 472 ":name" and "internal:name" (the latter is historical one).
472 473
473 474 The second argument is one of merge types below:
474 475
475 476 ========== ======== ======== =========
476 477 merge type precheck premerge fullmerge
477 478 ========== ======== ======== =========
478 479 nomerge x x x
479 480 mergeonly o x o
480 481 fullmerge o o o
481 482 ========== ======== ======== =========
482 483
483 484 Optional argument 'onfailure' is the format of warning message
484 485 to be used at failure of merging (target filename is specified
485 486 at formatting). Or, None or so, if warning message should be
486 487 suppressed.
487 488
488 489 Optional argument 'precheck' is the function to be used
489 490 before actual invocation of internal merge tool itself.
490 491 It takes as same arguments as internal merge tool does, other than
491 492 'files' and 'labels'. If it returns false value, merging is aborted
492 493 immediately (and file is marked as "unresolved").
493 494
494 495 Optional argument 'binary' is a binary files capability of internal
495 496 merge tool. 'nomerge' merge type implies binary=True.
496 497
497 498 Optional argument 'symlink' is a symlinks capability of inetrnal
498 499 merge function. 'nomerge' merge type implies symlink=True.
499 500
500 501 'internalmerge' instance in example above can be used to
501 502 decorate multiple functions.
502 503
503 504 Decorated functions are registered automatically at loading
504 505 extension, if an instance named as 'internalmerge' is used for
505 506 decorating in extension.
506 507
507 508 Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
508 509 """
509 510
510 511 _docformat = b"``:%s``\n %s"
511 512
512 513 # merge type definitions:
513 514 nomerge = None
514 515 mergeonly = b'mergeonly' # just the full merge, no premerge
515 516 fullmerge = b'fullmerge' # both premerge and merge
516 517
517 518 def _extrasetup(
518 519 self,
519 520 name,
520 521 func,
521 522 mergetype,
522 523 onfailure=None,
523 524 precheck=None,
524 525 binary=False,
525 526 symlink=False,
526 527 ):
527 528 func.mergetype = mergetype
528 529 func.onfailure = onfailure
529 530 func.precheck = precheck
530 531
531 532 binarycap = binary or mergetype == self.nomerge
532 533 symlinkcap = symlink or mergetype == self.nomerge
533 534
534 535 # actual capabilities, which this internal merge tool has
535 536 func.capabilities = {b"binary": binarycap, b"symlink": symlinkcap}
537
538
539 class verify_check(_funcregistrarbase):
540 """Decorator to register a check for admin::verify
541
542 options is a list of (name, default value, help) to be passed to the check
543 """
544
545 def __init__(self, table=None, alias_table=None):
546 super().__init__(table)
547 if alias_table is None:
548 self._alias_table = {}
549 else:
550 self._alias_table = alias_table
551
552 def _extrasetup(
553 self,
554 name,
555 func,
556 alias: Optional[bytes] = None,
557 options: Optional[List[Tuple[bytes, Any, bytes]]] = None,
558 ):
559 func.alias = alias
560 func.options = options
561
562 if alias:
563 self._alias_table[alias] = name
@@ -1,455 +1,458 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 abort
4 4 add
5 5 addremove
6 admin::verify
6 7 annotate
7 8 archive
8 9 backout
9 10 bisect
10 11 bookmarks
11 12 branch
12 13 branches
13 14 bundle
14 15 cat
15 16 clone
16 17 commit
17 18 config
18 19 continue
19 20 copy
20 21 diff
21 22 export
22 23 files
23 24 forget
24 25 graft
25 26 grep
26 27 heads
27 28 help
28 29 identify
29 30 import
30 31 incoming
31 32 init
32 33 locate
33 34 log
34 35 manifest
35 36 merge
36 37 outgoing
37 38 parents
38 39 paths
39 40 phase
40 41 pull
41 42 purge
42 43 push
43 44 recover
44 45 remove
45 46 rename
46 47 resolve
47 48 revert
48 49 rollback
49 50 root
50 51 serve
51 52 shelve
52 53 status
53 54 summary
54 55 tag
55 56 tags
56 57 tip
57 58 unbundle
58 59 unshelve
59 60 update
60 61 verify
61 62 version
62 63
63 64 Show all commands that start with "a"
64 65 $ hg debugcomplete a
65 66 abort
66 67 add
67 68 addremove
69 admin::verify
68 70 annotate
69 71 archive
70 72
71 73 Do not show debug commands if there are other candidates
72 74 $ hg debugcomplete d
73 75 diff
74 76
75 77 Show debug commands if there are no other candidates
76 78 $ hg debugcomplete debug
77 79 debug-delta-find
78 80 debug-repair-issue6528
79 81 debug-revlog-index
80 82 debug-revlog-stats
81 83 debug::stable-tail-sort
82 84 debug::stable-tail-sort-leaps
83 85 debugancestor
84 86 debugantivirusrunning
85 87 debugapplystreamclonebundle
86 88 debugbackupbundle
87 89 debugbuilddag
88 90 debugbundle
89 91 debugcapabilities
90 92 debugchangedfiles
91 93 debugcheckstate
92 94 debugcolor
93 95 debugcommands
94 96 debugcomplete
95 97 debugconfig
96 98 debugcreatestreamclonebundle
97 99 debugdag
98 100 debugdata
99 101 debugdate
100 102 debugdeltachain
101 103 debugdirstate
102 104 debugdirstateignorepatternshash
103 105 debugdiscovery
104 106 debugdownload
105 107 debugextensions
106 108 debugfileset
107 109 debugformat
108 110 debugfsinfo
109 111 debuggetbundle
110 112 debugignore
111 113 debugindexdot
112 114 debugindexstats
113 115 debuginstall
114 116 debugknown
115 117 debuglabelcomplete
116 118 debuglocks
117 119 debugmanifestfulltextcache
118 120 debugmergestate
119 121 debugnamecomplete
120 122 debugnodemap
121 123 debugobsolete
122 124 debugp1copies
123 125 debugp2copies
124 126 debugpathcomplete
125 127 debugpathcopies
126 128 debugpeer
127 129 debugpickmergetool
128 130 debugpushkey
129 131 debugpvec
130 132 debugrebuilddirstate
131 133 debugrebuildfncache
132 134 debugrename
133 135 debugrequires
134 136 debugrevlog
135 137 debugrevlogindex
136 138 debugrevspec
137 139 debugserve
138 140 debugsetparents
139 141 debugshell
140 142 debugsidedata
141 143 debugssl
142 144 debugstrip
143 145 debugsub
144 146 debugsuccessorssets
145 147 debugtagscache
146 148 debugtemplate
147 149 debuguigetpass
148 150 debuguiprompt
149 151 debugupdatecaches
150 152 debugupgraderepo
151 153 debugwalk
152 154 debugwhyunstable
153 155 debugwireargs
154 156 debugwireproto
155 157
156 158 Do not show the alias of a debug command if there are other candidates
157 159 (this should hide rawcommit)
158 160 $ hg debugcomplete r
159 161 recover
160 162 remove
161 163 rename
162 164 resolve
163 165 revert
164 166 rollback
165 167 root
166 168 Show the alias of a debug command if there are no other candidates
167 169 $ hg debugcomplete rawc
168 170
169 171
170 172 Show the global options
171 173 $ hg debugcomplete --options | sort
172 174 --color
173 175 --config
174 176 --cwd
175 177 --debug
176 178 --debugger
177 179 --encoding
178 180 --encodingmode
179 181 --help
180 182 --hidden
181 183 --noninteractive
182 184 --pager
183 185 --profile
184 186 --quiet
185 187 --repository
186 188 --time
187 189 --traceback
188 190 --verbose
189 191 --version
190 192 -R
191 193 -h
192 194 -q
193 195 -v
194 196 -y
195 197
196 198 Show the options for the "serve" command
197 199 $ hg debugcomplete --options serve | sort
198 200 --accesslog
199 201 --address
200 202 --certificate
201 203 --cmdserver
202 204 --color
203 205 --config
204 206 --cwd
205 207 --daemon
206 208 --daemon-postexec
207 209 --debug
208 210 --debugger
209 211 --encoding
210 212 --encodingmode
211 213 --errorlog
212 214 --help
213 215 --hidden
214 216 --ipv6
215 217 --name
216 218 --noninteractive
217 219 --pager
218 220 --pid-file
219 221 --port
220 222 --prefix
221 223 --print-url
222 224 --profile
223 225 --quiet
224 226 --repository
225 227 --stdio
226 228 --style
227 229 --subrepos
228 230 --templates
229 231 --time
230 232 --traceback
231 233 --verbose
232 234 --version
233 235 --web-conf
234 236 -6
235 237 -A
236 238 -E
237 239 -R
238 240 -S
239 241 -a
240 242 -d
241 243 -h
242 244 -n
243 245 -p
244 246 -q
245 247 -t
246 248 -v
247 249 -y
248 250
249 251 Show an error if we use --options with an ambiguous abbreviation
250 252 $ hg debugcomplete --options s
251 253 hg: command 's' is ambiguous:
252 254 serve shelve showconfig status summary
253 255 [10]
254 256
255 257 Show all commands + options
256 258 $ hg debugcommands
257 259 abort: dry-run
258 260 add: include, exclude, subrepos, dry-run
259 261 addremove: similarity, subrepos, include, exclude, dry-run
262 admin::verify: check, option
260 263 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
261 264 archive: no-decode, prefix, rev, type, subrepos, include, exclude
262 265 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
263 266 bisect: reset, good, bad, skip, extend, command, noupdate
264 267 bookmarks: force, rev, delete, rename, inactive, list, template
265 268 branch: force, clean, rev
266 269 branches: active, closed, rev, template
267 270 bundle: exact, force, rev, branch, base, all, type, ssh, remotecmd, insecure
268 271 cat: output, rev, decode, include, exclude, template
269 272 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
270 273 commit: addremove, close-branch, amend, secret, draft, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
271 274 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
272 275 continue: dry-run
273 276 copy: forget, after, at-rev, force, include, exclude, dry-run
274 277 debug-delta-find: changelog, manifest, dir, template, source
275 278 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
276 279 debug-revlog-index: changelog, manifest, dir, template
277 280 debug-revlog-stats: changelog, manifest, filelogs, template
278 281 debug::stable-tail-sort: template
279 282 debug::stable-tail-sort-leaps: template, specific
280 283 debugancestor:
281 284 debugantivirusrunning:
282 285 debugapplystreamclonebundle:
283 286 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
284 287 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
285 288 debugbundle: all, part-type, spec
286 289 debugcapabilities:
287 290 debugchangedfiles: compute
288 291 debugcheckstate:
289 292 debugcolor: style
290 293 debugcommands:
291 294 debugcomplete: options
292 295 debugcreatestreamclonebundle:
293 296 debugdag: tags, branches, dots, spaces
294 297 debugdata: changelog, manifest, dir
295 298 debugdate: extended
296 299 debugdeltachain: changelog, manifest, dir, template
297 300 debugdirstateignorepatternshash:
298 301 debugdirstate: nodates, dates, datesort, docket, all
299 302 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
300 303 debugdownload: output
301 304 debugextensions: template
302 305 debugfileset: rev, all-files, show-matcher, show-stage
303 306 debugformat: template
304 307 debugfsinfo:
305 308 debuggetbundle: head, common, type
306 309 debugignore:
307 310 debugindexdot: changelog, manifest, dir
308 311 debugindexstats:
309 312 debuginstall: template
310 313 debugknown:
311 314 debuglabelcomplete:
312 315 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
313 316 debugmanifestfulltextcache: clear, add
314 317 debugmergestate: style, template
315 318 debugnamecomplete:
316 319 debugnodemap: changelog, manifest, dir, dump-new, dump-disk, check, metadata
317 320 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
318 321 debugp1copies: rev
319 322 debugp2copies: rev
320 323 debugpathcomplete: full, normal, added, removed
321 324 debugpathcopies: include, exclude
322 325 debugpeer:
323 326 debugpickmergetool: rev, changedelete, include, exclude, tool
324 327 debugpushkey:
325 328 debugpvec:
326 329 debugrebuilddirstate: rev, minimal
327 330 debugrebuildfncache: only-data
328 331 debugrename: rev
329 332 debugrequires:
330 333 debugrevlog: changelog, manifest, dir, dump
331 334 debugrevlogindex: changelog, manifest, dir, format
332 335 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
333 336 debugserve: sshstdio, logiofd, logiofile
334 337 debugsetparents:
335 338 debugshell: command
336 339 debugsidedata: changelog, manifest, dir
337 340 debugssl:
338 341 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
339 342 debugsub: rev
340 343 debugsuccessorssets: closest
341 344 debugtagscache:
342 345 debugtemplate: rev, define
343 346 debuguigetpass: prompt
344 347 debuguiprompt: prompt
345 348 debugupdatecaches:
346 349 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
347 350 debugwalk: include, exclude
348 351 debugwhyunstable:
349 352 debugwireargs: three, four, five, ssh, remotecmd, insecure
350 353 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
351 354 diff: rev, from, to, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
352 355 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
353 356 files: rev, print0, include, exclude, template, subrepos
354 357 forget: interactive, include, exclude, dry-run
355 358 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
356 359 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
357 360 heads: rev, topo, active, closed, style, template
358 361 help: extension, command, keyword, system
359 362 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
360 363 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
361 364 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
362 365 init: ssh, remotecmd, insecure
363 366 locate: rev, print0, fullpath, include, exclude
364 367 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
365 368 manifest: rev, all, template
366 369 merge: force, rev, preview, abort, tool
367 370 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
368 371 parents: rev, style, template
369 372 paths: template
370 373 phase: public, draft, secret, force, rev
371 374 pull: update, force, confirm, rev, bookmark, branch, remote-hidden, ssh, remotecmd, insecure
372 375 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
373 376 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
374 377 recover: verify
375 378 remove: after, force, subrepos, include, exclude, dry-run
376 379 rename: forget, after, at-rev, force, include, exclude, dry-run
377 380 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
378 381 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
379 382 rollback: dry-run, force
380 383 root: template
381 384 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
382 385 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
383 386 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
384 387 summary: remote
385 388 tag: force, local, rev, remove, edit, message, date, user
386 389 tags: template
387 390 tip: patch, git, style, template
388 391 unbundle: update
389 392 unshelve: abort, continue, interactive, keep, name, tool, date
390 393 update: clean, check, merge, date, rev, tool
391 394 verify: full
392 395 version: template
393 396
394 397 $ hg init a
395 398 $ cd a
396 399 $ echo fee > fee
397 400 $ hg ci -q -Amfee
398 401 $ hg tag fee
399 402 $ mkdir fie
400 403 $ echo dead > fie/dead
401 404 $ echo live > fie/live
402 405 $ hg bookmark fo
403 406 $ hg branch -q fie
404 407 $ hg ci -q -Amfie
405 408 $ echo fo > fo
406 409 $ hg branch -qf default
407 410 $ hg ci -q -Amfo
408 411 $ echo Fum > Fum
409 412 $ hg ci -q -AmFum
410 413 $ hg bookmark Fum
411 414
412 415 Test debugpathcomplete
413 416
414 417 $ hg debugpathcomplete f
415 418 fee
416 419 fie
417 420 fo
418 421 $ hg debugpathcomplete -f f
419 422 fee
420 423 fie/dead
421 424 fie/live
422 425 fo
423 426
424 427 $ hg rm Fum
425 428 $ hg debugpathcomplete -r F
426 429 Fum
427 430
428 431 Test debugnamecomplete
429 432
430 433 $ hg debugnamecomplete
431 434 Fum
432 435 default
433 436 fee
434 437 fie
435 438 fo
436 439 tip
437 440 $ hg debugnamecomplete f
438 441 fee
439 442 fie
440 443 fo
441 444
442 445 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
443 446 used for completions in some shells.
444 447
445 448 $ hg debuglabelcomplete
446 449 Fum
447 450 default
448 451 fee
449 452 fie
450 453 fo
451 454 tip
452 455 $ hg debuglabelcomplete f
453 456 fee
454 457 fie
455 458 fo
@@ -1,573 +1,577 b''
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo a > a
4 4 $ hg ci -A -d'1 0' -m a
5 5 adding a
6 6
7 7 $ cd ..
8 8
9 9 $ hg init b
10 10 $ cd b
11 11 $ echo b > b
12 12 $ hg ci -A -d'1 0' -m b
13 13 adding b
14 14
15 15 $ cd ..
16 16
17 17 $ hg clone a c
18 18 updating to branch default
19 19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 20 $ cd c
21 21 $ cat >> .hg/hgrc <<EOF
22 22 > [paths]
23 23 > relative = ../a
24 24 > EOF
25 25 $ hg pull -f ../b
26 26 pulling from ../b
27 27 searching for changes
28 28 warning: repository is unrelated
29 29 requesting all changes
30 30 adding changesets
31 31 adding manifests
32 32 adding file changes
33 33 added 1 changesets with 1 changes to 1 files (+1 heads)
34 34 new changesets b6c483daf290
35 35 (run 'hg heads' to see heads, 'hg merge' to merge)
36 36 $ hg merge
37 37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 38 (branch merge, don't forget to commit)
39 39
40 40 $ cd ..
41 41
42 42 Testing -R/--repository:
43 43
44 44 $ hg -R a tip
45 45 changeset: 0:8580ff50825a
46 46 tag: tip
47 47 user: test
48 48 date: Thu Jan 01 00:00:01 1970 +0000
49 49 summary: a
50 50
51 51 $ hg --repository b tip
52 52 changeset: 0:b6c483daf290
53 53 tag: tip
54 54 user: test
55 55 date: Thu Jan 01 00:00:01 1970 +0000
56 56 summary: b
57 57
58 58
59 59 -R with a URL:
60 60
61 61 $ hg -R file:a identify
62 62 8580ff50825a tip
63 63 $ hg -R file://localhost/`pwd`/a/ identify
64 64 8580ff50825a tip
65 65
66 66 -R with path aliases:
67 67
68 68 $ cd c
69 69 $ hg -R default identify
70 70 8580ff50825a tip
71 71 $ hg -R relative identify
72 72 8580ff50825a tip
73 73 $ echo '[paths]' >> $HGRCPATH
74 74 $ echo 'relativetohome = a' >> $HGRCPATH
75 75 $ hg path | grep relativetohome
76 76 relativetohome = $TESTTMP/a
77 77 $ HOME=`pwd`/../ hg path | grep relativetohome
78 78 relativetohome = $TESTTMP/a
79 79 $ HOME=`pwd`/../ hg -R relativetohome identify
80 80 8580ff50825a tip
81 81 $ cd ..
82 82
83 83 #if no-outer-repo
84 84
85 85 Implicit -R:
86 86
87 87 $ hg ann a/a
88 88 0: a
89 89 $ hg ann a/a a/a
90 90 0: a
91 91 $ hg ann a/a b/b
92 92 abort: no repository found in '$TESTTMP' (.hg not found)
93 93 [10]
94 94 $ hg -R b ann a/a
95 95 abort: a/a not under root '$TESTTMP/b'
96 96 (consider using '--cwd b')
97 97 [255]
98 98 $ hg log
99 99 abort: no repository found in '$TESTTMP' (.hg not found)
100 100 [10]
101 101
102 102 #endif
103 103
104 104 Abbreviation of long option:
105 105
106 106 $ hg --repo c tip
107 107 changeset: 1:b6c483daf290
108 108 tag: tip
109 109 parent: -1:000000000000
110 110 user: test
111 111 date: Thu Jan 01 00:00:01 1970 +0000
112 112 summary: b
113 113
114 114
115 115 earlygetopt with duplicate options (36d23de02da1):
116 116
117 117 $ hg --cwd a --cwd b --cwd c tip
118 118 changeset: 1:b6c483daf290
119 119 tag: tip
120 120 parent: -1:000000000000
121 121 user: test
122 122 date: Thu Jan 01 00:00:01 1970 +0000
123 123 summary: b
124 124
125 125 $ hg --repo c --repository b -R a tip
126 126 changeset: 0:8580ff50825a
127 127 tag: tip
128 128 user: test
129 129 date: Thu Jan 01 00:00:01 1970 +0000
130 130 summary: a
131 131
132 132
133 133 earlygetopt short option without following space:
134 134
135 135 $ hg -q -Rb tip
136 136 0:b6c483daf290
137 137
138 138 earlygetopt with illegal abbreviations:
139 139
140 140 $ hg --confi "foo.bar=baz"
141 141 abort: option --config may not be abbreviated
142 142 [10]
143 143 $ hg --cw a tip
144 144 abort: option --cwd may not be abbreviated
145 145 [10]
146 146 $ hg --rep a tip
147 147 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo
148 148 [10]
149 149 $ hg --repositor a tip
150 150 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo
151 151 [10]
152 152 $ hg -qR a tip
153 153 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo
154 154 [10]
155 155 $ hg -qRa tip
156 156 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo
157 157 [10]
158 158
159 159 Testing --cwd:
160 160
161 161 $ hg --cwd a parents
162 162 changeset: 0:8580ff50825a
163 163 tag: tip
164 164 user: test
165 165 date: Thu Jan 01 00:00:01 1970 +0000
166 166 summary: a
167 167
168 168
169 169 Testing -y/--noninteractive - just be sure it is parsed:
170 170
171 171 $ hg --cwd a tip -q --noninteractive
172 172 0:8580ff50825a
173 173 $ hg --cwd a tip -q -y
174 174 0:8580ff50825a
175 175
176 176 Testing -q/--quiet:
177 177
178 178 $ hg -R a -q tip
179 179 0:8580ff50825a
180 180 $ hg -R b -q tip
181 181 0:b6c483daf290
182 182 $ hg -R c --quiet parents
183 183 0:8580ff50825a
184 184 1:b6c483daf290
185 185
186 186 Testing -v/--verbose:
187 187
188 188 $ hg --cwd c head -v
189 189 changeset: 1:b6c483daf290
190 190 tag: tip
191 191 parent: -1:000000000000
192 192 user: test
193 193 date: Thu Jan 01 00:00:01 1970 +0000
194 194 files: b
195 195 description:
196 196 b
197 197
198 198
199 199 changeset: 0:8580ff50825a
200 200 user: test
201 201 date: Thu Jan 01 00:00:01 1970 +0000
202 202 files: a
203 203 description:
204 204 a
205 205
206 206
207 207 $ hg --cwd b tip --verbose
208 208 changeset: 0:b6c483daf290
209 209 tag: tip
210 210 user: test
211 211 date: Thu Jan 01 00:00:01 1970 +0000
212 212 files: b
213 213 description:
214 214 b
215 215
216 216
217 217
218 218 Testing --config:
219 219
220 220 $ hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
221 221 quuxfoo
222 222 TODO: add rhg support for detailed exit codes
223 223 $ hg --cwd c --config '' tip -q
224 224 abort: malformed --config option: '' (use --config section.name=value)
225 225 [10]
226 226 $ hg --cwd c --config a.b tip -q
227 227 abort: malformed --config option: 'a.b' (use --config section.name=value)
228 228 [10]
229 229 $ hg --cwd c --config a tip -q
230 230 abort: malformed --config option: 'a' (use --config section.name=value)
231 231 [10]
232 232 $ hg --cwd c --config a.= tip -q
233 233 abort: malformed --config option: 'a.=' (use --config section.name=value)
234 234 [10]
235 235 $ hg --cwd c --config .b= tip -q
236 236 abort: malformed --config option: '.b=' (use --config section.name=value)
237 237 [10]
238 238
239 239 Testing --debug:
240 240
241 241 $ hg --cwd c log --debug
242 242 changeset: 1:b6c483daf2907ce5825c0bb50f5716226281cc1a
243 243 tag: tip
244 244 phase: public
245 245 parent: -1:0000000000000000000000000000000000000000
246 246 parent: -1:0000000000000000000000000000000000000000
247 247 manifest: 1:23226e7a252cacdc2d99e4fbdc3653441056de49
248 248 user: test
249 249 date: Thu Jan 01 00:00:01 1970 +0000
250 250 files+: b
251 251 extra: branch=default
252 252 description:
253 253 b
254 254
255 255
256 256 changeset: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
257 257 phase: public
258 258 parent: -1:0000000000000000000000000000000000000000
259 259 parent: -1:0000000000000000000000000000000000000000
260 260 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
261 261 user: test
262 262 date: Thu Jan 01 00:00:01 1970 +0000
263 263 files+: a
264 264 extra: branch=default
265 265 description:
266 266 a
267 267
268 268
269 269
270 270 Testing --traceback:
271 271
272 272 #if no-chg no-rhg
273 273 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
274 274 Traceback (most recent call last):
275 275 Traceback (most recent call last):
276 276 #else
277 277 Traceback for '--config' errors not supported with chg.
278 278 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
279 279 [1]
280 280 #endif
281 281
282 282 Testing --time:
283 283
284 284 $ hg --cwd a --time id
285 285 8580ff50825a tip
286 286 time: real * (glob)
287 287
288 288 Testing --version:
289 289
290 290 $ hg --version -q
291 291 Mercurial Distributed SCM * (glob)
292 292
293 293 hide outer repo
294 294 $ hg init
295 295
296 296 Testing -h/--help:
297 297
298 298 #if no-extraextensions
299 299
300 300 $ hg -h
301 301 Mercurial Distributed SCM
302 302
303 303 list of commands:
304 304
305 305 Repository creation:
306 306
307 307 clone make a copy of an existing repository
308 308 init create a new repository in the given directory
309 309
310 310 Remote repository management:
311 311
312 312 incoming show new changesets found in source
313 313 outgoing show changesets not found in the destination
314 314 paths show aliases for remote repositories
315 315 pull pull changes from the specified source
316 316 push push changes to the specified destination
317 317 serve start stand-alone webserver
318 318
319 319 Change creation:
320 320
321 321 commit commit the specified files or all outstanding changes
322 322
323 323 Change manipulation:
324 324
325 325 backout reverse effect of earlier changeset
326 326 graft copy changes from other branches onto the current branch
327 327 merge merge another revision into working directory
328 328
329 329 Change organization:
330 330
331 331 bookmarks create a new bookmark or list existing bookmarks
332 332 branch set or show the current branch name
333 333 branches list repository named branches
334 334 phase set or show the current phase name
335 335 tag add one or more tags for the current or given revision
336 336 tags list repository tags
337 337
338 338 File content management:
339 339
340 340 annotate show changeset information by line for each file
341 341 cat output the current or given revision of files
342 342 copy mark files as copied for the next commit
343 343 diff diff repository (or selected files)
344 344 grep search for a pattern in specified files
345 345
346 346 Change navigation:
347 347
348 348 bisect subdivision search of changesets
349 349 heads show branch heads
350 350 identify identify the working directory or specified revision
351 351 log show revision history of entire repository or files
352 352
353 353 Working directory management:
354 354
355 355 add add the specified files on the next commit
356 356 addremove add all new files, delete all missing files
357 357 files list tracked files
358 358 forget forget the specified files on the next commit
359 359 purge removes files not tracked by Mercurial
360 360 remove remove the specified files on the next commit
361 361 rename rename files; equivalent of copy + remove
362 362 resolve redo merges or set/view the merge status of files
363 363 revert restore files to their checkout state
364 364 root print the root (top) of the current working directory
365 365 shelve save and set aside changes from the working directory
366 366 status show changed files in the working directory
367 367 summary summarize working directory state
368 368 unshelve restore a shelved change to the working directory
369 369 update update working directory (or switch revisions)
370 370
371 371 Change import/export:
372 372
373 373 archive create an unversioned archive of a repository revision
374 374 bundle create a bundle file
375 375 export dump the header and diffs for one or more changesets
376 376 import import an ordered set of patches
377 377 unbundle apply one or more bundle files
378 378
379 379 Repository maintenance:
380 380
381 admin::verify
382 verify the integrity of the repository
381 383 manifest output the current or given revision of the project manifest
382 384 recover roll back an interrupted transaction
383 385 verify verify the integrity of the repository
384 386
385 387 Help:
386 388
387 389 config show combined config settings from all hgrc files
388 390 help show help for a given topic or a help overview
389 391 version output version and copyright information
390 392
391 393 additional help topics:
392 394
393 395 Mercurial identifiers:
394 396
395 397 filesets Specifying File Sets
396 398 hgignore Syntax for Mercurial Ignore Files
397 399 patterns File Name Patterns
398 400 revisions Specifying Revisions
399 401 urls URL Paths
400 402
401 403 Mercurial output:
402 404
403 405 color Colorizing Outputs
404 406 dates Date Formats
405 407 diffs Diff Formats
406 408 templating Template Usage
407 409
408 410 Mercurial configuration:
409 411
410 412 config Configuration Files
411 413 environment Environment Variables
412 414 extensions Using Additional Features
413 415 flags Command-line flags
414 416 hgweb Configuring hgweb
415 417 merge-tools Merge Tools
416 418 pager Pager Support
417 419 rust Rust in Mercurial
418 420
419 421 Concepts:
420 422
421 423 bundlespec Bundle File Formats
422 424 evolution Safely rewriting history (EXPERIMENTAL)
423 425 glossary Glossary
424 426 phases Working with Phases
425 427 subrepos Subrepositories
426 428
427 429 Miscellaneous:
428 430
429 431 deprecated Deprecated Features
430 432 internals Technical implementation topics
431 433 scripting Using Mercurial from scripts and automation
432 434
433 435 (use 'hg help -v' to show built-in aliases and global options)
434 436
435 437 $ hg --help
436 438 Mercurial Distributed SCM
437 439
438 440 list of commands:
439 441
440 442 Repository creation:
441 443
442 444 clone make a copy of an existing repository
443 445 init create a new repository in the given directory
444 446
445 447 Remote repository management:
446 448
447 449 incoming show new changesets found in source
448 450 outgoing show changesets not found in the destination
449 451 paths show aliases for remote repositories
450 452 pull pull changes from the specified source
451 453 push push changes to the specified destination
452 454 serve start stand-alone webserver
453 455
454 456 Change creation:
455 457
456 458 commit commit the specified files or all outstanding changes
457 459
458 460 Change manipulation:
459 461
460 462 backout reverse effect of earlier changeset
461 463 graft copy changes from other branches onto the current branch
462 464 merge merge another revision into working directory
463 465
464 466 Change organization:
465 467
466 468 bookmarks create a new bookmark or list existing bookmarks
467 469 branch set or show the current branch name
468 470 branches list repository named branches
469 471 phase set or show the current phase name
470 472 tag add one or more tags for the current or given revision
471 473 tags list repository tags
472 474
473 475 File content management:
474 476
475 477 annotate show changeset information by line for each file
476 478 cat output the current or given revision of files
477 479 copy mark files as copied for the next commit
478 480 diff diff repository (or selected files)
479 481 grep search for a pattern in specified files
480 482
481 483 Change navigation:
482 484
483 485 bisect subdivision search of changesets
484 486 heads show branch heads
485 487 identify identify the working directory or specified revision
486 488 log show revision history of entire repository or files
487 489
488 490 Working directory management:
489 491
490 492 add add the specified files on the next commit
491 493 addremove add all new files, delete all missing files
492 494 files list tracked files
493 495 forget forget the specified files on the next commit
494 496 purge removes files not tracked by Mercurial
495 497 remove remove the specified files on the next commit
496 498 rename rename files; equivalent of copy + remove
497 499 resolve redo merges or set/view the merge status of files
498 500 revert restore files to their checkout state
499 501 root print the root (top) of the current working directory
500 502 shelve save and set aside changes from the working directory
501 503 status show changed files in the working directory
502 504 summary summarize working directory state
503 505 unshelve restore a shelved change to the working directory
504 506 update update working directory (or switch revisions)
505 507
506 508 Change import/export:
507 509
508 510 archive create an unversioned archive of a repository revision
509 511 bundle create a bundle file
510 512 export dump the header and diffs for one or more changesets
511 513 import import an ordered set of patches
512 514 unbundle apply one or more bundle files
513 515
514 516 Repository maintenance:
515 517
518 admin::verify
519 verify the integrity of the repository
516 520 manifest output the current or given revision of the project manifest
517 521 recover roll back an interrupted transaction
518 522 verify verify the integrity of the repository
519 523
520 524 Help:
521 525
522 526 config show combined config settings from all hgrc files
523 527 help show help for a given topic or a help overview
524 528 version output version and copyright information
525 529
526 530 additional help topics:
527 531
528 532 Mercurial identifiers:
529 533
530 534 filesets Specifying File Sets
531 535 hgignore Syntax for Mercurial Ignore Files
532 536 patterns File Name Patterns
533 537 revisions Specifying Revisions
534 538 urls URL Paths
535 539
536 540 Mercurial output:
537 541
538 542 color Colorizing Outputs
539 543 dates Date Formats
540 544 diffs Diff Formats
541 545 templating Template Usage
542 546
543 547 Mercurial configuration:
544 548
545 549 config Configuration Files
546 550 environment Environment Variables
547 551 extensions Using Additional Features
548 552 flags Command-line flags
549 553 hgweb Configuring hgweb
550 554 merge-tools Merge Tools
551 555 pager Pager Support
552 556 rust Rust in Mercurial
553 557
554 558 Concepts:
555 559
556 560 bundlespec Bundle File Formats
557 561 evolution Safely rewriting history (EXPERIMENTAL)
558 562 glossary Glossary
559 563 phases Working with Phases
560 564 subrepos Subrepositories
561 565
562 566 Miscellaneous:
563 567
564 568 deprecated Deprecated Features
565 569 internals Technical implementation topics
566 570 scripting Using Mercurial from scripts and automation
567 571
568 572 (use 'hg help -v' to show built-in aliases and global options)
569 573
570 574 #endif
571 575
572 576 Not tested: --debugger
573 577
@@ -1,265 +1,269 b''
1 1 Test hiding some commands (which also happens to hide an entire category).
2 2
3 3 $ hg --config help.hidden-command.clone=true \
4 4 > --config help.hidden-command.init=true help
5 5 Mercurial Distributed SCM
6 6
7 7 list of commands:
8 8
9 9 Remote repository management:
10 10
11 11 incoming show new changesets found in source
12 12 outgoing show changesets not found in the destination
13 13 paths show aliases for remote repositories
14 14 pull pull changes from the specified source
15 15 push push changes to the specified destination
16 16 serve start stand-alone webserver
17 17
18 18 Change creation:
19 19
20 20 commit commit the specified files or all outstanding changes
21 21
22 22 Change manipulation:
23 23
24 24 backout reverse effect of earlier changeset
25 25 graft copy changes from other branches onto the current branch
26 26 merge merge another revision into working directory
27 27
28 28 Change organization:
29 29
30 30 bookmarks create a new bookmark or list existing bookmarks
31 31 branch set or show the current branch name
32 32 branches list repository named branches
33 33 phase set or show the current phase name
34 34 tag add one or more tags for the current or given revision
35 35 tags list repository tags
36 36
37 37 File content management:
38 38
39 39 annotate show changeset information by line for each file
40 40 cat output the current or given revision of files
41 41 copy mark files as copied for the next commit
42 42 diff diff repository (or selected files)
43 43 grep search for a pattern in specified files
44 44
45 45 Change navigation:
46 46
47 47 bisect subdivision search of changesets
48 48 heads show branch heads
49 49 identify identify the working directory or specified revision
50 50 log show revision history of entire repository or files
51 51
52 52 Working directory management:
53 53
54 54 add add the specified files on the next commit
55 55 addremove add all new files, delete all missing files
56 56 files list tracked files
57 57 forget forget the specified files on the next commit
58 58 purge removes files not tracked by Mercurial
59 59 remove remove the specified files on the next commit
60 60 rename rename files; equivalent of copy + remove
61 61 resolve redo merges or set/view the merge status of files
62 62 revert restore files to their checkout state
63 63 root print the root (top) of the current working directory
64 64 shelve save and set aside changes from the working directory
65 65 status show changed files in the working directory
66 66 summary summarize working directory state
67 67 unshelve restore a shelved change to the working directory
68 68 update update working directory (or switch revisions)
69 69
70 70 Change import/export:
71 71
72 72 archive create an unversioned archive of a repository revision
73 73 bundle create a bundle file
74 74 export dump the header and diffs for one or more changesets
75 75 import import an ordered set of patches
76 76 unbundle apply one or more bundle files
77 77
78 78 Repository maintenance:
79 79
80 admin::verify
81 verify the integrity of the repository
80 82 manifest output the current or given revision of the project manifest
81 83 recover roll back an interrupted transaction
82 84 verify verify the integrity of the repository
83 85
84 86 Help:
85 87
86 88 config show combined config settings from all hgrc files
87 89 help show help for a given topic or a help overview
88 90 version output version and copyright information
89 91
90 92 additional help topics:
91 93
92 94 Mercurial identifiers:
93 95
94 96 filesets Specifying File Sets
95 97 hgignore Syntax for Mercurial Ignore Files
96 98 patterns File Name Patterns
97 99 revisions Specifying Revisions
98 100 urls URL Paths
99 101
100 102 Mercurial output:
101 103
102 104 color Colorizing Outputs
103 105 dates Date Formats
104 106 diffs Diff Formats
105 107 templating Template Usage
106 108
107 109 Mercurial configuration:
108 110
109 111 config Configuration Files
110 112 environment Environment Variables
111 113 extensions Using Additional Features
112 114 flags Command-line flags
113 115 hgweb Configuring hgweb
114 116 merge-tools Merge Tools
115 117 pager Pager Support
116 118 rust Rust in Mercurial
117 119
118 120 Concepts:
119 121
120 122 bundlespec Bundle File Formats
121 123 evolution Safely rewriting history (EXPERIMENTAL)
122 124 glossary Glossary
123 125 phases Working with Phases
124 126 subrepos Subrepositories
125 127
126 128 Miscellaneous:
127 129
128 130 deprecated Deprecated Features
129 131 internals Technical implementation topics
130 132 scripting Using Mercurial from scripts and automation
131 133
132 134 (use 'hg help -v' to show built-in aliases and global options)
133 135
134 136 Test hiding some topics.
135 137
136 138 $ hg --config help.hidden-topic.deprecated=true \
137 139 > --config help.hidden-topic.internals=true \
138 140 > --config help.hidden-topic.scripting=true help
139 141 Mercurial Distributed SCM
140 142
141 143 list of commands:
142 144
143 145 Repository creation:
144 146
145 147 clone make a copy of an existing repository
146 148 init create a new repository in the given directory
147 149
148 150 Remote repository management:
149 151
150 152 incoming show new changesets found in source
151 153 outgoing show changesets not found in the destination
152 154 paths show aliases for remote repositories
153 155 pull pull changes from the specified source
154 156 push push changes to the specified destination
155 157 serve start stand-alone webserver
156 158
157 159 Change creation:
158 160
159 161 commit commit the specified files or all outstanding changes
160 162
161 163 Change manipulation:
162 164
163 165 backout reverse effect of earlier changeset
164 166 graft copy changes from other branches onto the current branch
165 167 merge merge another revision into working directory
166 168
167 169 Change organization:
168 170
169 171 bookmarks create a new bookmark or list existing bookmarks
170 172 branch set or show the current branch name
171 173 branches list repository named branches
172 174 phase set or show the current phase name
173 175 tag add one or more tags for the current or given revision
174 176 tags list repository tags
175 177
176 178 File content management:
177 179
178 180 annotate show changeset information by line for each file
179 181 cat output the current or given revision of files
180 182 copy mark files as copied for the next commit
181 183 diff diff repository (or selected files)
182 184 grep search for a pattern in specified files
183 185
184 186 Change navigation:
185 187
186 188 bisect subdivision search of changesets
187 189 heads show branch heads
188 190 identify identify the working directory or specified revision
189 191 log show revision history of entire repository or files
190 192
191 193 Working directory management:
192 194
193 195 add add the specified files on the next commit
194 196 addremove add all new files, delete all missing files
195 197 files list tracked files
196 198 forget forget the specified files on the next commit
197 199 purge removes files not tracked by Mercurial
198 200 remove remove the specified files on the next commit
199 201 rename rename files; equivalent of copy + remove
200 202 resolve redo merges or set/view the merge status of files
201 203 revert restore files to their checkout state
202 204 root print the root (top) of the current working directory
203 205 shelve save and set aside changes from the working directory
204 206 status show changed files in the working directory
205 207 summary summarize working directory state
206 208 unshelve restore a shelved change to the working directory
207 209 update update working directory (or switch revisions)
208 210
209 211 Change import/export:
210 212
211 213 archive create an unversioned archive of a repository revision
212 214 bundle create a bundle file
213 215 export dump the header and diffs for one or more changesets
214 216 import import an ordered set of patches
215 217 unbundle apply one or more bundle files
216 218
217 219 Repository maintenance:
218 220
221 admin::verify
222 verify the integrity of the repository
219 223 manifest output the current or given revision of the project manifest
220 224 recover roll back an interrupted transaction
221 225 verify verify the integrity of the repository
222 226
223 227 Help:
224 228
225 229 config show combined config settings from all hgrc files
226 230 help show help for a given topic or a help overview
227 231 version output version and copyright information
228 232
229 233 additional help topics:
230 234
231 235 Mercurial identifiers:
232 236
233 237 filesets Specifying File Sets
234 238 hgignore Syntax for Mercurial Ignore Files
235 239 patterns File Name Patterns
236 240 revisions Specifying Revisions
237 241 urls URL Paths
238 242
239 243 Mercurial output:
240 244
241 245 color Colorizing Outputs
242 246 dates Date Formats
243 247 diffs Diff Formats
244 248 templating Template Usage
245 249
246 250 Mercurial configuration:
247 251
248 252 config Configuration Files
249 253 environment Environment Variables
250 254 extensions Using Additional Features
251 255 flags Command-line flags
252 256 hgweb Configuring hgweb
253 257 merge-tools Merge Tools
254 258 pager Pager Support
255 259 rust Rust in Mercurial
256 260
257 261 Concepts:
258 262
259 263 bundlespec Bundle File Formats
260 264 evolution Safely rewriting history (EXPERIMENTAL)
261 265 glossary Glossary
262 266 phases Working with Phases
263 267 subrepos Subrepositories
264 268
265 269 (use 'hg help -v' to show built-in aliases and global options)
@@ -1,4085 +1,4106 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 Extra extensions will be printed in help output in a non-reliable order since
48 48 the extension is unknown.
49 49 #if no-extraextensions
50 50
51 51 $ hg help
52 52 Mercurial Distributed SCM
53 53
54 54 list of commands:
55 55
56 56 Repository creation:
57 57
58 58 clone make a copy of an existing repository
59 59 init create a new repository in the given directory
60 60
61 61 Remote repository management:
62 62
63 63 incoming show new changesets found in source
64 64 outgoing show changesets not found in the destination
65 65 paths show aliases for remote repositories
66 66 pull pull changes from the specified source
67 67 push push changes to the specified destination
68 68 serve start stand-alone webserver
69 69
70 70 Change creation:
71 71
72 72 commit commit the specified files or all outstanding changes
73 73
74 74 Change manipulation:
75 75
76 76 backout reverse effect of earlier changeset
77 77 graft copy changes from other branches onto the current branch
78 78 merge merge another revision into working directory
79 79
80 80 Change organization:
81 81
82 82 bookmarks create a new bookmark or list existing bookmarks
83 83 branch set or show the current branch name
84 84 branches list repository named branches
85 85 phase set or show the current phase name
86 86 tag add one or more tags for the current or given revision
87 87 tags list repository tags
88 88
89 89 File content management:
90 90
91 91 annotate show changeset information by line for each file
92 92 cat output the current or given revision of files
93 93 copy mark files as copied for the next commit
94 94 diff diff repository (or selected files)
95 95 grep search for a pattern in specified files
96 96
97 97 Change navigation:
98 98
99 99 bisect subdivision search of changesets
100 100 heads show branch heads
101 101 identify identify the working directory or specified revision
102 102 log show revision history of entire repository or files
103 103
104 104 Working directory management:
105 105
106 106 add add the specified files on the next commit
107 107 addremove add all new files, delete all missing files
108 108 files list tracked files
109 109 forget forget the specified files on the next commit
110 110 purge removes files not tracked by Mercurial
111 111 remove remove the specified files on the next commit
112 112 rename rename files; equivalent of copy + remove
113 113 resolve redo merges or set/view the merge status of files
114 114 revert restore files to their checkout state
115 115 root print the root (top) of the current working directory
116 116 shelve save and set aside changes from the working directory
117 117 status show changed files in the working directory
118 118 summary summarize working directory state
119 119 unshelve restore a shelved change to the working directory
120 120 update update working directory (or switch revisions)
121 121
122 122 Change import/export:
123 123
124 124 archive create an unversioned archive of a repository revision
125 125 bundle create a bundle file
126 126 export dump the header and diffs for one or more changesets
127 127 import import an ordered set of patches
128 128 unbundle apply one or more bundle files
129 129
130 130 Repository maintenance:
131 131
132 admin::verify
133 verify the integrity of the repository
132 134 manifest output the current or given revision of the project manifest
133 135 recover roll back an interrupted transaction
134 136 verify verify the integrity of the repository
135 137
136 138 Help:
137 139
138 140 config show combined config settings from all hgrc files
139 141 help show help for a given topic or a help overview
140 142 version output version and copyright information
141 143
142 144 additional help topics:
143 145
144 146 Mercurial identifiers:
145 147
146 148 filesets Specifying File Sets
147 149 hgignore Syntax for Mercurial Ignore Files
148 150 patterns File Name Patterns
149 151 revisions Specifying Revisions
150 152 urls URL Paths
151 153
152 154 Mercurial output:
153 155
154 156 color Colorizing Outputs
155 157 dates Date Formats
156 158 diffs Diff Formats
157 159 templating Template Usage
158 160
159 161 Mercurial configuration:
160 162
161 163 config Configuration Files
162 164 environment Environment Variables
163 165 extensions Using Additional Features
164 166 flags Command-line flags
165 167 hgweb Configuring hgweb
166 168 merge-tools Merge Tools
167 169 pager Pager Support
168 170 rust Rust in Mercurial
169 171
170 172 Concepts:
171 173
172 174 bundlespec Bundle File Formats
173 175 evolution Safely rewriting history (EXPERIMENTAL)
174 176 glossary Glossary
175 177 phases Working with Phases
176 178 subrepos Subrepositories
177 179
178 180 Miscellaneous:
179 181
180 182 deprecated Deprecated Features
181 183 internals Technical implementation topics
182 184 scripting Using Mercurial from scripts and automation
183 185
184 186 (use 'hg help -v' to show built-in aliases and global options)
185 187
186 188 $ hg -q help
187 189 Repository creation:
188 190
189 191 clone make a copy of an existing repository
190 192 init create a new repository in the given directory
191 193
192 194 Remote repository management:
193 195
194 196 incoming show new changesets found in source
195 197 outgoing show changesets not found in the destination
196 198 paths show aliases for remote repositories
197 199 pull pull changes from the specified source
198 200 push push changes to the specified destination
199 201 serve start stand-alone webserver
200 202
201 203 Change creation:
202 204
203 205 commit commit the specified files or all outstanding changes
204 206
205 207 Change manipulation:
206 208
207 209 backout reverse effect of earlier changeset
208 210 graft copy changes from other branches onto the current branch
209 211 merge merge another revision into working directory
210 212
211 213 Change organization:
212 214
213 215 bookmarks create a new bookmark or list existing bookmarks
214 216 branch set or show the current branch name
215 217 branches list repository named branches
216 218 phase set or show the current phase name
217 219 tag add one or more tags for the current or given revision
218 220 tags list repository tags
219 221
220 222 File content management:
221 223
222 224 annotate show changeset information by line for each file
223 225 cat output the current or given revision of files
224 226 copy mark files as copied for the next commit
225 227 diff diff repository (or selected files)
226 228 grep search for a pattern in specified files
227 229
228 230 Change navigation:
229 231
230 232 bisect subdivision search of changesets
231 233 heads show branch heads
232 234 identify identify the working directory or specified revision
233 235 log show revision history of entire repository or files
234 236
235 237 Working directory management:
236 238
237 239 add add the specified files on the next commit
238 240 addremove add all new files, delete all missing files
239 241 files list tracked files
240 242 forget forget the specified files on the next commit
241 243 purge removes files not tracked by Mercurial
242 244 remove remove the specified files on the next commit
243 245 rename rename files; equivalent of copy + remove
244 246 resolve redo merges or set/view the merge status of files
245 247 revert restore files to their checkout state
246 248 root print the root (top) of the current working directory
247 249 shelve save and set aside changes from the working directory
248 250 status show changed files in the working directory
249 251 summary summarize working directory state
250 252 unshelve restore a shelved change to the working directory
251 253 update update working directory (or switch revisions)
252 254
253 255 Change import/export:
254 256
255 257 archive create an unversioned archive of a repository revision
256 258 bundle create a bundle file
257 259 export dump the header and diffs for one or more changesets
258 260 import import an ordered set of patches
259 261 unbundle apply one or more bundle files
260 262
261 263 Repository maintenance:
262 264
265 admin::verify
266 verify the integrity of the repository
263 267 manifest output the current or given revision of the project manifest
264 268 recover roll back an interrupted transaction
265 269 verify verify the integrity of the repository
266 270
267 271 Help:
268 272
269 273 config show combined config settings from all hgrc files
270 274 help show help for a given topic or a help overview
271 275 version output version and copyright information
272 276
273 277 additional help topics:
274 278
275 279 Mercurial identifiers:
276 280
277 281 filesets Specifying File Sets
278 282 hgignore Syntax for Mercurial Ignore Files
279 283 patterns File Name Patterns
280 284 revisions Specifying Revisions
281 285 urls URL Paths
282 286
283 287 Mercurial output:
284 288
285 289 color Colorizing Outputs
286 290 dates Date Formats
287 291 diffs Diff Formats
288 292 templating Template Usage
289 293
290 294 Mercurial configuration:
291 295
292 296 config Configuration Files
293 297 environment Environment Variables
294 298 extensions Using Additional Features
295 299 flags Command-line flags
296 300 hgweb Configuring hgweb
297 301 merge-tools Merge Tools
298 302 pager Pager Support
299 303 rust Rust in Mercurial
300 304
301 305 Concepts:
302 306
303 307 bundlespec Bundle File Formats
304 308 evolution Safely rewriting history (EXPERIMENTAL)
305 309 glossary Glossary
306 310 phases Working with Phases
307 311 subrepos Subrepositories
308 312
309 313 Miscellaneous:
310 314
311 315 deprecated Deprecated Features
312 316 internals Technical implementation topics
313 317 scripting Using Mercurial from scripts and automation
314 318
315 319 Test extension help:
316 320 $ hg help extensions --config extensions.rebase= --config extensions.children=
317 321 Using Additional Features
318 322 """""""""""""""""""""""""
319 323
320 324 Mercurial has the ability to add new features through the use of
321 325 extensions. Extensions may add new commands, add options to existing
322 326 commands, change the default behavior of commands, or implement hooks.
323 327
324 328 To enable the "foo" extension, either shipped with Mercurial or in the
325 329 Python search path, create an entry for it in your configuration file,
326 330 like this:
327 331
328 332 [extensions]
329 333 foo =
330 334
331 335 You may also specify the full path to an extension:
332 336
333 337 [extensions]
334 338 myfeature = ~/.hgext/myfeature.py
335 339
336 340 See 'hg help config' for more information on configuration files.
337 341
338 342 Extensions are not loaded by default for a variety of reasons: they can
339 343 increase startup overhead; they may be meant for advanced usage only; they
340 344 may provide potentially dangerous abilities (such as letting you destroy
341 345 or modify history); they might not be ready for prime time; or they may
342 346 alter some usual behaviors of stock Mercurial. It is thus up to the user
343 347 to activate extensions as needed.
344 348
345 349 To explicitly disable an extension enabled in a configuration file of
346 350 broader scope, prepend its path with !:
347 351
348 352 [extensions]
349 353 # disabling extension bar residing in /path/to/extension/bar.py
350 354 bar = !/path/to/extension/bar.py
351 355 # ditto, but no path was supplied for extension baz
352 356 baz = !
353 357
354 358 enabled extensions:
355 359
356 360 children command to display child changesets (DEPRECATED)
357 361 rebase command to move sets of revisions to a different ancestor
358 362
359 363 disabled extensions:
360 364
361 365 acl hooks for controlling repository access
362 366 blackbox log repository events to a blackbox for debugging
363 367 bugzilla hooks for integrating with the Bugzilla bug tracker
364 368 censor erase file content at a given revision
365 369 churn command to display statistics about repository history
366 370 clonebundles advertise pre-generated bundles to seed clones
367 371 closehead close arbitrary heads without checking them out first
368 372 convert import revisions from foreign VCS repositories into
369 373 Mercurial
370 374 eol automatically manage newlines in repository files
371 375 extdiff command to allow external programs to compare revisions
372 376 factotum http authentication with factotum
373 377 fastexport export repositories as git fast-import stream
374 378 githelp try mapping git commands to Mercurial commands
375 379 gpg commands to sign and verify changesets
376 380 hgk browse the repository in a graphical way
377 381 highlight syntax highlighting for hgweb (requires Pygments)
378 382 histedit interactive history editing
379 383 keyword expand keywords in tracked files
380 384 largefiles track large binary files
381 385 mq manage a stack of patches
382 386 notify hooks for sending email push notifications
383 387 patchbomb command to send changesets as (a series of) patch emails
384 388 relink recreates hardlinks between repository clones
385 389 schemes extend schemes with shortcuts to repository swarms
386 390 share share a common history between several working directories
387 391 transplant command to transplant changesets from another branch
388 392 win32mbcs allow the use of MBCS paths with problematic encodings
389 393 zeroconf discover and advertise repositories on the local network
390 394
391 395 #endif
392 396
393 397 Verify that deprecated extensions are included if --verbose:
394 398
395 399 $ hg -v help extensions | grep children
396 400 children command to display child changesets (DEPRECATED)
397 401
398 402 Verify that extension keywords appear in help templates
399 403
400 404 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
401 405
402 406 Test short command list with verbose option
403 407
404 408 $ hg -v help shortlist
405 409 Mercurial Distributed SCM
406 410
407 411 basic commands:
408 412
409 413 abort abort an unfinished operation (EXPERIMENTAL)
410 414 add add the specified files on the next commit
411 415 annotate, blame
412 416 show changeset information by line for each file
413 417 clone make a copy of an existing repository
414 418 commit, ci commit the specified files or all outstanding changes
415 419 continue resumes an interrupted operation (EXPERIMENTAL)
416 420 diff diff repository (or selected files)
417 421 export dump the header and diffs for one or more changesets
418 422 forget forget the specified files on the next commit
419 423 init create a new repository in the given directory
420 424 log, history show revision history of entire repository or files
421 425 merge merge another revision into working directory
422 426 pull pull changes from the specified source
423 427 push push changes to the specified destination
424 428 remove, rm remove the specified files on the next commit
425 429 serve start stand-alone webserver
426 430 status, st show changed files in the working directory
427 431 summary, sum summarize working directory state
428 432 update, up, checkout, co
429 433 update working directory (or switch revisions)
430 434
431 435 global options ([+] can be repeated):
432 436
433 437 -R --repository REPO repository root directory or name of overlay bundle
434 438 file
435 439 --cwd DIR change working directory
436 440 -y --noninteractive do not prompt, automatically pick the first choice for
437 441 all prompts
438 442 -q --quiet suppress output
439 443 -v --verbose enable additional output
440 444 --color TYPE when to colorize (boolean, always, auto, never, or
441 445 debug)
442 446 --config CONFIG [+] set/override config option (use 'section.name=value')
443 447 --debug enable debugging output
444 448 --debugger start debugger
445 449 --encoding ENCODE set the charset encoding (default: ascii)
446 450 --encodingmode MODE set the charset encoding mode (default: strict)
447 451 --traceback always print a traceback on exception
448 452 --time time how long the command takes
449 453 --profile print command execution profile
450 454 --version output version information and exit
451 455 -h --help display help and exit
452 456 --hidden consider hidden changesets
453 457 --pager TYPE when to paginate (boolean, always, auto, or never)
454 458 (default: auto)
455 459
456 460 (use 'hg help' for the full list of commands)
457 461
458 462 $ hg add -h
459 463 hg add [OPTION]... [FILE]...
460 464
461 465 add the specified files on the next commit
462 466
463 467 Schedule files to be version controlled and added to the repository.
464 468
465 469 The files will be added to the repository at the next commit. To undo an
466 470 add before that, see 'hg forget'.
467 471
468 472 If no names are given, add all files to the repository (except files
469 473 matching ".hgignore").
470 474
471 475 Returns 0 if all files are successfully added.
472 476
473 477 options ([+] can be repeated):
474 478
475 479 -I --include PATTERN [+] include names matching the given patterns
476 480 -X --exclude PATTERN [+] exclude names matching the given patterns
477 481 -S --subrepos recurse into subrepositories
478 482 -n --dry-run do not perform actions, just print output
479 483
480 484 (some details hidden, use --verbose to show complete help)
481 485
482 486 Verbose help for add
483 487
484 488 $ hg add -hv
485 489 hg add [OPTION]... [FILE]...
486 490
487 491 add the specified files on the next commit
488 492
489 493 Schedule files to be version controlled and added to the repository.
490 494
491 495 The files will be added to the repository at the next commit. To undo an
492 496 add before that, see 'hg forget'.
493 497
494 498 If no names are given, add all files to the repository (except files
495 499 matching ".hgignore").
496 500
497 501 Examples:
498 502
499 503 - New (unknown) files are added automatically by 'hg add':
500 504
501 505 $ ls
502 506 foo.c
503 507 $ hg status
504 508 ? foo.c
505 509 $ hg add
506 510 adding foo.c
507 511 $ hg status
508 512 A foo.c
509 513
510 514 - Specific files to be added can be specified:
511 515
512 516 $ ls
513 517 bar.c foo.c
514 518 $ hg status
515 519 ? bar.c
516 520 ? foo.c
517 521 $ hg add bar.c
518 522 $ hg status
519 523 A bar.c
520 524 ? foo.c
521 525
522 526 Returns 0 if all files are successfully added.
523 527
524 528 options ([+] can be repeated):
525 529
526 530 -I --include PATTERN [+] include names matching the given patterns
527 531 -X --exclude PATTERN [+] exclude names matching the given patterns
528 532 -S --subrepos recurse into subrepositories
529 533 -n --dry-run do not perform actions, just print output
530 534
531 535 global options ([+] can be repeated):
532 536
533 537 -R --repository REPO repository root directory or name of overlay bundle
534 538 file
535 539 --cwd DIR change working directory
536 540 -y --noninteractive do not prompt, automatically pick the first choice for
537 541 all prompts
538 542 -q --quiet suppress output
539 543 -v --verbose enable additional output
540 544 --color TYPE when to colorize (boolean, always, auto, never, or
541 545 debug)
542 546 --config CONFIG [+] set/override config option (use 'section.name=value')
543 547 --debug enable debugging output
544 548 --debugger start debugger
545 549 --encoding ENCODE set the charset encoding (default: ascii)
546 550 --encodingmode MODE set the charset encoding mode (default: strict)
547 551 --traceback always print a traceback on exception
548 552 --time time how long the command takes
549 553 --profile print command execution profile
550 554 --version output version information and exit
551 555 -h --help display help and exit
552 556 --hidden consider hidden changesets
553 557 --pager TYPE when to paginate (boolean, always, auto, or never)
554 558 (default: auto)
555 559
556 560 Test the textwidth config option
557 561
558 562 $ hg root -h --config ui.textwidth=50
559 563 hg root
560 564
561 565 print the root (top) of the current working
562 566 directory
563 567
564 568 Print the root directory of the current
565 569 repository.
566 570
567 571 Returns 0 on success.
568 572
569 573 options:
570 574
571 575 -T --template TEMPLATE display with template
572 576
573 577 (some details hidden, use --verbose to show
574 578 complete help)
575 579
576 580 Test help option with version option
577 581
578 582 $ hg add -h --version
579 583 Mercurial Distributed SCM (version *) (glob)
580 584 (see https://mercurial-scm.org for more information)
581 585
582 586 Copyright (C) 2005-* Olivia Mackall and others (glob)
583 587 This is free software; see the source for copying conditions. There is NO
584 588 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
585 589
586 590 $ hg add --skjdfks
587 591 hg add: option --skjdfks not recognized
588 592 hg add [OPTION]... [FILE]...
589 593
590 594 add the specified files on the next commit
591 595
592 596 options ([+] can be repeated):
593 597
594 598 -I --include PATTERN [+] include names matching the given patterns
595 599 -X --exclude PATTERN [+] exclude names matching the given patterns
596 600 -S --subrepos recurse into subrepositories
597 601 -n --dry-run do not perform actions, just print output
598 602
599 603 (use 'hg add -h' to show more help)
600 604 [10]
601 605
602 606 Test ambiguous command help
603 607
604 608 $ hg help ad
605 609 list of commands:
606 610
611 Working directory management:
612
607 613 add add the specified files on the next commit
608 614 addremove add all new files, delete all missing files
609 615
616 Repository maintenance:
617
618 admin::verify
619 verify the integrity of the repository
620
610 621 (use 'hg help -v ad' to show built-in aliases and global options)
611 622
612 623 Test command without options
613 624
614 625 $ hg help verify
615 626 hg verify
616 627
617 628 verify the integrity of the repository
618 629
619 630 Verify the integrity of the current repository.
620 631
621 632 This will perform an extensive check of the repository's integrity,
622 633 validating the hashes and checksums of each entry in the changelog,
623 634 manifest, and tracked files, as well as the integrity of their crosslinks
624 635 and indices.
625 636
626 637 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
627 638 information about recovery from corruption of the repository.
628 639
640 For an alternative UI with a lot more control over the verification
641 process and better error reporting, try 'hg help admin::verify'.
642
629 643 Returns 0 on success, 1 if errors are encountered.
630 644
631 645 options:
632 646
633 647 (some details hidden, use --verbose to show complete help)
634 648
635 649 $ hg help diff
636 650 hg diff [OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...
637 651
638 652 diff repository (or selected files)
639 653
640 654 Show differences between revisions for the specified files.
641 655
642 656 Differences between files are shown using the unified diff format.
643 657
644 658 Note:
645 659 'hg diff' may generate unexpected results for merges, as it will
646 660 default to comparing against the working directory's first parent
647 661 changeset if no revisions are specified. To diff against the conflict
648 662 regions, you can use '--config diff.merge=yes'.
649 663
650 664 By default, the working directory files are compared to its first parent.
651 665 To see the differences from another revision, use --from. To see the
652 666 difference to another revision, use --to. For example, 'hg diff --from .^'
653 667 will show the differences from the working copy's grandparent to the
654 668 working copy, 'hg diff --to .' will show the diff from the working copy to
655 669 its parent (i.e. the reverse of the default), and 'hg diff --from 1.0 --to
656 670 1.2' will show the diff between those two revisions.
657 671
658 672 Alternatively you can specify -c/--change with a revision to see the
659 673 changes in that changeset relative to its first parent (i.e. 'hg diff -c
660 674 42' is equivalent to 'hg diff --from 42^ --to 42')
661 675
662 676 Without the -a/--text option, diff will avoid generating diffs of files it
663 677 detects as binary. With -a, diff will generate a diff anyway, probably
664 678 with undesirable results.
665 679
666 680 Use the -g/--git option to generate diffs in the git extended diff format.
667 681 For more information, read 'hg help diffs'.
668 682
669 683 Returns 0 on success.
670 684
671 685 options ([+] can be repeated):
672 686
673 687 --from REV1 revision to diff from
674 688 --to REV2 revision to diff to
675 689 -c --change REV change made by revision
676 690 -a --text treat all files as text
677 691 -g --git use git extended diff format
678 692 --binary generate binary diffs in git mode (default)
679 693 --nodates omit dates from diff headers
680 694 --noprefix omit a/ and b/ prefixes from filenames
681 695 -p --show-function show which function each change is in
682 696 --reverse produce a diff that undoes the changes
683 697 -w --ignore-all-space ignore white space when comparing lines
684 698 -b --ignore-space-change ignore changes in the amount of white space
685 699 -B --ignore-blank-lines ignore changes whose lines are all blank
686 700 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
687 701 -U --unified NUM number of lines of context to show
688 702 --stat output diffstat-style summary of changes
689 703 --root DIR produce diffs relative to subdirectory
690 704 -I --include PATTERN [+] include names matching the given patterns
691 705 -X --exclude PATTERN [+] exclude names matching the given patterns
692 706 -S --subrepos recurse into subrepositories
693 707
694 708 (some details hidden, use --verbose to show complete help)
695 709
696 710 $ hg help status
697 711 hg status [OPTION]... [FILE]...
698 712
699 713 aliases: st
700 714
701 715 show changed files in the working directory
702 716
703 717 Show status of files in the repository. If names are given, only files
704 718 that match are shown. Files that are clean or ignored or the source of a
705 719 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
706 720 -C/--copies or -A/--all are given. Unless options described with "show
707 721 only ..." are given, the options -mardu are used.
708 722
709 723 Option -q/--quiet hides untracked (unknown and ignored) files unless
710 724 explicitly requested with -u/--unknown or -i/--ignored.
711 725
712 726 Note:
713 727 'hg status' may appear to disagree with diff if permissions have
714 728 changed or a merge has occurred. The standard diff format does not
715 729 report permission changes and diff only reports changes relative to one
716 730 merge parent.
717 731
718 732 If one revision is given, it is used as the base revision. If two
719 733 revisions are given, the differences between them are shown. The --change
720 734 option can also be used as a shortcut to list the changed files of a
721 735 revision from its first parent.
722 736
723 737 The codes used to show the status of files are:
724 738
725 739 M = modified
726 740 A = added
727 741 R = removed
728 742 C = clean
729 743 ! = missing (deleted by non-hg command, but still tracked)
730 744 ? = not tracked
731 745 I = ignored
732 746 = origin of the previous file (with --copies)
733 747
734 748 Returns 0 on success.
735 749
736 750 options ([+] can be repeated):
737 751
738 752 -A --all show status of all files
739 753 -m --modified show only modified files
740 754 -a --added show only added files
741 755 -r --removed show only removed files
742 756 -d --deleted show only missing files
743 757 -c --clean show only files without changes
744 758 -u --unknown show only unknown (not tracked) files
745 759 -i --ignored show only ignored files
746 760 -n --no-status hide status prefix
747 761 -C --copies show source of copied files
748 762 -0 --print0 end filenames with NUL, for use with xargs
749 763 --rev REV [+] show difference from revision
750 764 --change REV list the changed files of a revision
751 765 -I --include PATTERN [+] include names matching the given patterns
752 766 -X --exclude PATTERN [+] exclude names matching the given patterns
753 767 -S --subrepos recurse into subrepositories
754 768 -T --template TEMPLATE display with template
755 769
756 770 (some details hidden, use --verbose to show complete help)
757 771
758 772 $ hg -q help status
759 773 hg status [OPTION]... [FILE]...
760 774
761 775 show changed files in the working directory
762 776
763 777 $ hg help foo
764 778 abort: no such help topic: foo
765 779 (try 'hg help --keyword foo')
766 780 [10]
767 781
768 782 $ hg skjdfks
769 783 hg: unknown command 'skjdfks'
770 784 (use 'hg help' for a list of commands)
771 785 [10]
772 786
773 787 Typoed command gives suggestion
774 788 $ hg puls
775 789 hg: unknown command 'puls'
776 790 (did you mean one of pull, push?)
777 791 [10]
778 792
779 793 Not enabled extension gets suggested
780 794
781 795 $ hg rebase
782 796 hg: unknown command 'rebase'
783 797 'rebase' is provided by the following extension:
784 798
785 799 rebase command to move sets of revisions to a different ancestor
786 800
787 801 (use 'hg help extensions' for information on enabling extensions)
788 802 [10]
789 803
790 804 Disabled extension gets suggested
791 805 $ hg --config extensions.rebase=! rebase
792 806 hg: unknown command 'rebase'
793 807 'rebase' is provided by the following extension:
794 808
795 809 rebase command to move sets of revisions to a different ancestor
796 810
797 811 (use 'hg help extensions' for information on enabling extensions)
798 812 [10]
799 813
800 814 Checking that help adapts based on the config:
801 815
802 816 $ hg help diff --config ui.tweakdefaults=true | grep -E -e '^ *(-g|config)'
803 817 -g --[no-]git use git extended diff format (default: on from
804 818 config)
805 819
806 820 Make sure that we don't run afoul of the help system thinking that
807 821 this is a section and erroring out weirdly.
808 822
809 823 $ hg .log
810 824 hg: unknown command '.log'
811 825 (did you mean log?)
812 826 [10]
813 827
814 828 $ hg log.
815 829 hg: unknown command 'log.'
816 830 (did you mean log?)
817 831 [10]
818 832 $ hg pu.lh
819 833 hg: unknown command 'pu.lh'
820 834 (did you mean one of pull, push?)
821 835 [10]
822 836
823 837 $ cat > helpext.py <<EOF
824 838 > import os
825 839 > from mercurial import commands, fancyopts, registrar
826 840 >
827 841 > def func(arg):
828 842 > return '%sfoo' % arg
829 843 > class customopt(fancyopts.customopt):
830 844 > def newstate(self, oldstate, newparam, abort):
831 845 > return '%sbar' % oldstate
832 846 > cmdtable = {}
833 847 > command = registrar.command(cmdtable)
834 848 >
835 849 > @command(b'nohelp',
836 850 > [(b'', b'longdesc', 3, b'x'*67),
837 851 > (b'n', b'', None, b'normal desc'),
838 852 > (b'', b'newline', b'', b'line1\nline2'),
839 853 > (b'', b'default-off', False, b'enable X'),
840 854 > (b'', b'default-on', True, b'enable Y'),
841 855 > (b'', b'callableopt', func, b'adds foo'),
842 856 > (b'', b'customopt', customopt(''), b'adds bar'),
843 857 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
844 858 > b'hg nohelp',
845 859 > norepo=True)
846 860 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
847 861 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
848 862 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
849 863 > def nohelp(ui, *args, **kwargs):
850 864 > pass
851 865 >
852 866 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
853 867 > def hashelp(ui, *args, **kwargs):
854 868 > """Extension command's help"""
855 869 >
856 870 > def uisetup(ui):
857 871 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
858 872 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
859 873 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
860 874 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
861 875 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
862 876 >
863 877 > EOF
864 878 $ echo '[extensions]' >> $HGRCPATH
865 879 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
866 880
867 881 Test for aliases
868 882
869 883 $ hg help | grep hgalias
870 884 hgalias My doc
871 885
872 886 $ hg help hgalias
873 887 hg hgalias [--remote]
874 888
875 889 alias for: hg summary
876 890
877 891 My doc
878 892
879 893 defined by: helpext
880 894
881 895 options:
882 896
883 897 --remote check for push and pull
884 898
885 899 (some details hidden, use --verbose to show complete help)
886 900 $ hg help hgaliasnodoc
887 901 hg hgaliasnodoc [--remote]
888 902
889 903 alias for: hg summary
890 904
891 905 summarize working directory state
892 906
893 907 This generates a brief summary of the working directory state, including
894 908 parents, branch, commit status, phase and available updates.
895 909
896 910 With the --remote option, this will check the default paths for incoming
897 911 and outgoing changes. This can be time-consuming.
898 912
899 913 Returns 0 on success.
900 914
901 915 defined by: helpext
902 916
903 917 options:
904 918
905 919 --remote check for push and pull
906 920
907 921 (some details hidden, use --verbose to show complete help)
908 922
909 923 $ hg help shellalias
910 924 hg shellalias
911 925
912 926 shell alias for: echo hi
913 927
914 928 (no help text available)
915 929
916 930 defined by: helpext
917 931
918 932 (some details hidden, use --verbose to show complete help)
919 933
920 934 Test command with no help text
921 935
922 936 $ hg help nohelp
923 937 hg nohelp
924 938
925 939 (no help text available)
926 940
927 941 options:
928 942
929 943 --longdesc VALUE
930 944 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
931 945 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
932 946 -n -- normal desc
933 947 --newline VALUE line1 line2
934 948 --default-off enable X
935 949 --[no-]default-on enable Y (default: on)
936 950 --callableopt VALUE adds foo
937 951 --customopt VALUE adds bar
938 952 --customopt-withdefault VALUE adds bar (default: foo)
939 953
940 954 (some details hidden, use --verbose to show complete help)
941 955
942 956 Test that default list of commands includes extension commands that have help,
943 957 but not those that don't, except in verbose mode, when a keyword is passed, or
944 958 when help about the extension is requested.
945 959
946 960 #if no-extraextensions
947 961
948 962 $ hg help | grep hashelp
949 963 hashelp Extension command's help
950 964 $ hg help | grep nohelp
951 965 [1]
952 966 $ hg help -v | grep nohelp
953 967 nohelp (no help text available)
954 968
955 969 $ hg help -k nohelp
956 970 Commands:
957 971
958 972 nohelp hg nohelp
959 973
960 974 Extension Commands:
961 975
962 976 nohelp (no help text available)
963 977
964 978 $ hg help helpext
965 979 helpext extension - no help text available
966 980
967 981 list of commands:
968 982
969 983 hashelp Extension command's help
970 984 nohelp (no help text available)
971 985
972 986 (use 'hg help -v helpext' to show built-in aliases and global options)
973 987
974 988 #endif
975 989
976 990 Test list of internal help commands
977 991
978 992 $ hg help debug
979 993 debug commands (internal and unsupported):
980 994
981 995 debug-delta-find
982 996 display the computation to get to a valid delta for storing REV
983 997 debug-repair-issue6528
984 998 find affected revisions and repair them. See issue6528 for more
985 999 details.
986 1000 debug-revlog-index
987 1001 dump index data for a revlog
988 1002 debug-revlog-stats
989 1003 display statistics about revlogs in the store
990 1004 debug::stable-tail-sort
991 1005 display the stable-tail sort of the ancestors of a given node
992 1006 debug::stable-tail-sort-leaps
993 1007 display the leaps in the stable-tail sort of a node, one per
994 1008 line
995 1009 debugancestor
996 1010 find the ancestor revision of two revisions in a given index
997 1011 debugantivirusrunning
998 1012 attempt to trigger an antivirus scanner to see if one is active
999 1013 debugapplystreamclonebundle
1000 1014 apply a stream clone bundle file
1001 1015 debugbackupbundle
1002 1016 lists the changesets available in backup bundles
1003 1017 debugbuilddag
1004 1018 builds a repo with a given DAG from scratch in the current
1005 1019 empty repo
1006 1020 debugbundle lists the contents of a bundle
1007 1021 debugcapabilities
1008 1022 lists the capabilities of a remote peer
1009 1023 debugchangedfiles
1010 1024 list the stored files changes for a revision
1011 1025 debugcheckstate
1012 1026 validate the correctness of the current dirstate
1013 1027 debugcolor show available color, effects or style
1014 1028 debugcommands
1015 1029 list all available commands and options
1016 1030 debugcomplete
1017 1031 returns the completion list associated with the given command
1018 1032 debugcreatestreamclonebundle
1019 1033 create a stream clone bundle file
1020 1034 debugdag format the changelog or an index DAG as a concise textual
1021 1035 description
1022 1036 debugdata dump the contents of a data file revision
1023 1037 debugdate parse and display a date
1024 1038 debugdeltachain
1025 1039 dump information about delta chains in a revlog
1026 1040 debugdirstate
1027 1041 show the contents of the current dirstate
1028 1042 debugdirstateignorepatternshash
1029 1043 show the hash of ignore patterns stored in dirstate if v2,
1030 1044 debugdiscovery
1031 1045 runs the changeset discovery protocol in isolation
1032 1046 debugdownload
1033 1047 download a resource using Mercurial logic and config
1034 1048 debugextensions
1035 1049 show information about active extensions
1036 1050 debugfileset parse and apply a fileset specification
1037 1051 debugformat display format information about the current repository
1038 1052 debugfsinfo show information detected about current filesystem
1039 1053 debuggetbundle
1040 1054 retrieves a bundle from a repo
1041 1055 debugignore display the combined ignore pattern and information about
1042 1056 ignored files
1043 1057 debugindexdot
1044 1058 dump an index DAG as a graphviz dot file
1045 1059 debugindexstats
1046 1060 show stats related to the changelog index
1047 1061 debuginstall test Mercurial installation
1048 1062 debugknown test whether node ids are known to a repo
1049 1063 debuglocks show or modify state of locks
1050 1064 debugmanifestfulltextcache
1051 1065 show, clear or amend the contents of the manifest fulltext
1052 1066 cache
1053 1067 debugmergestate
1054 1068 print merge state
1055 1069 debugnamecomplete
1056 1070 complete "names" - tags, open branch names, bookmark names
1057 1071 debugnodemap write and inspect on disk nodemap
1058 1072 debugobsolete
1059 1073 create arbitrary obsolete marker
1060 1074 debugoptADV (no help text available)
1061 1075 debugoptDEP (no help text available)
1062 1076 debugoptEXP (no help text available)
1063 1077 debugp1copies
1064 1078 dump copy information compared to p1
1065 1079 debugp2copies
1066 1080 dump copy information compared to p2
1067 1081 debugpathcomplete
1068 1082 complete part or all of a tracked path
1069 1083 debugpathcopies
1070 1084 show copies between two revisions
1071 1085 debugpeer establish a connection to a peer repository
1072 1086 debugpickmergetool
1073 1087 examine which merge tool is chosen for specified file
1074 1088 debugpushkey access the pushkey key/value protocol
1075 1089 debugpvec (no help text available)
1076 1090 debugrebuilddirstate
1077 1091 rebuild the dirstate as it would look like for the given
1078 1092 revision
1079 1093 debugrebuildfncache
1080 1094 rebuild the fncache file
1081 1095 debugrename dump rename information
1082 1096 debugrequires
1083 1097 print the current repo requirements
1084 1098 debugrevlog show data and statistics about a revlog
1085 1099 debugrevlogindex
1086 1100 dump the contents of a revlog index
1087 1101 debugrevspec parse and apply a revision specification
1088 1102 debugserve run a server with advanced settings
1089 1103 debugsetparents
1090 1104 manually set the parents of the current working directory
1091 1105 (DANGEROUS)
1092 1106 debugshell run an interactive Python interpreter
1093 1107 debugsidedata
1094 1108 dump the side data for a cl/manifest/file revision
1095 1109 debugssl test a secure connection to a server
1096 1110 debugstrip strip changesets and all their descendants from the repository
1097 1111 debugsub (no help text available)
1098 1112 debugsuccessorssets
1099 1113 show set of successors for revision
1100 1114 debugtagscache
1101 1115 display the contents of .hg/cache/hgtagsfnodes1
1102 1116 debugtemplate
1103 1117 parse and apply a template
1104 1118 debuguigetpass
1105 1119 show prompt to type password
1106 1120 debuguiprompt
1107 1121 show plain prompt
1108 1122 debugupdatecaches
1109 1123 warm all known caches in the repository
1110 1124 debugupgraderepo
1111 1125 upgrade a repository to use different features
1112 1126 debugwalk show how files match on given patterns
1113 1127 debugwhyunstable
1114 1128 explain instabilities of a changeset
1115 1129 debugwireargs
1116 1130 (no help text available)
1117 1131 debugwireproto
1118 1132 send wire protocol commands to a server
1119 1133
1120 1134 (use 'hg help -v debug' to show built-in aliases and global options)
1121 1135
1122 1136 internals topic renders index of available sub-topics
1123 1137
1124 1138 $ hg help internals
1125 1139 Technical implementation topics
1126 1140 """""""""""""""""""""""""""""""
1127 1141
1128 1142 To access a subtopic, use "hg help internals.{subtopic-name}"
1129 1143
1130 1144 bid-merge Bid Merge Algorithm
1131 1145 bundle2 Bundle2
1132 1146 bundles Bundles
1133 1147 cbor CBOR
1134 1148 censor Censor
1135 1149 changegroups Changegroups
1136 1150 config Config Registrar
1137 1151 dirstate-v2 dirstate-v2 file format
1138 1152 extensions Extension API
1139 1153 mergestate Mergestate
1140 1154 requirements Repository Requirements
1141 1155 revlogs Revision Logs
1142 1156 wireprotocol Wire Protocol
1143 1157 wireprotocolrpc
1144 1158 Wire Protocol RPC
1145 1159 wireprotocolv2
1146 1160 Wire Protocol Version 2
1147 1161
1148 1162 sub-topics can be accessed
1149 1163
1150 1164 $ hg help internals.changegroups
1151 1165 Changegroups
1152 1166 """"""""""""
1153 1167
1154 1168 Changegroups are representations of repository revlog data, specifically
1155 1169 the changelog data, root/flat manifest data, treemanifest data, and
1156 1170 filelogs.
1157 1171
1158 1172 There are 4 versions of changegroups: "1", "2", "3" and "4". From a high-
1159 1173 level, versions "1" and "2" are almost exactly the same, with the only
1160 1174 difference being an additional item in the *delta header*. Version "3"
1161 1175 adds support for storage flags in the *delta header* and optionally
1162 1176 exchanging treemanifests (enabled by setting an option on the
1163 1177 "changegroup" part in the bundle2). Version "4" adds support for
1164 1178 exchanging sidedata (additional revision metadata not part of the digest).
1165 1179
1166 1180 Changegroups when not exchanging treemanifests consist of 3 logical
1167 1181 segments:
1168 1182
1169 1183 +---------------------------------+
1170 1184 | | | |
1171 1185 | changeset | manifest | filelogs |
1172 1186 | | | |
1173 1187 | | | |
1174 1188 +---------------------------------+
1175 1189
1176 1190 When exchanging treemanifests, there are 4 logical segments:
1177 1191
1178 1192 +-------------------------------------------------+
1179 1193 | | | | |
1180 1194 | changeset | root | treemanifests | filelogs |
1181 1195 | | manifest | | |
1182 1196 | | | | |
1183 1197 +-------------------------------------------------+
1184 1198
1185 1199 The principle building block of each segment is a *chunk*. A *chunk* is a
1186 1200 framed piece of data:
1187 1201
1188 1202 +---------------------------------------+
1189 1203 | | |
1190 1204 | length | data |
1191 1205 | (4 bytes) | (<length - 4> bytes) |
1192 1206 | | |
1193 1207 +---------------------------------------+
1194 1208
1195 1209 All integers are big-endian signed integers. Each chunk starts with a
1196 1210 32-bit integer indicating the length of the entire chunk (including the
1197 1211 length field itself).
1198 1212
1199 1213 There is a special case chunk that has a value of 0 for the length
1200 1214 ("0x00000000"). We call this an *empty chunk*.
1201 1215
1202 1216 Delta Groups
1203 1217 ============
1204 1218
1205 1219 A *delta group* expresses the content of a revlog as a series of deltas,
1206 1220 or patches against previous revisions.
1207 1221
1208 1222 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1209 1223 to signal the end of the delta group:
1210 1224
1211 1225 +------------------------------------------------------------------------+
1212 1226 | | | | | |
1213 1227 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1214 1228 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1215 1229 | | | | | |
1216 1230 +------------------------------------------------------------------------+
1217 1231
1218 1232 Each *chunk*'s data consists of the following:
1219 1233
1220 1234 +---------------------------------------+
1221 1235 | | |
1222 1236 | delta header | delta data |
1223 1237 | (various by version) | (various) |
1224 1238 | | |
1225 1239 +---------------------------------------+
1226 1240
1227 1241 The *delta data* is a series of *delta*s that describe a diff from an
1228 1242 existing entry (either that the recipient already has, or previously
1229 1243 specified in the bundle/changegroup).
1230 1244
1231 1245 The *delta header* is different between versions "1", "2", "3" and "4" of
1232 1246 the changegroup format.
1233 1247
1234 1248 Version 1 (headerlen=80):
1235 1249
1236 1250 +------------------------------------------------------+
1237 1251 | | | | |
1238 1252 | node | p1 node | p2 node | link node |
1239 1253 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1240 1254 | | | | |
1241 1255 +------------------------------------------------------+
1242 1256
1243 1257 Version 2 (headerlen=100):
1244 1258
1245 1259 +------------------------------------------------------------------+
1246 1260 | | | | | |
1247 1261 | node | p1 node | p2 node | base node | link node |
1248 1262 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1249 1263 | | | | | |
1250 1264 +------------------------------------------------------------------+
1251 1265
1252 1266 Version 3 (headerlen=102):
1253 1267
1254 1268 +------------------------------------------------------------------------------+
1255 1269 | | | | | | |
1256 1270 | node | p1 node | p2 node | base node | link node | flags |
1257 1271 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1258 1272 | | | | | | |
1259 1273 +------------------------------------------------------------------------------+
1260 1274
1261 1275 Version 4 (headerlen=103):
1262 1276
1263 1277 +------------------------------------------------------------------------------+----------+
1264 1278 | | | | | | | |
1265 1279 | node | p1 node | p2 node | base node | link node | flags | pflags |
1266 1280 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
1267 1281 | | | | | | | |
1268 1282 +------------------------------------------------------------------------------+----------+
1269 1283
1270 1284 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1271 1285 contain a series of *delta*s, densely packed (no separators). These deltas
1272 1286 describe a diff from an existing entry (either that the recipient already
1273 1287 has, or previously specified in the bundle/changegroup). The format is
1274 1288 described more fully in "hg help internals.bdiff", but briefly:
1275 1289
1276 1290 +---------------------------------------------------------------+
1277 1291 | | | | |
1278 1292 | start offset | end offset | new length | content |
1279 1293 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1280 1294 | | | | |
1281 1295 +---------------------------------------------------------------+
1282 1296
1283 1297 Please note that the length field in the delta data does *not* include
1284 1298 itself.
1285 1299
1286 1300 In version 1, the delta is always applied against the previous node from
1287 1301 the changegroup or the first parent if this is the first entry in the
1288 1302 changegroup.
1289 1303
1290 1304 In version 2 and up, the delta base node is encoded in the entry in the
1291 1305 changegroup. This allows the delta to be expressed against any parent,
1292 1306 which can result in smaller deltas and more efficient encoding of data.
1293 1307
1294 1308 The *flags* field holds bitwise flags affecting the processing of revision
1295 1309 data. The following flags are defined:
1296 1310
1297 1311 32768
1298 1312 Censored revision. The revision's fulltext has been replaced by censor
1299 1313 metadata. May only occur on file revisions.
1300 1314
1301 1315 16384
1302 1316 Ellipsis revision. Revision hash does not match data (likely due to
1303 1317 rewritten parents).
1304 1318
1305 1319 8192
1306 1320 Externally stored. The revision fulltext contains "key:value" "\n"
1307 1321 delimited metadata defining an object stored elsewhere. Used by the LFS
1308 1322 extension.
1309 1323
1310 1324 4096
1311 1325 Contains copy information. This revision changes files in a way that
1312 1326 could affect copy tracing. This does *not* affect changegroup handling,
1313 1327 but is relevant for other parts of Mercurial.
1314 1328
1315 1329 For historical reasons, the integer values are identical to revlog version
1316 1330 1 per-revision storage flags and correspond to bits being set in this
1317 1331 2-byte field. Bits were allocated starting from the most-significant bit,
1318 1332 hence the reverse ordering and allocation of these flags.
1319 1333
1320 1334 The *pflags* (protocol flags) field holds bitwise flags affecting the
1321 1335 protocol itself. They are first in the header since they may affect the
1322 1336 handling of the rest of the fields in a future version. They are defined
1323 1337 as such:
1324 1338
1325 1339 1 indicates whether to read a chunk of sidedata (of variable length) right
1326 1340 after the revision flags.
1327 1341
1328 1342 Changeset Segment
1329 1343 =================
1330 1344
1331 1345 The *changeset segment* consists of a single *delta group* holding
1332 1346 changelog data. The *empty chunk* at the end of the *delta group* denotes
1333 1347 the boundary to the *manifest segment*.
1334 1348
1335 1349 Manifest Segment
1336 1350 ================
1337 1351
1338 1352 The *manifest segment* consists of a single *delta group* holding manifest
1339 1353 data. If treemanifests are in use, it contains only the manifest for the
1340 1354 root directory of the repository. Otherwise, it contains the entire
1341 1355 manifest data. The *empty chunk* at the end of the *delta group* denotes
1342 1356 the boundary to the next segment (either the *treemanifests segment* or
1343 1357 the *filelogs segment*, depending on version and the request options).
1344 1358
1345 1359 Treemanifests Segment
1346 1360 ---------------------
1347 1361
1348 1362 The *treemanifests segment* only exists in changegroup version "3" and
1349 1363 "4", and only if the 'treemanifest' param is part of the bundle2
1350 1364 changegroup part (it is not possible to use changegroup version 3 or 4
1351 1365 outside of bundle2). Aside from the filenames in the *treemanifests
1352 1366 segment* containing a trailing "/" character, it behaves identically to
1353 1367 the *filelogs segment* (see below). The final sub-segment is followed by
1354 1368 an *empty chunk* (logically, a sub-segment with filename size 0). This
1355 1369 denotes the boundary to the *filelogs segment*.
1356 1370
1357 1371 Filelogs Segment
1358 1372 ================
1359 1373
1360 1374 The *filelogs segment* consists of multiple sub-segments, each
1361 1375 corresponding to an individual file whose data is being described:
1362 1376
1363 1377 +--------------------------------------------------+
1364 1378 | | | | | |
1365 1379 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1366 1380 | | | | | (4 bytes) |
1367 1381 | | | | | |
1368 1382 +--------------------------------------------------+
1369 1383
1370 1384 The final filelog sub-segment is followed by an *empty chunk* (logically,
1371 1385 a sub-segment with filename size 0). This denotes the end of the segment
1372 1386 and of the overall changegroup.
1373 1387
1374 1388 Each filelog sub-segment consists of the following:
1375 1389
1376 1390 +------------------------------------------------------+
1377 1391 | | | |
1378 1392 | filename length | filename | delta group |
1379 1393 | (4 bytes) | (<length - 4> bytes) | (various) |
1380 1394 | | | |
1381 1395 +------------------------------------------------------+
1382 1396
1383 1397 That is, a *chunk* consisting of the filename (not terminated or padded)
1384 1398 followed by N chunks constituting the *delta group* for this file. The
1385 1399 *empty chunk* at the end of each *delta group* denotes the boundary to the
1386 1400 next filelog sub-segment.
1387 1401
1388 1402 non-existent subtopics print an error
1389 1403
1390 1404 $ hg help internals.foo
1391 1405 abort: no such help topic: internals.foo
1392 1406 (try 'hg help --keyword foo')
1393 1407 [10]
1394 1408
1395 1409 test advanced, deprecated and experimental options are hidden in command help
1396 1410 $ hg help debugoptADV
1397 1411 hg debugoptADV
1398 1412
1399 1413 (no help text available)
1400 1414
1401 1415 options:
1402 1416
1403 1417 (some details hidden, use --verbose to show complete help)
1404 1418 $ hg help debugoptDEP
1405 1419 hg debugoptDEP
1406 1420
1407 1421 (no help text available)
1408 1422
1409 1423 options:
1410 1424
1411 1425 (some details hidden, use --verbose to show complete help)
1412 1426
1413 1427 $ hg help debugoptEXP
1414 1428 hg debugoptEXP
1415 1429
1416 1430 (no help text available)
1417 1431
1418 1432 options:
1419 1433
1420 1434 (some details hidden, use --verbose to show complete help)
1421 1435
1422 1436 test advanced, deprecated and experimental options are shown with -v
1423 1437 $ hg help -v debugoptADV | grep aopt
1424 1438 --aopt option is (ADVANCED)
1425 1439 $ hg help -v debugoptDEP | grep dopt
1426 1440 --dopt option is (DEPRECATED)
1427 1441 $ hg help -v debugoptEXP | grep eopt
1428 1442 --eopt option is (EXPERIMENTAL)
1429 1443
1430 1444 #if gettext
1431 1445 test deprecated option is hidden with translation with untranslated description
1432 1446 (use many globy for not failing on changed transaction)
1433 1447 $ LANGUAGE=sv hg help debugoptDEP
1434 1448 hg debugoptDEP
1435 1449
1436 1450 (*) (glob)
1437 1451
1438 1452 options:
1439 1453
1440 1454 (some details hidden, use --verbose to show complete help)
1441 1455 #endif
1442 1456
1443 1457 Test commands that collide with topics (issue4240)
1444 1458
1445 1459 $ hg config -hq
1446 1460 hg config [-u] [NAME]...
1447 1461
1448 1462 show combined config settings from all hgrc files
1449 1463 $ hg showconfig -hq
1450 1464 hg config [-u] [NAME]...
1451 1465
1452 1466 show combined config settings from all hgrc files
1453 1467
1454 1468 Test a help topic
1455 1469
1456 1470 $ hg help dates
1457 1471 Date Formats
1458 1472 """"""""""""
1459 1473
1460 1474 Some commands allow the user to specify a date, e.g.:
1461 1475
1462 1476 - backout, commit, import, tag: Specify the commit date.
1463 1477 - log, revert, update: Select revision(s) by date.
1464 1478
1465 1479 Many date formats are valid. Here are some examples:
1466 1480
1467 1481 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1468 1482 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1469 1483 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1470 1484 - "Dec 6" (midnight)
1471 1485 - "13:18" (today assumed)
1472 1486 - "3:39" (3:39AM assumed)
1473 1487 - "3:39pm" (15:39)
1474 1488 - "2006-12-06 13:18:29" (ISO 8601 format)
1475 1489 - "2006-12-6 13:18"
1476 1490 - "2006-12-6"
1477 1491 - "12-6"
1478 1492 - "12/6"
1479 1493 - "12/6/6" (Dec 6 2006)
1480 1494 - "today" (midnight)
1481 1495 - "yesterday" (midnight)
1482 1496 - "now" - right now
1483 1497
1484 1498 Lastly, there is Mercurial's internal format:
1485 1499
1486 1500 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1487 1501
1488 1502 This is the internal representation format for dates. The first number is
1489 1503 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1490 1504 is the offset of the local timezone, in seconds west of UTC (negative if
1491 1505 the timezone is east of UTC).
1492 1506
1493 1507 The log command also accepts date ranges:
1494 1508
1495 1509 - "<DATE" - at or before a given date/time
1496 1510 - ">DATE" - on or after a given date/time
1497 1511 - "DATE to DATE" - a date range, inclusive
1498 1512 - "-DAYS" - within a given number of days from today
1499 1513
1500 1514 Test repeated config section name
1501 1515
1502 1516 $ hg help config.host
1503 1517 "http_proxy.host"
1504 1518 Host name and (optional) port of the proxy server, for example
1505 1519 "myproxy:8000".
1506 1520
1507 1521 "smtp.host"
1508 1522 Host name of mail server, e.g. "mail.example.com".
1509 1523
1510 1524
1511 1525 Test section name with dot
1512 1526
1513 1527 $ hg help config.ui.username
1514 1528 "ui.username"
1515 1529 The committer of a changeset created when running "commit". Typically
1516 1530 a person's name and email address, e.g. "Fred Widget
1517 1531 <fred@example.com>". Environment variables in the username are
1518 1532 expanded.
1519 1533
1520 1534 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1521 1535 empty, e.g. if the system admin set "username =" in the system hgrc,
1522 1536 it has to be specified manually or in a different hgrc file)
1523 1537
1524 1538
1525 1539 $ hg help config.annotate.git
1526 1540 abort: help section not found: config.annotate.git
1527 1541 [10]
1528 1542
1529 1543 $ hg help config.update.check
1530 1544 "commands.update.check"
1531 1545 Determines what level of checking 'hg update' will perform before
1532 1546 moving to a destination revision. Valid values are "abort", "none",
1533 1547 "linear", and "noconflict".
1534 1548
1535 1549 - "abort" always fails if the working directory has uncommitted
1536 1550 changes.
1537 1551 - "none" performs no checking, and may result in a merge with
1538 1552 uncommitted changes.
1539 1553 - "linear" allows any update as long as it follows a straight line in
1540 1554 the revision history, and may trigger a merge with uncommitted
1541 1555 changes.
1542 1556 - "noconflict" will allow any update which would not trigger a merge
1543 1557 with uncommitted changes, if any are present.
1544 1558
1545 1559 (default: "linear")
1546 1560
1547 1561
1548 1562 $ hg help config.commands.update.check
1549 1563 "commands.update.check"
1550 1564 Determines what level of checking 'hg update' will perform before
1551 1565 moving to a destination revision. Valid values are "abort", "none",
1552 1566 "linear", and "noconflict".
1553 1567
1554 1568 - "abort" always fails if the working directory has uncommitted
1555 1569 changes.
1556 1570 - "none" performs no checking, and may result in a merge with
1557 1571 uncommitted changes.
1558 1572 - "linear" allows any update as long as it follows a straight line in
1559 1573 the revision history, and may trigger a merge with uncommitted
1560 1574 changes.
1561 1575 - "noconflict" will allow any update which would not trigger a merge
1562 1576 with uncommitted changes, if any are present.
1563 1577
1564 1578 (default: "linear")
1565 1579
1566 1580
1567 1581 $ hg help config.ommands.update.check
1568 1582 abort: help section not found: config.ommands.update.check
1569 1583 [10]
1570 1584
1571 1585 Unrelated trailing paragraphs shouldn't be included
1572 1586
1573 1587 $ hg help config.extramsg | grep '^$'
1574 1588
1575 1589
1576 1590 Test capitalized section name
1577 1591
1578 1592 $ hg help scripting.HGPLAIN > /dev/null
1579 1593
1580 1594 Help subsection:
1581 1595
1582 1596 $ hg help config.charsets |grep "Email example:" > /dev/null
1583 1597 [1]
1584 1598
1585 1599 Show nested definitions
1586 1600 ("profiling.type"[break]"ls"[break]"stat"[break])
1587 1601
1588 1602 $ hg help config.type | grep -E '^$'|wc -l
1589 1603 \s*3 (re)
1590 1604
1591 1605 $ hg help config.profiling.type.ls
1592 1606 "profiling.type.ls"
1593 1607 Use Python's built-in instrumenting profiler. This profiler works on
1594 1608 all platforms, but each line number it reports is the first line of
1595 1609 a function. This restriction makes it difficult to identify the
1596 1610 expensive parts of a non-trivial function.
1597 1611
1598 1612
1599 1613 Separate sections from subsections
1600 1614
1601 1615 $ hg help config.format | grep -E '^ ("|-)|^\s*$' | uniq
1602 1616 "format"
1603 1617 --------
1604 1618
1605 1619 "usegeneraldelta"
1606 1620
1607 1621 "dotencode"
1608 1622
1609 1623 "usefncache"
1610 1624
1611 1625 "use-dirstate-v2"
1612 1626
1613 1627 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories"
1614 1628
1615 1629 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet"
1616 1630
1617 1631 "use-dirstate-tracked-hint"
1618 1632
1619 1633 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories"
1620 1634
1621 1635 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet"
1622 1636
1623 1637 "use-persistent-nodemap"
1624 1638
1625 1639 "use-share-safe"
1626 1640
1627 1641 "use-share-safe.automatic-upgrade-of-mismatching-repositories"
1628 1642
1629 1643 "use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet"
1630 1644
1631 1645 "usestore"
1632 1646
1633 1647 "sparse-revlog"
1634 1648
1635 1649 "revlog-compression"
1636 1650
1637 1651 "bookmarks-in-store"
1638 1652
1639 1653 "profiling"
1640 1654 -----------
1641 1655
1642 1656 "format"
1643 1657
1644 1658 "progress"
1645 1659 ----------
1646 1660
1647 1661 "format"
1648 1662
1649 1663
1650 1664 Last item in help config.*:
1651 1665
1652 1666 $ hg help config.`hg help config|grep '^ "'| \
1653 1667 > tail -1|sed 's![ "]*!!g'`| \
1654 1668 > grep 'hg help -c config' > /dev/null
1655 1669 [1]
1656 1670
1657 1671 note to use help -c for general hg help config:
1658 1672
1659 1673 $ hg help config |grep 'hg help -c config' > /dev/null
1660 1674
1661 1675 Test templating help
1662 1676
1663 1677 $ hg help templating | grep -E '(desc|diffstat|firstline|nonempty) '
1664 1678 desc String. The text of the changeset description.
1665 1679 diffstat String. Statistics of changes with the following format:
1666 1680 firstline Any text. Returns the first line of text.
1667 1681 nonempty Any text. Returns '(none)' if the string is empty.
1668 1682
1669 1683 Test deprecated items
1670 1684
1671 1685 $ hg help -v templating | grep currentbookmark
1672 1686 currentbookmark
1673 1687 $ hg help templating | (grep currentbookmark || true)
1674 1688
1675 1689 Test help hooks
1676 1690
1677 1691 $ cat > helphook1.py <<EOF
1678 1692 > from mercurial import help
1679 1693 >
1680 1694 > def rewrite(ui, topic, doc):
1681 1695 > return doc + b'\nhelphook1\n'
1682 1696 >
1683 1697 > def extsetup(ui):
1684 1698 > help.addtopichook(b'revisions', rewrite)
1685 1699 > EOF
1686 1700 $ cat > helphook2.py <<EOF
1687 1701 > from mercurial import help
1688 1702 >
1689 1703 > def rewrite(ui, topic, doc):
1690 1704 > return doc + b'\nhelphook2\n'
1691 1705 >
1692 1706 > def extsetup(ui):
1693 1707 > help.addtopichook(b'revisions', rewrite)
1694 1708 > EOF
1695 1709 $ echo '[extensions]' >> $HGRCPATH
1696 1710 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1697 1711 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1698 1712 $ hg help revsets | grep helphook
1699 1713 helphook1
1700 1714 helphook2
1701 1715
1702 1716 help -c should only show debug --debug
1703 1717
1704 1718 $ hg help -c --debug|grep -E debug|wc -l|grep -E '^\s*0\s*$'
1705 1719 [1]
1706 1720
1707 1721 help -c should only show deprecated for -v
1708 1722
1709 1723 $ hg help -c -v|grep -E DEPRECATED|wc -l|grep -E '^\s*0\s*$'
1710 1724 [1]
1711 1725
1712 1726 Test -s / --system
1713 1727
1714 1728 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1715 1729 > wc -l | sed -e 's/ //g'
1716 1730 0
1717 1731 $ hg help config.files --system unix | grep 'USER' | \
1718 1732 > wc -l | sed -e 's/ //g'
1719 1733 0
1720 1734
1721 1735 Test -e / -c / -k combinations
1722 1736
1723 1737 $ hg help -c|grep -E '^[A-Z].*:|^ debug'
1724 1738 Commands:
1725 1739 $ hg help -e|grep -E '^[A-Z].*:|^ debug'
1726 1740 Extensions:
1727 1741 $ hg help -k|grep -E '^[A-Z].*:|^ debug'
1728 1742 Topics:
1729 1743 Commands:
1730 1744 Extensions:
1731 1745 Extension Commands:
1732 1746 $ hg help -c schemes
1733 1747 abort: no such help topic: schemes
1734 1748 (try 'hg help --keyword schemes')
1735 1749 [10]
1736 1750 $ hg help -e schemes |head -1
1737 1751 schemes extension - extend schemes with shortcuts to repository swarms
1738 1752 $ hg help -c -k dates |grep -E '^(Topics|Extensions|Commands):'
1739 1753 Commands:
1740 1754 $ hg help -e -k a |grep -E '^(Topics|Extensions|Commands):'
1741 1755 Extensions:
1742 1756 $ hg help -e -c -k date |grep -E '^(Topics|Extensions|Commands):'
1743 1757 Extensions:
1744 1758 Commands:
1745 1759 $ hg help -c commit > /dev/null
1746 1760 $ hg help -e -c commit > /dev/null
1747 1761 $ hg help -e commit
1748 1762 abort: no such help topic: commit
1749 1763 (try 'hg help --keyword commit')
1750 1764 [10]
1751 1765
1752 1766 Test keyword search help
1753 1767
1754 1768 $ cat > prefixedname.py <<EOF
1755 1769 > '''matched against word "clone"
1756 1770 > '''
1757 1771 > EOF
1758 1772 $ echo '[extensions]' >> $HGRCPATH
1759 1773 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1760 1774 $ hg help -k clone
1761 1775 Topics:
1762 1776
1763 1777 config Configuration Files
1764 1778 extensions Using Additional Features
1765 1779 glossary Glossary
1766 1780 phases Working with Phases
1767 1781 subrepos Subrepositories
1768 1782 urls URL Paths
1769 1783
1770 1784 Commands:
1771 1785
1772 1786 bookmarks create a new bookmark or list existing bookmarks
1773 1787 clone make a copy of an existing repository
1774 1788 paths show aliases for remote repositories
1775 1789 pull pull changes from the specified source
1776 1790 update update working directory (or switch revisions)
1777 1791
1778 1792 Extensions:
1779 1793
1780 1794 clonebundles advertise pre-generated bundles to seed clones
1781 1795 narrow create clones which fetch history data for subset of files
1782 1796 (EXPERIMENTAL)
1783 1797 prefixedname matched against word "clone"
1784 1798 relink recreates hardlinks between repository clones
1785 1799
1786 1800 Extension Commands:
1787 1801
1788 1802 admin::clone-bundles-clear remove existing clone bundle caches
1789 1803 admin::clone-bundles-refresh generate clone bundles according to the
1790 1804 configuration
1791 1805 qclone clone main and patch repository at same time
1792 1806
1793 1807 Test unfound topic
1794 1808
1795 1809 $ hg help nonexistingtopicthatwillneverexisteverever
1796 1810 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1797 1811 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1798 1812 [10]
1799 1813
1800 1814 Test unfound keyword
1801 1815
1802 1816 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1803 1817 abort: no matches
1804 1818 (try 'hg help' for a list of topics)
1805 1819 [10]
1806 1820
1807 1821 Test omit indicating for help
1808 1822
1809 1823 $ cat > addverboseitems.py <<EOF
1810 1824 > r'''extension to test omit indicating.
1811 1825 >
1812 1826 > This paragraph is never omitted (for extension)
1813 1827 >
1814 1828 > .. container:: verbose
1815 1829 >
1816 1830 > This paragraph is omitted,
1817 1831 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1818 1832 >
1819 1833 > This paragraph is never omitted, too (for extension)
1820 1834 > '''
1821 1835 > from mercurial import commands, help
1822 1836 > testtopic = br"""This paragraph is never omitted (for topic).
1823 1837 >
1824 1838 > .. container:: verbose
1825 1839 >
1826 1840 > This paragraph is omitted,
1827 1841 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1828 1842 >
1829 1843 > This paragraph is never omitted, too (for topic)
1830 1844 > """
1831 1845 > def extsetup(ui):
1832 1846 > help.helptable.append(([b"topic-containing-verbose"],
1833 1847 > b"This is the topic to test omit indicating.",
1834 1848 > lambda ui: testtopic))
1835 1849 > EOF
1836 1850 $ echo '[extensions]' >> $HGRCPATH
1837 1851 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1838 1852 $ hg help addverboseitems
1839 1853 addverboseitems extension - extension to test omit indicating.
1840 1854
1841 1855 This paragraph is never omitted (for extension)
1842 1856
1843 1857 This paragraph is never omitted, too (for extension)
1844 1858
1845 1859 (some details hidden, use --verbose to show complete help)
1846 1860
1847 1861 no commands defined
1848 1862 $ hg help -v addverboseitems
1849 1863 addverboseitems extension - extension to test omit indicating.
1850 1864
1851 1865 This paragraph is never omitted (for extension)
1852 1866
1853 1867 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1854 1868 extension)
1855 1869
1856 1870 This paragraph is never omitted, too (for extension)
1857 1871
1858 1872 no commands defined
1859 1873 $ hg help topic-containing-verbose
1860 1874 This is the topic to test omit indicating.
1861 1875 """"""""""""""""""""""""""""""""""""""""""
1862 1876
1863 1877 This paragraph is never omitted (for topic).
1864 1878
1865 1879 This paragraph is never omitted, too (for topic)
1866 1880
1867 1881 (some details hidden, use --verbose to show complete help)
1868 1882 $ hg help -v topic-containing-verbose
1869 1883 This is the topic to test omit indicating.
1870 1884 """"""""""""""""""""""""""""""""""""""""""
1871 1885
1872 1886 This paragraph is never omitted (for topic).
1873 1887
1874 1888 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1875 1889 topic)
1876 1890
1877 1891 This paragraph is never omitted, too (for topic)
1878 1892
1879 1893 Test section lookup
1880 1894
1881 1895 $ hg help revset.merge
1882 1896 "merge()"
1883 1897 Changeset is a merge changeset.
1884 1898
1885 1899 $ hg help glossary.dag
1886 1900 DAG
1887 1901 The repository of changesets of a distributed version control system
1888 1902 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1889 1903 of nodes and edges, where nodes correspond to changesets and edges
1890 1904 imply a parent -> child relation. This graph can be visualized by
1891 1905 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1892 1906 limited by the requirement for children to have at most two parents.
1893 1907
1894 1908
1895 1909 $ hg help hgrc.paths
1896 1910 "paths"
1897 1911 -------
1898 1912
1899 1913 Assigns symbolic names and behavior to repositories.
1900 1914
1901 1915 Options are symbolic names defining the URL or directory that is the
1902 1916 location of the repository. Example:
1903 1917
1904 1918 [paths]
1905 1919 my_server = https://example.com/my_repo
1906 1920 local_path = /home/me/repo
1907 1921
1908 1922 These symbolic names can be used from the command line. To pull from
1909 1923 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1910 1924 local_path'. You can check 'hg help urls' for details about valid URLs.
1911 1925
1912 1926 Options containing colons (":") denote sub-options that can influence
1913 1927 behavior for that specific path. Example:
1914 1928
1915 1929 [paths]
1916 1930 my_server = https://example.com/my_path
1917 1931 my_server:pushurl = ssh://example.com/my_path
1918 1932
1919 1933 Paths using the 'path://otherpath' scheme will inherit the sub-options
1920 1934 value from the path they point to.
1921 1935
1922 1936 The following sub-options can be defined:
1923 1937
1924 1938 "multi-urls"
1925 1939 A boolean option. When enabled the value of the '[paths]' entry will be
1926 1940 parsed as a list and the alias will resolve to multiple destination. If
1927 1941 some of the list entry use the 'path://' syntax, the suboption will be
1928 1942 inherited individually.
1929 1943
1930 1944 "pushurl"
1931 1945 The URL to use for push operations. If not defined, the location
1932 1946 defined by the path's main entry is used.
1933 1947
1934 1948 "pushrev"
1935 1949 A revset defining which revisions to push by default.
1936 1950
1937 1951 When 'hg push' is executed without a "-r" argument, the revset defined
1938 1952 by this sub-option is evaluated to determine what to push.
1939 1953
1940 1954 For example, a value of "." will push the working directory's revision
1941 1955 by default.
1942 1956
1943 1957 Revsets specifying bookmarks will not result in the bookmark being
1944 1958 pushed.
1945 1959
1946 1960 "bookmarks.mode"
1947 1961 How bookmark will be dealt during the exchange. It support the following
1948 1962 value
1949 1963
1950 1964 - "default": the default behavior, local and remote bookmarks are
1951 1965 "merged" on push/pull.
1952 1966 - "mirror": when pulling, replace local bookmarks by remote bookmarks.
1953 1967 This is useful to replicate a repository, or as an optimization.
1954 1968 - "ignore": ignore bookmarks during exchange. (This currently only
1955 1969 affect pulling)
1956 1970
1957 1971 The following special named paths exist:
1958 1972
1959 1973 "default"
1960 1974 The URL or directory to use when no source or remote is specified.
1961 1975
1962 1976 'hg clone' will automatically define this path to the location the
1963 1977 repository was cloned from.
1964 1978
1965 1979 "default-push"
1966 1980 (deprecated) The URL or directory for the default 'hg push' location.
1967 1981 "default:pushurl" should be used instead.
1968 1982
1969 1983 $ hg help glossary.mcguffin
1970 1984 abort: help section not found: glossary.mcguffin
1971 1985 [10]
1972 1986
1973 1987 $ hg help glossary.mc.guffin
1974 1988 abort: help section not found: glossary.mc.guffin
1975 1989 [10]
1976 1990
1977 1991 $ hg help template.files
1978 1992 files List of strings. All files modified, added, or removed by
1979 1993 this changeset.
1980 1994 files(pattern)
1981 1995 All files of the current changeset matching the pattern. See
1982 1996 'hg help patterns'.
1983 1997
1984 1998 Test section lookup by translated message
1985 1999
1986 2000 str.lower() instead of encoding.lower(str) on translated message might
1987 2001 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1988 2002 as the second or later byte of multi-byte character.
1989 2003
1990 2004 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1991 2005 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1992 2006 replacement makes message meaningless.
1993 2007
1994 2008 This tests that section lookup by translated string isn't broken by
1995 2009 such str.lower().
1996 2010
1997 2011 $ "$PYTHON" <<EOF
1998 2012 > def escape(s):
1999 2013 > return b''.join(br'\\u%x' % ord(uc) for uc in s.decode('cp932'))
2000 2014 > # translation of "record" in ja_JP.cp932
2001 2015 > upper = b"\x8bL\x98^"
2002 2016 > # str.lower()-ed section name should be treated as different one
2003 2017 > lower = b"\x8bl\x98^"
2004 2018 > with open('ambiguous.py', 'wb') as fp:
2005 2019 > fp.write(b"""# ambiguous section names in ja_JP.cp932
2006 2020 > u'''summary of extension
2007 2021 >
2008 2022 > %s
2009 2023 > ----
2010 2024 >
2011 2025 > Upper name should show only this message
2012 2026 >
2013 2027 > %s
2014 2028 > ----
2015 2029 >
2016 2030 > Lower name should show only this message
2017 2031 >
2018 2032 > subsequent section
2019 2033 > ------------------
2020 2034 >
2021 2035 > This should be hidden at 'hg help ambiguous' with section name.
2022 2036 > '''
2023 2037 > """ % (escape(upper), escape(lower)))
2024 2038 > EOF
2025 2039
2026 2040 $ cat >> $HGRCPATH <<EOF
2027 2041 > [extensions]
2028 2042 > ambiguous = ./ambiguous.py
2029 2043 > EOF
2030 2044
2031 2045 $ "$PYTHON" <<EOF | sh
2032 2046 > from mercurial.utils import procutil
2033 2047 > upper = b"\x8bL\x98^"
2034 2048 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
2035 2049 > EOF
2036 2050 \x8bL\x98^ (esc)
2037 2051 ----
2038 2052
2039 2053 Upper name should show only this message
2040 2054
2041 2055
2042 2056 $ "$PYTHON" <<EOF | sh
2043 2057 > from mercurial.utils import procutil
2044 2058 > lower = b"\x8bl\x98^"
2045 2059 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
2046 2060 > EOF
2047 2061 \x8bl\x98^ (esc)
2048 2062 ----
2049 2063
2050 2064 Lower name should show only this message
2051 2065
2052 2066
2053 2067 $ cat >> $HGRCPATH <<EOF
2054 2068 > [extensions]
2055 2069 > ambiguous = !
2056 2070 > EOF
2057 2071
2058 2072 Show help content of disabled extensions
2059 2073
2060 2074 $ cat >> $HGRCPATH <<EOF
2061 2075 > [extensions]
2062 2076 > ambiguous = !./ambiguous.py
2063 2077 > EOF
2064 2078 $ hg help -e ambiguous
2065 2079 ambiguous extension - (no help text available)
2066 2080
2067 2081 (use 'hg help extensions' for information on enabling extensions)
2068 2082
2069 2083 Test dynamic list of merge tools only shows up once
2070 2084 $ hg help merge-tools
2071 2085 Merge Tools
2072 2086 """""""""""
2073 2087
2074 2088 To merge files Mercurial uses merge tools.
2075 2089
2076 2090 A merge tool combines two different versions of a file into a merged file.
2077 2091 Merge tools are given the two files and the greatest common ancestor of
2078 2092 the two file versions, so they can determine the changes made on both
2079 2093 branches.
2080 2094
2081 2095 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
2082 2096 backout' and in several extensions.
2083 2097
2084 2098 Usually, the merge tool tries to automatically reconcile the files by
2085 2099 combining all non-overlapping changes that occurred separately in the two
2086 2100 different evolutions of the same initial base file. Furthermore, some
2087 2101 interactive merge programs make it easier to manually resolve conflicting
2088 2102 merges, either in a graphical way, or by inserting some conflict markers.
2089 2103 Mercurial does not include any interactive merge programs but relies on
2090 2104 external tools for that.
2091 2105
2092 2106 Available merge tools
2093 2107 =====================
2094 2108
2095 2109 External merge tools and their properties are configured in the merge-
2096 2110 tools configuration section - see hgrc(5) - but they can often just be
2097 2111 named by their executable.
2098 2112
2099 2113 A merge tool is generally usable if its executable can be found on the
2100 2114 system and if it can handle the merge. The executable is found if it is an
2101 2115 absolute or relative executable path or the name of an application in the
2102 2116 executable search path. The tool is assumed to be able to handle the merge
2103 2117 if it can handle symlinks if the file is a symlink, if it can handle
2104 2118 binary files if the file is binary, and if a GUI is available if the tool
2105 2119 requires a GUI.
2106 2120
2107 2121 There are some internal merge tools which can be used. The internal merge
2108 2122 tools are:
2109 2123
2110 2124 ":dump"
2111 2125 Creates three versions of the files to merge, containing the contents of
2112 2126 local, other and base. These files can then be used to perform a merge
2113 2127 manually. If the file to be merged is named "a.txt", these files will
2114 2128 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
2115 2129 they will be placed in the same directory as "a.txt".
2116 2130
2117 2131 This implies premerge. Therefore, files aren't dumped, if premerge runs
2118 2132 successfully. Use :forcedump to forcibly write files out.
2119 2133
2120 2134 (actual capabilities: binary, symlink)
2121 2135
2122 2136 ":fail"
2123 2137 Rather than attempting to merge files that were modified on both
2124 2138 branches, it marks them as unresolved. The resolve command must be used
2125 2139 to resolve these conflicts.
2126 2140
2127 2141 (actual capabilities: binary, symlink)
2128 2142
2129 2143 ":forcedump"
2130 2144 Creates three versions of the files as same as :dump, but omits
2131 2145 premerge.
2132 2146
2133 2147 (actual capabilities: binary, symlink)
2134 2148
2135 2149 ":local"
2136 2150 Uses the local 'p1()' version of files as the merged version.
2137 2151
2138 2152 (actual capabilities: binary, symlink)
2139 2153
2140 2154 ":merge"
2141 2155 Uses the internal non-interactive simple merge algorithm for merging
2142 2156 files. It will fail if there are any conflicts and leave markers in the
2143 2157 partially merged file. Markers will have two sections, one for each side
2144 2158 of merge.
2145 2159
2146 2160 ":merge-local"
2147 2161 Like :merge, but resolve all conflicts non-interactively in favor of the
2148 2162 local 'p1()' changes.
2149 2163
2150 2164 ":merge-other"
2151 2165 Like :merge, but resolve all conflicts non-interactively in favor of the
2152 2166 other 'p2()' changes.
2153 2167
2154 2168 ":merge3"
2155 2169 Uses the internal non-interactive simple merge algorithm for merging
2156 2170 files. It will fail if there are any conflicts and leave markers in the
2157 2171 partially merged file. Marker will have three sections, one from each
2158 2172 side of the merge and one for the base content.
2159 2173
2160 2174 ":mergediff"
2161 2175 Uses the internal non-interactive simple merge algorithm for merging
2162 2176 files. It will fail if there are any conflicts and leave markers in the
2163 2177 partially merged file. The marker will have two sections, one with the
2164 2178 content from one side of the merge, and one with a diff from the base
2165 2179 content to the content on the other side. (experimental)
2166 2180
2167 2181 ":other"
2168 2182 Uses the other 'p2()' version of files as the merged version.
2169 2183
2170 2184 (actual capabilities: binary, symlink)
2171 2185
2172 2186 ":prompt"
2173 2187 Asks the user which of the local 'p1()' or the other 'p2()' version to
2174 2188 keep as the merged version.
2175 2189
2176 2190 (actual capabilities: binary, symlink)
2177 2191
2178 2192 ":tagmerge"
2179 2193 Uses the internal tag merge algorithm (experimental).
2180 2194
2181 2195 ":union"
2182 2196 Uses the internal non-interactive simple merge algorithm for merging
2183 2197 files. It will use both local and other sides for conflict regions by
2184 2198 adding local on top of other. No markers are inserted.
2185 2199
2186 2200 ":union-other-first"
2187 2201 Like :union, but add other on top of local.
2188 2202
2189 2203 Internal tools are always available and do not require a GUI but will by
2190 2204 default not handle symlinks or binary files. See next section for detail
2191 2205 about "actual capabilities" described above.
2192 2206
2193 2207 Choosing a merge tool
2194 2208 =====================
2195 2209
2196 2210 Mercurial uses these rules when deciding which merge tool to use:
2197 2211
2198 2212 1. If a tool has been specified with the --tool option to merge or
2199 2213 resolve, it is used. If it is the name of a tool in the merge-tools
2200 2214 configuration, its configuration is used. Otherwise the specified tool
2201 2215 must be executable by the shell.
2202 2216 2. If the "HGMERGE" environment variable is present, its value is used and
2203 2217 must be executable by the shell.
2204 2218 3. If the filename of the file to be merged matches any of the patterns in
2205 2219 the merge-patterns configuration section, the first usable merge tool
2206 2220 corresponding to a matching pattern is used.
2207 2221 4. If ui.merge is set it will be considered next. If the value is not the
2208 2222 name of a configured tool, the specified value is used and must be
2209 2223 executable by the shell. Otherwise the named tool is used if it is
2210 2224 usable.
2211 2225 5. If any usable merge tools are present in the merge-tools configuration
2212 2226 section, the one with the highest priority is used.
2213 2227 6. If a program named "hgmerge" can be found on the system, it is used -
2214 2228 but it will by default not be used for symlinks and binary files.
2215 2229 7. If the file to be merged is not binary and is not a symlink, then
2216 2230 internal ":merge" is used.
2217 2231 8. Otherwise, ":prompt" is used.
2218 2232
2219 2233 For historical reason, Mercurial treats merge tools as below while
2220 2234 examining rules above.
2221 2235
2222 2236 step specified via binary symlink
2223 2237 ----------------------------------
2224 2238 1. --tool o/o o/o
2225 2239 2. HGMERGE o/o o/o
2226 2240 3. merge-patterns o/o(*) x/?(*)
2227 2241 4. ui.merge x/?(*) x/?(*)
2228 2242
2229 2243 Each capability column indicates Mercurial behavior for internal/external
2230 2244 merge tools at examining each rule.
2231 2245
2232 2246 - "o": "assume that a tool has capability"
2233 2247 - "x": "assume that a tool does not have capability"
2234 2248 - "?": "check actual capability of a tool"
2235 2249
2236 2250 If "merge.strict-capability-check" configuration is true, Mercurial checks
2237 2251 capabilities of merge tools strictly in (*) cases above (= each capability
2238 2252 column becomes "?/?"). It is false by default for backward compatibility.
2239 2253
2240 2254 Note:
2241 2255 After selecting a merge program, Mercurial will by default attempt to
2242 2256 merge the files using a simple merge algorithm first. Only if it
2243 2257 doesn't succeed because of conflicting changes will Mercurial actually
2244 2258 execute the merge program. Whether to use the simple merge algorithm
2245 2259 first can be controlled by the premerge setting of the merge tool.
2246 2260 Premerge is enabled by default unless the file is binary or a symlink.
2247 2261
2248 2262 See the merge-tools and ui sections of hgrc(5) for details on the
2249 2263 configuration of merge tools.
2250 2264
2251 2265 Compression engines listed in `hg help bundlespec`
2252 2266
2253 2267 $ hg help bundlespec | grep gzip
2254 2268 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2255 2269 An algorithm that produces smaller bundles than "gzip".
2256 2270 This engine will likely produce smaller bundles than "gzip" but will be
2257 2271 "gzip"
2258 2272 better compression than "gzip". It also frequently yields better (?)
2259 2273
2260 2274 Test usage of section marks in help documents
2261 2275
2262 2276 $ cd "$TESTDIR"/../doc
2263 2277 $ "$PYTHON" check-seclevel.py
2264 2278 $ cd $TESTTMP
2265 2279
2266 2280 #if serve
2267 2281
2268 2282 Test the help pages in hgweb.
2269 2283
2270 2284 Dish up an empty repo; serve it cold.
2271 2285
2272 2286 $ hg init "$TESTTMP/test"
2273 2287 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2274 2288 $ cat hg.pid >> $DAEMON_PIDS
2275 2289
2276 2290 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2277 2291 200 Script output follows
2278 2292
2279 2293 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2280 2294 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2281 2295 <head>
2282 2296 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2283 2297 <meta name="robots" content="index, nofollow" />
2284 2298 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2285 2299 <script type="text/javascript" src="/static/mercurial.js"></script>
2286 2300
2287 2301 <title>Help: Index</title>
2288 2302 </head>
2289 2303 <body>
2290 2304
2291 2305 <div class="container">
2292 2306 <div class="menu">
2293 2307 <div class="logo">
2294 2308 <a href="https://mercurial-scm.org/">
2295 2309 <img src="/static/hglogo.png" alt="mercurial" /></a>
2296 2310 </div>
2297 2311 <ul>
2298 2312 <li><a href="/shortlog">log</a></li>
2299 2313 <li><a href="/graph">graph</a></li>
2300 2314 <li><a href="/tags">tags</a></li>
2301 2315 <li><a href="/bookmarks">bookmarks</a></li>
2302 2316 <li><a href="/branches">branches</a></li>
2303 2317 </ul>
2304 2318 <ul>
2305 2319 <li class="active">help</li>
2306 2320 </ul>
2307 2321 </div>
2308 2322
2309 2323 <div class="main">
2310 2324 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2311 2325
2312 2326 <form class="search" action="/log">
2313 2327
2314 2328 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2315 2329 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2316 2330 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2317 2331 </form>
2318 2332 <table class="bigtable">
2319 2333 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2320 2334
2321 2335 <tr><td>
2322 2336 <a href="/help/bundlespec">
2323 2337 bundlespec
2324 2338 </a>
2325 2339 </td><td>
2326 2340 Bundle File Formats
2327 2341 </td></tr>
2328 2342 <tr><td>
2329 2343 <a href="/help/color">
2330 2344 color
2331 2345 </a>
2332 2346 </td><td>
2333 2347 Colorizing Outputs
2334 2348 </td></tr>
2335 2349 <tr><td>
2336 2350 <a href="/help/config">
2337 2351 config
2338 2352 </a>
2339 2353 </td><td>
2340 2354 Configuration Files
2341 2355 </td></tr>
2342 2356 <tr><td>
2343 2357 <a href="/help/dates">
2344 2358 dates
2345 2359 </a>
2346 2360 </td><td>
2347 2361 Date Formats
2348 2362 </td></tr>
2349 2363 <tr><td>
2350 2364 <a href="/help/deprecated">
2351 2365 deprecated
2352 2366 </a>
2353 2367 </td><td>
2354 2368 Deprecated Features
2355 2369 </td></tr>
2356 2370 <tr><td>
2357 2371 <a href="/help/diffs">
2358 2372 diffs
2359 2373 </a>
2360 2374 </td><td>
2361 2375 Diff Formats
2362 2376 </td></tr>
2363 2377 <tr><td>
2364 2378 <a href="/help/environment">
2365 2379 environment
2366 2380 </a>
2367 2381 </td><td>
2368 2382 Environment Variables
2369 2383 </td></tr>
2370 2384 <tr><td>
2371 2385 <a href="/help/evolution">
2372 2386 evolution
2373 2387 </a>
2374 2388 </td><td>
2375 2389 Safely rewriting history (EXPERIMENTAL)
2376 2390 </td></tr>
2377 2391 <tr><td>
2378 2392 <a href="/help/extensions">
2379 2393 extensions
2380 2394 </a>
2381 2395 </td><td>
2382 2396 Using Additional Features
2383 2397 </td></tr>
2384 2398 <tr><td>
2385 2399 <a href="/help/filesets">
2386 2400 filesets
2387 2401 </a>
2388 2402 </td><td>
2389 2403 Specifying File Sets
2390 2404 </td></tr>
2391 2405 <tr><td>
2392 2406 <a href="/help/flags">
2393 2407 flags
2394 2408 </a>
2395 2409 </td><td>
2396 2410 Command-line flags
2397 2411 </td></tr>
2398 2412 <tr><td>
2399 2413 <a href="/help/glossary">
2400 2414 glossary
2401 2415 </a>
2402 2416 </td><td>
2403 2417 Glossary
2404 2418 </td></tr>
2405 2419 <tr><td>
2406 2420 <a href="/help/hgignore">
2407 2421 hgignore
2408 2422 </a>
2409 2423 </td><td>
2410 2424 Syntax for Mercurial Ignore Files
2411 2425 </td></tr>
2412 2426 <tr><td>
2413 2427 <a href="/help/hgweb">
2414 2428 hgweb
2415 2429 </a>
2416 2430 </td><td>
2417 2431 Configuring hgweb
2418 2432 </td></tr>
2419 2433 <tr><td>
2420 2434 <a href="/help/internals">
2421 2435 internals
2422 2436 </a>
2423 2437 </td><td>
2424 2438 Technical implementation topics
2425 2439 </td></tr>
2426 2440 <tr><td>
2427 2441 <a href="/help/merge-tools">
2428 2442 merge-tools
2429 2443 </a>
2430 2444 </td><td>
2431 2445 Merge Tools
2432 2446 </td></tr>
2433 2447 <tr><td>
2434 2448 <a href="/help/pager">
2435 2449 pager
2436 2450 </a>
2437 2451 </td><td>
2438 2452 Pager Support
2439 2453 </td></tr>
2440 2454 <tr><td>
2441 2455 <a href="/help/patterns">
2442 2456 patterns
2443 2457 </a>
2444 2458 </td><td>
2445 2459 File Name Patterns
2446 2460 </td></tr>
2447 2461 <tr><td>
2448 2462 <a href="/help/phases">
2449 2463 phases
2450 2464 </a>
2451 2465 </td><td>
2452 2466 Working with Phases
2453 2467 </td></tr>
2454 2468 <tr><td>
2455 2469 <a href="/help/revisions">
2456 2470 revisions
2457 2471 </a>
2458 2472 </td><td>
2459 2473 Specifying Revisions
2460 2474 </td></tr>
2461 2475 <tr><td>
2462 2476 <a href="/help/rust">
2463 2477 rust
2464 2478 </a>
2465 2479 </td><td>
2466 2480 Rust in Mercurial
2467 2481 </td></tr>
2468 2482 <tr><td>
2469 2483 <a href="/help/scripting">
2470 2484 scripting
2471 2485 </a>
2472 2486 </td><td>
2473 2487 Using Mercurial from scripts and automation
2474 2488 </td></tr>
2475 2489 <tr><td>
2476 2490 <a href="/help/subrepos">
2477 2491 subrepos
2478 2492 </a>
2479 2493 </td><td>
2480 2494 Subrepositories
2481 2495 </td></tr>
2482 2496 <tr><td>
2483 2497 <a href="/help/templating">
2484 2498 templating
2485 2499 </a>
2486 2500 </td><td>
2487 2501 Template Usage
2488 2502 </td></tr>
2489 2503 <tr><td>
2490 2504 <a href="/help/urls">
2491 2505 urls
2492 2506 </a>
2493 2507 </td><td>
2494 2508 URL Paths
2495 2509 </td></tr>
2496 2510 <tr><td>
2497 2511 <a href="/help/topic-containing-verbose">
2498 2512 topic-containing-verbose
2499 2513 </a>
2500 2514 </td><td>
2501 2515 This is the topic to test omit indicating.
2502 2516 </td></tr>
2503 2517
2504 2518
2505 2519 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2506 2520
2507 2521 <tr><td>
2508 2522 <a href="/help/abort">
2509 2523 abort
2510 2524 </a>
2511 2525 </td><td>
2512 2526 abort an unfinished operation (EXPERIMENTAL)
2513 2527 </td></tr>
2514 2528 <tr><td>
2515 2529 <a href="/help/add">
2516 2530 add
2517 2531 </a>
2518 2532 </td><td>
2519 2533 add the specified files on the next commit
2520 2534 </td></tr>
2521 2535 <tr><td>
2522 2536 <a href="/help/annotate">
2523 2537 annotate
2524 2538 </a>
2525 2539 </td><td>
2526 2540 show changeset information by line for each file
2527 2541 </td></tr>
2528 2542 <tr><td>
2529 2543 <a href="/help/clone">
2530 2544 clone
2531 2545 </a>
2532 2546 </td><td>
2533 2547 make a copy of an existing repository
2534 2548 </td></tr>
2535 2549 <tr><td>
2536 2550 <a href="/help/commit">
2537 2551 commit
2538 2552 </a>
2539 2553 </td><td>
2540 2554 commit the specified files or all outstanding changes
2541 2555 </td></tr>
2542 2556 <tr><td>
2543 2557 <a href="/help/continue">
2544 2558 continue
2545 2559 </a>
2546 2560 </td><td>
2547 2561 resumes an interrupted operation (EXPERIMENTAL)
2548 2562 </td></tr>
2549 2563 <tr><td>
2550 2564 <a href="/help/diff">
2551 2565 diff
2552 2566 </a>
2553 2567 </td><td>
2554 2568 diff repository (or selected files)
2555 2569 </td></tr>
2556 2570 <tr><td>
2557 2571 <a href="/help/export">
2558 2572 export
2559 2573 </a>
2560 2574 </td><td>
2561 2575 dump the header and diffs for one or more changesets
2562 2576 </td></tr>
2563 2577 <tr><td>
2564 2578 <a href="/help/forget">
2565 2579 forget
2566 2580 </a>
2567 2581 </td><td>
2568 2582 forget the specified files on the next commit
2569 2583 </td></tr>
2570 2584 <tr><td>
2571 2585 <a href="/help/init">
2572 2586 init
2573 2587 </a>
2574 2588 </td><td>
2575 2589 create a new repository in the given directory
2576 2590 </td></tr>
2577 2591 <tr><td>
2578 2592 <a href="/help/log">
2579 2593 log
2580 2594 </a>
2581 2595 </td><td>
2582 2596 show revision history of entire repository or files
2583 2597 </td></tr>
2584 2598 <tr><td>
2585 2599 <a href="/help/merge">
2586 2600 merge
2587 2601 </a>
2588 2602 </td><td>
2589 2603 merge another revision into working directory
2590 2604 </td></tr>
2591 2605 <tr><td>
2592 2606 <a href="/help/pull">
2593 2607 pull
2594 2608 </a>
2595 2609 </td><td>
2596 2610 pull changes from the specified source
2597 2611 </td></tr>
2598 2612 <tr><td>
2599 2613 <a href="/help/push">
2600 2614 push
2601 2615 </a>
2602 2616 </td><td>
2603 2617 push changes to the specified destination
2604 2618 </td></tr>
2605 2619 <tr><td>
2606 2620 <a href="/help/remove">
2607 2621 remove
2608 2622 </a>
2609 2623 </td><td>
2610 2624 remove the specified files on the next commit
2611 2625 </td></tr>
2612 2626 <tr><td>
2613 2627 <a href="/help/serve">
2614 2628 serve
2615 2629 </a>
2616 2630 </td><td>
2617 2631 start stand-alone webserver
2618 2632 </td></tr>
2619 2633 <tr><td>
2620 2634 <a href="/help/status">
2621 2635 status
2622 2636 </a>
2623 2637 </td><td>
2624 2638 show changed files in the working directory
2625 2639 </td></tr>
2626 2640 <tr><td>
2627 2641 <a href="/help/summary">
2628 2642 summary
2629 2643 </a>
2630 2644 </td><td>
2631 2645 summarize working directory state
2632 2646 </td></tr>
2633 2647 <tr><td>
2634 2648 <a href="/help/update">
2635 2649 update
2636 2650 </a>
2637 2651 </td><td>
2638 2652 update working directory (or switch revisions)
2639 2653 </td></tr>
2640 2654
2641 2655
2642 2656
2643 2657 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2644 2658
2645 2659 <tr><td>
2646 2660 <a href="/help/addremove">
2647 2661 addremove
2648 2662 </a>
2649 2663 </td><td>
2650 2664 add all new files, delete all missing files
2651 2665 </td></tr>
2652 2666 <tr><td>
2667 <a href="/help/admin::verify">
2668 admin::verify
2669 </a>
2670 </td><td>
2671 verify the integrity of the repository
2672 </td></tr>
2673 <tr><td>
2653 2674 <a href="/help/archive">
2654 2675 archive
2655 2676 </a>
2656 2677 </td><td>
2657 2678 create an unversioned archive of a repository revision
2658 2679 </td></tr>
2659 2680 <tr><td>
2660 2681 <a href="/help/backout">
2661 2682 backout
2662 2683 </a>
2663 2684 </td><td>
2664 2685 reverse effect of earlier changeset
2665 2686 </td></tr>
2666 2687 <tr><td>
2667 2688 <a href="/help/bisect">
2668 2689 bisect
2669 2690 </a>
2670 2691 </td><td>
2671 2692 subdivision search of changesets
2672 2693 </td></tr>
2673 2694 <tr><td>
2674 2695 <a href="/help/bookmarks">
2675 2696 bookmarks
2676 2697 </a>
2677 2698 </td><td>
2678 2699 create a new bookmark or list existing bookmarks
2679 2700 </td></tr>
2680 2701 <tr><td>
2681 2702 <a href="/help/branch">
2682 2703 branch
2683 2704 </a>
2684 2705 </td><td>
2685 2706 set or show the current branch name
2686 2707 </td></tr>
2687 2708 <tr><td>
2688 2709 <a href="/help/branches">
2689 2710 branches
2690 2711 </a>
2691 2712 </td><td>
2692 2713 list repository named branches
2693 2714 </td></tr>
2694 2715 <tr><td>
2695 2716 <a href="/help/bundle">
2696 2717 bundle
2697 2718 </a>
2698 2719 </td><td>
2699 2720 create a bundle file
2700 2721 </td></tr>
2701 2722 <tr><td>
2702 2723 <a href="/help/cat">
2703 2724 cat
2704 2725 </a>
2705 2726 </td><td>
2706 2727 output the current or given revision of files
2707 2728 </td></tr>
2708 2729 <tr><td>
2709 2730 <a href="/help/config">
2710 2731 config
2711 2732 </a>
2712 2733 </td><td>
2713 2734 show combined config settings from all hgrc files
2714 2735 </td></tr>
2715 2736 <tr><td>
2716 2737 <a href="/help/copy">
2717 2738 copy
2718 2739 </a>
2719 2740 </td><td>
2720 2741 mark files as copied for the next commit
2721 2742 </td></tr>
2722 2743 <tr><td>
2723 2744 <a href="/help/files">
2724 2745 files
2725 2746 </a>
2726 2747 </td><td>
2727 2748 list tracked files
2728 2749 </td></tr>
2729 2750 <tr><td>
2730 2751 <a href="/help/graft">
2731 2752 graft
2732 2753 </a>
2733 2754 </td><td>
2734 2755 copy changes from other branches onto the current branch
2735 2756 </td></tr>
2736 2757 <tr><td>
2737 2758 <a href="/help/grep">
2738 2759 grep
2739 2760 </a>
2740 2761 </td><td>
2741 2762 search for a pattern in specified files
2742 2763 </td></tr>
2743 2764 <tr><td>
2744 2765 <a href="/help/hashelp">
2745 2766 hashelp
2746 2767 </a>
2747 2768 </td><td>
2748 2769 Extension command's help
2749 2770 </td></tr>
2750 2771 <tr><td>
2751 2772 <a href="/help/heads">
2752 2773 heads
2753 2774 </a>
2754 2775 </td><td>
2755 2776 show branch heads
2756 2777 </td></tr>
2757 2778 <tr><td>
2758 2779 <a href="/help/help">
2759 2780 help
2760 2781 </a>
2761 2782 </td><td>
2762 2783 show help for a given topic or a help overview
2763 2784 </td></tr>
2764 2785 <tr><td>
2765 2786 <a href="/help/hgalias">
2766 2787 hgalias
2767 2788 </a>
2768 2789 </td><td>
2769 2790 My doc
2770 2791 </td></tr>
2771 2792 <tr><td>
2772 2793 <a href="/help/hgaliasnodoc">
2773 2794 hgaliasnodoc
2774 2795 </a>
2775 2796 </td><td>
2776 2797 summarize working directory state
2777 2798 </td></tr>
2778 2799 <tr><td>
2779 2800 <a href="/help/identify">
2780 2801 identify
2781 2802 </a>
2782 2803 </td><td>
2783 2804 identify the working directory or specified revision
2784 2805 </td></tr>
2785 2806 <tr><td>
2786 2807 <a href="/help/import">
2787 2808 import
2788 2809 </a>
2789 2810 </td><td>
2790 2811 import an ordered set of patches
2791 2812 </td></tr>
2792 2813 <tr><td>
2793 2814 <a href="/help/incoming">
2794 2815 incoming
2795 2816 </a>
2796 2817 </td><td>
2797 2818 show new changesets found in source
2798 2819 </td></tr>
2799 2820 <tr><td>
2800 2821 <a href="/help/manifest">
2801 2822 manifest
2802 2823 </a>
2803 2824 </td><td>
2804 2825 output the current or given revision of the project manifest
2805 2826 </td></tr>
2806 2827 <tr><td>
2807 2828 <a href="/help/nohelp">
2808 2829 nohelp
2809 2830 </a>
2810 2831 </td><td>
2811 2832 (no help text available)
2812 2833 </td></tr>
2813 2834 <tr><td>
2814 2835 <a href="/help/outgoing">
2815 2836 outgoing
2816 2837 </a>
2817 2838 </td><td>
2818 2839 show changesets not found in the destination
2819 2840 </td></tr>
2820 2841 <tr><td>
2821 2842 <a href="/help/paths">
2822 2843 paths
2823 2844 </a>
2824 2845 </td><td>
2825 2846 show aliases for remote repositories
2826 2847 </td></tr>
2827 2848 <tr><td>
2828 2849 <a href="/help/phase">
2829 2850 phase
2830 2851 </a>
2831 2852 </td><td>
2832 2853 set or show the current phase name
2833 2854 </td></tr>
2834 2855 <tr><td>
2835 2856 <a href="/help/purge">
2836 2857 purge
2837 2858 </a>
2838 2859 </td><td>
2839 2860 removes files not tracked by Mercurial
2840 2861 </td></tr>
2841 2862 <tr><td>
2842 2863 <a href="/help/recover">
2843 2864 recover
2844 2865 </a>
2845 2866 </td><td>
2846 2867 roll back an interrupted transaction
2847 2868 </td></tr>
2848 2869 <tr><td>
2849 2870 <a href="/help/rename">
2850 2871 rename
2851 2872 </a>
2852 2873 </td><td>
2853 2874 rename files; equivalent of copy + remove
2854 2875 </td></tr>
2855 2876 <tr><td>
2856 2877 <a href="/help/resolve">
2857 2878 resolve
2858 2879 </a>
2859 2880 </td><td>
2860 2881 redo merges or set/view the merge status of files
2861 2882 </td></tr>
2862 2883 <tr><td>
2863 2884 <a href="/help/revert">
2864 2885 revert
2865 2886 </a>
2866 2887 </td><td>
2867 2888 restore files to their checkout state
2868 2889 </td></tr>
2869 2890 <tr><td>
2870 2891 <a href="/help/root">
2871 2892 root
2872 2893 </a>
2873 2894 </td><td>
2874 2895 print the root (top) of the current working directory
2875 2896 </td></tr>
2876 2897 <tr><td>
2877 2898 <a href="/help/shellalias">
2878 2899 shellalias
2879 2900 </a>
2880 2901 </td><td>
2881 2902 (no help text available)
2882 2903 </td></tr>
2883 2904 <tr><td>
2884 2905 <a href="/help/shelve">
2885 2906 shelve
2886 2907 </a>
2887 2908 </td><td>
2888 2909 save and set aside changes from the working directory
2889 2910 </td></tr>
2890 2911 <tr><td>
2891 2912 <a href="/help/tag">
2892 2913 tag
2893 2914 </a>
2894 2915 </td><td>
2895 2916 add one or more tags for the current or given revision
2896 2917 </td></tr>
2897 2918 <tr><td>
2898 2919 <a href="/help/tags">
2899 2920 tags
2900 2921 </a>
2901 2922 </td><td>
2902 2923 list repository tags
2903 2924 </td></tr>
2904 2925 <tr><td>
2905 2926 <a href="/help/unbundle">
2906 2927 unbundle
2907 2928 </a>
2908 2929 </td><td>
2909 2930 apply one or more bundle files
2910 2931 </td></tr>
2911 2932 <tr><td>
2912 2933 <a href="/help/unshelve">
2913 2934 unshelve
2914 2935 </a>
2915 2936 </td><td>
2916 2937 restore a shelved change to the working directory
2917 2938 </td></tr>
2918 2939 <tr><td>
2919 2940 <a href="/help/verify">
2920 2941 verify
2921 2942 </a>
2922 2943 </td><td>
2923 2944 verify the integrity of the repository
2924 2945 </td></tr>
2925 2946 <tr><td>
2926 2947 <a href="/help/version">
2927 2948 version
2928 2949 </a>
2929 2950 </td><td>
2930 2951 output version and copyright information
2931 2952 </td></tr>
2932 2953
2933 2954
2934 2955 </table>
2935 2956 </div>
2936 2957 </div>
2937 2958
2938 2959
2939 2960
2940 2961 </body>
2941 2962 </html>
2942 2963
2943 2964
2944 2965 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2945 2966 200 Script output follows
2946 2967
2947 2968 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2948 2969 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2949 2970 <head>
2950 2971 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2951 2972 <meta name="robots" content="index, nofollow" />
2952 2973 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2953 2974 <script type="text/javascript" src="/static/mercurial.js"></script>
2954 2975
2955 2976 <title>Help: add</title>
2956 2977 </head>
2957 2978 <body>
2958 2979
2959 2980 <div class="container">
2960 2981 <div class="menu">
2961 2982 <div class="logo">
2962 2983 <a href="https://mercurial-scm.org/">
2963 2984 <img src="/static/hglogo.png" alt="mercurial" /></a>
2964 2985 </div>
2965 2986 <ul>
2966 2987 <li><a href="/shortlog">log</a></li>
2967 2988 <li><a href="/graph">graph</a></li>
2968 2989 <li><a href="/tags">tags</a></li>
2969 2990 <li><a href="/bookmarks">bookmarks</a></li>
2970 2991 <li><a href="/branches">branches</a></li>
2971 2992 </ul>
2972 2993 <ul>
2973 2994 <li class="active"><a href="/help">help</a></li>
2974 2995 </ul>
2975 2996 </div>
2976 2997
2977 2998 <div class="main">
2978 2999 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2979 3000 <h3>Help: add</h3>
2980 3001
2981 3002 <form class="search" action="/log">
2982 3003
2983 3004 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2984 3005 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2985 3006 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2986 3007 </form>
2987 3008 <div id="doc">
2988 3009 <p>
2989 3010 hg add [OPTION]... [FILE]...
2990 3011 </p>
2991 3012 <p>
2992 3013 add the specified files on the next commit
2993 3014 </p>
2994 3015 <p>
2995 3016 Schedule files to be version controlled and added to the
2996 3017 repository.
2997 3018 </p>
2998 3019 <p>
2999 3020 The files will be added to the repository at the next commit. To
3000 3021 undo an add before that, see 'hg forget'.
3001 3022 </p>
3002 3023 <p>
3003 3024 If no names are given, add all files to the repository (except
3004 3025 files matching &quot;.hgignore&quot;).
3005 3026 </p>
3006 3027 <p>
3007 3028 Examples:
3008 3029 </p>
3009 3030 <ul>
3010 3031 <li> New (unknown) files are added automatically by 'hg add':
3011 3032 <pre>
3012 3033 \$ ls (re)
3013 3034 foo.c
3014 3035 \$ hg status (re)
3015 3036 ? foo.c
3016 3037 \$ hg add (re)
3017 3038 adding foo.c
3018 3039 \$ hg status (re)
3019 3040 A foo.c
3020 3041 </pre>
3021 3042 <li> Specific files to be added can be specified:
3022 3043 <pre>
3023 3044 \$ ls (re)
3024 3045 bar.c foo.c
3025 3046 \$ hg status (re)
3026 3047 ? bar.c
3027 3048 ? foo.c
3028 3049 \$ hg add bar.c (re)
3029 3050 \$ hg status (re)
3030 3051 A bar.c
3031 3052 ? foo.c
3032 3053 </pre>
3033 3054 </ul>
3034 3055 <p>
3035 3056 Returns 0 if all files are successfully added.
3036 3057 </p>
3037 3058 <p>
3038 3059 options ([+] can be repeated):
3039 3060 </p>
3040 3061 <table>
3041 3062 <tr><td>-I</td>
3042 3063 <td>--include PATTERN [+]</td>
3043 3064 <td>include names matching the given patterns</td></tr>
3044 3065 <tr><td>-X</td>
3045 3066 <td>--exclude PATTERN [+]</td>
3046 3067 <td>exclude names matching the given patterns</td></tr>
3047 3068 <tr><td>-S</td>
3048 3069 <td>--subrepos</td>
3049 3070 <td>recurse into subrepositories</td></tr>
3050 3071 <tr><td>-n</td>
3051 3072 <td>--dry-run</td>
3052 3073 <td>do not perform actions, just print output</td></tr>
3053 3074 </table>
3054 3075 <p>
3055 3076 global options ([+] can be repeated):
3056 3077 </p>
3057 3078 <table>
3058 3079 <tr><td>-R</td>
3059 3080 <td>--repository REPO</td>
3060 3081 <td>repository root directory or name of overlay bundle file</td></tr>
3061 3082 <tr><td></td>
3062 3083 <td>--cwd DIR</td>
3063 3084 <td>change working directory</td></tr>
3064 3085 <tr><td>-y</td>
3065 3086 <td>--noninteractive</td>
3066 3087 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3067 3088 <tr><td>-q</td>
3068 3089 <td>--quiet</td>
3069 3090 <td>suppress output</td></tr>
3070 3091 <tr><td>-v</td>
3071 3092 <td>--verbose</td>
3072 3093 <td>enable additional output</td></tr>
3073 3094 <tr><td></td>
3074 3095 <td>--color TYPE</td>
3075 3096 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3076 3097 <tr><td></td>
3077 3098 <td>--config CONFIG [+]</td>
3078 3099 <td>set/override config option (use 'section.name=value')</td></tr>
3079 3100 <tr><td></td>
3080 3101 <td>--debug</td>
3081 3102 <td>enable debugging output</td></tr>
3082 3103 <tr><td></td>
3083 3104 <td>--debugger</td>
3084 3105 <td>start debugger</td></tr>
3085 3106 <tr><td></td>
3086 3107 <td>--encoding ENCODE</td>
3087 3108 <td>set the charset encoding (default: ascii)</td></tr>
3088 3109 <tr><td></td>
3089 3110 <td>--encodingmode MODE</td>
3090 3111 <td>set the charset encoding mode (default: strict)</td></tr>
3091 3112 <tr><td></td>
3092 3113 <td>--traceback</td>
3093 3114 <td>always print a traceback on exception</td></tr>
3094 3115 <tr><td></td>
3095 3116 <td>--time</td>
3096 3117 <td>time how long the command takes</td></tr>
3097 3118 <tr><td></td>
3098 3119 <td>--profile</td>
3099 3120 <td>print command execution profile</td></tr>
3100 3121 <tr><td></td>
3101 3122 <td>--version</td>
3102 3123 <td>output version information and exit</td></tr>
3103 3124 <tr><td>-h</td>
3104 3125 <td>--help</td>
3105 3126 <td>display help and exit</td></tr>
3106 3127 <tr><td></td>
3107 3128 <td>--hidden</td>
3108 3129 <td>consider hidden changesets</td></tr>
3109 3130 <tr><td></td>
3110 3131 <td>--pager TYPE</td>
3111 3132 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3112 3133 </table>
3113 3134
3114 3135 </div>
3115 3136 </div>
3116 3137 </div>
3117 3138
3118 3139
3119 3140
3120 3141 </body>
3121 3142 </html>
3122 3143
3123 3144
3124 3145 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
3125 3146 200 Script output follows
3126 3147
3127 3148 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3128 3149 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3129 3150 <head>
3130 3151 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3131 3152 <meta name="robots" content="index, nofollow" />
3132 3153 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3133 3154 <script type="text/javascript" src="/static/mercurial.js"></script>
3134 3155
3135 3156 <title>Help: remove</title>
3136 3157 </head>
3137 3158 <body>
3138 3159
3139 3160 <div class="container">
3140 3161 <div class="menu">
3141 3162 <div class="logo">
3142 3163 <a href="https://mercurial-scm.org/">
3143 3164 <img src="/static/hglogo.png" alt="mercurial" /></a>
3144 3165 </div>
3145 3166 <ul>
3146 3167 <li><a href="/shortlog">log</a></li>
3147 3168 <li><a href="/graph">graph</a></li>
3148 3169 <li><a href="/tags">tags</a></li>
3149 3170 <li><a href="/bookmarks">bookmarks</a></li>
3150 3171 <li><a href="/branches">branches</a></li>
3151 3172 </ul>
3152 3173 <ul>
3153 3174 <li class="active"><a href="/help">help</a></li>
3154 3175 </ul>
3155 3176 </div>
3156 3177
3157 3178 <div class="main">
3158 3179 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3159 3180 <h3>Help: remove</h3>
3160 3181
3161 3182 <form class="search" action="/log">
3162 3183
3163 3184 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3164 3185 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3165 3186 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3166 3187 </form>
3167 3188 <div id="doc">
3168 3189 <p>
3169 3190 hg remove [OPTION]... FILE...
3170 3191 </p>
3171 3192 <p>
3172 3193 aliases: rm
3173 3194 </p>
3174 3195 <p>
3175 3196 remove the specified files on the next commit
3176 3197 </p>
3177 3198 <p>
3178 3199 Schedule the indicated files for removal from the current branch.
3179 3200 </p>
3180 3201 <p>
3181 3202 This command schedules the files to be removed at the next commit.
3182 3203 To undo a remove before that, see 'hg revert'. To undo added
3183 3204 files, see 'hg forget'.
3184 3205 </p>
3185 3206 <p>
3186 3207 -A/--after can be used to remove only files that have already
3187 3208 been deleted, -f/--force can be used to force deletion, and -Af
3188 3209 can be used to remove files from the next revision without
3189 3210 deleting them from the working directory.
3190 3211 </p>
3191 3212 <p>
3192 3213 The following table details the behavior of remove for different
3193 3214 file states (columns) and option combinations (rows). The file
3194 3215 states are Added [A], Clean [C], Modified [M] and Missing [!]
3195 3216 (as reported by 'hg status'). The actions are Warn, Remove
3196 3217 (from branch) and Delete (from disk):
3197 3218 </p>
3198 3219 <table>
3199 3220 <tr><td>opt/state</td>
3200 3221 <td>A</td>
3201 3222 <td>C</td>
3202 3223 <td>M</td>
3203 3224 <td>!</td></tr>
3204 3225 <tr><td>none</td>
3205 3226 <td>W</td>
3206 3227 <td>RD</td>
3207 3228 <td>W</td>
3208 3229 <td>R</td></tr>
3209 3230 <tr><td>-f</td>
3210 3231 <td>R</td>
3211 3232 <td>RD</td>
3212 3233 <td>RD</td>
3213 3234 <td>R</td></tr>
3214 3235 <tr><td>-A</td>
3215 3236 <td>W</td>
3216 3237 <td>W</td>
3217 3238 <td>W</td>
3218 3239 <td>R</td></tr>
3219 3240 <tr><td>-Af</td>
3220 3241 <td>R</td>
3221 3242 <td>R</td>
3222 3243 <td>R</td>
3223 3244 <td>R</td></tr>
3224 3245 </table>
3225 3246 <p>
3226 3247 <b>Note:</b>
3227 3248 </p>
3228 3249 <p>
3229 3250 'hg remove' never deletes files in Added [A] state from the
3230 3251 working directory, not even if &quot;--force&quot; is specified.
3231 3252 </p>
3232 3253 <p>
3233 3254 Returns 0 on success, 1 if any warnings encountered.
3234 3255 </p>
3235 3256 <p>
3236 3257 options ([+] can be repeated):
3237 3258 </p>
3238 3259 <table>
3239 3260 <tr><td>-A</td>
3240 3261 <td>--after</td>
3241 3262 <td>record delete for missing files</td></tr>
3242 3263 <tr><td>-f</td>
3243 3264 <td>--force</td>
3244 3265 <td>forget added files, delete modified files</td></tr>
3245 3266 <tr><td>-S</td>
3246 3267 <td>--subrepos</td>
3247 3268 <td>recurse into subrepositories</td></tr>
3248 3269 <tr><td>-I</td>
3249 3270 <td>--include PATTERN [+]</td>
3250 3271 <td>include names matching the given patterns</td></tr>
3251 3272 <tr><td>-X</td>
3252 3273 <td>--exclude PATTERN [+]</td>
3253 3274 <td>exclude names matching the given patterns</td></tr>
3254 3275 <tr><td>-n</td>
3255 3276 <td>--dry-run</td>
3256 3277 <td>do not perform actions, just print output</td></tr>
3257 3278 </table>
3258 3279 <p>
3259 3280 global options ([+] can be repeated):
3260 3281 </p>
3261 3282 <table>
3262 3283 <tr><td>-R</td>
3263 3284 <td>--repository REPO</td>
3264 3285 <td>repository root directory or name of overlay bundle file</td></tr>
3265 3286 <tr><td></td>
3266 3287 <td>--cwd DIR</td>
3267 3288 <td>change working directory</td></tr>
3268 3289 <tr><td>-y</td>
3269 3290 <td>--noninteractive</td>
3270 3291 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3271 3292 <tr><td>-q</td>
3272 3293 <td>--quiet</td>
3273 3294 <td>suppress output</td></tr>
3274 3295 <tr><td>-v</td>
3275 3296 <td>--verbose</td>
3276 3297 <td>enable additional output</td></tr>
3277 3298 <tr><td></td>
3278 3299 <td>--color TYPE</td>
3279 3300 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3280 3301 <tr><td></td>
3281 3302 <td>--config CONFIG [+]</td>
3282 3303 <td>set/override config option (use 'section.name=value')</td></tr>
3283 3304 <tr><td></td>
3284 3305 <td>--debug</td>
3285 3306 <td>enable debugging output</td></tr>
3286 3307 <tr><td></td>
3287 3308 <td>--debugger</td>
3288 3309 <td>start debugger</td></tr>
3289 3310 <tr><td></td>
3290 3311 <td>--encoding ENCODE</td>
3291 3312 <td>set the charset encoding (default: ascii)</td></tr>
3292 3313 <tr><td></td>
3293 3314 <td>--encodingmode MODE</td>
3294 3315 <td>set the charset encoding mode (default: strict)</td></tr>
3295 3316 <tr><td></td>
3296 3317 <td>--traceback</td>
3297 3318 <td>always print a traceback on exception</td></tr>
3298 3319 <tr><td></td>
3299 3320 <td>--time</td>
3300 3321 <td>time how long the command takes</td></tr>
3301 3322 <tr><td></td>
3302 3323 <td>--profile</td>
3303 3324 <td>print command execution profile</td></tr>
3304 3325 <tr><td></td>
3305 3326 <td>--version</td>
3306 3327 <td>output version information and exit</td></tr>
3307 3328 <tr><td>-h</td>
3308 3329 <td>--help</td>
3309 3330 <td>display help and exit</td></tr>
3310 3331 <tr><td></td>
3311 3332 <td>--hidden</td>
3312 3333 <td>consider hidden changesets</td></tr>
3313 3334 <tr><td></td>
3314 3335 <td>--pager TYPE</td>
3315 3336 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3316 3337 </table>
3317 3338
3318 3339 </div>
3319 3340 </div>
3320 3341 </div>
3321 3342
3322 3343
3323 3344
3324 3345 </body>
3325 3346 </html>
3326 3347
3327 3348
3328 3349 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3329 3350 200 Script output follows
3330 3351
3331 3352 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3332 3353 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3333 3354 <head>
3334 3355 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3335 3356 <meta name="robots" content="index, nofollow" />
3336 3357 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3337 3358 <script type="text/javascript" src="/static/mercurial.js"></script>
3338 3359
3339 3360 <title>Help: dates</title>
3340 3361 </head>
3341 3362 <body>
3342 3363
3343 3364 <div class="container">
3344 3365 <div class="menu">
3345 3366 <div class="logo">
3346 3367 <a href="https://mercurial-scm.org/">
3347 3368 <img src="/static/hglogo.png" alt="mercurial" /></a>
3348 3369 </div>
3349 3370 <ul>
3350 3371 <li><a href="/shortlog">log</a></li>
3351 3372 <li><a href="/graph">graph</a></li>
3352 3373 <li><a href="/tags">tags</a></li>
3353 3374 <li><a href="/bookmarks">bookmarks</a></li>
3354 3375 <li><a href="/branches">branches</a></li>
3355 3376 </ul>
3356 3377 <ul>
3357 3378 <li class="active"><a href="/help">help</a></li>
3358 3379 </ul>
3359 3380 </div>
3360 3381
3361 3382 <div class="main">
3362 3383 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3363 3384 <h3>Help: dates</h3>
3364 3385
3365 3386 <form class="search" action="/log">
3366 3387
3367 3388 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3368 3389 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3369 3390 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3370 3391 </form>
3371 3392 <div id="doc">
3372 3393 <h1>Date Formats</h1>
3373 3394 <p>
3374 3395 Some commands allow the user to specify a date, e.g.:
3375 3396 </p>
3376 3397 <ul>
3377 3398 <li> backout, commit, import, tag: Specify the commit date.
3378 3399 <li> log, revert, update: Select revision(s) by date.
3379 3400 </ul>
3380 3401 <p>
3381 3402 Many date formats are valid. Here are some examples:
3382 3403 </p>
3383 3404 <ul>
3384 3405 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3385 3406 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3386 3407 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3387 3408 <li> &quot;Dec 6&quot; (midnight)
3388 3409 <li> &quot;13:18&quot; (today assumed)
3389 3410 <li> &quot;3:39&quot; (3:39AM assumed)
3390 3411 <li> &quot;3:39pm&quot; (15:39)
3391 3412 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3392 3413 <li> &quot;2006-12-6 13:18&quot;
3393 3414 <li> &quot;2006-12-6&quot;
3394 3415 <li> &quot;12-6&quot;
3395 3416 <li> &quot;12/6&quot;
3396 3417 <li> &quot;12/6/6&quot; (Dec 6 2006)
3397 3418 <li> &quot;today&quot; (midnight)
3398 3419 <li> &quot;yesterday&quot; (midnight)
3399 3420 <li> &quot;now&quot; - right now
3400 3421 </ul>
3401 3422 <p>
3402 3423 Lastly, there is Mercurial's internal format:
3403 3424 </p>
3404 3425 <ul>
3405 3426 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3406 3427 </ul>
3407 3428 <p>
3408 3429 This is the internal representation format for dates. The first number
3409 3430 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3410 3431 second is the offset of the local timezone, in seconds west of UTC
3411 3432 (negative if the timezone is east of UTC).
3412 3433 </p>
3413 3434 <p>
3414 3435 The log command also accepts date ranges:
3415 3436 </p>
3416 3437 <ul>
3417 3438 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3418 3439 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3419 3440 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3420 3441 <li> &quot;-DAYS&quot; - within a given number of days from today
3421 3442 </ul>
3422 3443
3423 3444 </div>
3424 3445 </div>
3425 3446 </div>
3426 3447
3427 3448
3428 3449
3429 3450 </body>
3430 3451 </html>
3431 3452
3432 3453
3433 3454 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3434 3455 200 Script output follows
3435 3456
3436 3457 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3437 3458 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3438 3459 <head>
3439 3460 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3440 3461 <meta name="robots" content="index, nofollow" />
3441 3462 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3442 3463 <script type="text/javascript" src="/static/mercurial.js"></script>
3443 3464
3444 3465 <title>Help: pager</title>
3445 3466 </head>
3446 3467 <body>
3447 3468
3448 3469 <div class="container">
3449 3470 <div class="menu">
3450 3471 <div class="logo">
3451 3472 <a href="https://mercurial-scm.org/">
3452 3473 <img src="/static/hglogo.png" alt="mercurial" /></a>
3453 3474 </div>
3454 3475 <ul>
3455 3476 <li><a href="/shortlog">log</a></li>
3456 3477 <li><a href="/graph">graph</a></li>
3457 3478 <li><a href="/tags">tags</a></li>
3458 3479 <li><a href="/bookmarks">bookmarks</a></li>
3459 3480 <li><a href="/branches">branches</a></li>
3460 3481 </ul>
3461 3482 <ul>
3462 3483 <li class="active"><a href="/help">help</a></li>
3463 3484 </ul>
3464 3485 </div>
3465 3486
3466 3487 <div class="main">
3467 3488 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3468 3489 <h3>Help: pager</h3>
3469 3490
3470 3491 <form class="search" action="/log">
3471 3492
3472 3493 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3473 3494 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3474 3495 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3475 3496 </form>
3476 3497 <div id="doc">
3477 3498 <h1>Pager Support</h1>
3478 3499 <p>
3479 3500 Some Mercurial commands can produce a lot of output, and Mercurial will
3480 3501 attempt to use a pager to make those commands more pleasant.
3481 3502 </p>
3482 3503 <p>
3483 3504 To set the pager that should be used, set the application variable:
3484 3505 </p>
3485 3506 <pre>
3486 3507 [pager]
3487 3508 pager = less -FRX
3488 3509 </pre>
3489 3510 <p>
3490 3511 If no pager is set in the user or repository configuration, Mercurial uses the
3491 3512 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3492 3513 or system configuration is used. If none of these are set, a default pager will
3493 3514 be used, typically 'less' on Unix and 'more' on Windows.
3494 3515 </p>
3495 3516 <p>
3496 3517 You can disable the pager for certain commands by adding them to the
3497 3518 pager.ignore list:
3498 3519 </p>
3499 3520 <pre>
3500 3521 [pager]
3501 3522 ignore = version, help, update
3502 3523 </pre>
3503 3524 <p>
3504 3525 To ignore global commands like 'hg version' or 'hg help', you have
3505 3526 to specify them in your user configuration file.
3506 3527 </p>
3507 3528 <p>
3508 3529 To control whether the pager is used at all for an individual command,
3509 3530 you can use --pager=&lt;value&gt;:
3510 3531 </p>
3511 3532 <ul>
3512 3533 <li> use as needed: 'auto'.
3513 3534 <li> require the pager: 'yes' or 'on'.
3514 3535 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3515 3536 </ul>
3516 3537 <p>
3517 3538 To globally turn off all attempts to use a pager, set:
3518 3539 </p>
3519 3540 <pre>
3520 3541 [ui]
3521 3542 paginate = never
3522 3543 </pre>
3523 3544 <p>
3524 3545 which will prevent the pager from running.
3525 3546 </p>
3526 3547
3527 3548 </div>
3528 3549 </div>
3529 3550 </div>
3530 3551
3531 3552
3532 3553
3533 3554 </body>
3534 3555 </html>
3535 3556
3536 3557
3537 3558 Sub-topic indexes rendered properly
3538 3559
3539 3560 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3540 3561 200 Script output follows
3541 3562
3542 3563 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3543 3564 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3544 3565 <head>
3545 3566 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3546 3567 <meta name="robots" content="index, nofollow" />
3547 3568 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3548 3569 <script type="text/javascript" src="/static/mercurial.js"></script>
3549 3570
3550 3571 <title>Help: internals</title>
3551 3572 </head>
3552 3573 <body>
3553 3574
3554 3575 <div class="container">
3555 3576 <div class="menu">
3556 3577 <div class="logo">
3557 3578 <a href="https://mercurial-scm.org/">
3558 3579 <img src="/static/hglogo.png" alt="mercurial" /></a>
3559 3580 </div>
3560 3581 <ul>
3561 3582 <li><a href="/shortlog">log</a></li>
3562 3583 <li><a href="/graph">graph</a></li>
3563 3584 <li><a href="/tags">tags</a></li>
3564 3585 <li><a href="/bookmarks">bookmarks</a></li>
3565 3586 <li><a href="/branches">branches</a></li>
3566 3587 </ul>
3567 3588 <ul>
3568 3589 <li><a href="/help">help</a></li>
3569 3590 </ul>
3570 3591 </div>
3571 3592
3572 3593 <div class="main">
3573 3594 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3574 3595
3575 3596 <form class="search" action="/log">
3576 3597
3577 3598 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3578 3599 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3579 3600 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3580 3601 </form>
3581 3602 <table class="bigtable">
3582 3603 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3583 3604
3584 3605 <tr><td>
3585 3606 <a href="/help/internals.bid-merge">
3586 3607 bid-merge
3587 3608 </a>
3588 3609 </td><td>
3589 3610 Bid Merge Algorithm
3590 3611 </td></tr>
3591 3612 <tr><td>
3592 3613 <a href="/help/internals.bundle2">
3593 3614 bundle2
3594 3615 </a>
3595 3616 </td><td>
3596 3617 Bundle2
3597 3618 </td></tr>
3598 3619 <tr><td>
3599 3620 <a href="/help/internals.bundles">
3600 3621 bundles
3601 3622 </a>
3602 3623 </td><td>
3603 3624 Bundles
3604 3625 </td></tr>
3605 3626 <tr><td>
3606 3627 <a href="/help/internals.cbor">
3607 3628 cbor
3608 3629 </a>
3609 3630 </td><td>
3610 3631 CBOR
3611 3632 </td></tr>
3612 3633 <tr><td>
3613 3634 <a href="/help/internals.censor">
3614 3635 censor
3615 3636 </a>
3616 3637 </td><td>
3617 3638 Censor
3618 3639 </td></tr>
3619 3640 <tr><td>
3620 3641 <a href="/help/internals.changegroups">
3621 3642 changegroups
3622 3643 </a>
3623 3644 </td><td>
3624 3645 Changegroups
3625 3646 </td></tr>
3626 3647 <tr><td>
3627 3648 <a href="/help/internals.config">
3628 3649 config
3629 3650 </a>
3630 3651 </td><td>
3631 3652 Config Registrar
3632 3653 </td></tr>
3633 3654 <tr><td>
3634 3655 <a href="/help/internals.dirstate-v2">
3635 3656 dirstate-v2
3636 3657 </a>
3637 3658 </td><td>
3638 3659 dirstate-v2 file format
3639 3660 </td></tr>
3640 3661 <tr><td>
3641 3662 <a href="/help/internals.extensions">
3642 3663 extensions
3643 3664 </a>
3644 3665 </td><td>
3645 3666 Extension API
3646 3667 </td></tr>
3647 3668 <tr><td>
3648 3669 <a href="/help/internals.mergestate">
3649 3670 mergestate
3650 3671 </a>
3651 3672 </td><td>
3652 3673 Mergestate
3653 3674 </td></tr>
3654 3675 <tr><td>
3655 3676 <a href="/help/internals.requirements">
3656 3677 requirements
3657 3678 </a>
3658 3679 </td><td>
3659 3680 Repository Requirements
3660 3681 </td></tr>
3661 3682 <tr><td>
3662 3683 <a href="/help/internals.revlogs">
3663 3684 revlogs
3664 3685 </a>
3665 3686 </td><td>
3666 3687 Revision Logs
3667 3688 </td></tr>
3668 3689 <tr><td>
3669 3690 <a href="/help/internals.wireprotocol">
3670 3691 wireprotocol
3671 3692 </a>
3672 3693 </td><td>
3673 3694 Wire Protocol
3674 3695 </td></tr>
3675 3696 <tr><td>
3676 3697 <a href="/help/internals.wireprotocolrpc">
3677 3698 wireprotocolrpc
3678 3699 </a>
3679 3700 </td><td>
3680 3701 Wire Protocol RPC
3681 3702 </td></tr>
3682 3703 <tr><td>
3683 3704 <a href="/help/internals.wireprotocolv2">
3684 3705 wireprotocolv2
3685 3706 </a>
3686 3707 </td><td>
3687 3708 Wire Protocol Version 2
3688 3709 </td></tr>
3689 3710
3690 3711
3691 3712
3692 3713
3693 3714
3694 3715 </table>
3695 3716 </div>
3696 3717 </div>
3697 3718
3698 3719
3699 3720
3700 3721 </body>
3701 3722 </html>
3702 3723
3703 3724
3704 3725 Sub-topic topics rendered properly
3705 3726
3706 3727 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3707 3728 200 Script output follows
3708 3729
3709 3730 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3710 3731 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3711 3732 <head>
3712 3733 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3713 3734 <meta name="robots" content="index, nofollow" />
3714 3735 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3715 3736 <script type="text/javascript" src="/static/mercurial.js"></script>
3716 3737
3717 3738 <title>Help: internals.changegroups</title>
3718 3739 </head>
3719 3740 <body>
3720 3741
3721 3742 <div class="container">
3722 3743 <div class="menu">
3723 3744 <div class="logo">
3724 3745 <a href="https://mercurial-scm.org/">
3725 3746 <img src="/static/hglogo.png" alt="mercurial" /></a>
3726 3747 </div>
3727 3748 <ul>
3728 3749 <li><a href="/shortlog">log</a></li>
3729 3750 <li><a href="/graph">graph</a></li>
3730 3751 <li><a href="/tags">tags</a></li>
3731 3752 <li><a href="/bookmarks">bookmarks</a></li>
3732 3753 <li><a href="/branches">branches</a></li>
3733 3754 </ul>
3734 3755 <ul>
3735 3756 <li class="active"><a href="/help">help</a></li>
3736 3757 </ul>
3737 3758 </div>
3738 3759
3739 3760 <div class="main">
3740 3761 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3741 3762 <h3>Help: internals.changegroups</h3>
3742 3763
3743 3764 <form class="search" action="/log">
3744 3765
3745 3766 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3746 3767 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3747 3768 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3748 3769 </form>
3749 3770 <div id="doc">
3750 3771 <h1>Changegroups</h1>
3751 3772 <p>
3752 3773 Changegroups are representations of repository revlog data, specifically
3753 3774 the changelog data, root/flat manifest data, treemanifest data, and
3754 3775 filelogs.
3755 3776 </p>
3756 3777 <p>
3757 3778 There are 4 versions of changegroups: &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;. From a
3758 3779 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3759 3780 only difference being an additional item in the *delta header*. Version
3760 3781 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3761 3782 exchanging treemanifests (enabled by setting an option on the
3762 3783 &quot;changegroup&quot; part in the bundle2). Version &quot;4&quot; adds support for exchanging
3763 3784 sidedata (additional revision metadata not part of the digest).
3764 3785 </p>
3765 3786 <p>
3766 3787 Changegroups when not exchanging treemanifests consist of 3 logical
3767 3788 segments:
3768 3789 </p>
3769 3790 <pre>
3770 3791 +---------------------------------+
3771 3792 | | | |
3772 3793 | changeset | manifest | filelogs |
3773 3794 | | | |
3774 3795 | | | |
3775 3796 +---------------------------------+
3776 3797 </pre>
3777 3798 <p>
3778 3799 When exchanging treemanifests, there are 4 logical segments:
3779 3800 </p>
3780 3801 <pre>
3781 3802 +-------------------------------------------------+
3782 3803 | | | | |
3783 3804 | changeset | root | treemanifests | filelogs |
3784 3805 | | manifest | | |
3785 3806 | | | | |
3786 3807 +-------------------------------------------------+
3787 3808 </pre>
3788 3809 <p>
3789 3810 The principle building block of each segment is a *chunk*. A *chunk*
3790 3811 is a framed piece of data:
3791 3812 </p>
3792 3813 <pre>
3793 3814 +---------------------------------------+
3794 3815 | | |
3795 3816 | length | data |
3796 3817 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3797 3818 | | |
3798 3819 +---------------------------------------+
3799 3820 </pre>
3800 3821 <p>
3801 3822 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3802 3823 integer indicating the length of the entire chunk (including the length field
3803 3824 itself).
3804 3825 </p>
3805 3826 <p>
3806 3827 There is a special case chunk that has a value of 0 for the length
3807 3828 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3808 3829 </p>
3809 3830 <h2>Delta Groups</h2>
3810 3831 <p>
3811 3832 A *delta group* expresses the content of a revlog as a series of deltas,
3812 3833 or patches against previous revisions.
3813 3834 </p>
3814 3835 <p>
3815 3836 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3816 3837 to signal the end of the delta group:
3817 3838 </p>
3818 3839 <pre>
3819 3840 +------------------------------------------------------------------------+
3820 3841 | | | | | |
3821 3842 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3822 3843 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3823 3844 | | | | | |
3824 3845 +------------------------------------------------------------------------+
3825 3846 </pre>
3826 3847 <p>
3827 3848 Each *chunk*'s data consists of the following:
3828 3849 </p>
3829 3850 <pre>
3830 3851 +---------------------------------------+
3831 3852 | | |
3832 3853 | delta header | delta data |
3833 3854 | (various by version) | (various) |
3834 3855 | | |
3835 3856 +---------------------------------------+
3836 3857 </pre>
3837 3858 <p>
3838 3859 The *delta data* is a series of *delta*s that describe a diff from an existing
3839 3860 entry (either that the recipient already has, or previously specified in the
3840 3861 bundle/changegroup).
3841 3862 </p>
3842 3863 <p>
3843 3864 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;
3844 3865 of the changegroup format.
3845 3866 </p>
3846 3867 <p>
3847 3868 Version 1 (headerlen=80):
3848 3869 </p>
3849 3870 <pre>
3850 3871 +------------------------------------------------------+
3851 3872 | | | | |
3852 3873 | node | p1 node | p2 node | link node |
3853 3874 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3854 3875 | | | | |
3855 3876 +------------------------------------------------------+
3856 3877 </pre>
3857 3878 <p>
3858 3879 Version 2 (headerlen=100):
3859 3880 </p>
3860 3881 <pre>
3861 3882 +------------------------------------------------------------------+
3862 3883 | | | | | |
3863 3884 | node | p1 node | p2 node | base node | link node |
3864 3885 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3865 3886 | | | | | |
3866 3887 +------------------------------------------------------------------+
3867 3888 </pre>
3868 3889 <p>
3869 3890 Version 3 (headerlen=102):
3870 3891 </p>
3871 3892 <pre>
3872 3893 +------------------------------------------------------------------------------+
3873 3894 | | | | | | |
3874 3895 | node | p1 node | p2 node | base node | link node | flags |
3875 3896 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3876 3897 | | | | | | |
3877 3898 +------------------------------------------------------------------------------+
3878 3899 </pre>
3879 3900 <p>
3880 3901 Version 4 (headerlen=103):
3881 3902 </p>
3882 3903 <pre>
3883 3904 +------------------------------------------------------------------------------+----------+
3884 3905 | | | | | | | |
3885 3906 | node | p1 node | p2 node | base node | link node | flags | pflags |
3886 3907 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
3887 3908 | | | | | | | |
3888 3909 +------------------------------------------------------------------------------+----------+
3889 3910 </pre>
3890 3911 <p>
3891 3912 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3892 3913 series of *delta*s, densely packed (no separators). These deltas describe a diff
3893 3914 from an existing entry (either that the recipient already has, or previously
3894 3915 specified in the bundle/changegroup). The format is described more fully in
3895 3916 &quot;hg help internals.bdiff&quot;, but briefly:
3896 3917 </p>
3897 3918 <pre>
3898 3919 +---------------------------------------------------------------+
3899 3920 | | | | |
3900 3921 | start offset | end offset | new length | content |
3901 3922 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3902 3923 | | | | |
3903 3924 +---------------------------------------------------------------+
3904 3925 </pre>
3905 3926 <p>
3906 3927 Please note that the length field in the delta data does *not* include itself.
3907 3928 </p>
3908 3929 <p>
3909 3930 In version 1, the delta is always applied against the previous node from
3910 3931 the changegroup or the first parent if this is the first entry in the
3911 3932 changegroup.
3912 3933 </p>
3913 3934 <p>
3914 3935 In version 2 and up, the delta base node is encoded in the entry in the
3915 3936 changegroup. This allows the delta to be expressed against any parent,
3916 3937 which can result in smaller deltas and more efficient encoding of data.
3917 3938 </p>
3918 3939 <p>
3919 3940 The *flags* field holds bitwise flags affecting the processing of revision
3920 3941 data. The following flags are defined:
3921 3942 </p>
3922 3943 <dl>
3923 3944 <dt>32768
3924 3945 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3925 3946 <dt>16384
3926 3947 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3927 3948 <dt>8192
3928 3949 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3929 3950 <dt>4096
3930 3951 <dd>Contains copy information. This revision changes files in a way that could affect copy tracing. This does *not* affect changegroup handling, but is relevant for other parts of Mercurial.
3931 3952 </dl>
3932 3953 <p>
3933 3954 For historical reasons, the integer values are identical to revlog version 1
3934 3955 per-revision storage flags and correspond to bits being set in this 2-byte
3935 3956 field. Bits were allocated starting from the most-significant bit, hence the
3936 3957 reverse ordering and allocation of these flags.
3937 3958 </p>
3938 3959 <p>
3939 3960 The *pflags* (protocol flags) field holds bitwise flags affecting the protocol
3940 3961 itself. They are first in the header since they may affect the handling of the
3941 3962 rest of the fields in a future version. They are defined as such:
3942 3963 </p>
3943 3964 <dl>
3944 3965 <dt>1 indicates whether to read a chunk of sidedata (of variable length) right
3945 3966 <dd>after the revision flags.
3946 3967 </dl>
3947 3968 <h2>Changeset Segment</h2>
3948 3969 <p>
3949 3970 The *changeset segment* consists of a single *delta group* holding
3950 3971 changelog data. The *empty chunk* at the end of the *delta group* denotes
3951 3972 the boundary to the *manifest segment*.
3952 3973 </p>
3953 3974 <h2>Manifest Segment</h2>
3954 3975 <p>
3955 3976 The *manifest segment* consists of a single *delta group* holding manifest
3956 3977 data. If treemanifests are in use, it contains only the manifest for the
3957 3978 root directory of the repository. Otherwise, it contains the entire
3958 3979 manifest data. The *empty chunk* at the end of the *delta group* denotes
3959 3980 the boundary to the next segment (either the *treemanifests segment* or the
3960 3981 *filelogs segment*, depending on version and the request options).
3961 3982 </p>
3962 3983 <h3>Treemanifests Segment</h3>
3963 3984 <p>
3964 3985 The *treemanifests segment* only exists in changegroup version &quot;3&quot; and &quot;4&quot;,
3965 3986 and only if the 'treemanifest' param is part of the bundle2 changegroup part
3966 3987 (it is not possible to use changegroup version 3 or 4 outside of bundle2).
3967 3988 Aside from the filenames in the *treemanifests segment* containing a
3968 3989 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3969 3990 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3970 3991 a sub-segment with filename size 0). This denotes the boundary to the
3971 3992 *filelogs segment*.
3972 3993 </p>
3973 3994 <h2>Filelogs Segment</h2>
3974 3995 <p>
3975 3996 The *filelogs segment* consists of multiple sub-segments, each
3976 3997 corresponding to an individual file whose data is being described:
3977 3998 </p>
3978 3999 <pre>
3979 4000 +--------------------------------------------------+
3980 4001 | | | | | |
3981 4002 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3982 4003 | | | | | (4 bytes) |
3983 4004 | | | | | |
3984 4005 +--------------------------------------------------+
3985 4006 </pre>
3986 4007 <p>
3987 4008 The final filelog sub-segment is followed by an *empty chunk* (logically,
3988 4009 a sub-segment with filename size 0). This denotes the end of the segment
3989 4010 and of the overall changegroup.
3990 4011 </p>
3991 4012 <p>
3992 4013 Each filelog sub-segment consists of the following:
3993 4014 </p>
3994 4015 <pre>
3995 4016 +------------------------------------------------------+
3996 4017 | | | |
3997 4018 | filename length | filename | delta group |
3998 4019 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3999 4020 | | | |
4000 4021 +------------------------------------------------------+
4001 4022 </pre>
4002 4023 <p>
4003 4024 That is, a *chunk* consisting of the filename (not terminated or padded)
4004 4025 followed by N chunks constituting the *delta group* for this file. The
4005 4026 *empty chunk* at the end of each *delta group* denotes the boundary to the
4006 4027 next filelog sub-segment.
4007 4028 </p>
4008 4029
4009 4030 </div>
4010 4031 </div>
4011 4032 </div>
4012 4033
4013 4034
4014 4035
4015 4036 </body>
4016 4037 </html>
4017 4038
4018 4039
4019 4040 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
4020 4041 404 Not Found
4021 4042
4022 4043 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4023 4044 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
4024 4045 <head>
4025 4046 <link rel="icon" href="/static/hgicon.png" type="image/png" />
4026 4047 <meta name="robots" content="index, nofollow" />
4027 4048 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
4028 4049 <script type="text/javascript" src="/static/mercurial.js"></script>
4029 4050
4030 4051 <title>test: error</title>
4031 4052 </head>
4032 4053 <body>
4033 4054
4034 4055 <div class="container">
4035 4056 <div class="menu">
4036 4057 <div class="logo">
4037 4058 <a href="https://mercurial-scm.org/">
4038 4059 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
4039 4060 </div>
4040 4061 <ul>
4041 4062 <li><a href="/shortlog">log</a></li>
4042 4063 <li><a href="/graph">graph</a></li>
4043 4064 <li><a href="/tags">tags</a></li>
4044 4065 <li><a href="/bookmarks">bookmarks</a></li>
4045 4066 <li><a href="/branches">branches</a></li>
4046 4067 </ul>
4047 4068 <ul>
4048 4069 <li><a href="/help">help</a></li>
4049 4070 </ul>
4050 4071 </div>
4051 4072
4052 4073 <div class="main">
4053 4074
4054 4075 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
4055 4076 <h3>error</h3>
4056 4077
4057 4078
4058 4079 <form class="search" action="/log">
4059 4080
4060 4081 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
4061 4082 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
4062 4083 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
4063 4084 </form>
4064 4085
4065 4086 <div class="description">
4066 4087 <p>
4067 4088 An error occurred while processing your request:
4068 4089 </p>
4069 4090 <p>
4070 4091 Not Found
4071 4092 </p>
4072 4093 </div>
4073 4094 </div>
4074 4095 </div>
4075 4096
4076 4097
4077 4098
4078 4099 </body>
4079 4100 </html>
4080 4101
4081 4102 [1]
4082 4103
4083 4104 $ killdaemons.py
4084 4105
4085 4106 #endif
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now