Mercurial > hg
comparison hgext/mq.py @ 9325:74e717a21779
Merge with mpm
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Thu, 06 Aug 2009 18:48:00 -0700 |
parents | 53fdf18fd63b 061eeb602354 |
children | 9a69ab6d7cf7 |
comparison
equal
deleted
inserted
replaced
9315:fb66a7d3f28f | 9325:74e717a21779 |
---|---|
6 # GNU General Public License version 2, incorporated herein by reference. | 6 # GNU General Public License version 2, incorporated herein by reference. |
7 | 7 |
8 '''manage a stack of patches | 8 '''manage a stack of patches |
9 | 9 |
10 This extension lets you work with a stack of patches in a Mercurial | 10 This extension lets you work with a stack of patches in a Mercurial |
11 repository. It manages two stacks of patches - all known patches, and | 11 repository. It manages two stacks of patches - all known patches, and applied |
12 applied patches (subset of known patches). | 12 patches (subset of known patches). |
13 | 13 |
14 Known patches are represented as patch files in the .hg/patches | 14 Known patches are represented as patch files in the .hg/patches directory. |
15 directory. Applied patches are both patch files and changesets. | 15 Applied patches are both patch files and changesets. |
16 | 16 |
17 Common tasks (use "hg help command" for more details): | 17 Common tasks (use "hg help command" for more details):: |
18 | 18 |
19 prepare repository to work with patches qinit | 19 prepare repository to work with patches qinit |
20 create new patch qnew | 20 create new patch qnew |
21 import existing patch qimport | 21 import existing patch qimport |
22 | 22 |
23 print patch series qseries | 23 print patch series qseries |
24 print applied patches qapplied | 24 print applied patches qapplied |
25 print name of top applied patch qtop | 25 print name of top applied patch qtop |
26 | 26 |
27 add known patch to applied stack qpush | 27 add known patch to applied stack qpush |
28 remove patch from applied stack qpop | 28 remove patch from applied stack qpop |
29 refresh contents of top applied patch qrefresh | 29 refresh contents of top applied patch qrefresh |
30 ''' | 30 ''' |
31 | 31 |
32 from mercurial.i18n import _ | 32 from mercurial.i18n import _ |
33 from mercurial.node import bin, hex, short, nullid, nullrev | 33 from mercurial.node import bin, hex, short, nullid, nullrev |
34 from mercurial.lock import release | 34 from mercurial.lock import release |
554 for patchname in series: | 554 for patchname in series: |
555 pushable, reason = self.pushable(patchname) | 555 pushable, reason = self.pushable(patchname) |
556 if not pushable: | 556 if not pushable: |
557 self.explain_pushable(patchname, all_patches=True) | 557 self.explain_pushable(patchname, all_patches=True) |
558 continue | 558 continue |
559 self.ui.warn(_("applying %s\n") % patchname) | 559 self.ui.status(_("applying %s\n") % patchname) |
560 pf = os.path.join(patchdir, patchname) | 560 pf = os.path.join(patchdir, patchname) |
561 | 561 |
562 try: | 562 try: |
563 ph = patchheader(self.join(patchname)) | 563 ph = patchheader(self.join(patchname)) |
564 except: | 564 except: |
1079 raise | 1079 raise |
1080 try: os.removedirs(os.path.dirname(repo.wjoin(f))) | 1080 try: os.removedirs(os.path.dirname(repo.wjoin(f))) |
1081 except: pass | 1081 except: pass |
1082 repo.dirstate.forget(f) | 1082 repo.dirstate.forget(f) |
1083 repo.dirstate.setparents(qp, nullid) | 1083 repo.dirstate.setparents(qp, nullid) |
1084 for patch in reversed(self.applied[start:end]): | |
1085 self.ui.status(_("popping %s\n") % patch.name) | |
1084 del self.applied[start:end] | 1086 del self.applied[start:end] |
1085 self.strip(repo, rev, update=False, backup='strip') | 1087 self.strip(repo, rev, update=False, backup='strip') |
1086 if len(self.applied): | 1088 if len(self.applied): |
1087 self.ui.write(_("now at: %s\n") % self.applied[-1].name) | 1089 self.ui.write(_("now at: %s\n") % self.applied[-1].name) |
1088 else: | 1090 else: |
1342 self.explain_pushable(i) | 1344 self.explain_pushable(i) |
1343 return unapplied | 1345 return unapplied |
1344 | 1346 |
1345 def qseries(self, repo, missing=None, start=0, length=None, status=None, | 1347 def qseries(self, repo, missing=None, start=0, length=None, status=None, |
1346 summary=False): | 1348 summary=False): |
1347 def displayname(patchname): | 1349 def displayname(pfx, patchname): |
1348 if summary: | 1350 if summary: |
1349 ph = patchheader(self.join(patchname)) | 1351 ph = patchheader(self.join(patchname)) |
1350 msg = ph.message | 1352 msg = ph.message |
1351 msg = msg and ': ' + msg[0] or ': ' | 1353 msg = msg and ': ' + msg[0] or ': ' |
1352 else: | 1354 else: |
1353 msg = '' | 1355 msg = '' |
1354 return '%s%s' % (patchname, msg) | 1356 msg = "%s%s%s" % (pfx, patchname, msg) |
1357 if self.ui.interactive(): | |
1358 msg = util.ellipsis(msg, util.termwidth()) | |
1359 self.ui.write(msg + '\n') | |
1355 | 1360 |
1356 applied = set([p.name for p in self.applied]) | 1361 applied = set([p.name for p in self.applied]) |
1357 if length is None: | 1362 if length is None: |
1358 length = len(self.series) - start | 1363 length = len(self.series) - start |
1359 if not missing: | 1364 if not missing: |
1365 if self.ui.verbose: | |
1366 idxwidth = len(str(start+length - 1)) | |
1360 for i in xrange(start, start+length): | 1367 for i in xrange(start, start+length): |
1361 patch = self.series[i] | 1368 patch = self.series[i] |
1362 if patch in applied: | 1369 if patch in applied: |
1363 stat = 'A' | 1370 stat = 'A' |
1364 elif self.pushable(i)[0]: | 1371 elif self.pushable(i)[0]: |
1365 stat = 'U' | 1372 stat = 'U' |
1366 else: | 1373 else: |
1367 stat = 'G' | 1374 stat = 'G' |
1368 pfx = '' | 1375 pfx = '' |
1369 if self.ui.verbose: | 1376 if self.ui.verbose: |
1370 pfx = '%d %s ' % (i, stat) | 1377 pfx = '%*d %s ' % (idxwidth, i, stat) |
1371 elif status and status != stat: | 1378 elif status and status != stat: |
1372 continue | 1379 continue |
1373 self.ui.write('%s%s\n' % (pfx, displayname(patch))) | 1380 displayname(pfx, patch) |
1374 else: | 1381 else: |
1375 msng_list = [] | 1382 msng_list = [] |
1376 for root, dirs, files in os.walk(self.path): | 1383 for root, dirs, files in os.walk(self.path): |
1377 d = root[len(self.path) + 1:] | 1384 d = root[len(self.path) + 1:] |
1378 for f in files: | 1385 for f in files: |
1382 self.guards_path) | 1389 self.guards_path) |
1383 and not fl.startswith('.')): | 1390 and not fl.startswith('.')): |
1384 msng_list.append(fl) | 1391 msng_list.append(fl) |
1385 for x in sorted(msng_list): | 1392 for x in sorted(msng_list): |
1386 pfx = self.ui.verbose and ('D ') or '' | 1393 pfx = self.ui.verbose and ('D ') or '' |
1387 self.ui.write("%s%s\n" % (pfx, displayname(x))) | 1394 displayname(pfx, x) |
1388 | 1395 |
1389 def issaveline(self, l): | 1396 def issaveline(self, l): |
1390 if l.name == '.hg.patches.save.line': | 1397 if l.name == '.hg.patches.save.line': |
1391 return True | 1398 return True |
1392 | 1399 |
1535 if rev: | 1542 if rev: |
1536 if files: | 1543 if files: |
1537 raise util.Abort(_('option "-r" not valid when importing ' | 1544 raise util.Abort(_('option "-r" not valid when importing ' |
1538 'files')) | 1545 'files')) |
1539 rev = cmdutil.revrange(repo, rev) | 1546 rev = cmdutil.revrange(repo, rev) |
1540 rev.sort(lambda x, y: cmp(y, x)) | 1547 rev.sort(reverse=True) |
1541 if (len(files) > 1 or len(rev) > 1) and patchname: | 1548 if (len(files) > 1 or len(rev) > 1) and patchname: |
1542 raise util.Abort(_('option "-n" not valid when importing multiple ' | 1549 raise util.Abort(_('option "-n" not valid when importing multiple ' |
1543 'patches')) | 1550 'patches')) |
1544 i = 0 | 1551 i = 0 |
1545 added = [] | 1552 added = [] |
1675 q.qseries(repo, start=start, status='U', summary=opts.get('summary')) | 1682 q.qseries(repo, start=start, status='U', summary=opts.get('summary')) |
1676 | 1683 |
1677 def qimport(ui, repo, *filename, **opts): | 1684 def qimport(ui, repo, *filename, **opts): |
1678 """import a patch | 1685 """import a patch |
1679 | 1686 |
1680 The patch is inserted into the series after the last applied | 1687 The patch is inserted into the series after the last applied patch. If no |
1681 patch. If no patches have been applied, qimport prepends the patch | 1688 patches have been applied, qimport prepends the patch to the series. |
1682 to the series. | 1689 |
1683 | 1690 The patch will have the same name as its source file unless you give it a |
1684 The patch will have the same name as its source file unless you | 1691 new one with -n/--name. |
1685 give it a new one with -n/--name. | 1692 |
1686 | 1693 You can register an existing patch inside the patch directory with the |
1687 You can register an existing patch inside the patch directory with | 1694 -e/--existing flag. |
1688 the -e/--existing flag. | 1695 |
1689 | 1696 With -f/--force, an existing patch of the same name will be overwritten. |
1690 With -f/--force, an existing patch of the same name will be | 1697 |
1691 overwritten. | 1698 An existing changeset may be placed under mq control with -r/--rev (e.g. |
1692 | 1699 qimport --rev tip -n patch will place tip under mq control). With |
1693 An existing changeset may be placed under mq control with -r/--rev | 1700 -g/--git, patches imported with --rev will use the git diff format. See |
1694 (e.g. qimport --rev tip -n patch will place tip under mq control). | 1701 the diffs help topic for information on why this is important for |
1695 With -g/--git, patches imported with --rev will use the git diff | 1702 preserving rename/copy information and permission changes. |
1696 format. See the diffs help topic for information on why this is | 1703 |
1697 important for preserving rename/copy information and permission | 1704 To import a patch from standard input, pass - as the patch file. When |
1698 changes. | 1705 importing from standard input, a patch name must be specified using the |
1699 | 1706 --name flag. |
1700 To import a patch from standard input, pass - as the patch file. | |
1701 When importing from standard input, a patch name must be specified | |
1702 using the --name flag. | |
1703 """ | 1707 """ |
1704 q = repo.mq | 1708 q = repo.mq |
1705 q.qimport(repo, filename, patchname=opts['name'], | 1709 q.qimport(repo, filename, patchname=opts['name'], |
1706 existing=opts['existing'], force=opts['force'], rev=opts['rev'], | 1710 existing=opts['existing'], force=opts['force'], rev=opts['rev'], |
1707 git=opts['git']) | 1711 git=opts['git']) |
1712 return 0 | 1716 return 0 |
1713 | 1717 |
1714 def init(ui, repo, **opts): | 1718 def init(ui, repo, **opts): |
1715 """init a new queue repository | 1719 """init a new queue repository |
1716 | 1720 |
1717 The queue repository is unversioned by default. If | 1721 The queue repository is unversioned by default. If -c/--create-repo is |
1718 -c/--create-repo is specified, qinit will create a separate nested | 1722 specified, qinit will create a separate nested repository for patches |
1719 repository for patches (qinit -c may also be run later to convert | 1723 (qinit -c may also be run later to convert an unversioned patch repository |
1720 an unversioned patch repository into a versioned one). You can use | 1724 into a versioned one). You can use qcommit to commit changes to this queue |
1721 qcommit to commit changes to this queue repository.""" | 1725 repository. |
1726 """ | |
1722 q = repo.mq | 1727 q = repo.mq |
1723 r = q.init(repo, create=opts['create_repo']) | 1728 r = q.init(repo, create=opts['create_repo']) |
1724 q.save_dirty() | 1729 q.save_dirty() |
1725 if r: | 1730 if r: |
1726 if not os.path.exists(r.wjoin('.hgignore')): | 1731 if not os.path.exists(r.wjoin('.hgignore')): |
1738 return 0 | 1743 return 0 |
1739 | 1744 |
1740 def clone(ui, source, dest=None, **opts): | 1745 def clone(ui, source, dest=None, **opts): |
1741 '''clone main and patch repository at same time | 1746 '''clone main and patch repository at same time |
1742 | 1747 |
1743 If source is local, destination will have no patches applied. If | 1748 If source is local, destination will have no patches applied. If source is |
1744 source is remote, this command can not check if patches are | 1749 remote, this command can not check if patches are applied in source, so |
1745 applied in source, so cannot guarantee that patches are not | 1750 cannot guarantee that patches are not applied in destination. If you clone |
1746 applied in destination. If you clone remote repository, be sure | 1751 remote repository, be sure before that it has no patches applied. |
1747 before that it has no patches applied. | 1752 |
1748 | 1753 Source patch repository is looked for in <src>/.hg/patches by default. Use |
1749 Source patch repository is looked for in <src>/.hg/patches by | 1754 -p <url> to change. |
1750 default. Use -p <url> to change. | 1755 |
1751 | 1756 The patch directory must be a nested Mercurial repository, as would be |
1752 The patch directory must be a nested Mercurial repository, as | 1757 created by qinit -c. |
1753 would be created by qinit -c. | |
1754 ''' | 1758 ''' |
1755 def patchdir(repo): | 1759 def patchdir(repo): |
1756 url = repo.url() | 1760 url = repo.url() |
1757 if url.endswith('/'): | 1761 if url.endswith('/'): |
1758 url = url[:-1] | 1762 url = url[:-1] |
1845 return 1 | 1849 return 1 |
1846 return q.qseries(repo, start=l-2, length=1, status='A', | 1850 return q.qseries(repo, start=l-2, length=1, status='A', |
1847 summary=opts.get('summary')) | 1851 summary=opts.get('summary')) |
1848 | 1852 |
1849 def setupheaderopts(ui, opts): | 1853 def setupheaderopts(ui, opts): |
1850 def do(opt,val): | 1854 def do(opt, val): |
1851 if not opts[opt] and opts['current' + opt]: | 1855 if not opts[opt] and opts['current' + opt]: |
1852 opts[opt] = val | 1856 opts[opt] = val |
1853 do('user', ui.username()) | 1857 do('user', ui.username()) |
1854 do('date', "%d %d" % util.makedate()) | 1858 do('date', "%d %d" % util.makedate()) |
1855 | 1859 |
1856 def new(ui, repo, patch, *args, **opts): | 1860 def new(ui, repo, patch, *args, **opts): |
1857 """create a new patch | 1861 """create a new patch |
1858 | 1862 |
1859 qnew creates a new patch on top of the currently-applied patch (if | 1863 qnew creates a new patch on top of the currently-applied patch (if any). |
1860 any). It will refuse to run if there are any outstanding changes | 1864 It will refuse to run if there are any outstanding changes unless |
1861 unless -f/--force is specified, in which case the patch will be | 1865 -f/--force is specified, in which case the patch will be initialized with |
1862 initialized with them. You may also use -I/--include, | 1866 them. You may also use -I/--include, -X/--exclude, and/or a list of files |
1863 -X/--exclude, and/or a list of files after the patch name to add | 1867 after the patch name to add only changes to matching files to the new |
1864 only changes to matching files to the new patch, leaving the rest | 1868 patch, leaving the rest as uncommitted modifications. |
1865 as uncommitted modifications. | 1869 |
1866 | 1870 -u/--user and -d/--date can be used to set the (given) user and date, |
1867 -u/--user and -d/--date can be used to set the (given) user and | 1871 respectively. -U/--currentuser and -D/--currentdate set user to current |
1868 date, respectively. -U/--currentuser and -D/--currentdate set user | 1872 user and date to current date. |
1869 to current user and date to current date. | 1873 |
1870 | 1874 -e/--edit, -m/--message or -l/--logfile set the patch header as well as |
1871 -e/--edit, -m/--message or -l/--logfile set the patch header as | 1875 the commit message. If none is specified, the header is empty and the |
1872 well as the commit message. If none is specified, the header is | 1876 commit message is '[mq]: PATCH'. |
1873 empty and the commit message is '[mq]: PATCH'. | 1877 |
1874 | 1878 Use the -g/--git option to keep the patch in the git extended diff format. |
1875 Use the -g/--git option to keep the patch in the git extended diff | 1879 Read the diffs help topic for more information on why this is important |
1876 format. Read the diffs help topic for more information on why this | 1880 for preserving permission changes and copy/rename information. |
1877 is important for preserving permission changes and copy/rename | |
1878 information. | |
1879 """ | 1881 """ |
1880 msg = cmdutil.logmessage(opts) | 1882 msg = cmdutil.logmessage(opts) |
1881 def getmsg(): return ui.edit(msg, ui.username()) | 1883 def getmsg(): return ui.edit(msg, ui.username()) |
1882 q = repo.mq | 1884 q = repo.mq |
1883 opts['msg'] = msg | 1885 opts['msg'] = msg |
1891 return 0 | 1893 return 0 |
1892 | 1894 |
1893 def refresh(ui, repo, *pats, **opts): | 1895 def refresh(ui, repo, *pats, **opts): |
1894 """update the current patch | 1896 """update the current patch |
1895 | 1897 |
1896 If any file patterns are provided, the refreshed patch will | 1898 If any file patterns are provided, the refreshed patch will contain only |
1897 contain only the modifications that match those patterns; the | 1899 the modifications that match those patterns; the remaining modifications |
1898 remaining modifications will remain in the working directory. | 1900 will remain in the working directory. |
1899 | 1901 |
1900 If -s/--short is specified, files currently included in the patch | 1902 If -s/--short is specified, files currently included in the patch will be |
1901 will be refreshed just like matched files and remain in the patch. | 1903 refreshed just like matched files and remain in the patch. |
1902 | 1904 |
1903 hg add/remove/copy/rename work as usual, though you might want to | 1905 hg add/remove/copy/rename work as usual, though you might want to use |
1904 use git-style patches (-g/--git or [diff] git=1) to track copies | 1906 git-style patches (-g/--git or [diff] git=1) to track copies and renames. |
1905 and renames. See the diffs help topic for more information on the | 1907 See the diffs help topic for more information on the git diff format. |
1906 git diff format. | |
1907 """ | 1908 """ |
1908 q = repo.mq | 1909 q = repo.mq |
1909 message = cmdutil.logmessage(opts) | 1910 message = cmdutil.logmessage(opts) |
1910 if opts['edit']: | 1911 if opts['edit']: |
1911 if not q.applied: | 1912 if not q.applied: |
1922 return ret | 1923 return ret |
1923 | 1924 |
1924 def diff(ui, repo, *pats, **opts): | 1925 def diff(ui, repo, *pats, **opts): |
1925 """diff of the current patch and subsequent modifications | 1926 """diff of the current patch and subsequent modifications |
1926 | 1927 |
1927 Shows a diff which includes the current patch as well as any | 1928 Shows a diff which includes the current patch as well as any changes which |
1928 changes which have been made in the working directory since the | 1929 have been made in the working directory since the last refresh (thus |
1929 last refresh (thus showing what the current patch would become | 1930 showing what the current patch would become after a qrefresh). |
1930 after a qrefresh). | 1931 |
1931 | 1932 Use 'hg diff' if you only want to see the changes made since the last |
1932 Use 'hg diff' if you only want to see the changes made since the | 1933 qrefresh, or 'hg export qtip' if you want to see changes made by the |
1933 last qrefresh, or 'hg export qtip' if you want to see changes made | 1934 current patch without including changes made since the qrefresh. |
1934 by the current patch without including changes made since the | |
1935 qrefresh. | |
1936 """ | 1935 """ |
1937 repo.mq.diff(repo, pats, opts) | 1936 repo.mq.diff(repo, pats, opts) |
1938 return 0 | 1937 return 0 |
1939 | 1938 |
1940 def fold(ui, repo, *files, **opts): | 1939 def fold(ui, repo, *files, **opts): |
1941 """fold the named patches into the current patch | 1940 """fold the named patches into the current patch |
1942 | 1941 |
1943 Patches must not yet be applied. Each patch will be successively | 1942 Patches must not yet be applied. Each patch will be successively applied |
1944 applied to the current patch in the order given. If all the | 1943 to the current patch in the order given. If all the patches apply |
1945 patches apply successfully, the current patch will be refreshed | 1944 successfully, the current patch will be refreshed with the new cumulative |
1946 with the new cumulative patch, and the folded patches will be | 1945 patch, and the folded patches will be deleted. With -k/--keep, the folded |
1947 deleted. With -k/--keep, the folded patch files will not be | 1946 patch files will not be removed afterwards. |
1948 removed afterwards. | 1947 |
1949 | 1948 The header for each folded patch will be concatenated with the current |
1950 The header for each folded patch will be concatenated with the | 1949 patch header, separated by a line of '* * *'. |
1951 current patch header, separated by a line of '* * *'.""" | 1950 """ |
1952 | 1951 |
1953 q = repo.mq | 1952 q = repo.mq |
1954 | 1953 |
1955 if not files: | 1954 if not files: |
1956 raise util.Abort(_('qfold requires at least one patch name')) | 1955 raise util.Abort(_('qfold requires at least one patch name')) |
2012 return ret | 2011 return ret |
2013 | 2012 |
2014 def guard(ui, repo, *args, **opts): | 2013 def guard(ui, repo, *args, **opts): |
2015 '''set or print guards for a patch | 2014 '''set or print guards for a patch |
2016 | 2015 |
2017 Guards control whether a patch can be pushed. A patch with no | 2016 Guards control whether a patch can be pushed. A patch with no guards is |
2018 guards is always pushed. A patch with a positive guard ("+foo") is | 2017 always pushed. A patch with a positive guard ("+foo") is pushed only if |
2019 pushed only if the qselect command has activated it. A patch with | 2018 the qselect command has activated it. A patch with a negative guard |
2020 a negative guard ("-foo") is never pushed if the qselect command | 2019 ("-foo") is never pushed if the qselect command has activated it. |
2021 has activated it. | 2020 |
2022 | 2021 With no arguments, print the currently active guards. With arguments, set |
2023 With no arguments, print the currently active guards. | 2022 guards for the named patch. |
2024 With arguments, set guards for the named patch. | |
2025 NOTE: Specifying negative guards now requires '--'. | 2023 NOTE: Specifying negative guards now requires '--'. |
2026 | 2024 |
2027 To set guards on another patch: | 2025 To set guards on another patch: |
2028 hg qguard -- other.patch +2.6.17 -stable | 2026 hg qguard -- other.patch +2.6.17 -stable |
2029 ''' | 2027 ''' |
2096 return newpath | 2094 return newpath |
2097 | 2095 |
2098 def push(ui, repo, patch=None, **opts): | 2096 def push(ui, repo, patch=None, **opts): |
2099 """push the next patch onto the stack | 2097 """push the next patch onto the stack |
2100 | 2098 |
2101 When -f/--force is applied, all local changes in patched files | 2099 When -f/--force is applied, all local changes in patched files will be |
2102 will be lost. | 2100 lost. |
2103 """ | 2101 """ |
2104 q = repo.mq | 2102 q = repo.mq |
2105 mergeq = None | 2103 mergeq = None |
2106 | 2104 |
2107 if opts['merge']: | 2105 if opts['merge']: |
2119 return ret | 2117 return ret |
2120 | 2118 |
2121 def pop(ui, repo, patch=None, **opts): | 2119 def pop(ui, repo, patch=None, **opts): |
2122 """pop the current patch off the stack | 2120 """pop the current patch off the stack |
2123 | 2121 |
2124 By default, pops off the top of the patch stack. If given a patch | 2122 By default, pops off the top of the patch stack. If given a patch name, |
2125 name, keeps popping off patches until the named patch is at the | 2123 keeps popping off patches until the named patch is at the top of the |
2126 top of the stack. | 2124 stack. |
2127 """ | 2125 """ |
2128 localupdate = True | 2126 localupdate = True |
2129 if opts['name']: | 2127 if opts['name']: |
2130 q = queue(ui, repo.join(""), repo.join(opts['name'])) | 2128 q = queue(ui, repo.join(""), repo.join(opts['name'])) |
2131 ui.warn(_('using patch queue: %s\n') % q.path) | 2129 ui.warn(_('using patch queue: %s\n') % q.path) |
2238 | 2236 |
2239 def strip(ui, repo, rev, **opts): | 2237 def strip(ui, repo, rev, **opts): |
2240 """strip a revision and all its descendants from the repository | 2238 """strip a revision and all its descendants from the repository |
2241 | 2239 |
2242 If one of the working directory's parent revisions is stripped, the | 2240 If one of the working directory's parent revisions is stripped, the |
2243 working directory will be updated to the parent of the stripped | 2241 working directory will be updated to the parent of the stripped revision. |
2244 revision. | |
2245 """ | 2242 """ |
2246 backup = 'all' | 2243 backup = 'all' |
2247 if opts['backup']: | 2244 if opts['backup']: |
2248 backup = 'strip' | 2245 backup = 'strip' |
2249 elif opts['nobackup']: | 2246 elif opts['nobackup']: |
2264 return 0 | 2261 return 0 |
2265 | 2262 |
2266 def select(ui, repo, *args, **opts): | 2263 def select(ui, repo, *args, **opts): |
2267 '''set or print guarded patches to push | 2264 '''set or print guarded patches to push |
2268 | 2265 |
2269 Use the qguard command to set or print guards on patch, then use | 2266 Use the qguard command to set or print guards on patch, then use qselect |
2270 qselect to tell mq which guards to use. A patch will be pushed if | 2267 to tell mq which guards to use. A patch will be pushed if it has no guards |
2271 it has no guards or any positive guards match the currently | 2268 or any positive guards match the currently selected guard, but will not be |
2272 selected guard, but will not be pushed if any negative guards | 2269 pushed if any negative guards match the current guard. For example: |
2273 match the current guard. For example: | |
2274 | 2270 |
2275 qguard foo.patch -stable (negative guard) | 2271 qguard foo.patch -stable (negative guard) |
2276 qguard bar.patch +stable (positive guard) | 2272 qguard bar.patch +stable (positive guard) |
2277 qselect stable | 2273 qselect stable |
2278 | 2274 |
2279 This activates the "stable" guard. mq will skip foo.patch (because | 2275 This activates the "stable" guard. mq will skip foo.patch (because it has |
2280 it has a negative match) but push bar.patch (because it has a | 2276 a negative match) but push bar.patch (because it has a positive match). |
2281 positive match). | 2277 |
2282 | 2278 With no arguments, prints the currently active guards. With one argument, |
2283 With no arguments, prints the currently active guards. | 2279 sets the active guard. |
2284 With one argument, sets the active guard. | 2280 |
2285 | 2281 Use -n/--none to deactivate guards (no other arguments needed). When no |
2286 Use -n/--none to deactivate guards (no other arguments needed). | 2282 guards are active, patches with positive guards are skipped and patches |
2287 When no guards are active, patches with positive guards are | 2283 with negative guards are pushed. |
2288 skipped and patches with negative guards are pushed. | 2284 |
2289 | 2285 qselect can change the guards on applied patches. It does not pop guarded |
2290 qselect can change the guards on applied patches. It does not pop | 2286 patches by default. Use --pop to pop back to the last applied patch that |
2291 guarded patches by default. Use --pop to pop back to the last | 2287 is not guarded. Use --reapply (which implies --pop) to push back to the |
2292 applied patch that is not guarded. Use --reapply (which implies | 2288 current patch afterwards, but skip guarded patches. |
2293 --pop) to push back to the current patch afterwards, but skip | 2289 |
2294 guarded patches. | 2290 Use -s/--series to print a list of all guards in the series file (no other |
2295 | 2291 arguments needed). Use -v for more information. |
2296 Use -s/--series to print a list of all guards in the series file | 2292 ''' |
2297 (no other arguments needed). Use -v for more information.''' | |
2298 | 2293 |
2299 q = repo.mq | 2294 q = repo.mq |
2300 guards = q.active() | 2295 guards = q.active() |
2301 if args or opts['none']: | 2296 if args or opts['none']: |
2302 old_unapplied = q.unapplied(repo) | 2297 old_unapplied = q.unapplied(repo) |
2328 guards.setdefault(g, 0) | 2323 guards.setdefault(g, 0) |
2329 guards[g] += 1 | 2324 guards[g] += 1 |
2330 if ui.verbose: | 2325 if ui.verbose: |
2331 guards['NONE'] = noguards | 2326 guards['NONE'] = noguards |
2332 guards = guards.items() | 2327 guards = guards.items() |
2333 guards.sort(lambda a, b: cmp(a[0][1:], b[0][1:])) | 2328 guards.sort(key=lambda x: x[0][1:]) |
2334 if guards: | 2329 if guards: |
2335 ui.note(_('guards in series file:\n')) | 2330 ui.note(_('guards in series file:\n')) |
2336 for guard, count in guards: | 2331 for guard, count in guards: |
2337 ui.note('%2d ' % count) | 2332 ui.note('%2d ' % count) |
2338 ui.write(guard, '\n') | 2333 ui.write(guard, '\n') |
2367 q.save_dirty() | 2362 q.save_dirty() |
2368 | 2363 |
2369 def finish(ui, repo, *revrange, **opts): | 2364 def finish(ui, repo, *revrange, **opts): |
2370 """move applied patches into repository history | 2365 """move applied patches into repository history |
2371 | 2366 |
2372 Finishes the specified revisions (corresponding to applied | 2367 Finishes the specified revisions (corresponding to applied patches) by |
2373 patches) by moving them out of mq control into regular repository | 2368 moving them out of mq control into regular repository history. |
2374 history. | 2369 |
2375 | 2370 Accepts a revision range or the -a/--applied option. If --applied is |
2376 Accepts a revision range or the -a/--applied option. If --applied | 2371 specified, all applied mq revisions are removed from mq control. |
2377 is specified, all applied mq revisions are removed from mq | 2372 Otherwise, the given revisions must be at the base of the stack of applied |
2378 control. Otherwise, the given revisions must be at the base of the | 2373 patches. |
2379 stack of applied patches. | 2374 |
2380 | 2375 This can be especially useful if your changes have been applied to an |
2381 This can be especially useful if your changes have been applied to | 2376 upstream repository, or if you are about to push your changes to upstream. |
2382 an upstream repository, or if you are about to push your changes | |
2383 to upstream. | |
2384 """ | 2377 """ |
2385 if not opts['applied'] and not revrange: | 2378 if not opts['applied'] and not revrange: |
2386 raise util.Abort(_('no revisions specified')) | 2379 raise util.Abort(_('no revisions specified')) |
2387 elif opts['applied']: | 2380 elif opts['applied']: |
2388 revrange = ('qbase:qtip',) + revrange | 2381 revrange = ('qbase:qtip',) + revrange |
2421 def push(self, remote, force=False, revs=None): | 2414 def push(self, remote, force=False, revs=None): |
2422 if self.mq.applied and not force and not revs: | 2415 if self.mq.applied and not force and not revs: |
2423 raise util.Abort(_('source has mq patches applied')) | 2416 raise util.Abort(_('source has mq patches applied')) |
2424 return super(mqrepo, self).push(remote, force, revs) | 2417 return super(mqrepo, self).push(remote, force, revs) |
2425 | 2418 |
2426 def tags(self): | 2419 def _findtags(self): |
2427 if self.tagscache: | 2420 '''augment tags from base class with patch tags''' |
2428 return self.tagscache | 2421 result = super(mqrepo, self)._findtags() |
2429 | |
2430 tagscache = super(mqrepo, self).tags() | |
2431 | 2422 |
2432 q = self.mq | 2423 q = self.mq |
2433 if not q.applied: | 2424 if not q.applied: |
2434 return tagscache | 2425 return result |
2435 | 2426 |
2436 mqtags = [(bin(patch.rev), patch.name) for patch in q.applied] | 2427 mqtags = [(bin(patch.rev), patch.name) for patch in q.applied] |
2437 | 2428 |
2438 if mqtags[-1][0] not in self.changelog.nodemap: | 2429 if mqtags[-1][0] not in self.changelog.nodemap: |
2439 self.ui.warn(_('mq status file refers to unknown node %s\n') | 2430 self.ui.warn(_('mq status file refers to unknown node %s\n') |
2440 % short(mqtags[-1][0])) | 2431 % short(mqtags[-1][0])) |
2441 return tagscache | 2432 return result |
2442 | 2433 |
2443 mqtags.append((mqtags[-1][0], 'qtip')) | 2434 mqtags.append((mqtags[-1][0], 'qtip')) |
2444 mqtags.append((mqtags[0][0], 'qbase')) | 2435 mqtags.append((mqtags[0][0], 'qbase')) |
2445 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent')) | 2436 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent')) |
2437 tags = result[0] | |
2446 for patch in mqtags: | 2438 for patch in mqtags: |
2447 if patch[1] in tagscache: | 2439 if patch[1] in tags: |
2448 self.ui.warn(_('Tag %s overrides mq patch of the same name\n') | 2440 self.ui.warn(_('Tag %s overrides mq patch of the same name\n') |
2449 % patch[1]) | 2441 % patch[1]) |
2450 else: | 2442 else: |
2451 tagscache[patch[1]] = patch[0] | 2443 tags[patch[1]] = patch[0] |
2452 | 2444 |
2453 return tagscache | 2445 return result |
2454 | 2446 |
2455 def _branchtags(self, partial, lrev): | 2447 def _branchtags(self, partial, lrev): |
2456 q = self.mq | 2448 q = self.mq |
2457 if not q.applied: | 2449 if not q.applied: |
2458 return super(mqrepo, self)._branchtags(partial, lrev) | 2450 return super(mqrepo, self)._branchtags(partial, lrev) |