mercurial/commands.py
changeset 2870 ffa2be02c4e5
parent 2869 8eaaf1321bfe
parent 2865 2893e51407a4
child 2873 4ec58b157265
equal deleted inserted replaced
2869:8eaaf1321bfe 2870:ffa2be02c4e5
     1 # commands.py - command processing for mercurial
     1 # commands.py - command processing for mercurial
     2 #
     2 #
     3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
     3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
     4 #
     4 #
     5 # This software may be used and distributed according to the terms
     5 # This software may be used and distributed according to the terms
     6 # of the GNU General Public License, incorporated herein by reference.
     6 # of the GNU General Public License, incorporated herein by reference.
     7 
     7 
     8 from demandload import demandload
     8 from demandload import demandload
     9 from node import *
     9 from node import *
    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 difflib random signal tempfile time")
    13 demandload(globals(), "fnmatch mdiff difflib patch 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 cStringIO changegroup email.Parser")
    15 demandload(globals(), "archival cStringIO changegroup")
    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):
   631 def show_version(ui):
   631 def show_version(ui):
   632     """output version and copyright information"""
   632     """output version and copyright information"""
   633     ui.write(_("Mercurial Distributed SCM (version %s)\n")
   633     ui.write(_("Mercurial Distributed SCM (version %s)\n")
   634              % version.get_version())
   634              % version.get_version())
   635     ui.status(_(
   635     ui.status(_(
   636         "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
   636         "\nCopyright (C) 2005, 2006 Matt Mackall <mpm@selenic.com>\n"
   637         "This is free software; see the source for copying conditions. "
   637         "This is free software; see the source for copying conditions. "
   638         "There is NO\nwarranty; "
   638         "There is NO\nwarranty; "
   639         "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
   639         "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
   640     ))
   640     ))
   641 
   641 
  1331         rev = repo.changelog.tip()
  1331         rev = repo.changelog.tip()
  1332     else:
  1332     else:
  1333         rev = repo.lookup(rev)
  1333         rev = repo.lookup(rev)
  1334     change = repo.changelog.read(rev)
  1334     change = repo.changelog.read(rev)
  1335     n = change[0]
  1335     n = change[0]
  1336     files = repo.manifest.readflags(n)
  1336     files = repo.manifest.read(n)
  1337     wlock = repo.wlock()
  1337     wlock = repo.wlock()
  1338     repo.dirstate.rebuild(rev, files.iteritems())
  1338     repo.dirstate.rebuild(rev, files)
  1339 
  1339 
  1340 def debugcheckstate(ui, repo):
  1340 def debugcheckstate(ui, repo):
  1341     """validate the correctness of the current dirstate"""
  1341     """validate the correctness of the current dirstate"""
  1342     parent1, parent2 = repo.dirstate.parents()
  1342     parent1, parent2 = repo.dirstate.parents()
  1343     repo.dirstate.read()
  1343     repo.dirstate.read()
  1841         bail_if_changed(repo)
  1841         bail_if_changed(repo)
  1842 
  1842 
  1843     d = opts["base"]
  1843     d = opts["base"]
  1844     strip = opts["strip"]
  1844     strip = opts["strip"]
  1845 
  1845 
  1846     mailre = re.compile(r'(?:From |[\w-]+:)')
       
  1847 
       
  1848     # attempt to detect the start of a patch
       
  1849     # (this heuristic is borrowed from quilt)
       
  1850     diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
       
  1851                         'retrieving revision [0-9]+(\.[0-9]+)*$|' +
       
  1852                         '(---|\*\*\*)[ \t])', re.MULTILINE)
       
  1853 
       
  1854     wlock = repo.wlock()
  1846     wlock = repo.wlock()
  1855     lock = repo.lock()
  1847     lock = repo.lock()
  1856 
  1848 
  1857     for patch in patches:
  1849     for p in patches:
  1858         pf = os.path.join(d, patch)
  1850         pf = os.path.join(d, p)
  1859 
  1851 
  1860         message = None
       
  1861         user = None
       
  1862         date = None
       
  1863         hgpatch = False
       
  1864 
       
  1865         p = email.Parser.Parser()
       
  1866         if pf == '-':
  1852         if pf == '-':
  1867             msg = p.parse(sys.stdin)
       
  1868             ui.status(_("applying patch from stdin\n"))
  1853             ui.status(_("applying patch from stdin\n"))
       
  1854             tmpname, message, user, date = patch.extract(ui, sys.stdin)
  1869         else:
  1855         else:
  1870             msg = p.parse(file(pf))
  1856             ui.status(_("applying %s\n") % p)
  1871             ui.status(_("applying %s\n") % patch)
  1857             tmpname, message, user, date = patch.extract(ui, file(pf))
  1872 
  1858 
  1873         fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
  1859         if tmpname is None:
  1874         tmpfp = os.fdopen(fd, 'w')
  1860             raise util.Abort(_('no diffs found'))
       
  1861 
  1875         try:
  1862         try:
  1876             message = msg['Subject']
       
  1877             if message:
       
  1878                 message = message.replace('\n\t', ' ')
       
  1879                 ui.debug('Subject: %s\n' % message)
       
  1880             user = msg['From']
       
  1881             if user:
       
  1882                 ui.debug('From: %s\n' % user)
       
  1883             diffs_seen = 0
       
  1884             ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
       
  1885             for part in msg.walk():
       
  1886                 content_type = part.get_content_type()
       
  1887                 ui.debug('Content-Type: %s\n' % content_type)
       
  1888                 if content_type not in ok_types:
       
  1889                     continue
       
  1890                 payload = part.get_payload(decode=True)
       
  1891                 m = diffre.search(payload)
       
  1892                 if m:
       
  1893                     ui.debug(_('found patch at byte %d\n') % m.start(0))
       
  1894                     diffs_seen += 1
       
  1895                     hgpatch = False
       
  1896                     fp = cStringIO.StringIO()
       
  1897                     if message:
       
  1898                         fp.write(message)
       
  1899                         fp.write('\n')
       
  1900                     for line in payload[:m.start(0)].splitlines():
       
  1901                         if line.startswith('# HG changeset patch'):
       
  1902                             ui.debug(_('patch generated by hg export\n'))
       
  1903                             hgpatch = True
       
  1904                             # drop earlier commit message content
       
  1905                             fp.seek(0)
       
  1906                             fp.truncate()
       
  1907                         elif hgpatch:
       
  1908                             if line.startswith('# User '):
       
  1909                                 user = line[7:]
       
  1910                                 ui.debug('From: %s\n' % user)
       
  1911                             elif line.startswith("# Date "):
       
  1912                                 date = line[7:]
       
  1913                         if not line.startswith('# '):
       
  1914                             fp.write(line)
       
  1915                             fp.write('\n')
       
  1916                     message = fp.getvalue()
       
  1917                     if tmpfp:
       
  1918                         tmpfp.write(payload)
       
  1919                         if not payload.endswith('\n'):
       
  1920                             tmpfp.write('\n')
       
  1921                 elif not diffs_seen and message and content_type == 'text/plain':
       
  1922                     message += '\n' + payload
       
  1923 
       
  1924             if opts['message']:
  1863             if opts['message']:
  1925                 # pickup the cmdline msg
  1864                 # pickup the cmdline msg
  1926                 message = opts['message']
  1865                 message = opts['message']
  1927             elif message:
  1866             elif message:
  1928                 # pickup the patch msg
  1867                 # pickup the patch msg
  1930             else:
  1869             else:
  1931                 # launch the editor
  1870                 # launch the editor
  1932                 message = None
  1871                 message = None
  1933             ui.debug(_('message:\n%s\n') % message)
  1872             ui.debug(_('message:\n%s\n') % message)
  1934 
  1873 
  1935             tmpfp.close()
  1874             files = patch.patch(strip, tmpname, ui, cwd=repo.root)
  1936             if not diffs_seen:
  1875             removes = []
  1937                 raise util.Abort(_('no diffs found'))
       
  1938 
       
  1939             files = util.patch(strip, tmpname, ui, cwd=repo.root)
       
  1940             if len(files) > 0:
  1876             if len(files) > 0:
  1941                 cfiles = files
  1877                 cfiles = files.keys()
       
  1878                 copies = []
       
  1879                 copts = {'after': False, 'force': False}
  1942                 cwd = repo.getcwd()
  1880                 cwd = repo.getcwd()
  1943                 if cwd:
  1881                 if cwd:
  1944                     cfiles = [util.pathto(cwd, f) for f in files]
  1882                     cfiles = [util.pathto(cwd, f) for f in files.keys()]
       
  1883                 for f in files:
       
  1884                     ctype, gp = files[f]
       
  1885                     if ctype == 'RENAME':
       
  1886                         copies.append((gp.oldpath, gp.path, gp.copymod))
       
  1887                         removes.append(gp.oldpath)
       
  1888                     elif ctype == 'COPY':
       
  1889                         copies.append((gp.oldpath, gp.path, gp.copymod))
       
  1890                     elif ctype == 'DELETE':
       
  1891                         removes.append(gp.path)
       
  1892                 for src, dst, after in copies:
       
  1893                     absdst = os.path.join(repo.root, dst)
       
  1894                     if not after and os.path.exists(absdst):
       
  1895                         raise util.Abort(_('patch creates existing file %s') % dst)
       
  1896                     if cwd:
       
  1897                         src, dst = [util.pathto(cwd, f) for f in (src, dst)]
       
  1898                     copts['after'] = after
       
  1899                     errs, copied = docopy(ui, repo, (src, dst), copts, wlock=wlock)
       
  1900                     if errs:
       
  1901                         raise util.Abort(errs)
       
  1902                 if removes:
       
  1903                     repo.remove(removes, True, wlock=wlock)
       
  1904                 for f in files:
       
  1905                     ctype, gp = files[f]
       
  1906                     if gp and gp.mode:
       
  1907                         x = gp.mode & 0100 != 0
       
  1908                         dst = os.path.join(repo.root, gp.path)
       
  1909                         util.set_exec(dst, x)
  1945                 addremove_lock(ui, repo, cfiles, {}, wlock=wlock)
  1910                 addremove_lock(ui, repo, cfiles, {}, wlock=wlock)
       
  1911             files = files.keys()
       
  1912             files.extend([r for r in removes if r not in files])
  1946             repo.commit(files, message, user, date, wlock=wlock, lock=lock)
  1913             repo.commit(files, message, user, date, wlock=wlock, lock=lock)
  1947         finally:
  1914         finally:
  1948             os.unlink(tmpname)
  1915             os.unlink(tmpname)
  1949 
  1916 
  1950 def incoming(ui, repo, source="default", **opts):
  1917 def incoming(ui, repo, source="default", **opts):
  2176         except hg.RepoError:
  2143         except hg.RepoError:
  2177             n = repo.manifest.lookup(rev)
  2144             n = repo.manifest.lookup(rev)
  2178     else:
  2145     else:
  2179         n = repo.manifest.tip()
  2146         n = repo.manifest.tip()
  2180     m = repo.manifest.read(n)
  2147     m = repo.manifest.read(n)
  2181     mf = repo.manifest.readflags(n)
       
  2182     files = m.keys()
  2148     files = m.keys()
  2183     files.sort()
  2149     files.sort()
  2184 
  2150 
  2185     for f in files:
  2151     for f in files:
  2186         ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
  2152         ui.write("%40s %3s %s\n" % (hex(m[f]),
       
  2153                                     m.execf(f) and "755" or "644", f))
  2187 
  2154 
  2188 def merge(ui, repo, node=None, force=None, branch=None):
  2155 def merge(ui, repo, node=None, force=None, branch=None):
  2189     """Merge working directory with another revision
  2156     """Merge working directory with another revision
  2190 
  2157 
  2191     Merge the contents of the current working directory and the
  2158     Merge the contents of the current working directory and the