comparison mercurial/commands.py @ 2509:6350b01d173f

merge with wsgi changes.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Tue, 27 Jun 2006 00:10:41 -0700
parents 158d3d2ae070
children cbff06469488
comparison
equal deleted inserted replaced
2508:ab460a3f0e3a 2509:6350b01d173f
10 from i18n import gettext as _ 10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal shutil imp urllib pdb") 11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo") 12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 demandload(globals(), "fnmatch mdiff random signal tempfile time") 13 demandload(globals(), "fnmatch mdiff random signal tempfile time")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2") 14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
15 demandload(globals(), "archival changegroup") 15 demandload(globals(), "archival cStringIO changegroup email.Parser")
16 demandload(globals(), "hgweb.server sshserver") 16 demandload(globals(), "hgweb.server sshserver")
17 17
18 class UnknownCommand(Exception): 18 class UnknownCommand(Exception):
19 """Exception raised if command is not in the command table.""" 19 """Exception raised if command is not in the command table."""
20 class AmbiguousCommand(Exception): 20 class AmbiguousCommand(Exception):
834 commit(ui, repo, **commit_opts) 834 commit(ui, repo, **commit_opts)
835 def nice(node): 835 def nice(node):
836 return '%d:%s' % (repo.changelog.rev(node), short(node)) 836 return '%d:%s' % (repo.changelog.rev(node), short(node))
837 ui.status(_('changeset %s backs out changeset %s\n') % 837 ui.status(_('changeset %s backs out changeset %s\n') %
838 (nice(repo.changelog.tip()), nice(node))) 838 (nice(repo.changelog.tip()), nice(node)))
839 if opts['merge'] and op1 != node: 839 if op1 != node:
840 ui.status(_('merging with changeset %s\n') % nice(op1)) 840 if opts['merge']:
841 doupdate(ui, repo, hex(op1), **opts) 841 ui.status(_('merging with changeset %s\n') % nice(op1))
842 842 doupdate(ui, repo, hex(op1), **opts)
843 def bundle(ui, repo, fname, dest="default-push", **opts): 843 else:
844 ui.status(_('the backout changeset is a new head - '
845 'do not forget to merge\n'))
846 ui.status(_('(use "backout -m" if you want to auto-merge)\n'))
847
848 def bundle(ui, repo, fname, dest=None, **opts):
844 """create a changegroup file 849 """create a changegroup file
845 850
846 Generate a compressed changegroup file collecting all changesets 851 Generate a compressed changegroup file collecting all changesets
847 not found in the other repository. 852 not found in the other repository.
848 853
853 extension is ".hg". 858 extension is ".hg".
854 859
855 Unlike import/export, this exactly preserves all changeset 860 Unlike import/export, this exactly preserves all changeset
856 contents including permissions, rename data, and revision history. 861 contents including permissions, rename data, and revision history.
857 """ 862 """
858 dest = ui.expandpath(dest) 863 dest = ui.expandpath(dest or 'default-push', dest or 'default')
859 other = hg.repository(ui, dest) 864 other = hg.repository(ui, dest)
860 o = repo.findoutgoing(other, force=opts['force']) 865 o = repo.findoutgoing(other, force=opts['force'])
861 cg = repo.changegroup(o, 'bundle') 866 cg = repo.changegroup(o, 'bundle')
862 write_bundle(cg, fname) 867 write_bundle(cg, fname)
863 868
1712 Import a list of patches and commit them individually. 1717 Import a list of patches and commit them individually.
1713 1718
1714 If there are outstanding changes in the working directory, import 1719 If there are outstanding changes in the working directory, import
1715 will abort unless given the -f flag. 1720 will abort unless given the -f flag.
1716 1721
1717 If a patch looks like a mail message (its first line starts with 1722 You can import a patch straight from a mail message. Even patches
1718 "From " or looks like an RFC822 header), it will not be applied 1723 as attachments work (body part must be type text/plain or
1719 unless the -f option is used. The importer neither parses nor 1724 text/x-patch to be used). Sender and subject line of email
1720 discards mail headers, so use -f only to override the "mailness" 1725 message are used as default committer and commit message. Any
1721 safety check, not to import a real mail message. 1726 text/plain body part before first diff is added to commit message.
1727
1728 If imported patch was generated by hg export, user and description
1729 from patch override values from message headers and body. Values
1730 given on command line with -m and -u override these.
1722 1731
1723 To read a patch from standard input, use patch name "-". 1732 To read a patch from standard input, use patch name "-".
1724 """ 1733 """
1725 patches = (patch1,) + patches 1734 patches = (patch1,) + patches
1726 1735
1732 1741
1733 mailre = re.compile(r'(?:From |[\w-]+:)') 1742 mailre = re.compile(r'(?:From |[\w-]+:)')
1734 1743
1735 # attempt to detect the start of a patch 1744 # attempt to detect the start of a patch
1736 # (this heuristic is borrowed from quilt) 1745 # (this heuristic is borrowed from quilt)
1737 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' + 1746 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1738 'retrieving revision [0-9]+(\.[0-9]+)*$|' + 1747 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1739 '(---|\*\*\*)[ \t])') 1748 '(---|\*\*\*)[ \t])', re.MULTILINE)
1740 1749
1741 for patch in patches: 1750 for patch in patches:
1742 pf = os.path.join(d, patch) 1751 pf = os.path.join(d, patch)
1743 1752
1744 message = [] 1753 message = None
1745 user = None 1754 user = None
1746 date = None 1755 date = None
1747 hgpatch = False 1756 hgpatch = False
1757
1758 p = email.Parser.Parser()
1748 if pf == '-': 1759 if pf == '-':
1749 f = sys.stdin 1760 msg = p.parse(sys.stdin)
1750 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
1751 pf = tmpname
1752 tmpfp = os.fdopen(fd, 'w')
1753 ui.status(_("applying patch from stdin\n")) 1761 ui.status(_("applying patch from stdin\n"))
1754 else: 1762 else:
1755 f = open(pf) 1763 msg = p.parse(file(pf))
1756 tmpfp, tmpname = None, None
1757 ui.status(_("applying %s\n") % patch) 1764 ui.status(_("applying %s\n") % patch)
1765
1766 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
1767 tmpfp = os.fdopen(fd, 'w')
1758 try: 1768 try:
1759 while True: 1769 message = msg['Subject']
1760 line = f.readline() 1770 if message:
1761 if not line: break 1771 message = message.replace('\n\t', ' ')
1762 if tmpfp: tmpfp.write(line) 1772 ui.debug('Subject: %s\n' % message)
1763 line = line.rstrip() 1773 user = msg['From']
1764 if (not message and not hgpatch and 1774 if user:
1765 mailre.match(line) and not opts['force']): 1775 ui.debug('From: %s\n' % user)
1766 if len(line) > 35: 1776 diffs_seen = 0
1767 line = line[:32] + '...' 1777 ok_types = ('text/plain', 'text/x-patch')
1768 raise util.Abort(_('first line looks like a ' 1778 for part in msg.walk():
1769 'mail header: ') + line) 1779 content_type = part.get_content_type()
1770 if diffre.match(line): 1780 ui.debug('Content-Type: %s\n' % content_type)
1781 if content_type not in ok_types:
1782 continue
1783 payload = part.get_payload(decode=True)
1784 m = diffre.search(payload)
1785 if m:
1786 ui.debug(_('found patch at byte %d\n') % m.start(0))
1787 diffs_seen += 1
1788 hgpatch = False
1789 fp = cStringIO.StringIO()
1790 for line in payload[:m.start(0)].splitlines():
1791 if line.startswith('# HG changeset patch'):
1792 ui.debug(_('patch generated by hg export\n'))
1793 hgpatch = True
1794 elif hgpatch:
1795 if line.startswith('# User '):
1796 user = line[7:]
1797 ui.debug('From: %s\n' % user)
1798 elif line.startswith("# Date "):
1799 date = line[7:]
1800 if not line.startswith('# '):
1801 fp.write(line)
1802 fp.write('\n')
1803 hgpatch = False
1804 message = fp.getvalue() or message
1771 if tmpfp: 1805 if tmpfp:
1772 for chunk in util.filechunkiter(f): 1806 tmpfp.write(payload)
1773 tmpfp.write(chunk) 1807 if not payload.endswith('\n'):
1774 break 1808 tmpfp.write('\n')
1775 elif hgpatch: 1809 elif not diffs_seen and message and content_type == 'text/plain':
1776 # parse values when importing the result of an hg export 1810 message += '\n' + payload
1777 if line.startswith("# User "):
1778 user = line[7:]
1779 ui.debug(_('User: %s\n') % user)
1780 elif line.startswith("# Date "):
1781 date = line[7:]
1782 elif not line.startswith("# ") and line:
1783 message.append(line)
1784 hgpatch = False
1785 elif line == '# HG changeset patch':
1786 hgpatch = True
1787 message = [] # We may have collected garbage
1788 elif message or line:
1789 message.append(line)
1790 1811
1791 if opts['message']: 1812 if opts['message']:
1792 # pickup the cmdline msg 1813 # pickup the cmdline msg
1793 message = opts['message'] 1814 message = opts['message']
1794 elif message: 1815 elif message:
1795 # pickup the patch msg 1816 # pickup the patch msg
1796 message = '\n'.join(message).rstrip() 1817 message = message.strip()
1797 else: 1818 else:
1798 # launch the editor 1819 # launch the editor
1799 message = None 1820 message = None
1800 ui.debug(_('message:\n%s\n') % message) 1821 ui.debug(_('message:\n%s\n') % message)
1801 1822
1802 if tmpfp: tmpfp.close() 1823 tmpfp.close()
1803 files = util.patch(strip, pf, ui) 1824 if not diffs_seen:
1804 1825 raise util.Abort(_('no diffs found'))
1826
1827 files = util.patch(strip, tmpname, ui)
1805 if len(files) > 0: 1828 if len(files) > 0:
1806 addremove_lock(ui, repo, files, {}) 1829 addremove_lock(ui, repo, files, {})
1807 repo.commit(files, message, user, date) 1830 repo.commit(files, message, user, date)
1808 finally: 1831 finally:
1809 if tmpname: os.unlink(tmpname) 1832 os.unlink(tmpname)
1810 1833
1811 def incoming(ui, repo, source="default", **opts): 1834 def incoming(ui, repo, source="default", **opts):
1812 """show new changesets found in source 1835 """show new changesets found in source
1813 1836
1814 Show new changesets found in the specified path/URL or the default 1837 Show new changesets found in the specified path/URL or the default
2040 marked as changed for the next commit and a commit must be 2063 marked as changed for the next commit and a commit must be
2041 performed before any further updates are allowed. 2064 performed before any further updates are allowed.
2042 """ 2065 """
2043 return doupdate(ui, repo, node=node, merge=True, **opts) 2066 return doupdate(ui, repo, node=node, merge=True, **opts)
2044 2067
2045 def outgoing(ui, repo, dest="default-push", **opts): 2068 def outgoing(ui, repo, dest=None, **opts):
2046 """show changesets not found in destination 2069 """show changesets not found in destination
2047 2070
2048 Show changesets not found in the specified destination repository or 2071 Show changesets not found in the specified destination repository or
2049 the default push location. These are the changesets that would be pushed 2072 the default push location. These are the changesets that would be pushed
2050 if a push was requested. 2073 if a push was requested.
2051 2074
2052 See pull for valid destination format details. 2075 See pull for valid destination format details.
2053 """ 2076 """
2054 dest = ui.expandpath(dest) 2077 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2055 if opts['ssh']: 2078 if opts['ssh']:
2056 ui.setconfig("ui", "ssh", opts['ssh']) 2079 ui.setconfig("ui", "ssh", opts['ssh'])
2057 if opts['remotecmd']: 2080 if opts['remotecmd']:
2058 ui.setconfig("ui", "remotecmd", opts['remotecmd']) 2081 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2059 2082
2172 elif opts['rev']: 2195 elif opts['rev']:
2173 revs = [other.lookup(rev) for rev in opts['rev']] 2196 revs = [other.lookup(rev) for rev in opts['rev']]
2174 modheads = repo.pull(other, heads=revs, force=opts['force']) 2197 modheads = repo.pull(other, heads=revs, force=opts['force'])
2175 return postincoming(ui, repo, modheads, opts['update']) 2198 return postincoming(ui, repo, modheads, opts['update'])
2176 2199
2177 def push(ui, repo, dest="default-push", **opts): 2200 def push(ui, repo, dest=None, **opts):
2178 """push changes to the specified destination 2201 """push changes to the specified destination
2179 2202
2180 Push changes from the local repository to the given destination. 2203 Push changes from the local repository to the given destination.
2181 2204
2182 This is the symmetrical operation for pull. It helps to move 2205 This is the symmetrical operation for pull. It helps to move
2194 ssh://[user@]host[:port][/path] 2217 ssh://[user@]host[:port][/path]
2195 2218
2196 Look at the help text for the pull command for important details 2219 Look at the help text for the pull command for important details
2197 about ssh:// URLs. 2220 about ssh:// URLs.
2198 """ 2221 """
2199 dest = ui.expandpath(dest) 2222 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2200 2223
2201 if opts['ssh']: 2224 if opts['ssh']:
2202 ui.setconfig("ui", "ssh", opts['ssh']) 2225 ui.setconfig("ui", "ssh", opts['ssh'])
2203 if opts['remotecmd']: 2226 if opts['remotecmd']:
2204 ui.setconfig("ui", "remotecmd", opts['remotecmd']) 2227 ui.setconfig("ui", "remotecmd", opts['remotecmd'])