102 dateutil, |
102 dateutil, |
103 stringutil, |
103 stringutil, |
104 ) |
104 ) |
105 |
105 |
106 release = lockmod.release |
106 release = lockmod.release |
107 seriesopts = [('s', 'summary', None, _('print first line of patch header'))] |
107 seriesopts = [(b's', b'summary', None, _(b'print first line of patch header'))] |
108 |
108 |
109 cmdtable = {} |
109 cmdtable = {} |
110 command = registrar.command(cmdtable) |
110 command = registrar.command(cmdtable) |
111 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
111 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
112 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
112 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
113 # be specifying the version(s) of Mercurial they are tested with, or |
113 # be specifying the version(s) of Mercurial they are tested with, or |
114 # leave the attribute unspecified. |
114 # leave the attribute unspecified. |
115 testedwith = 'ships-with-hg-core' |
115 testedwith = b'ships-with-hg-core' |
116 |
116 |
117 configtable = {} |
117 configtable = {} |
118 configitem = registrar.configitem(configtable) |
118 configitem = registrar.configitem(configtable) |
119 |
119 |
120 configitem( |
120 configitem( |
121 'mq', 'git', default='auto', |
121 b'mq', b'git', default=b'auto', |
122 ) |
122 ) |
123 configitem( |
123 configitem( |
124 'mq', 'keepchanges', default=False, |
124 b'mq', b'keepchanges', default=False, |
125 ) |
125 ) |
126 configitem( |
126 configitem( |
127 'mq', 'plain', default=False, |
127 b'mq', b'plain', default=False, |
128 ) |
128 ) |
129 configitem( |
129 configitem( |
130 'mq', 'secret', default=False, |
130 b'mq', b'secret', default=False, |
131 ) |
131 ) |
132 |
132 |
133 # force load strip extension formerly included in mq and import some utility |
133 # force load strip extension formerly included in mq and import some utility |
134 try: |
134 try: |
135 stripext = extensions.find('strip') |
135 stripext = extensions.find(b'strip') |
136 except KeyError: |
136 except KeyError: |
137 # note: load is lazy so we could avoid the try-except, |
137 # note: load is lazy so we could avoid the try-except, |
138 # but I (marmoute) prefer this explicit code. |
138 # but I (marmoute) prefer this explicit code. |
139 class dummyui(object): |
139 class dummyui(object): |
140 def debug(self, msg): |
140 def debug(self, msg): |
141 pass |
141 pass |
142 |
142 |
143 def log(self, event, msgfmt, *msgargs, **opts): |
143 def log(self, event, msgfmt, *msgargs, **opts): |
144 pass |
144 pass |
145 |
145 |
146 stripext = extensions.load(dummyui(), 'strip', '') |
146 stripext = extensions.load(dummyui(), b'strip', b'') |
147 |
147 |
148 strip = stripext.strip |
148 strip = stripext.strip |
149 |
149 |
150 |
150 |
151 def checksubstate(repo, baserev=None): |
151 def checksubstate(repo, baserev=None): |
309 subject = None |
309 subject = None |
310 branch = None |
310 branch = None |
311 nodeid = None |
311 nodeid = None |
312 diffstart = 0 |
312 diffstart = 0 |
313 |
313 |
314 for line in open(pf, 'rb'): |
314 for line in open(pf, b'rb'): |
315 line = line.rstrip() |
315 line = line.rstrip() |
316 if line.startswith('diff --git') or ( |
316 if line.startswith(b'diff --git') or ( |
317 diffstart and line.startswith('+++ ') |
317 diffstart and line.startswith(b'+++ ') |
318 ): |
318 ): |
319 diffstart = 2 |
319 diffstart = 2 |
320 break |
320 break |
321 diffstart = 0 # reset |
321 diffstart = 0 # reset |
322 if line.startswith("--- "): |
322 if line.startswith(b"--- "): |
323 diffstart = 1 |
323 diffstart = 1 |
324 continue |
324 continue |
325 elif format == "hgpatch": |
325 elif format == b"hgpatch": |
326 # parse values when importing the result of an hg export |
326 # parse values when importing the result of an hg export |
327 if line.startswith("# User "): |
327 if line.startswith(b"# User "): |
328 user = line[7:] |
328 user = line[7:] |
329 elif line.startswith("# Date "): |
329 elif line.startswith(b"# Date "): |
330 date = line[7:] |
330 date = line[7:] |
331 elif line.startswith("# Parent "): |
331 elif line.startswith(b"# Parent "): |
332 parent = line[9:].lstrip() # handle double trailing space |
332 parent = line[9:].lstrip() # handle double trailing space |
333 elif line.startswith("# Branch "): |
333 elif line.startswith(b"# Branch "): |
334 branch = line[9:] |
334 branch = line[9:] |
335 elif line.startswith("# Node ID "): |
335 elif line.startswith(b"# Node ID "): |
336 nodeid = line[10:] |
336 nodeid = line[10:] |
337 elif not line.startswith("# ") and line: |
337 elif not line.startswith(b"# ") and line: |
338 message.append(line) |
338 message.append(line) |
339 format = None |
339 format = None |
340 elif line == '# HG changeset patch': |
340 elif line == b'# HG changeset patch': |
341 message = [] |
341 message = [] |
342 format = "hgpatch" |
342 format = b"hgpatch" |
343 elif format != "tagdone" and ( |
343 elif format != b"tagdone" and ( |
344 line.startswith("Subject: ") or line.startswith("subject: ") |
344 line.startswith(b"Subject: ") or line.startswith(b"subject: ") |
345 ): |
345 ): |
346 subject = line[9:] |
346 subject = line[9:] |
347 format = "tag" |
347 format = b"tag" |
348 elif format != "tagdone" and ( |
348 elif format != b"tagdone" and ( |
349 line.startswith("From: ") or line.startswith("from: ") |
349 line.startswith(b"From: ") or line.startswith(b"from: ") |
350 ): |
350 ): |
351 user = line[6:] |
351 user = line[6:] |
352 format = "tag" |
352 format = b"tag" |
353 elif format != "tagdone" and ( |
353 elif format != b"tagdone" and ( |
354 line.startswith("Date: ") or line.startswith("date: ") |
354 line.startswith(b"Date: ") or line.startswith(b"date: ") |
355 ): |
355 ): |
356 date = line[6:] |
356 date = line[6:] |
357 format = "tag" |
357 format = b"tag" |
358 elif format == "tag" and line == "": |
358 elif format == b"tag" and line == b"": |
359 # when looking for tags (subject: from: etc) they |
359 # when looking for tags (subject: from: etc) they |
360 # end once you find a blank line in the source |
360 # end once you find a blank line in the source |
361 format = "tagdone" |
361 format = b"tagdone" |
362 elif message or line: |
362 elif message or line: |
363 message.append(line) |
363 message.append(line) |
364 comments.append(line) |
364 comments.append(line) |
365 |
365 |
366 eatdiff(message) |
366 eatdiff(message) |
384 self.nodeid = nodeid |
384 self.nodeid = nodeid |
385 self.branch = branch |
385 self.branch = branch |
386 self.haspatch = diffstart > 1 |
386 self.haspatch = diffstart > 1 |
387 self.plainmode = ( |
387 self.plainmode = ( |
388 plainmode |
388 plainmode |
389 or '# HG changeset patch' not in self.comments |
389 or b'# HG changeset patch' not in self.comments |
390 and any( |
390 and any( |
391 c.startswith('Date: ') or c.startswith('From: ') |
391 c.startswith(b'Date: ') or c.startswith(b'From: ') |
392 for c in self.comments |
392 for c in self.comments |
393 ) |
393 ) |
394 ) |
394 ) |
395 |
395 |
396 def setuser(self, user): |
396 def setuser(self, user): |
397 try: |
397 try: |
398 inserthgheader(self.comments, '# User ', user) |
398 inserthgheader(self.comments, b'# User ', user) |
399 except ValueError: |
399 except ValueError: |
400 if self.plainmode: |
400 if self.plainmode: |
401 insertplainheader(self.comments, 'From', user) |
401 insertplainheader(self.comments, b'From', user) |
402 else: |
402 else: |
403 tmp = ['# HG changeset patch', '# User ' + user] |
403 tmp = [b'# HG changeset patch', b'# User ' + user] |
404 self.comments = tmp + self.comments |
404 self.comments = tmp + self.comments |
405 self.user = user |
405 self.user = user |
406 |
406 |
407 def setdate(self, date): |
407 def setdate(self, date): |
408 try: |
408 try: |
409 inserthgheader(self.comments, '# Date ', date) |
409 inserthgheader(self.comments, b'# Date ', date) |
410 except ValueError: |
410 except ValueError: |
411 if self.plainmode: |
411 if self.plainmode: |
412 insertplainheader(self.comments, 'Date', date) |
412 insertplainheader(self.comments, b'Date', date) |
413 else: |
413 else: |
414 tmp = ['# HG changeset patch', '# Date ' + date] |
414 tmp = [b'# HG changeset patch', b'# Date ' + date] |
415 self.comments = tmp + self.comments |
415 self.comments = tmp + self.comments |
416 self.date = date |
416 self.date = date |
417 |
417 |
418 def setparent(self, parent): |
418 def setparent(self, parent): |
419 try: |
419 try: |
420 inserthgheader(self.comments, '# Parent ', parent) |
420 inserthgheader(self.comments, b'# Parent ', parent) |
421 except ValueError: |
421 except ValueError: |
422 if not self.plainmode: |
422 if not self.plainmode: |
423 tmp = ['# HG changeset patch', '# Parent ' + parent] |
423 tmp = [b'# HG changeset patch', b'# Parent ' + parent] |
424 self.comments = tmp + self.comments |
424 self.comments = tmp + self.comments |
425 self.parent = parent |
425 self.parent = parent |
426 |
426 |
427 def setmessage(self, message): |
427 def setmessage(self, message): |
428 if self.comments: |
428 if self.comments: |
429 self._delmsg() |
429 self._delmsg() |
430 self.message = [message] |
430 self.message = [message] |
431 if message: |
431 if message: |
432 if self.plainmode and self.comments and self.comments[-1]: |
432 if self.plainmode and self.comments and self.comments[-1]: |
433 self.comments.append('') |
433 self.comments.append(b'') |
434 self.comments.append(message) |
434 self.comments.append(message) |
435 |
435 |
436 def __bytes__(self): |
436 def __bytes__(self): |
437 s = '\n'.join(self.comments).rstrip() |
437 s = b'\n'.join(self.comments).rstrip() |
438 if not s: |
438 if not s: |
439 return '' |
439 return b'' |
440 return s + '\n\n' |
440 return s + b'\n\n' |
441 |
441 |
442 __str__ = encoding.strmethod(__bytes__) |
442 __str__ = encoding.strmethod(__bytes__) |
443 |
443 |
444 def _delmsg(self): |
444 def _delmsg(self): |
445 '''Remove existing message, keeping the rest of the comments fields. |
445 '''Remove existing message, keeping the rest of the comments fields. |
446 If comments contains 'subject: ', message will prepend |
446 If comments contains 'subject: ', message will prepend |
447 the field and a blank line.''' |
447 the field and a blank line.''' |
448 if self.message: |
448 if self.message: |
449 subj = 'subject: ' + self.message[0].lower() |
449 subj = b'subject: ' + self.message[0].lower() |
450 for i in pycompat.xrange(len(self.comments)): |
450 for i in pycompat.xrange(len(self.comments)): |
451 if subj == self.comments[i].lower(): |
451 if subj == self.comments[i].lower(): |
452 del self.comments[i] |
452 del self.comments[i] |
453 self.message = self.message[2:] |
453 self.message = self.message[2:] |
454 break |
454 break |
483 |
483 |
484 class queue(object): |
484 class queue(object): |
485 def __init__(self, ui, baseui, path, patchdir=None): |
485 def __init__(self, ui, baseui, path, patchdir=None): |
486 self.basepath = path |
486 self.basepath = path |
487 try: |
487 try: |
488 with open(os.path.join(path, 'patches.queue'), r'rb') as fh: |
488 with open(os.path.join(path, b'patches.queue'), r'rb') as fh: |
489 cur = fh.read().rstrip() |
489 cur = fh.read().rstrip() |
490 |
490 |
491 if not cur: |
491 if not cur: |
492 curpath = os.path.join(path, 'patches') |
492 curpath = os.path.join(path, b'patches') |
493 else: |
493 else: |
494 curpath = os.path.join(path, 'patches-' + cur) |
494 curpath = os.path.join(path, b'patches-' + cur) |
495 except IOError: |
495 except IOError: |
496 curpath = os.path.join(path, 'patches') |
496 curpath = os.path.join(path, b'patches') |
497 self.path = patchdir or curpath |
497 self.path = patchdir or curpath |
498 self.opener = vfsmod.vfs(self.path) |
498 self.opener = vfsmod.vfs(self.path) |
499 self.ui = ui |
499 self.ui = ui |
500 self.baseui = baseui |
500 self.baseui = baseui |
501 self.applieddirty = False |
501 self.applieddirty = False |
502 self.seriesdirty = False |
502 self.seriesdirty = False |
503 self.added = [] |
503 self.added = [] |
504 self.seriespath = "series" |
504 self.seriespath = b"series" |
505 self.statuspath = "status" |
505 self.statuspath = b"status" |
506 self.guardspath = "guards" |
506 self.guardspath = b"guards" |
507 self.activeguards = None |
507 self.activeguards = None |
508 self.guardsdirty = False |
508 self.guardsdirty = False |
509 # Handle mq.git as a bool with extended values |
509 # Handle mq.git as a bool with extended values |
510 gitmode = ui.config('mq', 'git').lower() |
510 gitmode = ui.config(b'mq', b'git').lower() |
511 boolmode = stringutil.parsebool(gitmode) |
511 boolmode = stringutil.parsebool(gitmode) |
512 if boolmode is not None: |
512 if boolmode is not None: |
513 if boolmode: |
513 if boolmode: |
514 gitmode = 'yes' |
514 gitmode = b'yes' |
515 else: |
515 else: |
516 gitmode = 'no' |
516 gitmode = b'no' |
517 self.gitmode = gitmode |
517 self.gitmode = gitmode |
518 # deprecated config: mq.plain |
518 # deprecated config: mq.plain |
519 self.plainmode = ui.configbool('mq', 'plain') |
519 self.plainmode = ui.configbool(b'mq', b'plain') |
520 self.checkapplied = True |
520 self.checkapplied = True |
521 |
521 |
522 @util.propertycache |
522 @util.propertycache |
523 def applied(self): |
523 def applied(self): |
524 def parselines(lines): |
524 def parselines(lines): |
525 for l in lines: |
525 for l in lines: |
526 entry = l.split(':', 1) |
526 entry = l.split(b':', 1) |
527 if len(entry) > 1: |
527 if len(entry) > 1: |
528 n, name = entry |
528 n, name = entry |
529 yield statusentry(bin(n), name) |
529 yield statusentry(bin(n), name) |
530 elif l.strip(): |
530 elif l.strip(): |
531 self.ui.warn( |
531 self.ui.warn( |
532 _('malformated mq status line: %s\n') |
532 _(b'malformated mq status line: %s\n') |
533 % stringutil.pprint(entry) |
533 % stringutil.pprint(entry) |
534 ) |
534 ) |
535 # else we ignore empty lines |
535 # else we ignore empty lines |
536 |
536 |
537 try: |
537 try: |
627 |
627 |
628 def parseseries(self): |
628 def parseseries(self): |
629 self.series = [] |
629 self.series = [] |
630 self.seriesguards = [] |
630 self.seriesguards = [] |
631 for l in self.fullseries: |
631 for l in self.fullseries: |
632 h = l.find('#') |
632 h = l.find(b'#') |
633 if h == -1: |
633 if h == -1: |
634 patch = l |
634 patch = l |
635 comment = '' |
635 comment = b'' |
636 elif h == 0: |
636 elif h == 0: |
637 continue |
637 continue |
638 else: |
638 else: |
639 patch = l[:h] |
639 patch = l[:h] |
640 comment = l[h:] |
640 comment = l[h:] |
641 patch = patch.strip() |
641 patch = patch.strip() |
642 if patch: |
642 if patch: |
643 if patch in self.series: |
643 if patch in self.series: |
644 raise error.Abort( |
644 raise error.Abort( |
645 _('%s appears more than once in %s') |
645 _(b'%s appears more than once in %s') |
646 % (patch, self.join(self.seriespath)) |
646 % (patch, self.join(self.seriespath)) |
647 ) |
647 ) |
648 self.series.append(patch) |
648 self.series.append(patch) |
649 self.seriesguards.append(self.guard_re.findall(comment)) |
649 self.seriesguards.append(self.guard_re.findall(comment)) |
650 |
650 |
651 def checkguard(self, guard): |
651 def checkguard(self, guard): |
652 if not guard: |
652 if not guard: |
653 return _('guard cannot be an empty string') |
653 return _(b'guard cannot be an empty string') |
654 bad_chars = '# \t\r\n\f' |
654 bad_chars = b'# \t\r\n\f' |
655 first = guard[0] |
655 first = guard[0] |
656 if first in '-+': |
656 if first in b'-+': |
657 return _('guard %r starts with invalid character: %r') % ( |
657 return _(b'guard %r starts with invalid character: %r') % ( |
658 guard, |
658 guard, |
659 first, |
659 first, |
660 ) |
660 ) |
661 for c in bad_chars: |
661 for c in bad_chars: |
662 if c in guard: |
662 if c in guard: |
663 return _('invalid character in guard %r: %r') % (guard, c) |
663 return _(b'invalid character in guard %r: %r') % (guard, c) |
664 |
664 |
665 def setactive(self, guards): |
665 def setactive(self, guards): |
666 for guard in guards: |
666 for guard in guards: |
667 bad = self.checkguard(guard) |
667 bad = self.checkguard(guard) |
668 if bad: |
668 if bad: |
669 raise error.Abort(bad) |
669 raise error.Abort(bad) |
670 guards = sorted(set(guards)) |
670 guards = sorted(set(guards)) |
671 self.ui.debug('active guards: %s\n' % ' '.join(guards)) |
671 self.ui.debug(b'active guards: %s\n' % b' '.join(guards)) |
672 self.activeguards = guards |
672 self.activeguards = guards |
673 self.guardsdirty = True |
673 self.guardsdirty = True |
674 |
674 |
675 def active(self): |
675 def active(self): |
676 if self.activeguards is None: |
676 if self.activeguards is None: |
840 |
841 |
841 if err == 0: |
842 if err == 0: |
842 return (err, n) |
843 return (err, n) |
843 |
844 |
844 if n is None: |
845 if n is None: |
845 raise error.Abort(_("apply failed for patch %s") % patch) |
846 raise error.Abort(_(b"apply failed for patch %s") % patch) |
846 |
847 |
847 self.ui.warn(_("patch didn't work out, merging %s\n") % patch) |
848 self.ui.warn(_(b"patch didn't work out, merging %s\n") % patch) |
848 |
849 |
849 # apply failed, strip away that rev and merge. |
850 # apply failed, strip away that rev and merge. |
850 hg.clean(repo, head) |
851 hg.clean(repo, head) |
851 strip(self.ui, repo, [n], update=False, backup=False) |
852 strip(self.ui, repo, [n], update=False, backup=False) |
852 |
853 |
853 ctx = repo[rev] |
854 ctx = repo[rev] |
854 ret = hg.merge(repo, rev) |
855 ret = hg.merge(repo, rev) |
855 if ret: |
856 if ret: |
856 raise error.Abort(_("update returned %d") % ret) |
857 raise error.Abort(_(b"update returned %d") % ret) |
857 n = newcommit(repo, None, ctx.description(), ctx.user(), force=True) |
858 n = newcommit(repo, None, ctx.description(), ctx.user(), force=True) |
858 if n is None: |
859 if n is None: |
859 raise error.Abort(_("repo commit failed")) |
860 raise error.Abort(_(b"repo commit failed")) |
860 try: |
861 try: |
861 ph = patchheader(mergeq.join(patch), self.plainmode) |
862 ph = patchheader(mergeq.join(patch), self.plainmode) |
862 except Exception: |
863 except Exception: |
863 raise error.Abort(_("unable to read %s") % patch) |
864 raise error.Abort(_(b"unable to read %s") % patch) |
864 |
865 |
865 diffopts = self.patchopts(diffopts, patch) |
866 diffopts = self.patchopts(diffopts, patch) |
866 patchf = self.opener(patch, "w") |
867 patchf = self.opener(patch, b"w") |
867 comments = bytes(ph) |
868 comments = bytes(ph) |
868 if comments: |
869 if comments: |
869 patchf.write(comments) |
870 patchf.write(comments) |
870 self.printdiff(repo, diffopts, head, n, fp=patchf) |
871 self.printdiff(repo, diffopts, head, n, fp=patchf) |
871 patchf.close() |
872 patchf.close() |
899 # can confuse the qrefresh, qdiff, and strip code because it |
900 # can confuse the qrefresh, qdiff, and strip code because it |
900 # needs to know which parent is actually in the patch queue. |
901 # needs to know which parent is actually in the patch queue. |
901 # so, we insert a merge marker with only one parent. This way |
902 # so, we insert a merge marker with only one parent. This way |
902 # the first patch in the queue is never a merge patch |
903 # the first patch in the queue is never a merge patch |
903 # |
904 # |
904 pname = ".hg.patches.merge.marker" |
905 pname = b".hg.patches.merge.marker" |
905 n = newcommit(repo, None, '[mq]: merge marker', force=True) |
906 n = newcommit(repo, None, b'[mq]: merge marker', force=True) |
906 self.removeundo(repo) |
907 self.removeundo(repo) |
907 self.applied.append(statusentry(n, pname)) |
908 self.applied.append(statusentry(n, pname)) |
908 self.applieddirty = True |
909 self.applieddirty = True |
909 |
910 |
910 head = self.qparents(repo) |
911 head = self.qparents(repo) |
911 |
912 |
912 for patch in series: |
913 for patch in series: |
913 patch = mergeq.lookup(patch, strict=True) |
914 patch = mergeq.lookup(patch, strict=True) |
914 if not patch: |
915 if not patch: |
915 self.ui.warn(_("patch %s does not exist\n") % patch) |
916 self.ui.warn(_(b"patch %s does not exist\n") % patch) |
916 return (1, None) |
917 return (1, None) |
917 pushable, reason = self.pushable(patch) |
918 pushable, reason = self.pushable(patch) |
918 if not pushable: |
919 if not pushable: |
919 self.explainpushable(patch, all_patches=True) |
920 self.explainpushable(patch, all_patches=True) |
920 continue |
921 continue |
921 info = mergeq.isapplied(patch) |
922 info = mergeq.isapplied(patch) |
922 if not info: |
923 if not info: |
923 self.ui.warn(_("patch %s is not applied\n") % patch) |
924 self.ui.warn(_(b"patch %s is not applied\n") % patch) |
924 return (1, None) |
925 return (1, None) |
925 rev = info[1] |
926 rev = info[1] |
926 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts) |
927 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts) |
927 if head: |
928 if head: |
928 self.applied.append(statusentry(head, patch)) |
929 self.applied.append(statusentry(head, patch)) |
1023 for patchname in series: |
1024 for patchname in series: |
1024 pushable, reason = self.pushable(patchname) |
1025 pushable, reason = self.pushable(patchname) |
1025 if not pushable: |
1026 if not pushable: |
1026 self.explainpushable(patchname, all_patches=True) |
1027 self.explainpushable(patchname, all_patches=True) |
1027 continue |
1028 continue |
1028 self.ui.status(_("applying %s\n") % patchname) |
1029 self.ui.status(_(b"applying %s\n") % patchname) |
1029 pf = os.path.join(patchdir, patchname) |
1030 pf = os.path.join(patchdir, patchname) |
1030 |
1031 |
1031 try: |
1032 try: |
1032 ph = patchheader(self.join(patchname), self.plainmode) |
1033 ph = patchheader(self.join(patchname), self.plainmode) |
1033 except IOError: |
1034 except IOError: |
1034 self.ui.warn(_("unable to read %s\n") % patchname) |
1035 self.ui.warn(_(b"unable to read %s\n") % patchname) |
1035 err = 1 |
1036 err = 1 |
1036 break |
1037 break |
1037 |
1038 |
1038 message = ph.message |
1039 message = ph.message |
1039 if not message: |
1040 if not message: |
1040 # The commit message should not be translated |
1041 # The commit message should not be translated |
1041 message = "imported patch %s\n" % patchname |
1042 message = b"imported patch %s\n" % patchname |
1042 else: |
1043 else: |
1043 if list: |
1044 if list: |
1044 # The commit message should not be translated |
1045 # The commit message should not be translated |
1045 message.append("\nimported patch %s" % patchname) |
1046 message.append(b"\nimported patch %s" % patchname) |
1046 message = '\n'.join(message) |
1047 message = b'\n'.join(message) |
1047 |
1048 |
1048 if ph.haspatch: |
1049 if ph.haspatch: |
1049 if tobackup: |
1050 if tobackup: |
1050 touched = patchmod.changedfiles(self.ui, repo, pf) |
1051 touched = patchmod.changedfiles(self.ui, repo, pf) |
1051 touched = set(touched) & tobackup |
1052 touched = set(touched) & tobackup |
1052 if touched and keepchanges: |
1053 if touched and keepchanges: |
1053 raise AbortNoCleanup( |
1054 raise AbortNoCleanup( |
1054 _("conflicting local changes found"), |
1055 _(b"conflicting local changes found"), |
1055 hint=_("did you forget to qrefresh?"), |
1056 hint=_(b"did you forget to qrefresh?"), |
1056 ) |
1057 ) |
1057 self.backup(repo, touched, copy=True) |
1058 self.backup(repo, touched, copy=True) |
1058 tobackup = tobackup - touched |
1059 tobackup = tobackup - touched |
1059 (patcherr, files, fuzz) = self.patch(repo, pf) |
1060 (patcherr, files, fuzz) = self.patch(repo, pf) |
1060 if all_files is not None: |
1061 if all_files is not None: |
1061 all_files.update(files) |
1062 all_files.update(files) |
1062 patcherr = not patcherr |
1063 patcherr = not patcherr |
1063 else: |
1064 else: |
1064 self.ui.warn(_("patch %s is empty\n") % patchname) |
1065 self.ui.warn(_(b"patch %s is empty\n") % patchname) |
1065 patcherr, files, fuzz = 0, [], 0 |
1066 patcherr, files, fuzz = 0, [], 0 |
1066 |
1067 |
1067 if merge and files: |
1068 if merge and files: |
1068 # Mark as removed/merged and update dirstate parent info |
1069 # Mark as removed/merged and update dirstate parent info |
1069 removed = [] |
1070 removed = [] |
1193 # Manually trigger phase computation to ensure phasedefaults is |
1196 # Manually trigger phase computation to ensure phasedefaults is |
1194 # executed before we remove the patches. |
1197 # executed before we remove the patches. |
1195 repo._phasecache |
1198 repo._phasecache |
1196 patches = self._revpatches(repo, sorted(revs)) |
1199 patches = self._revpatches(repo, sorted(revs)) |
1197 qfinished = self._cleanup(patches, len(patches)) |
1200 qfinished = self._cleanup(patches, len(patches)) |
1198 if qfinished and repo.ui.configbool('mq', 'secret'): |
1201 if qfinished and repo.ui.configbool(b'mq', b'secret'): |
1199 # only use this logic when the secret option is added |
1202 # only use this logic when the secret option is added |
1200 oldqbase = repo[qfinished[0]] |
1203 oldqbase = repo[qfinished[0]] |
1201 tphase = phases.newcommitphase(repo.ui) |
1204 tphase = phases.newcommitphase(repo.ui) |
1202 if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase: |
1205 if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase: |
1203 with repo.transaction('qfinish') as tr: |
1206 with repo.transaction(b'qfinish') as tr: |
1204 phases.advanceboundary(repo, tr, tphase, qfinished) |
1207 phases.advanceboundary(repo, tr, tphase, qfinished) |
1205 |
1208 |
1206 def delete(self, repo, patches, opts): |
1209 def delete(self, repo, patches, opts): |
1207 if not patches and not opts.get('rev'): |
1210 if not patches and not opts.get(b'rev'): |
1208 raise error.Abort( |
1211 raise error.Abort( |
1209 _('qdelete requires at least one revision or ' 'patch name') |
1212 _(b'qdelete requires at least one revision or ' b'patch name') |
1210 ) |
1213 ) |
1211 |
1214 |
1212 realpatches = [] |
1215 realpatches = [] |
1213 for patch in patches: |
1216 for patch in patches: |
1214 patch = self.lookup(patch, strict=True) |
1217 patch = self.lookup(patch, strict=True) |
1215 info = self.isapplied(patch) |
1218 info = self.isapplied(patch) |
1216 if info: |
1219 if info: |
1217 raise error.Abort(_("cannot delete applied patch %s") % patch) |
1220 raise error.Abort(_(b"cannot delete applied patch %s") % patch) |
1218 if patch not in self.series: |
1221 if patch not in self.series: |
1219 raise error.Abort(_("patch %s not in series file") % patch) |
1222 raise error.Abort(_(b"patch %s not in series file") % patch) |
1220 if patch not in realpatches: |
1223 if patch not in realpatches: |
1221 realpatches.append(patch) |
1224 realpatches.append(patch) |
1222 |
1225 |
1223 numrevs = 0 |
1226 numrevs = 0 |
1224 if opts.get('rev'): |
1227 if opts.get(b'rev'): |
1225 if not self.applied: |
1228 if not self.applied: |
1226 raise error.Abort(_('no patches applied')) |
1229 raise error.Abort(_(b'no patches applied')) |
1227 revs = scmutil.revrange(repo, opts.get('rev')) |
1230 revs = scmutil.revrange(repo, opts.get(b'rev')) |
1228 revs.sort() |
1231 revs.sort() |
1229 revpatches = self._revpatches(repo, revs) |
1232 revpatches = self._revpatches(repo, revs) |
1230 realpatches += revpatches |
1233 realpatches += revpatches |
1231 numrevs = len(revpatches) |
1234 numrevs = len(revpatches) |
1232 |
1235 |
1233 self._cleanup(realpatches, numrevs, opts.get('keep')) |
1236 self._cleanup(realpatches, numrevs, opts.get(b'keep')) |
1234 |
1237 |
1235 def checktoppatch(self, repo): |
1238 def checktoppatch(self, repo): |
1236 '''check that working directory is at qtip''' |
1239 '''check that working directory is at qtip''' |
1237 if self.applied: |
1240 if self.applied: |
1238 top = self.applied[-1].node |
1241 top = self.applied[-1].node |
1239 patch = self.applied[-1].name |
1242 patch = self.applied[-1].name |
1240 if repo.dirstate.p1() != top: |
1243 if repo.dirstate.p1() != top: |
1241 raise error.Abort(_("working directory revision is not qtip")) |
1244 raise error.Abort(_(b"working directory revision is not qtip")) |
1242 return top, patch |
1245 return top, patch |
1243 return None, None |
1246 return None, None |
1244 |
1247 |
1245 def putsubstate2changes(self, substatestate, changes): |
1248 def putsubstate2changes(self, substatestate, changes): |
1246 for files in changes[:3]: |
1249 for files in changes[:3]: |
1247 if '.hgsubstate' in files: |
1250 if b'.hgsubstate' in files: |
1248 return # already listed up |
1251 return # already listed up |
1249 # not yet listed up |
1252 # not yet listed up |
1250 if substatestate in 'a?': |
1253 if substatestate in b'a?': |
1251 changes[1].append('.hgsubstate') |
1254 changes[1].append(b'.hgsubstate') |
1252 elif substatestate in 'r': |
1255 elif substatestate in b'r': |
1253 changes[2].append('.hgsubstate') |
1256 changes[2].append(b'.hgsubstate') |
1254 else: # modified |
1257 else: # modified |
1255 changes[0].append('.hgsubstate') |
1258 changes[0].append(b'.hgsubstate') |
1256 |
1259 |
1257 def checklocalchanges(self, repo, force=False, refresh=True): |
1260 def checklocalchanges(self, repo, force=False, refresh=True): |
1258 excsuffix = '' |
1261 excsuffix = b'' |
1259 if refresh: |
1262 if refresh: |
1260 excsuffix = ', qrefresh first' |
1263 excsuffix = b', qrefresh first' |
1261 # plain versions for i18n tool to detect them |
1264 # plain versions for i18n tool to detect them |
1262 _("local changes found, qrefresh first") |
1265 _(b"local changes found, qrefresh first") |
1263 _("local changed subrepos found, qrefresh first") |
1266 _(b"local changed subrepos found, qrefresh first") |
1264 |
1267 |
1265 s = repo.status() |
1268 s = repo.status() |
1266 if not force: |
1269 if not force: |
1267 cmdutil.checkunfinished(repo) |
1270 cmdutil.checkunfinished(repo) |
1268 if s.modified or s.added or s.removed or s.deleted: |
1271 if s.modified or s.added or s.removed or s.deleted: |
1269 _("local changes found") # i18n tool detection |
1272 _(b"local changes found") # i18n tool detection |
1270 raise error.Abort(_("local changes found" + excsuffix)) |
1273 raise error.Abort(_(b"local changes found" + excsuffix)) |
1271 if checksubstate(repo): |
1274 if checksubstate(repo): |
1272 _("local changed subrepos found") # i18n tool detection |
1275 _(b"local changed subrepos found") # i18n tool detection |
1273 raise error.Abort(_("local changed subrepos found" + excsuffix)) |
1276 raise error.Abort( |
|
1277 _(b"local changed subrepos found" + excsuffix) |
|
1278 ) |
1274 else: |
1279 else: |
1275 cmdutil.checkunfinished(repo, skipmerge=True) |
1280 cmdutil.checkunfinished(repo, skipmerge=True) |
1276 return s |
1281 return s |
1277 |
1282 |
1278 _reserved = ('series', 'status', 'guards', '.', '..') |
1283 _reserved = (b'series', b'status', b'guards', b'.', b'..') |
1279 |
1284 |
1280 def checkreservedname(self, name): |
1285 def checkreservedname(self, name): |
1281 if name in self._reserved: |
1286 if name in self._reserved: |
1282 raise error.Abort( |
1287 raise error.Abort( |
1283 _('"%s" cannot be used as the name of a patch') % name |
1288 _(b'"%s" cannot be used as the name of a patch') % name |
1284 ) |
1289 ) |
1285 if name != name.strip(): |
1290 if name != name.strip(): |
1286 # whitespace is stripped by parseseries() |
1291 # whitespace is stripped by parseseries() |
1287 raise error.Abort( |
1292 raise error.Abort( |
1288 _('patch name cannot begin or end with ' 'whitespace') |
1293 _(b'patch name cannot begin or end with ' b'whitespace') |
1289 ) |
1294 ) |
1290 for prefix in ('.hg', '.mq'): |
1295 for prefix in (b'.hg', b'.mq'): |
1291 if name.startswith(prefix): |
1296 if name.startswith(prefix): |
1292 raise error.Abort( |
1297 raise error.Abort( |
1293 _('patch name cannot begin with "%s"') % prefix |
1298 _(b'patch name cannot begin with "%s"') % prefix |
1294 ) |
1299 ) |
1295 for c in ('#', ':', '\r', '\n'): |
1300 for c in (b'#', b':', b'\r', b'\n'): |
1296 if c in name: |
1301 if c in name: |
1297 raise error.Abort( |
1302 raise error.Abort( |
1298 _('%r cannot be used in the name of a patch') |
1303 _(b'%r cannot be used in the name of a patch') |
1299 % pycompat.bytestr(c) |
1304 % pycompat.bytestr(c) |
1300 ) |
1305 ) |
1301 |
1306 |
1302 def checkpatchname(self, name, force=False): |
1307 def checkpatchname(self, name, force=False): |
1303 self.checkreservedname(name) |
1308 self.checkreservedname(name) |
1304 if not force and os.path.exists(self.join(name)): |
1309 if not force and os.path.exists(self.join(name)): |
1305 if os.path.isdir(self.join(name)): |
1310 if os.path.isdir(self.join(name)): |
1306 raise error.Abort( |
1311 raise error.Abort( |
1307 _('"%s" already exists as a directory') % name |
1312 _(b'"%s" already exists as a directory') % name |
1308 ) |
1313 ) |
1309 else: |
1314 else: |
1310 raise error.Abort(_('patch "%s" already exists') % name) |
1315 raise error.Abort(_(b'patch "%s" already exists') % name) |
1311 |
1316 |
1312 def makepatchname(self, title, fallbackname): |
1317 def makepatchname(self, title, fallbackname): |
1313 """Return a suitable filename for title, adding a suffix to make |
1318 """Return a suitable filename for title, adding a suffix to make |
1314 it unique in the existing list""" |
1319 it unique in the existing list""" |
1315 namebase = re.sub(br'[\s\W_]+', b'_', title.lower()).strip(b'_') |
1320 namebase = re.sub(br'[\s\W_]+', b'_', title.lower()).strip(b'_') |
1329 self.checkpatchname(name) |
1334 self.checkpatchname(name) |
1330 break |
1335 break |
1331 except error.Abort: |
1336 except error.Abort: |
1332 pass |
1337 pass |
1333 i += 1 |
1338 i += 1 |
1334 name = '%s__%d' % (namebase, i) |
1339 name = b'%s__%d' % (namebase, i) |
1335 return name |
1340 return name |
1336 |
1341 |
1337 def checkkeepchanges(self, keepchanges, force): |
1342 def checkkeepchanges(self, keepchanges, force): |
1338 if force and keepchanges: |
1343 if force and keepchanges: |
1339 raise error.Abort(_('cannot use both --force and --keep-changes')) |
1344 raise error.Abort(_(b'cannot use both --force and --keep-changes')) |
1340 |
1345 |
1341 def new(self, repo, patchfn, *pats, **opts): |
1346 def new(self, repo, patchfn, *pats, **opts): |
1342 """options: |
1347 """options: |
1343 msg: a string or a no-argument function returning a string |
1348 msg: a string or a no-argument function returning a string |
1344 """ |
1349 """ |
1345 opts = pycompat.byteskwargs(opts) |
1350 opts = pycompat.byteskwargs(opts) |
1346 msg = opts.get('msg') |
1351 msg = opts.get(b'msg') |
1347 edit = opts.get('edit') |
1352 edit = opts.get(b'edit') |
1348 editform = opts.get('editform', 'mq.qnew') |
1353 editform = opts.get(b'editform', b'mq.qnew') |
1349 user = opts.get('user') |
1354 user = opts.get(b'user') |
1350 date = opts.get('date') |
1355 date = opts.get(b'date') |
1351 if date: |
1356 if date: |
1352 date = dateutil.parsedate(date) |
1357 date = dateutil.parsedate(date) |
1353 diffopts = self.diffopts({'git': opts.get('git')}, plain=True) |
1358 diffopts = self.diffopts({b'git': opts.get(b'git')}, plain=True) |
1354 if opts.get('checkname', True): |
1359 if opts.get(b'checkname', True): |
1355 self.checkpatchname(patchfn) |
1360 self.checkpatchname(patchfn) |
1356 inclsubs = checksubstate(repo) |
1361 inclsubs = checksubstate(repo) |
1357 if inclsubs: |
1362 if inclsubs: |
1358 substatestate = repo.dirstate['.hgsubstate'] |
1363 substatestate = repo.dirstate[b'.hgsubstate'] |
1359 if opts.get('include') or opts.get('exclude') or pats: |
1364 if opts.get(b'include') or opts.get(b'exclude') or pats: |
1360 # detect missing files in pats |
1365 # detect missing files in pats |
1361 def badfn(f, msg): |
1366 def badfn(f, msg): |
1362 if f != '.hgsubstate': # .hgsubstate is auto-created |
1367 if f != b'.hgsubstate': # .hgsubstate is auto-created |
1363 raise error.Abort('%s: %s' % (f, msg)) |
1368 raise error.Abort(b'%s: %s' % (f, msg)) |
1364 |
1369 |
1365 match = scmutil.match(repo[None], pats, opts, badfn=badfn) |
1370 match = scmutil.match(repo[None], pats, opts, badfn=badfn) |
1366 changes = repo.status(match=match) |
1371 changes = repo.status(match=match) |
1367 else: |
1372 else: |
1368 changes = self.checklocalchanges(repo, force=True) |
1373 changes = self.checklocalchanges(repo, force=True) |
1369 commitfiles = list(inclsubs) |
1374 commitfiles = list(inclsubs) |
1370 for files in changes[:3]: |
1375 for files in changes[:3]: |
1371 commitfiles.extend(files) |
1376 commitfiles.extend(files) |
1372 match = scmutil.matchfiles(repo, commitfiles) |
1377 match = scmutil.matchfiles(repo, commitfiles) |
1373 if len(repo[None].parents()) > 1: |
1378 if len(repo[None].parents()) > 1: |
1374 raise error.Abort(_('cannot manage merge changesets')) |
1379 raise error.Abort(_(b'cannot manage merge changesets')) |
1375 self.checktoppatch(repo) |
1380 self.checktoppatch(repo) |
1376 insert = self.fullseriesend() |
1381 insert = self.fullseriesend() |
1377 with repo.wlock(): |
1382 with repo.wlock(): |
1378 try: |
1383 try: |
1379 # if patch file write fails, abort early |
1384 # if patch file write fails, abort early |
1380 p = self.opener(patchfn, "w") |
1385 p = self.opener(patchfn, b"w") |
1381 except IOError as e: |
1386 except IOError as e: |
1382 raise error.Abort( |
1387 raise error.Abort( |
1383 _('cannot write patch "%s": %s') |
1388 _(b'cannot write patch "%s": %s') |
1384 % (patchfn, encoding.strtolocal(e.strerror)) |
1389 % (patchfn, encoding.strtolocal(e.strerror)) |
1385 ) |
1390 ) |
1386 try: |
1391 try: |
1387 defaultmsg = "[mq]: %s" % patchfn |
1392 defaultmsg = b"[mq]: %s" % patchfn |
1388 editor = cmdutil.getcommiteditor(editform=editform) |
1393 editor = cmdutil.getcommiteditor(editform=editform) |
1389 if edit: |
1394 if edit: |
1390 |
1395 |
1391 def finishdesc(desc): |
1396 def finishdesc(desc): |
1392 if desc.rstrip(): |
1397 if desc.rstrip(): |
1393 return desc |
1398 return desc |
1394 else: |
1399 else: |
1395 return defaultmsg |
1400 return defaultmsg |
1396 |
1401 |
1397 # i18n: this message is shown in editor with "HG: " prefix |
1402 # i18n: this message is shown in editor with "HG: " prefix |
1398 extramsg = _('Leave message empty to use default message.') |
1403 extramsg = _(b'Leave message empty to use default message.') |
1399 editor = cmdutil.getcommiteditor( |
1404 editor = cmdutil.getcommiteditor( |
1400 finishdesc=finishdesc, |
1405 finishdesc=finishdesc, |
1401 extramsg=extramsg, |
1406 extramsg=extramsg, |
1402 editform=editform, |
1407 editform=editform, |
1403 ) |
1408 ) |
1558 for hs in repo.branchmap().iterheads(): |
1563 for hs in repo.branchmap().iterheads(): |
1559 heads.extend(hs) |
1564 heads.extend(hs) |
1560 if not heads: |
1565 if not heads: |
1561 heads = [nullid] |
1566 heads = [nullid] |
1562 if repo.dirstate.p1() not in heads and not exact: |
1567 if repo.dirstate.p1() not in heads and not exact: |
1563 self.ui.status(_("(working directory not at a head)\n")) |
1568 self.ui.status(_(b"(working directory not at a head)\n")) |
1564 |
1569 |
1565 if not self.series: |
1570 if not self.series: |
1566 self.ui.warn(_('no patches in series\n')) |
1571 self.ui.warn(_(b'no patches in series\n')) |
1567 return 0 |
1572 return 0 |
1568 |
1573 |
1569 # Suppose our series file is: A B C and the current 'top' |
1574 # Suppose our series file is: A B C and the current 'top' |
1570 # patch is B. qpush C should be performed (moving forward) |
1575 # patch is B. qpush C should be performed (moving forward) |
1571 # qpush B is a NOP (no change) qpush A is an error (can't |
1576 # qpush B is a NOP (no change) qpush A is an error (can't |
1572 # go backwards with qpush) |
1577 # go backwards with qpush) |
1573 if patch: |
1578 if patch: |
1574 patch = self.lookup(patch) |
1579 patch = self.lookup(patch) |
1575 info = self.isapplied(patch) |
1580 info = self.isapplied(patch) |
1576 if info and info[0] >= len(self.applied) - 1: |
1581 if info and info[0] >= len(self.applied) - 1: |
1577 self.ui.warn(_('qpush: %s is already at the top\n') % patch) |
1582 self.ui.warn( |
|
1583 _(b'qpush: %s is already at the top\n') % patch |
|
1584 ) |
1578 return 0 |
1585 return 0 |
1579 |
1586 |
1580 pushable, reason = self.pushable(patch) |
1587 pushable, reason = self.pushable(patch) |
1581 if pushable: |
1588 if pushable: |
1582 if self.series.index(patch) < self.seriesend(): |
1589 if self.series.index(patch) < self.seriesend(): |
1583 raise error.Abort( |
1590 raise error.Abort( |
1584 _("cannot push to a previous patch: %s") % patch |
1591 _(b"cannot push to a previous patch: %s") % patch |
1585 ) |
1592 ) |
1586 else: |
1593 else: |
1587 if reason: |
1594 if reason: |
1588 reason = _('guarded by %s') % reason |
1595 reason = _(b'guarded by %s') % reason |
1589 else: |
1596 else: |
1590 reason = _('no matching guards') |
1597 reason = _(b'no matching guards') |
1591 self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason)) |
1598 self.ui.warn( |
|
1599 _(b"cannot push '%s' - %s\n") % (patch, reason) |
|
1600 ) |
1592 return 1 |
1601 return 1 |
1593 elif all: |
1602 elif all: |
1594 patch = self.series[-1] |
1603 patch = self.series[-1] |
1595 if self.isapplied(patch): |
1604 if self.isapplied(patch): |
1596 self.ui.warn(_('all patches are currently applied\n')) |
1605 self.ui.warn(_(b'all patches are currently applied\n')) |
1597 return 0 |
1606 return 0 |
1598 |
1607 |
1599 # Following the above example, starting at 'top' of B: |
1608 # Following the above example, starting at 'top' of B: |
1600 # qpush should be performed (pushes C), but a subsequent |
1609 # qpush should be performed (pushes C), but a subsequent |
1601 # qpush without an argument is an error (nothing to |
1610 # qpush without an argument is an error (nothing to |
1602 # apply). This allows a loop of "...while hg qpush..." to |
1611 # apply). This allows a loop of "...while hg qpush..." to |
1603 # work as it detects an error when done |
1612 # work as it detects an error when done |
1604 start = self.seriesend() |
1613 start = self.seriesend() |
1605 if start == len(self.series): |
1614 if start == len(self.series): |
1606 self.ui.warn(_('patch series already fully applied\n')) |
1615 self.ui.warn(_(b'patch series already fully applied\n')) |
1607 return 1 |
1616 return 1 |
1608 if not force and not keepchanges: |
1617 if not force and not keepchanges: |
1609 self.checklocalchanges(repo, refresh=self.applied) |
1618 self.checklocalchanges(repo, refresh=self.applied) |
1610 |
1619 |
1611 if exact: |
1620 if exact: |
1612 if keepchanges: |
1621 if keepchanges: |
1613 raise error.Abort( |
1622 raise error.Abort( |
1614 _("cannot use --exact and --keep-changes together") |
1623 _(b"cannot use --exact and --keep-changes together") |
1615 ) |
1624 ) |
1616 if move: |
1625 if move: |
1617 raise error.Abort( |
1626 raise error.Abort( |
1618 _('cannot use --exact and --move ' 'together') |
1627 _(b'cannot use --exact and --move ' b'together') |
1619 ) |
1628 ) |
1620 if self.applied: |
1629 if self.applied: |
1621 raise error.Abort( |
1630 raise error.Abort( |
1622 _('cannot push --exact with applied ' 'patches') |
1631 _(b'cannot push --exact with applied ' b'patches') |
1623 ) |
1632 ) |
1624 root = self.series[start] |
1633 root = self.series[start] |
1625 target = patchheader(self.join(root), self.plainmode).parent |
1634 target = patchheader(self.join(root), self.plainmode).parent |
1626 if not target: |
1635 if not target: |
1627 raise error.Abort( |
1636 raise error.Abort( |
1628 _("%s does not have a parent recorded") % root |
1637 _(b"%s does not have a parent recorded") % root |
1629 ) |
1638 ) |
1630 if not repo[target] == repo['.']: |
1639 if not repo[target] == repo[b'.']: |
1631 hg.update(repo, target) |
1640 hg.update(repo, target) |
1632 |
1641 |
1633 if move: |
1642 if move: |
1634 if not patch: |
1643 if not patch: |
1635 raise error.Abort(_("please specify the patch to move")) |
1644 raise error.Abort(_(b"please specify the patch to move")) |
1636 for fullstart, rpn in enumerate(self.fullseries): |
1645 for fullstart, rpn in enumerate(self.fullseries): |
1637 # strip markers for patch guards |
1646 # strip markers for patch guards |
1638 if self.guard_re.split(rpn, 1)[0] == self.series[start]: |
1647 if self.guard_re.split(rpn, 1)[0] == self.series[start]: |
1639 break |
1648 break |
1640 for i, rpn in enumerate(self.fullseries[fullstart:]): |
1649 for i, rpn in enumerate(self.fullseries[fullstart:]): |
1782 |
1791 |
1783 try: |
1792 try: |
1784 heads = repo.changelog.heads(rev) |
1793 heads = repo.changelog.heads(rev) |
1785 except error.LookupError: |
1794 except error.LookupError: |
1786 node = short(rev) |
1795 node = short(rev) |
1787 raise error.Abort(_('trying to pop unknown node %s') % node) |
1796 raise error.Abort(_(b'trying to pop unknown node %s') % node) |
1788 |
1797 |
1789 if heads != [self.applied[-1].node]: |
1798 if heads != [self.applied[-1].node]: |
1790 raise error.Abort( |
1799 raise error.Abort( |
1791 _( |
1800 _( |
1792 "popping would remove a revision not " |
1801 b"popping would remove a revision not " |
1793 "managed by this patch queue" |
1802 b"managed by this patch queue" |
1794 ) |
1803 ) |
1795 ) |
1804 ) |
1796 if not repo[self.applied[-1].node].mutable(): |
1805 if not repo[self.applied[-1].node].mutable(): |
1797 raise error.Abort( |
1806 raise error.Abort( |
1798 _("popping would remove a public revision"), |
1807 _(b"popping would remove a public revision"), |
1799 hint=_("see 'hg help phases' for details"), |
1808 hint=_(b"see 'hg help phases' for details"), |
1800 ) |
1809 ) |
1801 |
1810 |
1802 # we know there are no local changes, so we can make a simplified |
1811 # we know there are no local changes, so we can make a simplified |
1803 # form of hg.update. |
1812 # form of hg.update. |
1804 if update: |
1813 if update: |
1805 qp = self.qparents(repo, rev) |
1814 qp = self.qparents(repo, rev) |
1806 ctx = repo[qp] |
1815 ctx = repo[qp] |
1807 m, a, r, d = repo.status(qp, '.')[:4] |
1816 m, a, r, d = repo.status(qp, b'.')[:4] |
1808 if d: |
1817 if d: |
1809 raise error.Abort(_("deletions found between repo revs")) |
1818 raise error.Abort(_(b"deletions found between repo revs")) |
1810 |
1819 |
1811 tobackup = set(a + m + r) & tobackup |
1820 tobackup = set(a + m + r) & tobackup |
1812 if keepchanges and tobackup: |
1821 if keepchanges and tobackup: |
1813 raise error.Abort(_("local changes found, qrefresh first")) |
1822 raise error.Abort(_(b"local changes found, qrefresh first")) |
1814 self.backup(repo, tobackup) |
1823 self.backup(repo, tobackup) |
1815 with repo.dirstate.parentchange(): |
1824 with repo.dirstate.parentchange(): |
1816 for f in a: |
1825 for f in a: |
1817 repo.wvfs.unlinkpath(f, ignoremissing=True) |
1826 repo.wvfs.unlinkpath(f, ignoremissing=True) |
1818 repo.dirstate.drop(f) |
1827 repo.dirstate.drop(f) |
1820 fctx = ctx[f] |
1829 fctx = ctx[f] |
1821 repo.wwrite(f, fctx.data(), fctx.flags()) |
1830 repo.wwrite(f, fctx.data(), fctx.flags()) |
1822 repo.dirstate.normal(f) |
1831 repo.dirstate.normal(f) |
1823 repo.setparents(qp, nullid) |
1832 repo.setparents(qp, nullid) |
1824 for patch in reversed(self.applied[start:end]): |
1833 for patch in reversed(self.applied[start:end]): |
1825 self.ui.status(_("popping %s\n") % patch.name) |
1834 self.ui.status(_(b"popping %s\n") % patch.name) |
1826 del self.applied[start:end] |
1835 del self.applied[start:end] |
1827 strip(self.ui, repo, [rev], update=False, backup=False) |
1836 strip(self.ui, repo, [rev], update=False, backup=False) |
1828 for s, state in repo['.'].substate.items(): |
1837 for s, state in repo[b'.'].substate.items(): |
1829 repo['.'].sub(s).get(state) |
1838 repo[b'.'].sub(s).get(state) |
1830 if self.applied: |
1839 if self.applied: |
1831 self.ui.write(_("now at: %s\n") % self.applied[-1].name) |
1840 self.ui.write(_(b"now at: %s\n") % self.applied[-1].name) |
1832 else: |
1841 else: |
1833 self.ui.write(_("patch queue now empty\n")) |
1842 self.ui.write(_(b"patch queue now empty\n")) |
1834 |
1843 |
1835 def diff(self, repo, pats, opts): |
1844 def diff(self, repo, pats, opts): |
1836 top, patch = self.checktoppatch(repo) |
1845 top, patch = self.checktoppatch(repo) |
1837 if not top: |
1846 if not top: |
1838 self.ui.write(_("no patches applied\n")) |
1847 self.ui.write(_(b"no patches applied\n")) |
1839 return |
1848 return |
1840 qp = self.qparents(repo, top) |
1849 qp = self.qparents(repo, top) |
1841 if opts.get('reverse'): |
1850 if opts.get(b'reverse'): |
1842 node1, node2 = None, qp |
1851 node1, node2 = None, qp |
1843 else: |
1852 else: |
1844 node1, node2 = qp, None |
1853 node1, node2 = qp, None |
1845 diffopts = self.diffopts(opts, patch) |
1854 diffopts = self.diffopts(opts, patch) |
1846 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts) |
1855 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts) |
1847 |
1856 |
1848 def refresh(self, repo, pats=None, **opts): |
1857 def refresh(self, repo, pats=None, **opts): |
1849 opts = pycompat.byteskwargs(opts) |
1858 opts = pycompat.byteskwargs(opts) |
1850 if not self.applied: |
1859 if not self.applied: |
1851 self.ui.write(_("no patches applied\n")) |
1860 self.ui.write(_(b"no patches applied\n")) |
1852 return 1 |
1861 return 1 |
1853 msg = opts.get('msg', '').rstrip() |
1862 msg = opts.get(b'msg', b'').rstrip() |
1854 edit = opts.get('edit') |
1863 edit = opts.get(b'edit') |
1855 editform = opts.get('editform', 'mq.qrefresh') |
1864 editform = opts.get(b'editform', b'mq.qrefresh') |
1856 newuser = opts.get('user') |
1865 newuser = opts.get(b'user') |
1857 newdate = opts.get('date') |
1866 newdate = opts.get(b'date') |
1858 if newdate: |
1867 if newdate: |
1859 newdate = '%d %d' % dateutil.parsedate(newdate) |
1868 newdate = b'%d %d' % dateutil.parsedate(newdate) |
1860 wlock = repo.wlock() |
1869 wlock = repo.wlock() |
1861 |
1870 |
1862 try: |
1871 try: |
1863 self.checktoppatch(repo) |
1872 self.checktoppatch(repo) |
1864 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) |
1873 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) |
1865 if repo.changelog.heads(top) != [top]: |
1874 if repo.changelog.heads(top) != [top]: |
1866 raise error.Abort(_("cannot qrefresh a revision with children")) |
1875 raise error.Abort( |
|
1876 _(b"cannot qrefresh a revision with children") |
|
1877 ) |
1867 if not repo[top].mutable(): |
1878 if not repo[top].mutable(): |
1868 raise error.Abort( |
1879 raise error.Abort( |
1869 _("cannot qrefresh public revision"), |
1880 _(b"cannot qrefresh public revision"), |
1870 hint=_("see 'hg help phases' for details"), |
1881 hint=_(b"see 'hg help phases' for details"), |
1871 ) |
1882 ) |
1872 |
1883 |
1873 cparents = repo.changelog.parents(top) |
1884 cparents = repo.changelog.parents(top) |
1874 patchparent = self.qparents(repo, top) |
1885 patchparent = self.qparents(repo, top) |
1875 |
1886 |
1876 inclsubs = checksubstate(repo, patchparent) |
1887 inclsubs = checksubstate(repo, patchparent) |
1877 if inclsubs: |
1888 if inclsubs: |
1878 substatestate = repo.dirstate['.hgsubstate'] |
1889 substatestate = repo.dirstate[b'.hgsubstate'] |
1879 |
1890 |
1880 ph = patchheader(self.join(patchfn), self.plainmode) |
1891 ph = patchheader(self.join(patchfn), self.plainmode) |
1881 diffopts = self.diffopts( |
1892 diffopts = self.diffopts( |
1882 {'git': opts.get('git')}, patchfn, plain=True |
1893 {b'git': opts.get(b'git')}, patchfn, plain=True |
1883 ) |
1894 ) |
1884 if newuser: |
1895 if newuser: |
1885 ph.setuser(newuser) |
1896 ph.setuser(newuser) |
1886 if newdate: |
1897 if newdate: |
1887 ph.setdate(newdate) |
1898 ph.setdate(newdate) |
1888 ph.setparent(hex(patchparent)) |
1899 ph.setparent(hex(patchparent)) |
1889 |
1900 |
1890 # only commit new patch when write is complete |
1901 # only commit new patch when write is complete |
1891 patchf = self.opener(patchfn, 'w', atomictemp=True) |
1902 patchf = self.opener(patchfn, b'w', atomictemp=True) |
1892 |
1903 |
1893 # update the dirstate in place, strip off the qtip commit |
1904 # update the dirstate in place, strip off the qtip commit |
1894 # and then commit. |
1905 # and then commit. |
1895 # |
1906 # |
1896 # this should really read: |
1907 # this should really read: |
2146 if summary: |
2157 if summary: |
2147 ph = patchheader(self.join(patchname), self.plainmode) |
2158 ph = patchheader(self.join(patchname), self.plainmode) |
2148 if ph.message: |
2159 if ph.message: |
2149 msg = ph.message[0] |
2160 msg = ph.message[0] |
2150 else: |
2161 else: |
2151 msg = '' |
2162 msg = b'' |
2152 |
2163 |
2153 if self.ui.formatted(): |
2164 if self.ui.formatted(): |
2154 width = self.ui.termwidth() - len(pfx) - len(patchname) - 2 |
2165 width = self.ui.termwidth() - len(pfx) - len(patchname) - 2 |
2155 if width > 0: |
2166 if width > 0: |
2156 msg = stringutil.ellipsis(msg, width) |
2167 msg = stringutil.ellipsis(msg, width) |
2157 else: |
2168 else: |
2158 msg = '' |
2169 msg = b'' |
2159 self.ui.write(patchname, label='qseries.' + state) |
2170 self.ui.write(patchname, label=b'qseries.' + state) |
2160 self.ui.write(': ') |
2171 self.ui.write(b': ') |
2161 self.ui.write(msg, label='qseries.message.' + state) |
2172 self.ui.write(msg, label=b'qseries.message.' + state) |
2162 else: |
2173 else: |
2163 self.ui.write(patchname, label='qseries.' + state) |
2174 self.ui.write(patchname, label=b'qseries.' + state) |
2164 self.ui.write('\n') |
2175 self.ui.write(b'\n') |
2165 |
2176 |
2166 applied = {p.name for p in self.applied} |
2177 applied = {p.name for p in self.applied} |
2167 if length is None: |
2178 if length is None: |
2168 length = len(self.series) - start |
2179 length = len(self.series) - start |
2169 if not missing: |
2180 if not missing: |
2170 if self.ui.verbose: |
2181 if self.ui.verbose: |
2171 idxwidth = len("%d" % (start + length - 1)) |
2182 idxwidth = len(b"%d" % (start + length - 1)) |
2172 for i in pycompat.xrange(start, start + length): |
2183 for i in pycompat.xrange(start, start + length): |
2173 patch = self.series[i] |
2184 patch = self.series[i] |
2174 if patch in applied: |
2185 if patch in applied: |
2175 char, state = 'A', 'applied' |
2186 char, state = b'A', b'applied' |
2176 elif self.pushable(i)[0]: |
2187 elif self.pushable(i)[0]: |
2177 char, state = 'U', 'unapplied' |
2188 char, state = b'U', b'unapplied' |
2178 else: |
2189 else: |
2179 char, state = 'G', 'guarded' |
2190 char, state = b'G', b'guarded' |
2180 pfx = '' |
2191 pfx = b'' |
2181 if self.ui.verbose: |
2192 if self.ui.verbose: |
2182 pfx = '%*d %s ' % (idxwidth, i, char) |
2193 pfx = b'%*d %s ' % (idxwidth, i, char) |
2183 elif status and status != char: |
2194 elif status and status != char: |
2184 continue |
2195 continue |
2185 displayname(pfx, patch, state) |
2196 displayname(pfx, patch, state) |
2186 else: |
2197 else: |
2187 msng_list = [] |
2198 msng_list = [] |
2195 not in ( |
2206 not in ( |
2196 self.statuspath, |
2207 self.statuspath, |
2197 self.seriespath, |
2208 self.seriespath, |
2198 self.guardspath, |
2209 self.guardspath, |
2199 ) |
2210 ) |
2200 and not fl.startswith('.') |
2211 and not fl.startswith(b'.') |
2201 ): |
2212 ): |
2202 msng_list.append(fl) |
2213 msng_list.append(fl) |
2203 for x in sorted(msng_list): |
2214 for x in sorted(msng_list): |
2204 pfx = self.ui.verbose and 'D ' or '' |
2215 pfx = self.ui.verbose and b'D ' or b'' |
2205 displayname(pfx, x, 'missing') |
2216 displayname(pfx, x, b'missing') |
2206 |
2217 |
2207 def issaveline(self, l): |
2218 def issaveline(self, l): |
2208 if l.name == '.hg.patches.save.line': |
2219 if l.name == b'.hg.patches.save.line': |
2209 return True |
2220 return True |
2210 |
2221 |
2211 def qrepo(self, create=False): |
2222 def qrepo(self, create=False): |
2212 ui = self.baseui.copy() |
2223 ui = self.baseui.copy() |
2213 # copy back attributes set by ui.pager() |
2224 # copy back attributes set by ui.pager() |
2214 if self.ui.pageractive and not ui.pageractive: |
2225 if self.ui.pageractive and not ui.pageractive: |
2215 ui.pageractive = self.ui.pageractive |
2226 ui.pageractive = self.ui.pageractive |
2216 # internal config: ui.formatted |
2227 # internal config: ui.formatted |
2217 ui.setconfig( |
2228 ui.setconfig( |
2218 'ui', 'formatted', self.ui.config('ui', 'formatted'), 'mqpager' |
2229 b'ui', |
|
2230 b'formatted', |
|
2231 self.ui.config(b'ui', b'formatted'), |
|
2232 b'mqpager', |
2219 ) |
2233 ) |
2220 ui.setconfig( |
2234 ui.setconfig( |
2221 'ui', |
2235 b'ui', |
2222 'interactive', |
2236 b'interactive', |
2223 self.ui.config('ui', 'interactive'), |
2237 self.ui.config(b'ui', b'interactive'), |
2224 'mqpager', |
2238 b'mqpager', |
2225 ) |
2239 ) |
2226 if create or os.path.isdir(self.join(".hg")): |
2240 if create or os.path.isdir(self.join(b".hg")): |
2227 return hg.repository(ui, path=self.path, create=create) |
2241 return hg.repository(ui, path=self.path, create=create) |
2228 |
2242 |
2229 def restore(self, repo, rev, delete=None, qupdate=None): |
2243 def restore(self, repo, rev, delete=None, qupdate=None): |
2230 desc = repo[rev].description().strip() |
2244 desc = repo[rev].description().strip() |
2231 lines = desc.splitlines() |
2245 lines = desc.splitlines() |
2233 datastart = None |
2247 datastart = None |
2234 series = [] |
2248 series = [] |
2235 applied = [] |
2249 applied = [] |
2236 qpp = None |
2250 qpp = None |
2237 for i, line in enumerate(lines): |
2251 for i, line in enumerate(lines): |
2238 if line == 'Patch Data:': |
2252 if line == b'Patch Data:': |
2239 datastart = i + 1 |
2253 datastart = i + 1 |
2240 elif line.startswith('Dirstate:'): |
2254 elif line.startswith(b'Dirstate:'): |
2241 l = line.rstrip() |
2255 l = line.rstrip() |
2242 l = l[10:].split(' ') |
2256 l = l[10:].split(b' ') |
2243 qpp = [bin(x) for x in l] |
2257 qpp = [bin(x) for x in l] |
2244 elif datastart is not None: |
2258 elif datastart is not None: |
2245 l = line.rstrip() |
2259 l = line.rstrip() |
2246 n, name = l.split(':', 1) |
2260 n, name = l.split(b':', 1) |
2247 if n: |
2261 if n: |
2248 applied.append(statusentry(bin(n), name)) |
2262 applied.append(statusentry(bin(n), name)) |
2249 else: |
2263 else: |
2250 series.append(l) |
2264 series.append(l) |
2251 if datastart is None: |
2265 if datastart is None: |
2252 self.ui.warn(_("no saved patch data found\n")) |
2266 self.ui.warn(_(b"no saved patch data found\n")) |
2253 return 1 |
2267 return 1 |
2254 self.ui.warn(_("restoring status: %s\n") % lines[0]) |
2268 self.ui.warn(_(b"restoring status: %s\n") % lines[0]) |
2255 self.fullseries = series |
2269 self.fullseries = series |
2256 self.applied = applied |
2270 self.applied = applied |
2257 self.parseseries() |
2271 self.parseseries() |
2258 self.seriesdirty = True |
2272 self.seriesdirty = True |
2259 self.applieddirty = True |
2273 self.applieddirty = True |
2260 heads = repo.changelog.heads() |
2274 heads = repo.changelog.heads() |
2261 if delete: |
2275 if delete: |
2262 if rev not in heads: |
2276 if rev not in heads: |
2263 self.ui.warn(_("save entry has children, leaving it alone\n")) |
2277 self.ui.warn(_(b"save entry has children, leaving it alone\n")) |
2264 else: |
2278 else: |
2265 self.ui.warn(_("removing save entry %s\n") % short(rev)) |
2279 self.ui.warn(_(b"removing save entry %s\n") % short(rev)) |
2266 pp = repo.dirstate.parents() |
2280 pp = repo.dirstate.parents() |
2267 if rev in pp: |
2281 if rev in pp: |
2268 update = True |
2282 update = True |
2269 else: |
2283 else: |
2270 update = False |
2284 update = False |
2271 strip(self.ui, repo, [rev], update=update, backup=False) |
2285 strip(self.ui, repo, [rev], update=update, backup=False) |
2272 if qpp: |
2286 if qpp: |
2273 self.ui.warn( |
2287 self.ui.warn( |
2274 _("saved queue repository parents: %s %s\n") |
2288 _(b"saved queue repository parents: %s %s\n") |
2275 % (short(qpp[0]), short(qpp[1])) |
2289 % (short(qpp[0]), short(qpp[1])) |
2276 ) |
2290 ) |
2277 if qupdate: |
2291 if qupdate: |
2278 self.ui.status(_("updating queue directory\n")) |
2292 self.ui.status(_(b"updating queue directory\n")) |
2279 r = self.qrepo() |
2293 r = self.qrepo() |
2280 if not r: |
2294 if not r: |
2281 self.ui.warn(_("unable to load queue repository\n")) |
2295 self.ui.warn(_(b"unable to load queue repository\n")) |
2282 return 1 |
2296 return 1 |
2283 hg.clean(r, qpp[0]) |
2297 hg.clean(r, qpp[0]) |
2284 |
2298 |
2285 def save(self, repo, msg=None): |
2299 def save(self, repo, msg=None): |
2286 if not self.applied: |
2300 if not self.applied: |
2287 self.ui.warn(_("save: no patches applied, exiting\n")) |
2301 self.ui.warn(_(b"save: no patches applied, exiting\n")) |
2288 return 1 |
2302 return 1 |
2289 if self.issaveline(self.applied[-1]): |
2303 if self.issaveline(self.applied[-1]): |
2290 self.ui.warn(_("status is already saved\n")) |
2304 self.ui.warn(_(b"status is already saved\n")) |
2291 return 1 |
2305 return 1 |
2292 |
2306 |
2293 if not msg: |
2307 if not msg: |
2294 msg = _("hg patches saved state") |
2308 msg = _(b"hg patches saved state") |
2295 else: |
2309 else: |
2296 msg = "hg patches: " + msg.rstrip('\r\n') |
2310 msg = b"hg patches: " + msg.rstrip(b'\r\n') |
2297 r = self.qrepo() |
2311 r = self.qrepo() |
2298 if r: |
2312 if r: |
2299 pp = r.dirstate.parents() |
2313 pp = r.dirstate.parents() |
2300 msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1])) |
2314 msg += b"\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1])) |
2301 msg += "\n\nPatch Data:\n" |
2315 msg += b"\n\nPatch Data:\n" |
2302 msg += ''.join('%s\n' % x for x in self.applied) |
2316 msg += b''.join(b'%s\n' % x for x in self.applied) |
2303 msg += ''.join(':%s\n' % x for x in self.fullseries) |
2317 msg += b''.join(b':%s\n' % x for x in self.fullseries) |
2304 n = repo.commit(msg, force=True) |
2318 n = repo.commit(msg, force=True) |
2305 if not n: |
2319 if not n: |
2306 self.ui.warn(_("repo commit failed\n")) |
2320 self.ui.warn(_(b"repo commit failed\n")) |
2307 return 1 |
2321 return 1 |
2308 self.applied.append(statusentry(n, '.hg.patches.save.line')) |
2322 self.applied.append(statusentry(n, b'.hg.patches.save.line')) |
2309 self.applieddirty = True |
2323 self.applieddirty = True |
2310 self.removeundo(repo) |
2324 self.removeundo(repo) |
2311 |
2325 |
2312 def fullseriesend(self): |
2326 def fullseriesend(self): |
2313 if self.applied: |
2327 if self.applied: |
2363 git=False, |
2377 git=False, |
2364 ): |
2378 ): |
2365 def checkseries(patchname): |
2379 def checkseries(patchname): |
2366 if patchname in self.series: |
2380 if patchname in self.series: |
2367 raise error.Abort( |
2381 raise error.Abort( |
2368 _('patch %s is already in the series file') % patchname |
2382 _(b'patch %s is already in the series file') % patchname |
2369 ) |
2383 ) |
2370 |
2384 |
2371 if rev: |
2385 if rev: |
2372 if files: |
2386 if files: |
2373 raise error.Abort( |
2387 raise error.Abort( |
2374 _('option "-r" not valid when importing ' 'files') |
2388 _(b'option "-r" not valid when importing ' b'files') |
2375 ) |
2389 ) |
2376 rev = scmutil.revrange(repo, rev) |
2390 rev = scmutil.revrange(repo, rev) |
2377 rev.sort(reverse=True) |
2391 rev.sort(reverse=True) |
2378 elif not files: |
2392 elif not files: |
2379 raise error.Abort(_('no files or revisions specified')) |
2393 raise error.Abort(_(b'no files or revisions specified')) |
2380 if (len(files) > 1 or len(rev) > 1) and patchname: |
2394 if (len(files) > 1 or len(rev) > 1) and patchname: |
2381 raise error.Abort( |
2395 raise error.Abort( |
2382 _('option "-n" not valid when importing multiple ' 'patches') |
2396 _(b'option "-n" not valid when importing multiple ' b'patches') |
2383 ) |
2397 ) |
2384 imported = [] |
2398 imported = [] |
2385 if rev: |
2399 if rev: |
2386 # If mq patches are applied, we can only import revisions |
2400 # If mq patches are applied, we can only import revisions |
2387 # that form a linear path to qbase. |
2401 # that form a linear path to qbase. |
2388 # Otherwise, they should form a linear path to a head. |
2402 # Otherwise, they should form a linear path to a head. |
2389 heads = repo.changelog.heads(repo.changelog.node(rev.first())) |
2403 heads = repo.changelog.heads(repo.changelog.node(rev.first())) |
2390 if len(heads) > 1: |
2404 if len(heads) > 1: |
2391 raise error.Abort( |
2405 raise error.Abort( |
2392 _('revision %d is the root of more than one ' 'branch') |
2406 _(b'revision %d is the root of more than one ' b'branch') |
2393 % rev.last() |
2407 % rev.last() |
2394 ) |
2408 ) |
2395 if self.applied: |
2409 if self.applied: |
2396 base = repo.changelog.node(rev.first()) |
2410 base = repo.changelog.node(rev.first()) |
2397 if base in [n.node for n in self.applied]: |
2411 if base in [n.node for n in self.applied]: |
2398 raise error.Abort( |
2412 raise error.Abort( |
2399 _('revision %d is already managed') % rev.first() |
2413 _(b'revision %d is already managed') % rev.first() |
2400 ) |
2414 ) |
2401 if heads != [self.applied[-1].node]: |
2415 if heads != [self.applied[-1].node]: |
2402 raise error.Abort( |
2416 raise error.Abort( |
2403 _('revision %d is not the parent of ' 'the queue') |
2417 _(b'revision %d is not the parent of ' b'the queue') |
2404 % rev.first() |
2418 % rev.first() |
2405 ) |
2419 ) |
2406 base = repo.changelog.rev(self.applied[0].node) |
2420 base = repo.changelog.rev(self.applied[0].node) |
2407 lastparent = repo.changelog.parentrevs(base)[0] |
2421 lastparent = repo.changelog.parentrevs(base)[0] |
2408 else: |
2422 else: |
2409 if heads != [repo.changelog.node(rev.first())]: |
2423 if heads != [repo.changelog.node(rev.first())]: |
2410 raise error.Abort( |
2424 raise error.Abort( |
2411 _('revision %d has unmanaged children') % rev.first() |
2425 _(b'revision %d has unmanaged children') % rev.first() |
2412 ) |
2426 ) |
2413 lastparent = None |
2427 lastparent = None |
2414 |
2428 |
2415 diffopts = self.diffopts({'git': git}) |
2429 diffopts = self.diffopts({b'git': git}) |
2416 with repo.transaction('qimport') as tr: |
2430 with repo.transaction(b'qimport') as tr: |
2417 for r in rev: |
2431 for r in rev: |
2418 if not repo[r].mutable(): |
2432 if not repo[r].mutable(): |
2419 raise error.Abort( |
2433 raise error.Abort( |
2420 _('revision %d is not mutable') % r, |
2434 _(b'revision %d is not mutable') % r, |
2421 hint=_("see 'hg help phases' " 'for details'), |
2435 hint=_(b"see 'hg help phases' " b'for details'), |
2422 ) |
2436 ) |
2423 p1, p2 = repo.changelog.parentrevs(r) |
2437 p1, p2 = repo.changelog.parentrevs(r) |
2424 n = repo.changelog.node(r) |
2438 n = repo.changelog.node(r) |
2425 if p2 != nullrev: |
2439 if p2 != nullrev: |
2426 raise error.Abort( |
2440 raise error.Abort( |
2427 _('cannot import merge revision %d') % r |
2441 _(b'cannot import merge revision %d') % r |
2428 ) |
2442 ) |
2429 if lastparent and lastparent != r: |
2443 if lastparent and lastparent != r: |
2430 raise error.Abort( |
2444 raise error.Abort( |
2431 _('revision %d is not the parent of ' '%d') |
2445 _(b'revision %d is not the parent of ' b'%d') |
2432 % (r, lastparent) |
2446 % (r, lastparent) |
2433 ) |
2447 ) |
2434 lastparent = p1 |
2448 lastparent = p1 |
2435 |
2449 |
2436 if not patchname: |
2450 if not patchname: |
2437 patchname = self.makepatchname( |
2451 patchname = self.makepatchname( |
2438 repo[r].description().split('\n', 1)[0], |
2452 repo[r].description().split(b'\n', 1)[0], |
2439 '%d.diff' % r, |
2453 b'%d.diff' % r, |
2440 ) |
2454 ) |
2441 checkseries(patchname) |
2455 checkseries(patchname) |
2442 self.checkpatchname(patchname, force) |
2456 self.checkpatchname(patchname, force) |
2443 self.fullseries.insert(0, patchname) |
2457 self.fullseries.insert(0, patchname) |
2444 |
2458 |
2445 with self.opener(patchname, "w") as fp: |
2459 with self.opener(patchname, b"w") as fp: |
2446 cmdutil.exportfile(repo, [n], fp, opts=diffopts) |
2460 cmdutil.exportfile(repo, [n], fp, opts=diffopts) |
2447 |
2461 |
2448 se = statusentry(n, patchname) |
2462 se = statusentry(n, patchname) |
2449 self.applied.insert(0, se) |
2463 self.applied.insert(0, se) |
2450 |
2464 |
2451 self.added.append(patchname) |
2465 self.added.append(patchname) |
2452 imported.append(patchname) |
2466 imported.append(patchname) |
2453 patchname = None |
2467 patchname = None |
2454 if rev and repo.ui.configbool('mq', 'secret'): |
2468 if rev and repo.ui.configbool(b'mq', b'secret'): |
2455 # if we added anything with --rev, move the secret root |
2469 # if we added anything with --rev, move the secret root |
2456 phases.retractboundary(repo, tr, phases.secret, [n]) |
2470 phases.retractboundary(repo, tr, phases.secret, [n]) |
2457 self.parseseries() |
2471 self.parseseries() |
2458 self.applieddirty = True |
2472 self.applieddirty = True |
2459 self.seriesdirty = True |
2473 self.seriesdirty = True |
2460 |
2474 |
2461 for i, filename in enumerate(files): |
2475 for i, filename in enumerate(files): |
2462 if existing: |
2476 if existing: |
2463 if filename == '-': |
2477 if filename == b'-': |
2464 raise error.Abort( |
2478 raise error.Abort( |
2465 _('-e is incompatible with import from -') |
2479 _(b'-e is incompatible with import from -') |
2466 ) |
2480 ) |
2467 filename = normname(filename) |
2481 filename = normname(filename) |
2468 self.checkreservedname(filename) |
2482 self.checkreservedname(filename) |
2469 if util.url(filename).islocal(): |
2483 if util.url(filename).islocal(): |
2470 originpath = self.join(filename) |
2484 originpath = self.join(filename) |
2471 if not os.path.isfile(originpath): |
2485 if not os.path.isfile(originpath): |
2472 raise error.Abort( |
2486 raise error.Abort( |
2473 _("patch %s does not exist") % filename |
2487 _(b"patch %s does not exist") % filename |
2474 ) |
2488 ) |
2475 |
2489 |
2476 if patchname: |
2490 if patchname: |
2477 self.checkpatchname(patchname, force) |
2491 self.checkpatchname(patchname, force) |
2478 |
2492 |
2479 self.ui.write( |
2493 self.ui.write( |
2480 _('renaming %s to %s\n') % (filename, patchname) |
2494 _(b'renaming %s to %s\n') % (filename, patchname) |
2481 ) |
2495 ) |
2482 util.rename(originpath, self.join(patchname)) |
2496 util.rename(originpath, self.join(patchname)) |
2483 else: |
2497 else: |
2484 patchname = filename |
2498 patchname = filename |
2485 |
2499 |
2486 else: |
2500 else: |
2487 if filename == '-' and not patchname: |
2501 if filename == b'-' and not patchname: |
2488 raise error.Abort(_('need --name to import a patch from -')) |
2502 raise error.Abort( |
|
2503 _(b'need --name to import a patch from -') |
|
2504 ) |
2489 elif not patchname: |
2505 elif not patchname: |
2490 patchname = normname(os.path.basename(filename.rstrip('/'))) |
2506 patchname = normname( |
|
2507 os.path.basename(filename.rstrip(b'/')) |
|
2508 ) |
2491 self.checkpatchname(patchname, force) |
2509 self.checkpatchname(patchname, force) |
2492 try: |
2510 try: |
2493 if filename == '-': |
2511 if filename == b'-': |
2494 text = self.ui.fin.read() |
2512 text = self.ui.fin.read() |
2495 else: |
2513 else: |
2496 fp = hg.openpath(self.ui, filename) |
2514 fp = hg.openpath(self.ui, filename) |
2497 text = fp.read() |
2515 text = fp.read() |
2498 fp.close() |
2516 fp.close() |
2499 except (OSError, IOError): |
2517 except (OSError, IOError): |
2500 raise error.Abort(_("unable to read file %s") % filename) |
2518 raise error.Abort(_(b"unable to read file %s") % filename) |
2501 patchf = self.opener(patchname, "w") |
2519 patchf = self.opener(patchname, b"w") |
2502 patchf.write(text) |
2520 patchf.write(text) |
2503 patchf.close() |
2521 patchf.close() |
2504 if not force: |
2522 if not force: |
2505 checkseries(patchname) |
2523 checkseries(patchname) |
2506 if patchname not in self.series: |
2524 if patchname not in self.series: |
2507 index = self.fullseriesend() + i |
2525 index = self.fullseriesend() + i |
2508 self.fullseries[index:index] = [patchname] |
2526 self.fullseries[index:index] = [patchname] |
2509 self.parseseries() |
2527 self.parseseries() |
2510 self.seriesdirty = True |
2528 self.seriesdirty = True |
2511 self.ui.warn(_("adding %s to series file\n") % patchname) |
2529 self.ui.warn(_(b"adding %s to series file\n") % patchname) |
2512 self.added.append(patchname) |
2530 self.added.append(patchname) |
2513 imported.append(patchname) |
2531 imported.append(patchname) |
2514 patchname = None |
2532 patchname = None |
2515 |
2533 |
2516 self.removeundo(repo) |
2534 self.removeundo(repo) |
2517 return imported |
2535 return imported |
2518 |
2536 |
2519 |
2537 |
2520 def fixkeepchangesopts(ui, opts): |
2538 def fixkeepchangesopts(ui, opts): |
2521 if ( |
2539 if ( |
2522 not ui.configbool('mq', 'keepchanges') |
2540 not ui.configbool(b'mq', b'keepchanges') |
2523 or opts.get('force') |
2541 or opts.get(b'force') |
2524 or opts.get('exact') |
2542 or opts.get(b'exact') |
2525 ): |
2543 ): |
2526 return opts |
2544 return opts |
2527 opts = dict(opts) |
2545 opts = dict(opts) |
2528 opts['keep_changes'] = True |
2546 opts[b'keep_changes'] = True |
2529 return opts |
2547 return opts |
2530 |
2548 |
2531 |
2549 |
2532 @command( |
2550 @command( |
2533 "qdelete|qremove|qrm", |
2551 b"qdelete|qremove|qrm", |
2534 [ |
2552 [ |
2535 ('k', 'keep', None, _('keep patch file')), |
2553 (b'k', b'keep', None, _(b'keep patch file')), |
2536 ('r', 'rev', [], _('stop managing a revision (DEPRECATED)'), _('REV')), |
2554 ( |
|
2555 b'r', |
|
2556 b'rev', |
|
2557 [], |
|
2558 _(b'stop managing a revision (DEPRECATED)'), |
|
2559 _(b'REV'), |
|
2560 ), |
2537 ], |
2561 ], |
2538 _('hg qdelete [-k] [PATCH]...'), |
2562 _(b'hg qdelete [-k] [PATCH]...'), |
2539 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2563 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2540 ) |
2564 ) |
2541 def delete(ui, repo, *patches, **opts): |
2565 def delete(ui, repo, *patches, **opts): |
2542 """remove patches from queue |
2566 """remove patches from queue |
2543 |
2567 |
2605 |
2629 |
2606 q = repo.mq |
2630 q = repo.mq |
2607 opts = pycompat.byteskwargs(opts) |
2631 opts = pycompat.byteskwargs(opts) |
2608 if patch: |
2632 if patch: |
2609 if patch not in q.series: |
2633 if patch not in q.series: |
2610 raise error.Abort(_("patch %s is not in series file") % patch) |
2634 raise error.Abort(_(b"patch %s is not in series file") % patch) |
2611 start = q.series.index(patch) + 1 |
2635 start = q.series.index(patch) + 1 |
2612 else: |
2636 else: |
2613 start = q.seriesend(True) |
2637 start = q.seriesend(True) |
2614 |
2638 |
2615 if start == len(q.series) and opts.get('first'): |
2639 if start == len(q.series) and opts.get(b'first'): |
2616 ui.write(_("all patches applied\n")) |
2640 ui.write(_(b"all patches applied\n")) |
2617 return 1 |
2641 return 1 |
2618 |
2642 |
2619 if opts.get('first'): |
2643 if opts.get(b'first'): |
2620 length = 1 |
2644 length = 1 |
2621 else: |
2645 else: |
2622 length = None |
2646 length = None |
2623 q.qseries( |
2647 q.qseries( |
2624 repo, |
2648 repo, |
2625 start=start, |
2649 start=start, |
2626 length=length, |
2650 length=length, |
2627 status='U', |
2651 status=b'U', |
2628 summary=opts.get('summary'), |
2652 summary=opts.get(b'summary'), |
2629 ) |
2653 ) |
2630 |
2654 |
2631 |
2655 |
2632 @command( |
2656 @command( |
2633 "qimport", |
2657 b"qimport", |
2634 [ |
2658 [ |
2635 ('e', 'existing', None, _('import file in patch directory')), |
2659 (b'e', b'existing', None, _(b'import file in patch directory')), |
2636 ('n', 'name', '', _('name of patch file'), _('NAME')), |
2660 (b'n', b'name', b'', _(b'name of patch file'), _(b'NAME')), |
2637 ('f', 'force', None, _('overwrite existing files')), |
2661 (b'f', b'force', None, _(b'overwrite existing files')), |
2638 ( |
2662 ( |
2639 'r', |
2663 b'r', |
2640 'rev', |
2664 b'rev', |
2641 [], |
2665 [], |
2642 _('place existing revisions under mq control'), |
2666 _(b'place existing revisions under mq control'), |
2643 _('REV'), |
2667 _(b'REV'), |
2644 ), |
2668 ), |
2645 ('g', 'git', None, _('use git extended diff format')), |
2669 (b'g', b'git', None, _(b'use git extended diff format')), |
2646 ('P', 'push', None, _('qpush after importing')), |
2670 (b'P', b'push', None, _(b'qpush after importing')), |
2647 ], |
2671 ], |
2648 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'), |
2672 _(b'hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'), |
2649 helpcategory=command.CATEGORY_IMPORT_EXPORT, |
2673 helpcategory=command.CATEGORY_IMPORT_EXPORT, |
2650 ) |
2674 ) |
2651 def qimport(ui, repo, *filename, **opts): |
2675 def qimport(ui, repo, *filename, **opts): |
2652 """import a patch or existing changeset |
2676 """import a patch or existing changeset |
2653 |
2677 |
2795 opts = pycompat.byteskwargs(opts) |
2824 opts = pycompat.byteskwargs(opts) |
2796 |
2825 |
2797 def patchdir(repo): |
2826 def patchdir(repo): |
2798 """compute a patch repo url from a repo object""" |
2827 """compute a patch repo url from a repo object""" |
2799 url = repo.url() |
2828 url = repo.url() |
2800 if url.endswith('/'): |
2829 if url.endswith(b'/'): |
2801 url = url[:-1] |
2830 url = url[:-1] |
2802 return url + '/.hg/patches' |
2831 return url + b'/.hg/patches' |
2803 |
2832 |
2804 # main repo (destination and sources) |
2833 # main repo (destination and sources) |
2805 if dest is None: |
2834 if dest is None: |
2806 dest = hg.defaultdest(source) |
2835 dest = hg.defaultdest(source) |
2807 sr = hg.peer(ui, opts, ui.expandpath(source)) |
2836 sr = hg.peer(ui, opts, ui.expandpath(source)) |
2808 |
2837 |
2809 # patches repo (source only) |
2838 # patches repo (source only) |
2810 if opts.get('patches'): |
2839 if opts.get(b'patches'): |
2811 patchespath = ui.expandpath(opts.get('patches')) |
2840 patchespath = ui.expandpath(opts.get(b'patches')) |
2812 else: |
2841 else: |
2813 patchespath = patchdir(sr) |
2842 patchespath = patchdir(sr) |
2814 try: |
2843 try: |
2815 hg.peer(ui, opts, patchespath) |
2844 hg.peer(ui, opts, patchespath) |
2816 except error.RepoError: |
2845 except error.RepoError: |
2817 raise error.Abort( |
2846 raise error.Abort( |
2818 _('versioned patch repository not found' ' (see init --mq)') |
2847 _(b'versioned patch repository not found' b' (see init --mq)') |
2819 ) |
2848 ) |
2820 qbase, destrev = None, None |
2849 qbase, destrev = None, None |
2821 if sr.local(): |
2850 if sr.local(): |
2822 repo = sr.local() |
2851 repo = sr.local() |
2823 if repo.mq.applied and repo[qbase].phase() != phases.secret: |
2852 if repo.mq.applied and repo[qbase].phase() != phases.secret: |
2824 qbase = repo.mq.applied[0].node |
2853 qbase = repo.mq.applied[0].node |
2825 if not hg.islocal(dest): |
2854 if not hg.islocal(dest): |
2826 heads = set(repo.heads()) |
2855 heads = set(repo.heads()) |
2827 destrev = list(heads.difference(repo.heads(qbase))) |
2856 destrev = list(heads.difference(repo.heads(qbase))) |
2828 destrev.append(repo.changelog.parents(qbase)[0]) |
2857 destrev.append(repo.changelog.parents(qbase)[0]) |
2829 elif sr.capable('lookup'): |
2858 elif sr.capable(b'lookup'): |
2830 try: |
2859 try: |
2831 qbase = sr.lookup('qbase') |
2860 qbase = sr.lookup(b'qbase') |
2832 except error.RepoError: |
2861 except error.RepoError: |
2833 pass |
2862 pass |
2834 |
2863 |
2835 ui.note(_('cloning main repository\n')) |
2864 ui.note(_(b'cloning main repository\n')) |
2836 sr, dr = hg.clone( |
2865 sr, dr = hg.clone( |
2837 ui, |
2866 ui, |
2838 opts, |
2867 opts, |
2839 sr.url(), |
2868 sr.url(), |
2840 dest, |
2869 dest, |
2841 pull=opts.get('pull'), |
2870 pull=opts.get(b'pull'), |
2842 revs=destrev, |
2871 revs=destrev, |
2843 update=False, |
2872 update=False, |
2844 stream=opts.get('uncompressed'), |
2873 stream=opts.get(b'uncompressed'), |
2845 ) |
2874 ) |
2846 |
2875 |
2847 ui.note(_('cloning patch repository\n')) |
2876 ui.note(_(b'cloning patch repository\n')) |
2848 hg.clone( |
2877 hg.clone( |
2849 ui, |
2878 ui, |
2850 opts, |
2879 opts, |
2851 opts.get('patches') or patchdir(sr), |
2880 opts.get(b'patches') or patchdir(sr), |
2852 patchdir(dr), |
2881 patchdir(dr), |
2853 pull=opts.get('pull'), |
2882 pull=opts.get(b'pull'), |
2854 update=not opts.get('noupdate'), |
2883 update=not opts.get(b'noupdate'), |
2855 stream=opts.get('uncompressed'), |
2884 stream=opts.get(b'uncompressed'), |
2856 ) |
2885 ) |
2857 |
2886 |
2858 if dr.local(): |
2887 if dr.local(): |
2859 repo = dr.local() |
2888 repo = dr.local() |
2860 if qbase: |
2889 if qbase: |
2861 ui.note( |
2890 ui.note( |
2862 _('stripping applied patches from destination ' 'repository\n') |
2891 _( |
|
2892 b'stripping applied patches from destination ' |
|
2893 b'repository\n' |
|
2894 ) |
2863 ) |
2895 ) |
2864 strip(ui, repo, [qbase], update=False, backup=None) |
2896 strip(ui, repo, [qbase], update=False, backup=None) |
2865 if not opts.get('noupdate'): |
2897 if not opts.get(b'noupdate'): |
2866 ui.note(_('updating destination repository\n')) |
2898 ui.note(_(b'updating destination repository\n')) |
2867 hg.update(repo, repo.changelog.tip()) |
2899 hg.update(repo, repo.changelog.tip()) |
2868 |
2900 |
2869 |
2901 |
2870 @command( |
2902 @command( |
2871 "qcommit|qci", |
2903 b"qcommit|qci", |
2872 commands.table["commit|ci"][1], |
2904 commands.table[b"commit|ci"][1], |
2873 _('hg qcommit [OPTION]... [FILE]...'), |
2905 _(b'hg qcommit [OPTION]... [FILE]...'), |
2874 helpcategory=command.CATEGORY_COMMITTING, |
2906 helpcategory=command.CATEGORY_COMMITTING, |
2875 inferrepo=True, |
2907 inferrepo=True, |
2876 ) |
2908 ) |
2877 def commit(ui, repo, *pats, **opts): |
2909 def commit(ui, repo, *pats, **opts): |
2878 """commit changes in the queue repository (DEPRECATED) |
2910 """commit changes in the queue repository (DEPRECATED) |
2879 |
2911 |
2880 This command is deprecated; use :hg:`commit --mq` instead.""" |
2912 This command is deprecated; use :hg:`commit --mq` instead.""" |
2881 q = repo.mq |
2913 q = repo.mq |
2882 r = q.qrepo() |
2914 r = q.qrepo() |
2883 if not r: |
2915 if not r: |
2884 raise error.Abort('no queue repository') |
2916 raise error.Abort(b'no queue repository') |
2885 commands.commit(r.ui, r, *pats, **opts) |
2917 commands.commit(r.ui, r, *pats, **opts) |
2886 |
2918 |
2887 |
2919 |
2888 @command( |
2920 @command( |
2889 "qseries", |
2921 b"qseries", |
2890 [('m', 'missing', None, _('print patches not in series')),] + seriesopts, |
2922 [(b'm', b'missing', None, _(b'print patches not in series')),] + seriesopts, |
2891 _('hg qseries [-ms]'), |
2923 _(b'hg qseries [-ms]'), |
2892 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2924 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2893 ) |
2925 ) |
2894 def series(ui, repo, **opts): |
2926 def series(ui, repo, **opts): |
2895 """print the entire series file |
2927 """print the entire series file |
2896 |
2928 |
2920 if t: |
2952 if t: |
2921 q.qseries( |
2953 q.qseries( |
2922 repo, |
2954 repo, |
2923 start=t - 1, |
2955 start=t - 1, |
2924 length=1, |
2956 length=1, |
2925 status='A', |
2957 status=b'A', |
2926 summary=opts.get(r'summary'), |
2958 summary=opts.get(r'summary'), |
2927 ) |
2959 ) |
2928 else: |
2960 else: |
2929 ui.write(_("no patches applied\n")) |
2961 ui.write(_(b"no patches applied\n")) |
2930 return 1 |
2962 return 1 |
2931 |
2963 |
2932 |
2964 |
2933 @command( |
2965 @command( |
2934 "qnext", |
2966 b"qnext", |
2935 seriesopts, |
2967 seriesopts, |
2936 _('hg qnext [-s]'), |
2968 _(b'hg qnext [-s]'), |
2937 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2969 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2938 ) |
2970 ) |
2939 def next(ui, repo, **opts): |
2971 def next(ui, repo, **opts): |
2940 """print the name of the next pushable patch |
2972 """print the name of the next pushable patch |
2941 |
2973 |
2942 Returns 0 on success.""" |
2974 Returns 0 on success.""" |
2943 q = repo.mq |
2975 q = repo.mq |
2944 end = q.seriesend() |
2976 end = q.seriesend() |
2945 if end == len(q.series): |
2977 if end == len(q.series): |
2946 ui.write(_("all patches applied\n")) |
2978 ui.write(_(b"all patches applied\n")) |
2947 return 1 |
2979 return 1 |
2948 q.qseries(repo, start=end, length=1, summary=opts.get(r'summary')) |
2980 q.qseries(repo, start=end, length=1, summary=opts.get(r'summary')) |
2949 |
2981 |
2950 |
2982 |
2951 @command( |
2983 @command( |
2952 "qprev", |
2984 b"qprev", |
2953 seriesopts, |
2985 seriesopts, |
2954 _('hg qprev [-s]'), |
2986 _(b'hg qprev [-s]'), |
2955 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2987 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
2956 ) |
2988 ) |
2957 def prev(ui, repo, **opts): |
2989 def prev(ui, repo, **opts): |
2958 """print the name of the preceding applied patch |
2990 """print the name of the preceding applied patch |
2959 |
2991 |
2960 Returns 0 on success.""" |
2992 Returns 0 on success.""" |
2961 q = repo.mq |
2993 q = repo.mq |
2962 l = len(q.applied) |
2994 l = len(q.applied) |
2963 if l == 1: |
2995 if l == 1: |
2964 ui.write(_("only one patch applied\n")) |
2996 ui.write(_(b"only one patch applied\n")) |
2965 return 1 |
2997 return 1 |
2966 if not l: |
2998 if not l: |
2967 ui.write(_("no patches applied\n")) |
2999 ui.write(_(b"no patches applied\n")) |
2968 return 1 |
3000 return 1 |
2969 idx = q.series.index(q.applied[-2].name) |
3001 idx = q.series.index(q.applied[-2].name) |
2970 q.qseries( |
3002 q.qseries( |
2971 repo, start=idx, length=1, status='A', summary=opts.get(r'summary') |
3003 repo, start=idx, length=1, status=b'A', summary=opts.get(r'summary') |
2972 ) |
3004 ) |
2973 |
3005 |
2974 |
3006 |
2975 def setupheaderopts(ui, opts): |
3007 def setupheaderopts(ui, opts): |
2976 if not opts.get('user') and opts.get('currentuser'): |
3008 if not opts.get(b'user') and opts.get(b'currentuser'): |
2977 opts['user'] = ui.username() |
3009 opts[b'user'] = ui.username() |
2978 if not opts.get('date') and opts.get('currentdate'): |
3010 if not opts.get(b'date') and opts.get(b'currentdate'): |
2979 opts['date'] = "%d %d" % dateutil.makedate() |
3011 opts[b'date'] = b"%d %d" % dateutil.makedate() |
2980 |
3012 |
2981 |
3013 |
2982 @command( |
3014 @command( |
2983 "qnew", |
3015 b"qnew", |
2984 [ |
3016 [ |
2985 ('e', 'edit', None, _('invoke editor on commit messages')), |
3017 (b'e', b'edit', None, _(b'invoke editor on commit messages')), |
2986 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')), |
3018 (b'f', b'force', None, _(b'import uncommitted changes (DEPRECATED)')), |
2987 ('g', 'git', None, _('use git extended diff format')), |
3019 (b'g', b'git', None, _(b'use git extended diff format')), |
2988 ('U', 'currentuser', None, _('add "From: <current user>" to patch')), |
3020 (b'U', b'currentuser', None, _(b'add "From: <current user>" to patch')), |
2989 ('u', 'user', '', _('add "From: <USER>" to patch'), _('USER')), |
3021 (b'u', b'user', b'', _(b'add "From: <USER>" to patch'), _(b'USER')), |
2990 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')), |
3022 (b'D', b'currentdate', None, _(b'add "Date: <current date>" to patch')), |
2991 ('d', 'date', '', _('add "Date: <DATE>" to patch'), _('DATE')), |
3023 (b'd', b'date', b'', _(b'add "Date: <DATE>" to patch'), _(b'DATE')), |
2992 ] |
3024 ] |
2993 + cmdutil.walkopts |
3025 + cmdutil.walkopts |
2994 + cmdutil.commitopts, |
3026 + cmdutil.commitopts, |
2995 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'), |
3027 _(b'hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'), |
2996 helpcategory=command.CATEGORY_COMMITTING, |
3028 helpcategory=command.CATEGORY_COMMITTING, |
2997 helpbasic=True, |
3029 helpbasic=True, |
2998 inferrepo=True, |
3030 inferrepo=True, |
2999 ) |
3031 ) |
3000 def new(ui, repo, patch, *args, **opts): |
3032 def new(ui, repo, patch, *args, **opts): |
3023 Returns 0 on successful creation of a new patch. |
3055 Returns 0 on successful creation of a new patch. |
3024 """ |
3056 """ |
3025 opts = pycompat.byteskwargs(opts) |
3057 opts = pycompat.byteskwargs(opts) |
3026 msg = cmdutil.logmessage(ui, opts) |
3058 msg = cmdutil.logmessage(ui, opts) |
3027 q = repo.mq |
3059 q = repo.mq |
3028 opts['msg'] = msg |
3060 opts[b'msg'] = msg |
3029 setupheaderopts(ui, opts) |
3061 setupheaderopts(ui, opts) |
3030 q.new(repo, patch, *args, **pycompat.strkwargs(opts)) |
3062 q.new(repo, patch, *args, **pycompat.strkwargs(opts)) |
3031 q.savedirty() |
3063 q.savedirty() |
3032 return 0 |
3064 return 0 |
3033 |
3065 |
3034 |
3066 |
3035 @command( |
3067 @command( |
3036 "qrefresh", |
3068 b"qrefresh", |
3037 [ |
3069 [ |
3038 ('e', 'edit', None, _('invoke editor on commit messages')), |
3070 (b'e', b'edit', None, _(b'invoke editor on commit messages')), |
3039 ('g', 'git', None, _('use git extended diff format')), |
3071 (b'g', b'git', None, _(b'use git extended diff format')), |
3040 ( |
3072 ( |
3041 's', |
3073 b's', |
3042 'short', |
3074 b'short', |
3043 None, |
3075 None, |
3044 _('refresh only files already in the patch and specified files'), |
3076 _(b'refresh only files already in the patch and specified files'), |
3045 ), |
3077 ), |
3046 ( |
3078 ( |
3047 'U', |
3079 b'U', |
3048 'currentuser', |
3080 b'currentuser', |
3049 None, |
3081 None, |
3050 _('add/update author field in patch with current user'), |
3082 _(b'add/update author field in patch with current user'), |
3051 ), |
3083 ), |
3052 ( |
3084 ( |
3053 'u', |
3085 b'u', |
3054 'user', |
3086 b'user', |
3055 '', |
3087 b'', |
3056 _('add/update author field in patch with given user'), |
3088 _(b'add/update author field in patch with given user'), |
3057 _('USER'), |
3089 _(b'USER'), |
3058 ), |
3090 ), |
3059 ( |
3091 ( |
3060 'D', |
3092 b'D', |
3061 'currentdate', |
3093 b'currentdate', |
3062 None, |
3094 None, |
3063 _('add/update date field in patch with current date'), |
3095 _(b'add/update date field in patch with current date'), |
3064 ), |
3096 ), |
3065 ( |
3097 ( |
3066 'd', |
3098 b'd', |
3067 'date', |
3099 b'date', |
3068 '', |
3100 b'', |
3069 _('add/update date field in patch with given date'), |
3101 _(b'add/update date field in patch with given date'), |
3070 _('DATE'), |
3102 _(b'DATE'), |
3071 ), |
3103 ), |
3072 ] |
3104 ] |
3073 + cmdutil.walkopts |
3105 + cmdutil.walkopts |
3074 + cmdutil.commitopts, |
3106 + cmdutil.commitopts, |
3075 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'), |
3107 _(b'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'), |
3076 helpcategory=command.CATEGORY_COMMITTING, |
3108 helpcategory=command.CATEGORY_COMMITTING, |
3077 helpbasic=True, |
3109 helpbasic=True, |
3078 inferrepo=True, |
3110 inferrepo=True, |
3079 ) |
3111 ) |
3080 def refresh(ui, repo, *pats, **opts): |
3112 def refresh(ui, repo, *pats, **opts): |
3189 if ph.message: |
3221 if ph.message: |
3190 messages.append(ph.message) |
3222 messages.append(ph.message) |
3191 pf = q.join(p) |
3223 pf = q.join(p) |
3192 (patchsuccess, files, fuzz) = q.patch(repo, pf) |
3224 (patchsuccess, files, fuzz) = q.patch(repo, pf) |
3193 if not patchsuccess: |
3225 if not patchsuccess: |
3194 raise error.Abort(_('error folding patch %s') % p) |
3226 raise error.Abort(_(b'error folding patch %s') % p) |
3195 |
3227 |
3196 if not message: |
3228 if not message: |
3197 ph = patchheader(q.join(parent), q.plainmode) |
3229 ph = patchheader(q.join(parent), q.plainmode) |
3198 message = ph.message |
3230 message = ph.message |
3199 for msg in messages: |
3231 for msg in messages: |
3200 if msg: |
3232 if msg: |
3201 if message: |
3233 if message: |
3202 message.append('* * *') |
3234 message.append(b'* * *') |
3203 message.extend(msg) |
3235 message.extend(msg) |
3204 message = '\n'.join(message) |
3236 message = b'\n'.join(message) |
3205 |
3237 |
3206 diffopts = q.patchopts(q.diffopts(), *patches) |
3238 diffopts = q.patchopts(q.diffopts(), *patches) |
3207 with repo.wlock(): |
3239 with repo.wlock(): |
3208 q.refresh( |
3240 q.refresh( |
3209 repo, |
3241 repo, |
3210 msg=message, |
3242 msg=message, |
3211 git=diffopts.git, |
3243 git=diffopts.git, |
3212 edit=opts.get('edit'), |
3244 edit=opts.get(b'edit'), |
3213 editform='mq.qfold', |
3245 editform=b'mq.qfold', |
3214 ) |
3246 ) |
3215 q.delete(repo, patches, opts) |
3247 q.delete(repo, patches, opts) |
3216 q.savedirty() |
3248 q.savedirty() |
3217 |
3249 |
3218 |
3250 |
3219 @command( |
3251 @command( |
3220 "qgoto", |
3252 b"qgoto", |
3221 [ |
3253 [ |
3222 ('', 'keep-changes', None, _('tolerate non-conflicting local changes')), |
3254 ( |
3223 ('f', 'force', None, _('overwrite any local changes')), |
3255 b'', |
3224 ('', 'no-backup', None, _('do not save backup copies of files')), |
3256 b'keep-changes', |
|
3257 None, |
|
3258 _(b'tolerate non-conflicting local changes'), |
|
3259 ), |
|
3260 (b'f', b'force', None, _(b'overwrite any local changes')), |
|
3261 (b'', b'no-backup', None, _(b'do not save backup copies of files')), |
3225 ], |
3262 ], |
3226 _('hg qgoto [OPTION]... PATCH'), |
3263 _(b'hg qgoto [OPTION]... PATCH'), |
3227 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3264 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3228 ) |
3265 ) |
3229 def goto(ui, repo, patch, **opts): |
3266 def goto(ui, repo, patch, **opts): |
3230 '''push or pop patches until named patch is at top of stack |
3267 '''push or pop patches until named patch is at top of stack |
3231 |
3268 |
3232 Returns 0 on success.''' |
3269 Returns 0 on success.''' |
3233 opts = pycompat.byteskwargs(opts) |
3270 opts = pycompat.byteskwargs(opts) |
3234 opts = fixkeepchangesopts(ui, opts) |
3271 opts = fixkeepchangesopts(ui, opts) |
3235 q = repo.mq |
3272 q = repo.mq |
3236 patch = q.lookup(patch) |
3273 patch = q.lookup(patch) |
3237 nobackup = opts.get('no_backup') |
3274 nobackup = opts.get(b'no_backup') |
3238 keepchanges = opts.get('keep_changes') |
3275 keepchanges = opts.get(b'keep_changes') |
3239 if q.isapplied(patch): |
3276 if q.isapplied(patch): |
3240 ret = q.pop( |
3277 ret = q.pop( |
3241 repo, |
3278 repo, |
3242 patch, |
3279 patch, |
3243 force=opts.get('force'), |
3280 force=opts.get(b'force'), |
3244 nobackup=nobackup, |
3281 nobackup=nobackup, |
3245 keepchanges=keepchanges, |
3282 keepchanges=keepchanges, |
3246 ) |
3283 ) |
3247 else: |
3284 else: |
3248 ret = q.push( |
3285 ret = q.push( |
3249 repo, |
3286 repo, |
3250 patch, |
3287 patch, |
3251 force=opts.get('force'), |
3288 force=opts.get(b'force'), |
3252 nobackup=nobackup, |
3289 nobackup=nobackup, |
3253 keepchanges=keepchanges, |
3290 keepchanges=keepchanges, |
3254 ) |
3291 ) |
3255 q.savedirty() |
3292 q.savedirty() |
3256 return ret |
3293 return ret |
3257 |
3294 |
3258 |
3295 |
3259 @command( |
3296 @command( |
3260 "qguard", |
3297 b"qguard", |
3261 [ |
3298 [ |
3262 ('l', 'list', None, _('list all patches and guards')), |
3299 (b'l', b'list', None, _(b'list all patches and guards')), |
3263 ('n', 'none', None, _('drop all guards')), |
3300 (b'n', b'none', None, _(b'drop all guards')), |
3264 ], |
3301 ], |
3265 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'), |
3302 _(b'hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'), |
3266 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3303 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3267 ) |
3304 ) |
3268 def guard(ui, repo, *args, **opts): |
3305 def guard(ui, repo, *args, **opts): |
3269 '''set or print guards for a patch |
3306 '''set or print guards for a patch |
3270 |
3307 |
3287 |
3324 |
3288 Returns 0 on success. |
3325 Returns 0 on success. |
3289 ''' |
3326 ''' |
3290 |
3327 |
3291 def status(idx): |
3328 def status(idx): |
3292 guards = q.seriesguards[idx] or ['unguarded'] |
3329 guards = q.seriesguards[idx] or [b'unguarded'] |
3293 if q.series[idx] in applied: |
3330 if q.series[idx] in applied: |
3294 state = 'applied' |
3331 state = b'applied' |
3295 elif q.pushable(idx)[0]: |
3332 elif q.pushable(idx)[0]: |
3296 state = 'unapplied' |
3333 state = b'unapplied' |
3297 else: |
3334 else: |
3298 state = 'guarded' |
3335 state = b'guarded' |
3299 label = 'qguard.patch qguard.%s qseries.%s' % (state, state) |
3336 label = b'qguard.patch qguard.%s qseries.%s' % (state, state) |
3300 ui.write('%s: ' % ui.label(q.series[idx], label)) |
3337 ui.write(b'%s: ' % ui.label(q.series[idx], label)) |
3301 |
3338 |
3302 for i, guard in enumerate(guards): |
3339 for i, guard in enumerate(guards): |
3303 if guard.startswith('+'): |
3340 if guard.startswith(b'+'): |
3304 ui.write(guard, label='qguard.positive') |
3341 ui.write(guard, label=b'qguard.positive') |
3305 elif guard.startswith('-'): |
3342 elif guard.startswith(b'-'): |
3306 ui.write(guard, label='qguard.negative') |
3343 ui.write(guard, label=b'qguard.negative') |
3307 else: |
3344 else: |
3308 ui.write(guard, label='qguard.unguarded') |
3345 ui.write(guard, label=b'qguard.unguarded') |
3309 if i != len(guards) - 1: |
3346 if i != len(guards) - 1: |
3310 ui.write(' ') |
3347 ui.write(b' ') |
3311 ui.write('\n') |
3348 ui.write(b'\n') |
3312 |
3349 |
3313 q = repo.mq |
3350 q = repo.mq |
3314 applied = set(p.name for p in q.applied) |
3351 applied = set(p.name for p in q.applied) |
3315 patch = None |
3352 patch = None |
3316 args = list(args) |
3353 args = list(args) |
3317 if opts.get(r'list'): |
3354 if opts.get(r'list'): |
3318 if args or opts.get(r'none'): |
3355 if args or opts.get(r'none'): |
3319 raise error.Abort( |
3356 raise error.Abort( |
3320 _('cannot mix -l/--list with options or ' 'arguments') |
3357 _(b'cannot mix -l/--list with options or ' b'arguments') |
3321 ) |
3358 ) |
3322 for i in pycompat.xrange(len(q.series)): |
3359 for i in pycompat.xrange(len(q.series)): |
3323 status(i) |
3360 status(i) |
3324 return |
3361 return |
3325 if not args or args[0][0:1] in '-+': |
3362 if not args or args[0][0:1] in b'-+': |
3326 if not q.applied: |
3363 if not q.applied: |
3327 raise error.Abort(_('no patches applied')) |
3364 raise error.Abort(_(b'no patches applied')) |
3328 patch = q.applied[-1].name |
3365 patch = q.applied[-1].name |
3329 if patch is None and args[0][0:1] not in '-+': |
3366 if patch is None and args[0][0:1] not in b'-+': |
3330 patch = args.pop(0) |
3367 patch = args.pop(0) |
3331 if patch is None: |
3368 if patch is None: |
3332 raise error.Abort(_('no patch to work with')) |
3369 raise error.Abort(_(b'no patch to work with')) |
3333 if args or opts.get(r'none'): |
3370 if args or opts.get(r'none'): |
3334 idx = q.findseries(patch) |
3371 idx = q.findseries(patch) |
3335 if idx is None: |
3372 if idx is None: |
3336 raise error.Abort(_('no patch named %s') % patch) |
3373 raise error.Abort(_(b'no patch named %s') % patch) |
3337 q.setguards(idx, args) |
3374 q.setguards(idx, args) |
3338 q.savedirty() |
3375 q.savedirty() |
3339 else: |
3376 else: |
3340 status(q.series.index(q.lookup(patch))) |
3377 status(q.series.index(q.lookup(patch))) |
3341 |
3378 |
3342 |
3379 |
3343 @command( |
3380 @command( |
3344 "qheader", |
3381 b"qheader", |
3345 [], |
3382 [], |
3346 _('hg qheader [PATCH]'), |
3383 _(b'hg qheader [PATCH]'), |
3347 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3384 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3348 ) |
3385 ) |
3349 def header(ui, repo, patch=None): |
3386 def header(ui, repo, patch=None): |
3350 """print the header of the topmost or specified patch |
3387 """print the header of the topmost or specified patch |
3351 |
3388 |
3384 |
3421 |
3385 def savename(path): |
3422 def savename(path): |
3386 (last, index) = lastsavename(path) |
3423 (last, index) = lastsavename(path) |
3387 if last is None: |
3424 if last is None: |
3388 index = 0 |
3425 index = 0 |
3389 newpath = path + ".%d" % (index + 1) |
3426 newpath = path + b".%d" % (index + 1) |
3390 return newpath |
3427 return newpath |
3391 |
3428 |
3392 |
3429 |
3393 @command( |
3430 @command( |
3394 "qpush", |
3431 b"qpush", |
3395 [ |
3432 [ |
3396 ('', 'keep-changes', None, _('tolerate non-conflicting local changes')), |
|
3397 ('f', 'force', None, _('apply on top of local changes')), |
|
3398 ( |
3433 ( |
3399 'e', |
3434 b'', |
3400 'exact', |
3435 b'keep-changes', |
3401 None, |
3436 None, |
3402 _('apply the target patch to its recorded parent'), |
3437 _(b'tolerate non-conflicting local changes'), |
3403 ), |
3438 ), |
3404 ('l', 'list', None, _('list patch name in commit text')), |
3439 (b'f', b'force', None, _(b'apply on top of local changes')), |
3405 ('a', 'all', None, _('apply all patches')), |
3440 ( |
3406 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')), |
3441 b'e', |
3407 ('n', 'name', '', _('merge queue name (DEPRECATED)'), _('NAME')), |
3442 b'exact', |
3408 ('', 'move', None, _('reorder patch series and apply only the patch')), |
3443 None, |
3409 ('', 'no-backup', None, _('do not save backup copies of files')), |
3444 _(b'apply the target patch to its recorded parent'), |
|
3445 ), |
|
3446 (b'l', b'list', None, _(b'list patch name in commit text')), |
|
3447 (b'a', b'all', None, _(b'apply all patches')), |
|
3448 (b'm', b'merge', None, _(b'merge from another queue (DEPRECATED)')), |
|
3449 (b'n', b'name', b'', _(b'merge queue name (DEPRECATED)'), _(b'NAME')), |
|
3450 ( |
|
3451 b'', |
|
3452 b'move', |
|
3453 None, |
|
3454 _(b'reorder patch series and apply only the patch'), |
|
3455 ), |
|
3456 (b'', b'no-backup', None, _(b'do not save backup copies of files')), |
3410 ], |
3457 ], |
3411 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'), |
3458 _(b'hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'), |
3412 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3459 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3413 helpbasic=True, |
3460 helpbasic=True, |
3414 ) |
3461 ) |
3415 def push(ui, repo, patch=None, **opts): |
3462 def push(ui, repo, patch=None, **opts): |
3416 """push the next patch onto the stack |
3463 """push the next patch onto the stack |
3425 q = repo.mq |
3472 q = repo.mq |
3426 mergeq = None |
3473 mergeq = None |
3427 |
3474 |
3428 opts = pycompat.byteskwargs(opts) |
3475 opts = pycompat.byteskwargs(opts) |
3429 opts = fixkeepchangesopts(ui, opts) |
3476 opts = fixkeepchangesopts(ui, opts) |
3430 if opts.get('merge'): |
3477 if opts.get(b'merge'): |
3431 if opts.get('name'): |
3478 if opts.get(b'name'): |
3432 newpath = repo.vfs.join(opts.get('name')) |
3479 newpath = repo.vfs.join(opts.get(b'name')) |
3433 else: |
3480 else: |
3434 newpath, i = lastsavename(q.path) |
3481 newpath, i = lastsavename(q.path) |
3435 if not newpath: |
3482 if not newpath: |
3436 ui.warn(_("no saved queues found, please use -n\n")) |
3483 ui.warn(_(b"no saved queues found, please use -n\n")) |
3437 return 1 |
3484 return 1 |
3438 mergeq = queue(ui, repo.baseui, repo.path, newpath) |
3485 mergeq = queue(ui, repo.baseui, repo.path, newpath) |
3439 ui.warn(_("merging with queue at: %s\n") % mergeq.path) |
3486 ui.warn(_(b"merging with queue at: %s\n") % mergeq.path) |
3440 ret = q.push( |
3487 ret = q.push( |
3441 repo, |
3488 repo, |
3442 patch, |
3489 patch, |
3443 force=opts.get('force'), |
3490 force=opts.get(b'force'), |
3444 list=opts.get('list'), |
3491 list=opts.get(b'list'), |
3445 mergeq=mergeq, |
3492 mergeq=mergeq, |
3446 all=opts.get('all'), |
3493 all=opts.get(b'all'), |
3447 move=opts.get('move'), |
3494 move=opts.get(b'move'), |
3448 exact=opts.get('exact'), |
3495 exact=opts.get(b'exact'), |
3449 nobackup=opts.get('no_backup'), |
3496 nobackup=opts.get(b'no_backup'), |
3450 keepchanges=opts.get('keep_changes'), |
3497 keepchanges=opts.get(b'keep_changes'), |
3451 ) |
3498 ) |
3452 return ret |
3499 return ret |
3453 |
3500 |
3454 |
3501 |
3455 @command( |
3502 @command( |
3456 "qpop", |
3503 b"qpop", |
3457 [ |
3504 [ |
3458 ('a', 'all', None, _('pop all patches')), |
3505 (b'a', b'all', None, _(b'pop all patches')), |
3459 ('n', 'name', '', _('queue name to pop (DEPRECATED)'), _('NAME')), |
3506 (b'n', b'name', b'', _(b'queue name to pop (DEPRECATED)'), _(b'NAME')), |
3460 ('', 'keep-changes', None, _('tolerate non-conflicting local changes')), |
3507 ( |
3461 ('f', 'force', None, _('forget any local changes to patched files')), |
3508 b'', |
3462 ('', 'no-backup', None, _('do not save backup copies of files')), |
3509 b'keep-changes', |
|
3510 None, |
|
3511 _(b'tolerate non-conflicting local changes'), |
|
3512 ), |
|
3513 (b'f', b'force', None, _(b'forget any local changes to patched files')), |
|
3514 (b'', b'no-backup', None, _(b'do not save backup copies of files')), |
3463 ], |
3515 ], |
3464 _('hg qpop [-a] [-f] [PATCH | INDEX]'), |
3516 _(b'hg qpop [-a] [-f] [PATCH | INDEX]'), |
3465 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3517 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3466 helpbasic=True, |
3518 helpbasic=True, |
3467 ) |
3519 ) |
3468 def pop(ui, repo, patch=None, **opts): |
3520 def pop(ui, repo, patch=None, **opts): |
3469 """pop the current patch off the stack |
3521 """pop the current patch off the stack |
3605 message = cmdutil.logmessage(ui, opts) |
3657 message = cmdutil.logmessage(ui, opts) |
3606 ret = q.save(repo, msg=message) |
3658 ret = q.save(repo, msg=message) |
3607 if ret: |
3659 if ret: |
3608 return ret |
3660 return ret |
3609 q.savedirty() # save to .hg/patches before copying |
3661 q.savedirty() # save to .hg/patches before copying |
3610 if opts.get('copy'): |
3662 if opts.get(b'copy'): |
3611 path = q.path |
3663 path = q.path |
3612 if opts.get('name'): |
3664 if opts.get(b'name'): |
3613 newpath = os.path.join(q.basepath, opts.get('name')) |
3665 newpath = os.path.join(q.basepath, opts.get(b'name')) |
3614 if os.path.exists(newpath): |
3666 if os.path.exists(newpath): |
3615 if not os.path.isdir(newpath): |
3667 if not os.path.isdir(newpath): |
3616 raise error.Abort( |
3668 raise error.Abort( |
3617 _('destination %s exists and is not ' 'a directory') |
3669 _(b'destination %s exists and is not ' b'a directory') |
3618 % newpath |
3670 % newpath |
3619 ) |
3671 ) |
3620 if not opts.get('force'): |
3672 if not opts.get(b'force'): |
3621 raise error.Abort( |
3673 raise error.Abort( |
3622 _('destination %s exists, ' 'use -f to force') % newpath |
3674 _(b'destination %s exists, ' b'use -f to force') |
|
3675 % newpath |
3623 ) |
3676 ) |
3624 else: |
3677 else: |
3625 newpath = savename(path) |
3678 newpath = savename(path) |
3626 ui.warn(_("copy %s to %s\n") % (path, newpath)) |
3679 ui.warn(_(b"copy %s to %s\n") % (path, newpath)) |
3627 util.copyfiles(path, newpath) |
3680 util.copyfiles(path, newpath) |
3628 if opts.get('empty'): |
3681 if opts.get(b'empty'): |
3629 del q.applied[:] |
3682 del q.applied[:] |
3630 q.applieddirty = True |
3683 q.applieddirty = True |
3631 q.savedirty() |
3684 q.savedirty() |
3632 return 0 |
3685 return 0 |
3633 |
3686 |
3634 |
3687 |
3635 @command( |
3688 @command( |
3636 "qselect", |
3689 b"qselect", |
3637 [ |
3690 [ |
3638 ('n', 'none', None, _('disable all guards')), |
3691 (b'n', b'none', None, _(b'disable all guards')), |
3639 ('s', 'series', None, _('list all guards in series file')), |
3692 (b's', b'series', None, _(b'list all guards in series file')), |
3640 ('', 'pop', None, _('pop to before first guarded applied patch')), |
3693 (b'', b'pop', None, _(b'pop to before first guarded applied patch')), |
3641 ('', 'reapply', None, _('pop, then reapply patches')), |
3694 (b'', b'reapply', None, _(b'pop, then reapply patches')), |
3642 ], |
3695 ], |
3643 _('hg qselect [OPTION]... [GUARD]...'), |
3696 _(b'hg qselect [OPTION]... [GUARD]...'), |
3644 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3697 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3645 ) |
3698 ) |
3646 def select(ui, repo, *args, **opts): |
3699 def select(ui, repo, *args, **opts): |
3647 '''set or print guarded patches to push |
3700 '''set or print guarded patches to push |
3648 |
3701 |
3680 |
3733 |
3681 q = repo.mq |
3734 q = repo.mq |
3682 opts = pycompat.byteskwargs(opts) |
3735 opts = pycompat.byteskwargs(opts) |
3683 guards = q.active() |
3736 guards = q.active() |
3684 pushable = lambda i: q.pushable(q.applied[i].name)[0] |
3737 pushable = lambda i: q.pushable(q.applied[i].name)[0] |
3685 if args or opts.get('none'): |
3738 if args or opts.get(b'none'): |
3686 old_unapplied = q.unapplied(repo) |
3739 old_unapplied = q.unapplied(repo) |
3687 old_guarded = [ |
3740 old_guarded = [ |
3688 i for i in pycompat.xrange(len(q.applied)) if not pushable(i) |
3741 i for i in pycompat.xrange(len(q.applied)) if not pushable(i) |
3689 ] |
3742 ] |
3690 q.setactive(args) |
3743 q.setactive(args) |
3691 q.savedirty() |
3744 q.savedirty() |
3692 if not args: |
3745 if not args: |
3693 ui.status(_('guards deactivated\n')) |
3746 ui.status(_(b'guards deactivated\n')) |
3694 if not opts.get('pop') and not opts.get('reapply'): |
3747 if not opts.get(b'pop') and not opts.get(b'reapply'): |
3695 unapplied = q.unapplied(repo) |
3748 unapplied = q.unapplied(repo) |
3696 guarded = [ |
3749 guarded = [ |
3697 i for i in pycompat.xrange(len(q.applied)) if not pushable(i) |
3750 i for i in pycompat.xrange(len(q.applied)) if not pushable(i) |
3698 ] |
3751 ] |
3699 if len(unapplied) != len(old_unapplied): |
3752 if len(unapplied) != len(old_unapplied): |
3700 ui.status( |
3753 ui.status( |
3701 _( |
3754 _( |
3702 'number of unguarded, unapplied patches has ' |
3755 b'number of unguarded, unapplied patches has ' |
3703 'changed from %d to %d\n' |
3756 b'changed from %d to %d\n' |
3704 ) |
3757 ) |
3705 % (len(old_unapplied), len(unapplied)) |
3758 % (len(old_unapplied), len(unapplied)) |
3706 ) |
3759 ) |
3707 if len(guarded) != len(old_guarded): |
3760 if len(guarded) != len(old_guarded): |
3708 ui.status( |
3761 ui.status( |
3709 _( |
3762 _( |
3710 'number of guarded, applied patches has changed ' |
3763 b'number of guarded, applied patches has changed ' |
3711 'from %d to %d\n' |
3764 b'from %d to %d\n' |
3712 ) |
3765 ) |
3713 % (len(old_guarded), len(guarded)) |
3766 % (len(old_guarded), len(guarded)) |
3714 ) |
3767 ) |
3715 elif opts.get('series'): |
3768 elif opts.get(b'series'): |
3716 guards = {} |
3769 guards = {} |
3717 noguards = 0 |
3770 noguards = 0 |
3718 for gs in q.seriesguards: |
3771 for gs in q.seriesguards: |
3719 if not gs: |
3772 if not gs: |
3720 noguards += 1 |
3773 noguards += 1 |
3721 for g in gs: |
3774 for g in gs: |
3722 guards.setdefault(g, 0) |
3775 guards.setdefault(g, 0) |
3723 guards[g] += 1 |
3776 guards[g] += 1 |
3724 if ui.verbose: |
3777 if ui.verbose: |
3725 guards['NONE'] = noguards |
3778 guards[b'NONE'] = noguards |
3726 guards = list(guards.items()) |
3779 guards = list(guards.items()) |
3727 guards.sort(key=lambda x: x[0][1:]) |
3780 guards.sort(key=lambda x: x[0][1:]) |
3728 if guards: |
3781 if guards: |
3729 ui.note(_('guards in series file:\n')) |
3782 ui.note(_(b'guards in series file:\n')) |
3730 for guard, count in guards: |
3783 for guard, count in guards: |
3731 ui.note('%2d ' % count) |
3784 ui.note(b'%2d ' % count) |
3732 ui.write(guard, '\n') |
3785 ui.write(guard, b'\n') |
3733 else: |
3786 else: |
3734 ui.note(_('no guards in series file\n')) |
3787 ui.note(_(b'no guards in series file\n')) |
3735 else: |
3788 else: |
3736 if guards: |
3789 if guards: |
3737 ui.note(_('active guards:\n')) |
3790 ui.note(_(b'active guards:\n')) |
3738 for g in guards: |
3791 for g in guards: |
3739 ui.write(g, '\n') |
3792 ui.write(g, b'\n') |
3740 else: |
3793 else: |
3741 ui.write(_('no active guards\n')) |
3794 ui.write(_(b'no active guards\n')) |
3742 reapply = opts.get('reapply') and q.applied and q.applied[-1].name |
3795 reapply = opts.get(b'reapply') and q.applied and q.applied[-1].name |
3743 popped = False |
3796 popped = False |
3744 if opts.get('pop') or opts.get('reapply'): |
3797 if opts.get(b'pop') or opts.get(b'reapply'): |
3745 for i in pycompat.xrange(len(q.applied)): |
3798 for i in pycompat.xrange(len(q.applied)): |
3746 if not pushable(i): |
3799 if not pushable(i): |
3747 ui.status(_('popping guarded patches\n')) |
3800 ui.status(_(b'popping guarded patches\n')) |
3748 popped = True |
3801 popped = True |
3749 if i == 0: |
3802 if i == 0: |
3750 q.pop(repo, all=True) |
3803 q.pop(repo, all=True) |
3751 else: |
3804 else: |
3752 q.pop(repo, q.applied[i - 1].name) |
3805 q.pop(repo, q.applied[i - 1].name) |
3753 break |
3806 break |
3754 if popped: |
3807 if popped: |
3755 try: |
3808 try: |
3756 if reapply: |
3809 if reapply: |
3757 ui.status(_('reapplying unguarded patches\n')) |
3810 ui.status(_(b'reapplying unguarded patches\n')) |
3758 q.push(repo, reapply) |
3811 q.push(repo, reapply) |
3759 finally: |
3812 finally: |
3760 q.savedirty() |
3813 q.savedirty() |
3761 |
3814 |
3762 |
3815 |
3763 @command( |
3816 @command( |
3764 "qfinish", |
3817 b"qfinish", |
3765 [('a', 'applied', None, _('finish all applied changesets'))], |
3818 [(b'a', b'applied', None, _(b'finish all applied changesets'))], |
3766 _('hg qfinish [-a] [REV]...'), |
3819 _(b'hg qfinish [-a] [REV]...'), |
3767 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3820 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3768 ) |
3821 ) |
3769 def finish(ui, repo, *revrange, **opts): |
3822 def finish(ui, repo, *revrange, **opts): |
3770 """move applied patches into repository history |
3823 """move applied patches into repository history |
3771 |
3824 |
3783 to upstream. |
3836 to upstream. |
3784 |
3837 |
3785 Returns 0 on success. |
3838 Returns 0 on success. |
3786 """ |
3839 """ |
3787 if not opts.get(r'applied') and not revrange: |
3840 if not opts.get(r'applied') and not revrange: |
3788 raise error.Abort(_('no revisions specified')) |
3841 raise error.Abort(_(b'no revisions specified')) |
3789 elif opts.get(r'applied'): |
3842 elif opts.get(r'applied'): |
3790 revrange = ('qbase::qtip',) + revrange |
3843 revrange = (b'qbase::qtip',) + revrange |
3791 |
3844 |
3792 q = repo.mq |
3845 q = repo.mq |
3793 if not q.applied: |
3846 if not q.applied: |
3794 ui.status(_('no patches applied\n')) |
3847 ui.status(_(b'no patches applied\n')) |
3795 return 0 |
3848 return 0 |
3796 |
3849 |
3797 revs = scmutil.revrange(repo, revrange) |
3850 revs = scmutil.revrange(repo, revrange) |
3798 if repo['.'].rev() in revs and repo[None].files(): |
3851 if repo[b'.'].rev() in revs and repo[None].files(): |
3799 ui.warn(_('warning: uncommitted changes in the working directory\n')) |
3852 ui.warn(_(b'warning: uncommitted changes in the working directory\n')) |
3800 # queue.finish may changes phases but leave the responsibility to lock the |
3853 # queue.finish may changes phases but leave the responsibility to lock the |
3801 # repo to the caller to avoid deadlock with wlock. This command code is |
3854 # repo to the caller to avoid deadlock with wlock. This command code is |
3802 # responsibility for this locking. |
3855 # responsibility for this locking. |
3803 with repo.lock(): |
3856 with repo.lock(): |
3804 q.finish(repo, revs) |
3857 q.finish(repo, revs) |
3805 q.savedirty() |
3858 q.savedirty() |
3806 return 0 |
3859 return 0 |
3807 |
3860 |
3808 |
3861 |
3809 @command( |
3862 @command( |
3810 "qqueue", |
3863 b"qqueue", |
3811 [ |
3864 [ |
3812 ('l', 'list', False, _('list all available queues')), |
3865 (b'l', b'list', False, _(b'list all available queues')), |
3813 ('', 'active', False, _('print name of active queue')), |
3866 (b'', b'active', False, _(b'print name of active queue')), |
3814 ('c', 'create', False, _('create new queue')), |
3867 (b'c', b'create', False, _(b'create new queue')), |
3815 ('', 'rename', False, _('rename active queue')), |
3868 (b'', b'rename', False, _(b'rename active queue')), |
3816 ('', 'delete', False, _('delete reference to queue')), |
3869 (b'', b'delete', False, _(b'delete reference to queue')), |
3817 ('', 'purge', False, _('delete queue, and remove patch dir')), |
3870 (b'', b'purge', False, _(b'delete queue, and remove patch dir')), |
3818 ], |
3871 ], |
3819 _('[OPTION] [QUEUE]'), |
3872 _(b'[OPTION] [QUEUE]'), |
3820 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3873 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3821 ) |
3874 ) |
3822 def qqueue(ui, repo, name=None, **opts): |
3875 def qqueue(ui, repo, name=None, **opts): |
3823 '''manage multiple patch queues |
3876 '''manage multiple patch queues |
3824 |
3877 |
3876 |
3929 |
3877 def _setactive(name): |
3930 def _setactive(name): |
3878 if q.applied: |
3931 if q.applied: |
3879 raise error.Abort( |
3932 raise error.Abort( |
3880 _( |
3933 _( |
3881 'new queue created, but cannot make active ' |
3934 b'new queue created, but cannot make active ' |
3882 'as patches are applied' |
3935 b'as patches are applied' |
3883 ) |
3936 ) |
3884 ) |
3937 ) |
3885 _setactivenocheck(name) |
3938 _setactivenocheck(name) |
3886 |
3939 |
3887 def _setactivenocheck(name): |
3940 def _setactivenocheck(name): |
3888 fh = repo.vfs(_activequeue, 'w') |
3941 fh = repo.vfs(_activequeue, b'w') |
3889 if name != 'patches': |
3942 if name != b'patches': |
3890 fh.write(name) |
3943 fh.write(name) |
3891 fh.close() |
3944 fh.close() |
3892 |
3945 |
3893 def _addqueue(name): |
3946 def _addqueue(name): |
3894 fh = repo.vfs(_allqueues, 'a') |
3947 fh = repo.vfs(_allqueues, b'a') |
3895 fh.write('%s\n' % (name,)) |
3948 fh.write(b'%s\n' % (name,)) |
3896 fh.close() |
3949 fh.close() |
3897 |
3950 |
3898 def _queuedir(name): |
3951 def _queuedir(name): |
3899 if name == 'patches': |
3952 if name == b'patches': |
3900 return repo.vfs.join('patches') |
3953 return repo.vfs.join(b'patches') |
3901 else: |
3954 else: |
3902 return repo.vfs.join('patches-' + name) |
3955 return repo.vfs.join(b'patches-' + name) |
3903 |
3956 |
3904 def _validname(name): |
3957 def _validname(name): |
3905 for n in name: |
3958 for n in name: |
3906 if n in ':\\/.': |
3959 if n in b':\\/.': |
3907 return False |
3960 return False |
3908 return True |
3961 return True |
3909 |
3962 |
3910 def _delete(name): |
3963 def _delete(name): |
3911 if name not in existing: |
3964 if name not in existing: |
3912 raise error.Abort(_('cannot delete queue that does not exist')) |
3965 raise error.Abort(_(b'cannot delete queue that does not exist')) |
3913 |
3966 |
3914 current = _getcurrent() |
3967 current = _getcurrent() |
3915 |
3968 |
3916 if name == current: |
3969 if name == current: |
3917 raise error.Abort(_('cannot delete currently active queue')) |
3970 raise error.Abort(_(b'cannot delete currently active queue')) |
3918 |
3971 |
3919 fh = repo.vfs('patches.queues.new', 'w') |
3972 fh = repo.vfs(b'patches.queues.new', b'w') |
3920 for queue in existing: |
3973 for queue in existing: |
3921 if queue == name: |
3974 if queue == name: |
3922 continue |
3975 continue |
3923 fh.write('%s\n' % (queue,)) |
3976 fh.write(b'%s\n' % (queue,)) |
3924 fh.close() |
3977 fh.close() |
3925 repo.vfs.rename('patches.queues.new', _allqueues) |
3978 repo.vfs.rename(b'patches.queues.new', _allqueues) |
3926 |
3979 |
3927 opts = pycompat.byteskwargs(opts) |
3980 opts = pycompat.byteskwargs(opts) |
3928 if not name or opts.get('list') or opts.get('active'): |
3981 if not name or opts.get(b'list') or opts.get(b'active'): |
3929 current = _getcurrent() |
3982 current = _getcurrent() |
3930 if opts.get('active'): |
3983 if opts.get(b'active'): |
3931 ui.write('%s\n' % (current,)) |
3984 ui.write(b'%s\n' % (current,)) |
3932 return |
3985 return |
3933 for queue in _getqueues(): |
3986 for queue in _getqueues(): |
3934 ui.write('%s' % (queue,)) |
3987 ui.write(b'%s' % (queue,)) |
3935 if queue == current and not ui.quiet: |
3988 if queue == current and not ui.quiet: |
3936 ui.write(_(' (active)\n')) |
3989 ui.write(_(b' (active)\n')) |
3937 else: |
3990 else: |
3938 ui.write('\n') |
3991 ui.write(b'\n') |
3939 return |
3992 return |
3940 |
3993 |
3941 if not _validname(name): |
3994 if not _validname(name): |
3942 raise error.Abort( |
3995 raise error.Abort( |
3943 _('invalid queue name, may not contain the characters ":\\/."') |
3996 _(b'invalid queue name, may not contain the characters ":\\/."') |
3944 ) |
3997 ) |
3945 |
3998 |
3946 with repo.wlock(): |
3999 with repo.wlock(): |
3947 existing = _getqueues() |
4000 existing = _getqueues() |
3948 |
4001 |
3949 if opts.get('create'): |
4002 if opts.get(b'create'): |
3950 if name in existing: |
4003 if name in existing: |
3951 raise error.Abort(_('queue "%s" already exists') % name) |
4004 raise error.Abort(_(b'queue "%s" already exists') % name) |
3952 if _noqueues(): |
4005 if _noqueues(): |
3953 _addqueue(_defaultqueue) |
4006 _addqueue(_defaultqueue) |
3954 _addqueue(name) |
4007 _addqueue(name) |
3955 _setactive(name) |
4008 _setactive(name) |
3956 elif opts.get('rename'): |
4009 elif opts.get(b'rename'): |
3957 current = _getcurrent() |
4010 current = _getcurrent() |
3958 if name == current: |
4011 if name == current: |
3959 raise error.Abort( |
4012 raise error.Abort( |
3960 _('can\'t rename "%s" to its current name') % name |
4013 _(b'can\'t rename "%s" to its current name') % name |
3961 ) |
4014 ) |
3962 if name in existing: |
4015 if name in existing: |
3963 raise error.Abort(_('queue "%s" already exists') % name) |
4016 raise error.Abort(_(b'queue "%s" already exists') % name) |
3964 |
4017 |
3965 olddir = _queuedir(current) |
4018 olddir = _queuedir(current) |
3966 newdir = _queuedir(name) |
4019 newdir = _queuedir(name) |
3967 |
4020 |
3968 if os.path.exists(newdir): |
4021 if os.path.exists(newdir): |
3969 raise error.Abort( |
4022 raise error.Abort( |
3970 _('non-queue directory "%s" already exists') % newdir |
4023 _(b'non-queue directory "%s" already exists') % newdir |
3971 ) |
4024 ) |
3972 |
4025 |
3973 fh = repo.vfs('patches.queues.new', 'w') |
4026 fh = repo.vfs(b'patches.queues.new', b'w') |
3974 for queue in existing: |
4027 for queue in existing: |
3975 if queue == current: |
4028 if queue == current: |
3976 fh.write('%s\n' % (name,)) |
4029 fh.write(b'%s\n' % (name,)) |
3977 if os.path.exists(olddir): |
4030 if os.path.exists(olddir): |
3978 util.rename(olddir, newdir) |
4031 util.rename(olddir, newdir) |
3979 else: |
4032 else: |
3980 fh.write('%s\n' % (queue,)) |
4033 fh.write(b'%s\n' % (queue,)) |
3981 fh.close() |
4034 fh.close() |
3982 repo.vfs.rename('patches.queues.new', _allqueues) |
4035 repo.vfs.rename(b'patches.queues.new', _allqueues) |
3983 _setactivenocheck(name) |
4036 _setactivenocheck(name) |
3984 elif opts.get('delete'): |
4037 elif opts.get(b'delete'): |
3985 _delete(name) |
4038 _delete(name) |
3986 elif opts.get('purge'): |
4039 elif opts.get(b'purge'): |
3987 if name in existing: |
4040 if name in existing: |
3988 _delete(name) |
4041 _delete(name) |
3989 qdir = _queuedir(name) |
4042 qdir = _queuedir(name) |
3990 if os.path.exists(qdir): |
4043 if os.path.exists(qdir): |
3991 shutil.rmtree(qdir) |
4044 shutil.rmtree(qdir) |
3992 else: |
4045 else: |
3993 if name not in existing: |
4046 if name not in existing: |
3994 raise error.Abort(_('use --create to create a new queue')) |
4047 raise error.Abort(_(b'use --create to create a new queue')) |
3995 _setactive(name) |
4048 _setactive(name) |
3996 |
4049 |
3997 |
4050 |
3998 def mqphasedefaults(repo, roots): |
4051 def mqphasedefaults(repo, roots): |
3999 """callback used to set mq changeset as secret when no phase data exists""" |
4052 """callback used to set mq changeset as secret when no phase data exists""" |
4000 if repo.mq.applied: |
4053 if repo.mq.applied: |
4001 if repo.ui.configbool('mq', 'secret'): |
4054 if repo.ui.configbool(b'mq', b'secret'): |
4002 mqphase = phases.secret |
4055 mqphase = phases.secret |
4003 else: |
4056 else: |
4004 mqphase = phases.draft |
4057 mqphase = phases.draft |
4005 qbase = repo[repo.mq.applied[0].node] |
4058 qbase = repo[repo.mq.applied[0].node] |
4006 roots[mqphase].add(qbase.node()) |
4059 roots[mqphase].add(qbase.node()) |
4155 return orig(ui, repo, *args, **kwargs) |
4208 return orig(ui, repo, *args, **kwargs) |
4156 |
4209 |
4157 q = repo.mq |
4210 q = repo.mq |
4158 r = q.qrepo() |
4211 r = q.qrepo() |
4159 if not r: |
4212 if not r: |
4160 raise error.Abort(_('no queue repository')) |
4213 raise error.Abort(_(b'no queue repository')) |
4161 return orig(r.ui, r, *args, **kwargs) |
4214 return orig(r.ui, r, *args, **kwargs) |
4162 |
4215 |
4163 |
4216 |
4164 def summaryhook(ui, repo): |
4217 def summaryhook(ui, repo): |
4165 q = repo.mq |
4218 q = repo.mq |
4166 m = [] |
4219 m = [] |
4167 a, u = len(q.applied), len(q.unapplied(repo)) |
4220 a, u = len(q.applied), len(q.unapplied(repo)) |
4168 if a: |
4221 if a: |
4169 m.append(ui.label(_("%d applied"), 'qseries.applied') % a) |
4222 m.append(ui.label(_(b"%d applied"), b'qseries.applied') % a) |
4170 if u: |
4223 if u: |
4171 m.append(ui.label(_("%d unapplied"), 'qseries.unapplied') % u) |
4224 m.append(ui.label(_(b"%d unapplied"), b'qseries.unapplied') % u) |
4172 if m: |
4225 if m: |
4173 # i18n: column positioning for "hg summary" |
4226 # i18n: column positioning for "hg summary" |
4174 ui.write(_("mq: %s\n") % ', '.join(m)) |
4227 ui.write(_(b"mq: %s\n") % b', '.join(m)) |
4175 else: |
4228 else: |
4176 # i18n: column positioning for "hg summary" |
4229 # i18n: column positioning for "hg summary" |
4177 ui.note(_("mq: (empty queue)\n")) |
4230 ui.note(_(b"mq: (empty queue)\n")) |
4178 |
4231 |
4179 |
4232 |
4180 revsetpredicate = registrar.revsetpredicate() |
4233 revsetpredicate = registrar.revsetpredicate() |
4181 |
4234 |
4182 |
4235 |
4183 @revsetpredicate('mq()') |
4236 @revsetpredicate(b'mq()') |
4184 def revsetmq(repo, subset, x): |
4237 def revsetmq(repo, subset, x): |
4185 """Changesets managed by MQ. |
4238 """Changesets managed by MQ. |
4186 """ |
4239 """ |
4187 revsetlang.getargs(x, 0, 0, _("mq takes no arguments")) |
4240 revsetlang.getargs(x, 0, 0, _(b"mq takes no arguments")) |
4188 applied = {repo[r.node].rev() for r in repo.mq.applied} |
4241 applied = {repo[r.node].rev() for r in repo.mq.applied} |
4189 return smartset.baseset([r for r in subset if r in applied]) |
4242 return smartset.baseset([r for r in subset if r in applied]) |
4190 |
4243 |
4191 |
4244 |
4192 # tell hggettext to extract docstrings from these functions: |
4245 # tell hggettext to extract docstrings from these functions: |