##// END OF EJS Templates
githelp: vendor Facebook authored extension...
Gregory Szorc -
r35732:11328166 default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (1081 lines changed) Show them Hide them
@@ -0,0 +1,1081 b''
1 # githelp.py - Try to map Git commands to Mercurial equivalents.
2 #
3 # Copyright 2013 Facebook, Inc.
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 """try mapping git commands to Mercurial commands
8
9 Tries to map a given git command to a Mercurial command:
10
11 $ hg githelp -- git checkout master
12 hg update master
13
14 If an unknown command or parameter combination is detected, an error is
15 produced.
16 """
17
18 from __future__ import absolute_import
19
20 import getopt
21 import re
22
23 from mercurial.i18n import _
24 from mercurial import (
25 error,
26 extensions,
27 fancyopts,
28 registrar,
29 util,
30 )
31
32 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
33 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
34 # be specifying the version(s) of Mercurial they are tested with, or
35 # leave the attribute unspecified.
36 testedwith = 'ships-with-hg-core'
37
38 cmdtable = {}
39 command = registrar.command(cmdtable)
40
41 def convert(s):
42 if s.startswith("origin/"):
43 return s[7:]
44 if 'HEAD' in s:
45 s = s.replace('HEAD', '.')
46 # HEAD~ in git is .~1 in mercurial
47 s = re.sub('~$', '~1', s)
48 return s
49
50 @command('^githelp|git', [
51 ], _('hg githelp'))
52 def githelp(ui, repo, *args, **kwargs):
53 '''suggests the Mercurial equivalent of the given git command
54
55 Usage: hg githelp -- <git command>
56 '''
57
58 if len(args) == 0 or (len(args) == 1 and args[0] =='git'):
59 raise error.Abort(_('missing git command - '
60 'usage: hg githelp -- <git command>'))
61
62 if args[0] == 'git':
63 args = args[1:]
64
65 cmd = args[0]
66 if not cmd in gitcommands:
67 raise error.Abort("error: unknown git command %s" % (cmd))
68
69 ui.pager('githelp')
70 args = args[1:]
71 return gitcommands[cmd](ui, repo, *args, **kwargs)
72
73 def parseoptions(ui, cmdoptions, args):
74 cmdoptions = list(cmdoptions)
75 opts = {}
76 args = list(args)
77 while True:
78 try:
79 args = fancyopts.fancyopts(list(args), cmdoptions, opts, True)
80 break
81 except getopt.GetoptError as ex:
82 flag = None
83 if "requires argument" in ex.msg:
84 raise
85 if ('--' + ex.opt) in ex.msg:
86 flag = '--' + ex.opt
87 elif ('-' + ex.opt) in ex.msg:
88 flag = '-' + ex.opt
89 else:
90 raise error.Abort("unknown option %s" % ex.opt)
91 try:
92 args.remove(flag)
93 except Exception:
94 raise error.Abort(
95 "unknown option {0} packed with other options\n"
96 "Please try passing the option as it's own flag: -{0}" \
97 .format(ex.opt))
98
99 ui.warn(_("ignoring unknown option %s\n") % flag)
100
101 args = list([convert(x) for x in args])
102 opts = dict([(k, convert(v)) if isinstance(v, str) else (k, v)
103 for k, v in opts.iteritems()])
104
105 return args, opts
106
107 class Command(object):
108 def __init__(self, name):
109 self.name = name
110 self.args = []
111 self.opts = {}
112
113 def __str__(self):
114 cmd = "hg " + self.name
115 if self.opts:
116 for k, values in sorted(self.opts.iteritems()):
117 for v in values:
118 if v:
119 cmd += " %s %s" % (k, v)
120 else:
121 cmd += " %s" % (k,)
122 if self.args:
123 cmd += " "
124 cmd += " ".join(self.args)
125 return cmd
126
127 def append(self, value):
128 self.args.append(value)
129
130 def extend(self, values):
131 self.args.extend(values)
132
133 def __setitem__(self, key, value):
134 values = self.opts.setdefault(key, [])
135 values.append(value)
136
137 def __and__(self, other):
138 return AndCommand(self, other)
139
140 class AndCommand(object):
141 def __init__(self, left, right):
142 self.left = left
143 self.right = right
144
145 def __str__(self):
146 return "%s && %s" % (self.left, self.right)
147
148 def __and__(self, other):
149 return AndCommand(self, other)
150
151 def add(ui, repo, *args, **kwargs):
152 cmdoptions = [
153 ('A', 'all', None, ''),
154 ('p', 'patch', None, ''),
155 ]
156 args, opts = parseoptions(ui, cmdoptions, args)
157
158 if (opts.get('patch')):
159 ui.status(_("note: hg crecord has a better UI to record changes\n"))
160 ui.status(_("note: record and crecord will commit when complete, "
161 "as there is no staging area in mercurial\n\n"))
162 cmd = Command('record')
163 else:
164 cmd = Command("add")
165
166 if not opts.get('all'):
167 cmd.extend(args)
168 else:
169 ui.status(_("note: use hg addremove to remove files that have "
170 "been deleted.\n\n"))
171 if not opts.get('all'):
172 cmd.extend(args)
173 else:
174 ui.status(_("note: use hg addremove to remove files that have "
175 "been deleted.\n\n"))
176
177 ui.status((str(cmd)), "\n")
178
179 def am(ui, repo, *args, **kwargs):
180 cmdoptions=[
181 ]
182 args, opts = parseoptions(ui, cmdoptions, args)
183 cmd = Command('mimport -m')
184 ui.status(str(cmd), "\n\n")
185 ui.status(_("note: requires the MboxExtension and the MqExtension.\n"))
186
187 def apply(ui, repo, *args, **kwargs):
188 cmdoptions = [
189 ('p', 'p', int, ''),
190 ]
191 args, opts = parseoptions(ui, cmdoptions, args)
192
193 cmd = Command('import --no-commit')
194 if (opts.get('p')):
195 cmd['-p'] = opts.get('p')
196 cmd.extend(args)
197
198 ui.status((str(cmd)), "\n")
199
200 def bisect(ui, repo, *args, **kwargs):
201 ui.status(_("See 'hg help bisect' for how to use bisect.\n\n"))
202
203 def blame(ui, repo, *args, **kwargs):
204 cmdoptions = [
205 ]
206 args, opts = parseoptions(ui, cmdoptions, args)
207 try:
208 # If tweakdefaults is enabled then we have access to -p, which adds
209 # Phabricator diff ID
210 extensions.find('tweakdefaults')
211 cmd = Command('annotate -pudl')
212 except KeyError:
213 cmd = Command('annotate -udl')
214 cmd.extend([convert(v) for v in args])
215 ui.status((str(cmd)), "\n")
216
217 def branch(ui, repo, *args, **kwargs):
218 cmdoptions = [
219 ('', 'set-upstream', None, ''),
220 ('', 'set-upstream-to', '', ''),
221 ('d', 'delete', None, ''),
222 ('D', 'delete', None, ''),
223 ('m', 'move', None, ''),
224 ('M', 'move', None, ''),
225 ]
226 args, opts = parseoptions(ui, cmdoptions, args)
227
228 cmd = Command("bookmark")
229
230 if opts.get('set_upstream') or opts.get('set_upstream_to'):
231 ui.status(_("Mercurial has no concept of upstream branches\n"))
232 return
233 elif opts.get('delete'):
234 cmd = Command("strip")
235 for branch in args:
236 cmd['-B'] = branch
237 else:
238 cmd['-B'] = None
239 elif opts.get('move'):
240 if len(args) > 0:
241 if len(args) > 1:
242 old = args.pop(0)
243 else:
244 # shell command to output the active bookmark for the active
245 # revision
246 old = '`hg log -T"{activebookmark}" -r .`'
247 new = args[0]
248 cmd['-m'] = old
249 cmd.append(new)
250 else:
251 if len(args) > 1:
252 cmd['-r'] = args[1]
253 cmd.append(args[0])
254 elif len(args) == 1:
255 cmd.append(args[0])
256 ui.status((str(cmd)), "\n")
257
258 def ispath(repo, string):
259 """
260 The first argument to git checkout can either be a revision or a path. Let's
261 generally assume it's a revision, unless it's obviously a path. There are
262 too many ways to spell revisions in git for us to reasonably catch all of
263 them, so let's be conservative.
264 """
265 if string in repo:
266 # if it's definitely a revision let's not even check if a file of the
267 # same name exists.
268 return False
269
270 cwd = repo.getcwd()
271 if cwd == '':
272 repopath = string
273 else:
274 repopath = cwd + '/' + string
275
276 exists = repo.wvfs.exists(repopath)
277 if exists:
278 return True
279
280 manifest = repo['.'].manifest()
281
282 didexist = (repopath in manifest) or manifest.hasdir(repopath)
283
284 return didexist
285
286 def checkout(ui, repo, *args, **kwargs):
287 cmdoptions = [
288 ('b', 'branch', '', ''),
289 ('B', 'branch', '', ''),
290 ('f', 'force', None, ''),
291 ('p', 'patch', None, ''),
292 ]
293 paths = []
294 if '--' in args:
295 sepindex = args.index('--')
296 paths.extend(args[sepindex + 1:])
297 args = args[:sepindex]
298
299 args, opts = parseoptions(ui, cmdoptions, args)
300
301 rev = None
302 if args and ispath(repo, args[0]):
303 paths = args + paths
304 elif args:
305 rev = args[0]
306 paths = args[1:] + paths
307
308 cmd = Command('update')
309
310 if opts.get('force'):
311 if paths or rev:
312 cmd['-C'] = None
313
314 if opts.get('patch'):
315 cmd = Command('revert')
316 cmd['-i'] = None
317
318 if opts.get('branch'):
319 if len(args) == 0:
320 cmd = Command('bookmark')
321 cmd.append(opts.get('branch'))
322 else:
323 cmd.append(args[0])
324 bookcmd = Command('bookmark')
325 bookcmd.append(opts.get('branch'))
326 cmd = cmd & bookcmd
327 # if there is any path argument supplied, use revert instead of update
328 elif len(paths) > 0:
329 ui.status(_("note: use --no-backup to avoid creating .orig files\n\n"))
330 cmd = Command('revert')
331 if opts.get('patch'):
332 cmd['-i'] = None
333 if rev:
334 cmd['-r'] = rev
335 cmd.extend(paths)
336 elif rev:
337 if opts.get('patch'):
338 cmd['-r'] = rev
339 else:
340 cmd.append(rev)
341 elif opts.get('force'):
342 cmd = Command('revert')
343 cmd['--all'] = None
344 else:
345 raise error.Abort("a commit must be specified")
346
347 ui.status((str(cmd)), "\n")
348
349 def cherrypick(ui, repo, *args, **kwargs):
350 cmdoptions = [
351 ('', 'continue', None, ''),
352 ('', 'abort', None, ''),
353 ('e', 'edit', None, ''),
354 ]
355 args, opts = parseoptions(ui, cmdoptions, args)
356
357 cmd = Command('graft')
358
359 if opts.get('edit'):
360 cmd['--edit'] = None
361 if opts.get('continue'):
362 cmd['--continue'] = None
363 elif opts.get('abort'):
364 ui.status(_("note: hg graft does not have --abort.\n\n"))
365 return
366 else:
367 cmd.extend(args)
368
369 ui.status((str(cmd)), "\n")
370
371 def clean(ui, repo, *args, **kwargs):
372 cmdoptions = [
373 ('d', 'd', None, ''),
374 ('f', 'force', None, ''),
375 ('x', 'x', None, ''),
376 ]
377 args, opts = parseoptions(ui, cmdoptions, args)
378
379 cmd = Command('purge')
380 if opts.get('x'):
381 cmd['--all'] = None
382 cmd.extend(args)
383
384 ui.status((str(cmd)), "\n")
385
386 def clone(ui, repo, *args, **kwargs):
387 cmdoptions = [
388 ('', 'bare', None, ''),
389 ('n', 'no-checkout', None, ''),
390 ('b', 'branch', '', ''),
391 ]
392 args, opts = parseoptions(ui, cmdoptions, args)
393
394 if len(args) == 0:
395 raise error.Abort("a repository to clone must be specified")
396
397 cmd = Command('clone')
398 cmd.append(args[0])
399 if len(args) > 1:
400 cmd.append(args[1])
401
402 if opts.get('bare'):
403 cmd['-U'] = None
404 ui.status(_("note: Mercurial does not have bare clones. " +
405 "-U will clone the repo without checking out a commit\n\n"))
406 elif opts.get('no_checkout'):
407 cmd['-U'] = None
408
409 if opts.get('branch'):
410 cocmd = Command("update")
411 cocmd.append(opts.get('branch'))
412 cmd = cmd & cocmd
413
414 ui.status((str(cmd)), "\n")
415
416 def commit(ui, repo, *args, **kwargs):
417 cmdoptions = [
418 ('a', 'all', None, ''),
419 ('m', 'message', '', ''),
420 ('p', 'patch', None, ''),
421 ('C', 'reuse-message', '', ''),
422 ('F', 'file', '', ''),
423 ('', 'author', '', ''),
424 ('', 'date', '', ''),
425 ('', 'amend', None, ''),
426 ('', 'no-edit', None, ''),
427 ]
428 args, opts = parseoptions(ui, cmdoptions, args)
429
430 cmd = Command('commit')
431 if opts.get('patch'):
432 cmd = Command('record')
433
434 if opts.get('amend'):
435 if opts.get('no_edit'):
436 cmd = Command('amend')
437 else:
438 cmd['--amend'] = None
439
440 if opts.get('reuse_message'):
441 cmd['-M'] = opts.get('reuse_message')
442
443 if opts.get('message'):
444 cmd['-m'] = "'%s'" % (opts.get('message'),)
445
446 if opts.get('all'):
447 ui.status(_("note: Mercurial doesn't have a staging area, " +
448 "so there is no --all. -A will add and remove files " +
449 "for you though.\n\n"))
450
451 if opts.get('file'):
452 cmd['-l'] = opts.get('file')
453
454 if opts.get('author'):
455 cmd['-u'] = opts.get('author')
456
457 if opts.get('date'):
458 cmd['-d'] = opts.get('date')
459
460 cmd.extend(args)
461
462 ui.status((str(cmd)), "\n")
463
464 def deprecated(ui, repo, *args, **kwargs):
465 ui.warn(_('This command has been deprecated in the git project, ' +
466 'thus isn\'t supported by this tool.\n\n'))
467
468 def diff(ui, repo, *args, **kwargs):
469 cmdoptions = [
470 ('a', 'all', None, ''),
471 ('', 'cached', None, ''),
472 ('R', 'reverse', None, ''),
473 ]
474 args, opts = parseoptions(ui, cmdoptions, args)
475
476 cmd = Command('diff')
477
478 if opts.get('cached'):
479 ui.status(_('note: Mercurial has no concept of a staging area, ' +
480 'so --cached does nothing.\n\n'))
481
482 if opts.get('reverse'):
483 cmd['--reverse'] = None
484
485 for a in list(args):
486 args.remove(a)
487 try:
488 repo.revs(a)
489 cmd['-r'] = a
490 except Exception:
491 cmd.append(a)
492
493 ui.status((str(cmd)), "\n")
494
495 def difftool(ui, repo, *args, **kwargs):
496 ui.status(_('Mercurial does not enable external difftool by default. You '
497 'need to enable the extdiff extension in your .hgrc file by adding\n'
498 'extdiff =\n'
499 'to the [extensions] section and then running\n\n'
500 'hg extdiff -p <program>\n\n'
501 'See \'hg help extdiff\' and \'hg help -e extdiff\' for more '
502 'information.\n'))
503
504 def fetch(ui, repo, *args, **kwargs):
505 cmdoptions = [
506 ('', 'all', None, ''),
507 ('f', 'force', None, ''),
508 ]
509 args, opts = parseoptions(ui, cmdoptions, args)
510
511 cmd = Command('pull')
512
513 if len(args) > 0:
514 cmd.append(args[0])
515 if len(args) > 1:
516 ui.status(_("note: Mercurial doesn't have refspecs. " +
517 "-r can be used to specify which commits you want to pull. " +
518 "-B can be used to specify which bookmark you want to pull." +
519 "\n\n"))
520 for v in args[1:]:
521 if v in repo._bookmarks:
522 cmd['-B'] = v
523 else:
524 cmd['-r'] = v
525
526 ui.status((str(cmd)), "\n")
527
528 def grep(ui, repo, *args, **kwargs):
529 cmdoptions = [
530 ]
531 args, opts = parseoptions(ui, cmdoptions, args)
532
533 cmd = Command('grep')
534
535 # For basic usage, git grep and hg grep are the same. They both have the
536 # pattern first, followed by paths.
537 cmd.extend(args)
538
539 ui.status((str(cmd)), "\n")
540
541 def init(ui, repo, *args, **kwargs):
542 cmdoptions = [
543 ]
544 args, opts = parseoptions(ui, cmdoptions, args)
545
546 cmd = Command('init')
547
548 if len(args) > 0:
549 cmd.append(args[0])
550
551 ui.status((str(cmd)), "\n")
552
553 def log(ui, repo, *args, **kwargs):
554 cmdoptions = [
555 ('', 'follow', None, ''),
556 ('', 'decorate', None, ''),
557 ('n', 'number', '', ''),
558 ('1', '1', None, ''),
559 ('', 'pretty', '', ''),
560 ('', 'format', '', ''),
561 ('', 'oneline', None, ''),
562 ('', 'stat', None, ''),
563 ('', 'graph', None, ''),
564 ('p', 'patch', None, ''),
565 ]
566 args, opts = parseoptions(ui, cmdoptions, args)
567 ui.status(_('note: -v prints the entire commit message like Git does. To ' +
568 'print just the first line, drop the -v.\n\n'))
569 ui.status(_("note: see hg help revset for information on how to filter " +
570 "log output.\n\n"))
571
572 cmd = Command('log')
573 cmd['-v'] = None
574
575 if opts.get('number'):
576 cmd['-l'] = opts.get('number')
577 if opts.get('1'):
578 cmd['-l'] = '1'
579 if opts.get('stat'):
580 cmd['--stat'] = None
581 if opts.get('graph'):
582 cmd['-G'] = None
583 if opts.get('patch'):
584 cmd['-p'] = None
585
586 if opts.get('pretty') or opts.get('format') or opts.get('oneline'):
587 format = opts.get('format', '')
588 if 'format:' in format:
589 ui.status(_("note: --format format:??? equates to Mercurial's " +
590 "--template. See hg help templates for more info.\n\n"))
591 cmd['--template'] = '???'
592 else:
593 ui.status(_("note: --pretty/format/oneline equate to Mercurial's " +
594 "--style or --template. See hg help templates for more info." +
595 "\n\n"))
596 cmd['--style'] = '???'
597
598 if len(args) > 0:
599 if '..' in args[0]:
600 since, until = args[0].split('..')
601 cmd['-r'] = "'%s::%s'" % (since, until)
602 del args[0]
603 cmd.extend(args)
604
605 ui.status((str(cmd)), "\n")
606
607 def lsfiles(ui, repo, *args, **kwargs):
608 cmdoptions = [
609 ('c', 'cached', None, ''),
610 ('d', 'deleted', None, ''),
611 ('m', 'modified', None, ''),
612 ('o', 'others', None, ''),
613 ('i', 'ignored', None, ''),
614 ('s', 'stage', None, ''),
615 ('z', '_zero', None, ''),
616 ]
617 args, opts = parseoptions(ui, cmdoptions, args)
618
619 if (opts.get('modified') or opts.get('deleted')
620 or opts.get('others') or opts.get('ignored')):
621 cmd = Command('status')
622 if opts.get('deleted'):
623 cmd['-d'] = None
624 if opts.get('modified'):
625 cmd['-m'] = None
626 if opts.get('others'):
627 cmd['-o'] = None
628 if opts.get('ignored'):
629 cmd['-i'] = None
630 else:
631 cmd = Command('files')
632 if opts.get('stage'):
633 ui.status(_("note: Mercurial doesn't have a staging area, ignoring "
634 "--stage\n"))
635 if opts.get('_zero'):
636 cmd['-0'] = None
637 cmd.append('.')
638 for include in args:
639 cmd['-I'] = util.shellquote(include)
640
641 ui.status((str(cmd)), "\n")
642
643 def merge(ui, repo, *args, **kwargs):
644 cmdoptions = [
645 ]
646 args, opts = parseoptions(ui, cmdoptions, args)
647
648 cmd = Command('merge')
649
650 if len(args) > 0:
651 cmd.append(args[len(args) - 1])
652
653 ui.status((str(cmd)), "\n")
654
655 def mergebase(ui, repo, *args, **kwargs):
656 cmdoptions = []
657 args, opts = parseoptions(ui, cmdoptions, args)
658
659 if len(args) != 2:
660 args = ['A', 'B']
661
662 cmd = Command("log -T '{node}\\n' -r 'ancestor(%s,%s)'"
663 % (args[0], args[1]))
664
665 ui.status(_('NOTE: ancestors() is part of the revset language.\n'),
666 _("Learn more about revsets with 'hg help revsets'\n\n"))
667 ui.status((str(cmd)), "\n")
668
669 def mergetool(ui, repo, *args, **kwargs):
670 cmdoptions = []
671 args, opts = parseoptions(ui, cmdoptions, args)
672
673 cmd = Command("resolve")
674
675 if len(args) == 0:
676 cmd['--all'] = None
677 cmd.extend(args)
678 ui.status((str(cmd)), "\n")
679
680 def mv(ui, repo, *args, **kwargs):
681 cmdoptions = [
682 ('f', 'force', None, ''),
683 ]
684 args, opts = parseoptions(ui, cmdoptions, args)
685
686 cmd = Command('mv')
687 cmd.extend(args)
688
689 if opts.get('force'):
690 cmd['-f'] = None
691
692 ui.status((str(cmd)), "\n")
693
694 def pull(ui, repo, *args, **kwargs):
695 cmdoptions = [
696 ('', 'all', None, ''),
697 ('f', 'force', None, ''),
698 ('r', 'rebase', None, ''),
699 ]
700 args, opts = parseoptions(ui, cmdoptions, args)
701
702 cmd = Command('pull')
703 cmd['--rebase'] = None
704
705 if len(args) > 0:
706 cmd.append(args[0])
707 if len(args) > 1:
708 ui.status(_("note: Mercurial doesn't have refspecs. " +
709 "-r can be used to specify which commits you want to pull. " +
710 "-B can be used to specify which bookmark you want to pull." +
711 "\n\n"))
712 for v in args[1:]:
713 if v in repo._bookmarks:
714 cmd['-B'] = v
715 else:
716 cmd['-r'] = v
717
718 ui.status((str(cmd)), "\n")
719
720 def push(ui, repo, *args, **kwargs):
721 cmdoptions = [
722 ('', 'all', None, ''),
723 ('f', 'force', None, ''),
724 ]
725 args, opts = parseoptions(ui, cmdoptions, args)
726
727 cmd = Command('push')
728
729 if len(args) > 0:
730 cmd.append(args[0])
731 if len(args) > 1:
732 ui.status(_("note: Mercurial doesn't have refspecs. " +
733 "-r can be used to specify which commits you want to push. " +
734 "-B can be used to specify which bookmark you want to push." +
735 "\n\n"))
736 for v in args[1:]:
737 if v in repo._bookmarks:
738 cmd['-B'] = v
739 else:
740 cmd['-r'] = v
741
742 if opts.get('force'):
743 cmd['-f'] = None
744
745 ui.status((str(cmd)), "\n")
746
747 def rebase(ui, repo, *args, **kwargs):
748 cmdoptions = [
749 ('', 'all', None, ''),
750 ('i', 'interactive', None, ''),
751 ('', 'onto', '', ''),
752 ('', 'abort', None, ''),
753 ('', 'continue', None, ''),
754 ('', 'skip', None, ''),
755 ]
756 args, opts = parseoptions(ui, cmdoptions, args)
757
758 if opts.get('interactive'):
759 ui.status(_("note: hg histedit does not perform a rebase. " +
760 "It just edits history.\n\n"))
761 cmd = Command('histedit')
762 if len(args) > 0:
763 ui.status(_("also note: 'hg histedit' will automatically detect"
764 " your stack, so no second argument is necessary.\n\n"))
765 ui.status((str(cmd)), "\n")
766 return
767
768 if opts.get('skip'):
769 cmd = Command('revert --all -r .')
770 ui.status((str(cmd)), "\n")
771
772 cmd = Command('rebase')
773
774 if opts.get('continue') or opts.get('skip'):
775 cmd['--continue'] = None
776 if opts.get('abort'):
777 cmd['--abort'] = None
778
779 if opts.get('onto'):
780 ui.status(_("note: if you're trying to lift a commit off one branch, " +
781 "try hg rebase -d <destination commit> -s <commit to be lifted>" +
782 "\n\n"))
783 cmd['-d'] = convert(opts.get('onto'))
784 if len(args) < 2:
785 raise error.Abort("Expected format: git rebase --onto X Y Z")
786 cmd['-s'] = "'::%s - ::%s'" % (convert(args[1]), convert(args[0]))
787 else:
788 if len(args) == 1:
789 cmd['-d'] = convert(args[0])
790 elif len(args) == 2:
791 cmd['-d'] = convert(args[0])
792 cmd['-b'] = convert(args[1])
793
794 ui.status((str(cmd)), "\n")
795
796 def reflog(ui, repo, *args, **kwargs):
797 cmdoptions = [
798 ('', 'all', None, ''),
799 ]
800 args, opts = parseoptions(ui, cmdoptions, args)
801
802 cmd = Command('journal')
803 if opts.get('all'):
804 cmd['--all'] = None
805 if len(args) > 0:
806 cmd.append(args[0])
807
808 ui.status(str(cmd), "\n\n")
809 ui.status(_("note: in hg commits can be deleted from repo but we always"
810 " have backups.\n"
811 "Please use 'hg backups --restore' or 'hg reset'" +
812 " to restore from backups.\n"))
813
814 def reset(ui, repo, *args, **kwargs):
815 cmdoptions = [
816 ('', 'soft', None, ''),
817 ('', 'hard', None, ''),
818 ('', 'mixed', None, ''),
819 ]
820 args, opts = parseoptions(ui, cmdoptions, args)
821
822 commit = convert(args[0] if len(args) > 0 else '.')
823 hard = opts.get('hard')
824
825 if opts.get('mixed'):
826 ui.status(_('NOTE: --mixed has no meaning since mercurial has no ' +
827 'staging area\n\n'))
828
829 cmd = Command('reset')
830 if hard:
831 cmd.append('--clean')
832 cmd.append(commit)
833
834 ui.status((str(cmd)), "\n")
835
836 def revert(ui, repo, *args, **kwargs):
837 cmdoptions = [
838 ]
839 args, opts = parseoptions(ui, cmdoptions, args)
840
841 if len(args) > 1:
842 ui.status(_("note: hg backout doesn't support multiple commits at " +
843 "once\n\n"))
844
845 cmd = Command('backout')
846 if args:
847 cmd.append(args[0])
848
849 ui.status((str(cmd)), "\n")
850
851 def revparse(ui, repo, *args, **kwargs):
852 cmdoptions = [
853 ('', 'show-cdup', None, ''),
854 ('', 'show-toplevel', None, ''),
855 ]
856 args, opts = parseoptions(ui, cmdoptions, args)
857
858 if opts.get('show_cdup') or opts.get('show_toplevel'):
859 cmd = Command('root')
860 if opts.get('show_cdup'):
861 ui.status(_("note: hg root prints the root of the repository\n\n"))
862 ui.status((str(cmd)), "\n")
863 else:
864 ui.status(_("note: see hg help revset for how to refer to commits\n"))
865
866 def rm(ui, repo, *args, **kwargs):
867 cmdoptions = [
868 ('f', 'force', None, ''),
869 ('n', 'dry-run', None, ''),
870 ]
871 args, opts = parseoptions(ui, cmdoptions, args)
872
873 cmd = Command('rm')
874 cmd.extend(args)
875
876 if opts.get('force'):
877 cmd['-f'] = None
878 if opts.get('dry_run'):
879 cmd['-n'] = None
880
881 ui.status((str(cmd)), "\n")
882
883 def show(ui, repo, *args, **kwargs):
884 cmdoptions = [
885 ('', 'name-status', None, ''),
886 ('', 'pretty', '', ''),
887 ('U', 'unified', int, ''),
888 ]
889 args, opts = parseoptions(ui, cmdoptions, args)
890
891 cmd = Command('show')
892 if opts.get('name_status'):
893 if opts.get('pretty') == 'format:':
894 cmd = Command('stat')
895 cmd['--change'] = 'tip'
896 else:
897 cmd = Command('log')
898 cmd.append('--style status')
899 cmd.append('-r tip')
900 elif len(args) > 0:
901 if ispath(repo, args[0]):
902 cmd.append('.')
903 cmd.extend(args)
904 if opts.get('unified'):
905 cmd.append('--config diff.unified=%d' % (opts['unified'],))
906 elif opts.get('unified'):
907 cmd.append('--config diff.unified=%d' % (opts['unified'],))
908
909 ui.status((str(cmd)), "\n")
910
911 def stash(ui, repo, *args, **kwargs):
912 cmdoptions = [
913 ]
914 args, opts = parseoptions(ui, cmdoptions, args)
915
916 cmd = Command('shelve')
917 action = args[0] if len(args) > 0 else None
918
919 if action == 'list':
920 cmd['-l'] = None
921 elif action == 'drop':
922 cmd['-d'] = None
923 if len(args) > 1:
924 cmd.append(args[1])
925 else:
926 cmd.append('<shelve name>')
927 elif action == 'pop' or action == 'apply':
928 cmd = Command('unshelve')
929 if len(args) > 1:
930 cmd.append(args[1])
931 if action == 'apply':
932 cmd['--keep'] = None
933 elif (action == 'branch' or action == 'show' or action == 'clear'
934 or action == 'create'):
935 ui.status(_("note: Mercurial doesn't have equivalents to the " +
936 "git stash branch, show, clear, or create actions.\n\n"))
937 return
938 else:
939 if len(args) > 0:
940 if args[0] != 'save':
941 cmd['--name'] = args[0]
942 elif len(args) > 1:
943 cmd['--name'] = args[1]
944
945 ui.status((str(cmd)), "\n")
946
947 def status(ui, repo, *args, **kwargs):
948 cmdoptions = [
949 ('', 'ignored', None, ''),
950 ]
951 args, opts = parseoptions(ui, cmdoptions, args)
952
953 cmd = Command('status')
954 cmd.extend(args)
955
956 if opts.get('ignored'):
957 cmd['-i'] = None
958
959 ui.status((str(cmd)), "\n")
960
961 def svn(ui, repo, *args, **kwargs):
962 svncmd = args[0]
963 if not svncmd in gitsvncommands:
964 ui.warn(_("error: unknown git svn command %s\n") % (svncmd))
965
966 args = args[1:]
967 return gitsvncommands[svncmd](ui, repo, *args, **kwargs)
968
969 def svndcommit(ui, repo, *args, **kwargs):
970 cmdoptions = [
971 ]
972 args, opts = parseoptions(ui, cmdoptions, args)
973
974 cmd = Command('push')
975
976 ui.status((str(cmd)), "\n")
977
978 def svnfetch(ui, repo, *args, **kwargs):
979 cmdoptions = [
980 ]
981 args, opts = parseoptions(ui, cmdoptions, args)
982
983 cmd = Command('pull')
984 cmd.append('default-push')
985
986 ui.status((str(cmd)), "\n")
987
988 def svnfindrev(ui, repo, *args, **kwargs):
989 cmdoptions = [
990 ]
991 args, opts = parseoptions(ui, cmdoptions, args)
992
993 cmd = Command('log')
994 cmd['-r'] = args[0]
995
996 ui.status((str(cmd)), "\n")
997
998 def svnrebase(ui, repo, *args, **kwargs):
999 cmdoptions = [
1000 ('l', 'local', None, ''),
1001 ]
1002 args, opts = parseoptions(ui, cmdoptions, args)
1003
1004 pullcmd = Command('pull')
1005 pullcmd.append('default-push')
1006 rebasecmd = Command('rebase')
1007 rebasecmd.append('tip')
1008
1009 cmd = pullcmd & rebasecmd
1010
1011 ui.status((str(cmd)), "\n")
1012
1013 def tag(ui, repo, *args, **kwargs):
1014 cmdoptions = [
1015 ('f', 'force', None, ''),
1016 ('l', 'list', None, ''),
1017 ('d', 'delete', None, ''),
1018 ]
1019 args, opts = parseoptions(ui, cmdoptions, args)
1020
1021 if opts.get('list'):
1022 cmd = Command('tags')
1023 else:
1024 cmd = Command('tag')
1025 cmd.append(args[0])
1026 if len(args) > 1:
1027 cmd['-r'] = args[1]
1028
1029 if opts.get('delete'):
1030 cmd['--remove'] = None
1031
1032 if opts.get('force'):
1033 cmd['-f'] = None
1034
1035 ui.status((str(cmd)), "\n")
1036
1037 gitcommands = {
1038 'add': add,
1039 'am': am,
1040 'apply': apply,
1041 'bisect': bisect,
1042 'blame': blame,
1043 'branch': branch,
1044 'checkout': checkout,
1045 'cherry-pick': cherrypick,
1046 'clean': clean,
1047 'clone': clone,
1048 'commit': commit,
1049 'diff': diff,
1050 'difftool': difftool,
1051 'fetch': fetch,
1052 'grep': grep,
1053 'init': init,
1054 'log': log,
1055 'ls-files': lsfiles,
1056 'merge': merge,
1057 'merge-base': mergebase,
1058 'mergetool': mergetool,
1059 'mv': mv,
1060 'pull': pull,
1061 'push': push,
1062 'rebase': rebase,
1063 'reflog': reflog,
1064 'reset': reset,
1065 'revert': revert,
1066 'rev-parse': revparse,
1067 'rm': rm,
1068 'show': show,
1069 'stash': stash,
1070 'status': status,
1071 'svn': svn,
1072 'tag': tag,
1073 'whatchanged': deprecated,
1074 }
1075
1076 gitsvncommands = {
1077 'dcommit': svndcommit,
1078 'fetch': svnfetch,
1079 'find-rev': svnfindrev,
1080 'rebase': svnrebase,
1081 }
@@ -0,0 +1,258 b''
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
3 > githelp =
4 > EOF
5
6 $ hg init repo
7 $ cd repo
8 $ echo foo > test_file
9 $ mkdir dir
10 $ echo foo > dir/file
11 $ echo foo > removed_file
12 $ echo foo > deleted_file
13 $ hg add -q .
14 $ hg commit -m 'bar'
15 $ hg bookmark both
16 $ touch both
17 $ touch untracked_file
18 $ hg remove removed_file
19 $ rm deleted_file
20
21 githelp on a single command should succeed
22 $ hg githelp -- commit
23 hg commit
24 $ hg githelp -- git commit
25 hg commit
26
27 githelp should fail nicely if we don't give it arguments
28 $ hg githelp
29 abort: missing git command - usage: hg githelp -- <git command>
30 [255]
31 $ hg githelp -- git
32 abort: missing git command - usage: hg githelp -- <git command>
33 [255]
34
35 githelp on a command with options should succeed
36 $ hg githelp -- commit -pm "abc"
37 hg record -m 'abc'
38
39 githelp on a command with standalone unrecognized option should succeed with warning
40 $ hg githelp -- commit -p -v
41 ignoring unknown option -v
42 hg record
43
44 githelp on a command with unrecognized option packed with other options should fail with error
45 $ hg githelp -- commit -pv
46 abort: unknown option v packed with other options
47 Please try passing the option as it's own flag: -v
48 [255]
49
50 githelp for git rebase --skip
51 $ hg githelp -- git rebase --skip
52 hg revert --all -r .
53 hg rebase --continue
54
55 githelp for git commit --amend (hg commit --amend pulls up an editor)
56 $ hg githelp -- commit --amend
57 hg commit --amend
58
59 githelp for git commit --amend --no-edit (hg amend does not pull up an editor)
60 $ hg githelp -- commit --amend --no-edit
61 hg amend
62
63 githelp for git checkout -- . (checking out a directory)
64 $ hg githelp -- checkout -- .
65 note: use --no-backup to avoid creating .orig files
66
67 hg revert .
68
69 githelp for git checkout "HEAD^" (should still work to pass a rev)
70 $ hg githelp -- checkout "HEAD^"
71 hg update .^
72
73 githelp checkout: args after -- should be treated as paths no matter what
74 $ hg githelp -- checkout -- HEAD
75 note: use --no-backup to avoid creating .orig files
76
77 hg revert HEAD
78
79 githelp for git checkout with rev and path
80 $ hg githelp -- checkout "HEAD^" -- file.txt
81 note: use --no-backup to avoid creating .orig files
82
83 hg revert -r .^ file.txt
84
85 githelp for git with rev and path, without separator
86 $ hg githelp -- checkout "HEAD^" file.txt
87 note: use --no-backup to avoid creating .orig files
88
89 hg revert -r .^ file.txt
90
91 githelp for checkout with a file as first argument
92 $ hg githelp -- checkout test_file
93 note: use --no-backup to avoid creating .orig files
94
95 hg revert test_file
96
97 githelp for checkout with a removed file as first argument
98 $ hg githelp -- checkout removed_file
99 note: use --no-backup to avoid creating .orig files
100
101 hg revert removed_file
102
103 githelp for checkout with a deleted file as first argument
104 $ hg githelp -- checkout deleted_file
105 note: use --no-backup to avoid creating .orig files
106
107 hg revert deleted_file
108
109 githelp for checkout with a untracked file as first argument
110 $ hg githelp -- checkout untracked_file
111 note: use --no-backup to avoid creating .orig files
112
113 hg revert untracked_file
114
115 githelp for checkout with a directory as first argument
116 $ hg githelp -- checkout dir
117 note: use --no-backup to avoid creating .orig files
118
119 hg revert dir
120
121 githelp for checkout when not in repo root
122 $ cd dir
123 $ hg githelp -- checkout file
124 note: use --no-backup to avoid creating .orig files
125
126 hg revert file
127
128 $ cd ..
129
130 githelp for checkout with an argument that is both a file and a revision
131 $ hg githelp -- checkout both
132 hg update both
133
134 githelp for checkout with the -p option
135 $ hg githelp -- git checkout -p xyz
136 hg revert -i -r xyz
137
138 $ hg githelp -- git checkout -p xyz -- abc
139 note: use --no-backup to avoid creating .orig files
140
141 hg revert -i -r xyz abc
142
143 githelp for checkout with the -f option and a rev
144 $ hg githelp -- git checkout -f xyz
145 hg update -C xyz
146 $ hg githelp -- git checkout --force xyz
147 hg update -C xyz
148
149 githelp for checkout with the -f option without an arg
150 $ hg githelp -- git checkout -f
151 hg revert --all
152 $ hg githelp -- git checkout --force
153 hg revert --all
154
155 githelp for grep with pattern and path
156 $ hg githelp -- grep shrubbery flib/intern/
157 hg grep shrubbery flib/intern/
158
159 githelp for reset, checking ~ in git becomes ~1 in mercurial
160 $ hg githelp -- reset HEAD~
161 hg reset .~1
162 $ hg githelp -- reset "HEAD^"
163 hg reset .^
164 $ hg githelp -- reset HEAD~3
165 hg reset .~3
166
167 githelp for git show --name-status
168 $ hg githelp -- git show --name-status
169 hg log --style status -r tip
170
171 githelp for git show --pretty=format: --name-status
172 $ hg githelp -- git show --pretty=format: --name-status
173 hg stat --change tip
174
175 githelp for show with no arguments
176 $ hg githelp -- show
177 hg show
178
179 githelp for show with a path
180 $ hg githelp -- show test_file
181 hg show . test_file
182
183 githelp for show with not a path:
184 $ hg githelp -- show rev
185 hg show rev
186
187 githelp for show with many arguments
188 $ hg githelp -- show argone argtwo
189 hg show argone argtwo
190 $ hg githelp -- show test_file argone argtwo
191 hg show . test_file argone argtwo
192
193 githelp for show with --unified options
194 $ hg githelp -- show --unified=10
195 hg show --config diff.unified=10
196 $ hg githelp -- show -U100
197 hg show --config diff.unified=100
198
199 githelp for show with a path and --unified
200 $ hg githelp -- show -U20 test_file
201 hg show . test_file --config diff.unified=20
202
203 githelp for stash drop without name
204 $ hg githelp -- git stash drop
205 hg shelve -d <shelve name>
206
207 githelp for stash drop with name
208 $ hg githelp -- git stash drop xyz
209 hg shelve -d xyz
210
211 githelp for whatchanged should show deprecated message
212 $ hg githelp -- whatchanged -p
213 This command has been deprecated in the git project, thus isn't supported by this tool.
214
215
216 githelp for git branch -m renaming
217 $ hg githelp -- git branch -m old new
218 hg bookmark -m old new
219
220 When the old name is omitted, git branch -m new renames the current branch.
221 $ hg githelp -- git branch -m new
222 hg bookmark -m `hg log -T"{activebookmark}" -r .` new
223
224 Branch deletion in git strips commits
225 $ hg githelp -- git branch -d
226 hg strip -B
227 $ hg githelp -- git branch -d feature
228 hg strip -B feature -B
229 $ hg githelp -- git branch --delete experiment1 experiment2
230 hg strip -B experiment1 -B experiment2 -B
231
232 githelp for reuse message using the shorthand
233 $ hg githelp -- git commit -C deadbeef
234 hg commit -M deadbeef
235
236 githelp for reuse message using the the long version
237 $ hg githelp -- git commit --reuse-message deadbeef
238 hg commit -M deadbeef
239
240 githelp for apply with no options
241 $ hg githelp -- apply
242 hg import --no-commit
243
244 githelp for apply with directory strip custom
245 $ hg githelp -- apply -p 5
246 hg import --no-commit -p 5
247
248 git merge-base
249 $ hg githelp -- git merge-base --is-ancestor
250 ignoring unknown option --is-ancestor
251 NOTE: ancestors() is part of the revset language.
252 Learn more about revsets with 'hg help revsets'
253
254 hg log -T '{node}\n' -r 'ancestor(A,B)'
255
256 githelp for git blame
257 $ hg githelp -- git blame
258 hg annotate -udl
@@ -261,6 +261,7 b' Test extension help:'
261 eol automatically manage newlines in repository files
261 eol automatically manage newlines in repository files
262 extdiff command to allow external programs to compare revisions
262 extdiff command to allow external programs to compare revisions
263 factotum http authentication with factotum
263 factotum http authentication with factotum
264 githelp try mapping git commands to Mercurial commands
264 gpg commands to sign and verify changesets
265 gpg commands to sign and verify changesets
265 hgk browse the repository in a graphical way
266 hgk browse the repository in a graphical way
266 highlight syntax highlighting for hgweb (requires Pygments)
267 highlight syntax highlighting for hgweb (requires Pygments)
General Comments 0
You need to be logged in to leave comments. Login now