diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1,6 +1,6 @@ # commands.py - command processing for mercurial # -# Copyright 2005 Matt Mackall +# Copyright 2005, 2006 Matt Mackall # # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. @@ -10,9 +10,9 @@ from node import * from i18n import gettext as _ demandload(globals(), "os re sys signal shutil imp urllib pdb") demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo") -demandload(globals(), "fnmatch mdiff difflib random signal tempfile time") +demandload(globals(), "fnmatch mdiff difflib patch random signal tempfile time") demandload(globals(), "traceback errno socket version struct atexit sets bz2") -demandload(globals(), "archival cStringIO changegroup email.Parser") +demandload(globals(), "archival cStringIO changegroup") demandload(globals(), "hgweb.server sshserver") class UnknownCommand(Exception): @@ -633,7 +633,7 @@ def show_version(ui): ui.write(_("Mercurial Distributed SCM (version %s)\n") % version.get_version()) ui.status(_( - "\nCopyright (C) 2005 Matt Mackall \n" + "\nCopyright (C) 2005, 2006 Matt Mackall \n" "This is free software; see the source for copying conditions. " "There is NO\nwarranty; " "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" @@ -1333,9 +1333,9 @@ def debugrebuildstate(ui, repo, rev=None rev = repo.lookup(rev) change = repo.changelog.read(rev) n = change[0] - files = repo.manifest.readflags(n) + files = repo.manifest.read(n) wlock = repo.wlock() - repo.dirstate.rebuild(rev, files.iteritems()) + repo.dirstate.rebuild(rev, files) def debugcheckstate(ui, repo): """validate the correctness of the current dirstate""" @@ -1843,84 +1843,23 @@ def import_(ui, repo, patch1, *patches, d = opts["base"] strip = opts["strip"] - mailre = re.compile(r'(?:From |[\w-]+:)') - - # attempt to detect the start of a patch - # (this heuristic is borrowed from quilt) - diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' + - 'retrieving revision [0-9]+(\.[0-9]+)*$|' + - '(---|\*\*\*)[ \t])', re.MULTILINE) - wlock = repo.wlock() lock = repo.lock() - for patch in patches: - pf = os.path.join(d, patch) - - message = None - user = None - date = None - hgpatch = False - - p = email.Parser.Parser() + for p in patches: + pf = os.path.join(d, p) + if pf == '-': - msg = p.parse(sys.stdin) ui.status(_("applying patch from stdin\n")) + tmpname, message, user, date = patch.extract(ui, sys.stdin) else: - msg = p.parse(file(pf)) - ui.status(_("applying %s\n") % patch) - - fd, tmpname = tempfile.mkstemp(prefix='hg-patch-') - tmpfp = os.fdopen(fd, 'w') + ui.status(_("applying %s\n") % p) + tmpname, message, user, date = patch.extract(ui, file(pf)) + + if tmpname is None: + raise util.Abort(_('no diffs found')) + try: - message = msg['Subject'] - if message: - message = message.replace('\n\t', ' ') - ui.debug('Subject: %s\n' % message) - user = msg['From'] - if user: - ui.debug('From: %s\n' % user) - diffs_seen = 0 - ok_types = ('text/plain', 'text/x-diff', 'text/x-patch') - for part in msg.walk(): - content_type = part.get_content_type() - ui.debug('Content-Type: %s\n' % content_type) - if content_type not in ok_types: - continue - payload = part.get_payload(decode=True) - m = diffre.search(payload) - if m: - ui.debug(_('found patch at byte %d\n') % m.start(0)) - diffs_seen += 1 - hgpatch = False - fp = cStringIO.StringIO() - if message: - fp.write(message) - fp.write('\n') - for line in payload[:m.start(0)].splitlines(): - if line.startswith('# HG changeset patch'): - ui.debug(_('patch generated by hg export\n')) - hgpatch = True - # drop earlier commit message content - fp.seek(0) - fp.truncate() - elif hgpatch: - if line.startswith('# User '): - user = line[7:] - ui.debug('From: %s\n' % user) - elif line.startswith("# Date "): - date = line[7:] - if not line.startswith('# '): - fp.write(line) - fp.write('\n') - message = fp.getvalue() - if tmpfp: - tmpfp.write(payload) - if not payload.endswith('\n'): - tmpfp.write('\n') - elif not diffs_seen and message and content_type == 'text/plain': - message += '\n' + payload - if opts['message']: # pickup the cmdline msg message = opts['message'] @@ -1932,17 +1871,45 @@ def import_(ui, repo, patch1, *patches, message = None ui.debug(_('message:\n%s\n') % message) - tmpfp.close() - if not diffs_seen: - raise util.Abort(_('no diffs found')) - - files = util.patch(strip, tmpname, ui, cwd=repo.root) + files = patch.patch(strip, tmpname, ui, cwd=repo.root) + removes = [] if len(files) > 0: - cfiles = files + cfiles = files.keys() + copies = [] + copts = {'after': False, 'force': False} cwd = repo.getcwd() if cwd: - cfiles = [util.pathto(cwd, f) for f in files] + cfiles = [util.pathto(cwd, f) for f in files.keys()] + for f in files: + ctype, gp = files[f] + if ctype == 'RENAME': + copies.append((gp.oldpath, gp.path, gp.copymod)) + removes.append(gp.oldpath) + elif ctype == 'COPY': + copies.append((gp.oldpath, gp.path, gp.copymod)) + elif ctype == 'DELETE': + removes.append(gp.path) + for src, dst, after in copies: + absdst = os.path.join(repo.root, dst) + if not after and os.path.exists(absdst): + raise util.Abort(_('patch creates existing file %s') % dst) + if cwd: + src, dst = [util.pathto(cwd, f) for f in (src, dst)] + copts['after'] = after + errs, copied = docopy(ui, repo, (src, dst), copts, wlock=wlock) + if errs: + raise util.Abort(errs) + if removes: + repo.remove(removes, True, wlock=wlock) + for f in files: + ctype, gp = files[f] + if gp and gp.mode: + x = gp.mode & 0100 != 0 + dst = os.path.join(repo.root, gp.path) + util.set_exec(dst, x) addremove_lock(ui, repo, cfiles, {}, wlock=wlock) + files = files.keys() + files.extend([r for r in removes if r not in files]) repo.commit(files, message, user, date, wlock=wlock, lock=lock) finally: os.unlink(tmpname) @@ -2178,12 +2145,12 @@ def manifest(ui, repo, rev=None): else: n = repo.manifest.tip() m = repo.manifest.read(n) - mf = repo.manifest.readflags(n) files = m.keys() files.sort() for f in files: - ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f)) + ui.write("%40s %3s %s\n" % (hex(m[f]), + m.execf(f) and "755" or "644", f)) def merge(ui, repo, node=None, force=None, branch=None): """Merge working directory with another revision