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)