Mercurial > hg > hg-fastimport
changeset 1:9461f5c3a67c
Actually imports something - incredible!
| author | Paul Crowley <paul@lshift.net> |
|---|---|
| date | Fri, 29 Feb 2008 17:58:31 +0000 |
| parents | d107c6d36780 |
| children | c0be990fe8a8 |
| files | fastimport/__init__.py fastimport/commands.py fastimport/hgechoprocessor.py fastimport/hgimport.py fastimport/parser.py fastimport/processor.py |
| diffstat | 6 files changed, 197 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/fastimport/__init__.py Fri Feb 29 12:19:18 2008 +0000 +++ b/fastimport/__init__.py Fri Feb 29 17:58:31 2008 +0000 @@ -1,17 +1,14 @@ from mercurial import commands import parser -#import dates -#import commands -#from fastimport.hgechoprocessor import HgEchoProcessor import hgechoprocessor -#import hhhh -#from hhhh import HgEchoProcessor +import hgimport def fastimport(ui, repo, source, **opts): ui.write("Source is %s\n" % source) f = open(source) - proc = hgechoprocessor.HgEchoProcessor(ui, repo, **opts) + proc = hgimport.HgImportProcessor(ui, repo, **opts) + #proc = hgechoprocessor.HgEchoProcessor(ui, repo, **opts) p = parser.ImportParser(f) proc.process(p.iter_commands)
--- a/fastimport/commands.py Fri Feb 29 12:19:18 2008 +0000 +++ b/fastimport/commands.py Fri Feb 29 17:58:31 2008 +0000 @@ -85,14 +85,15 @@ class CommitCommand(ImportCommand): - def __init__(self, ref, mark, author, committer, message, parents, - file_iter, lineno=0): + def __init__(self, ref, mark, author, committer, message, from_, + parents, file_iter, lineno=0): ImportCommand.__init__(self, 'commit') self.ref = ref self.mark = mark self.author = author self.committer = committer self.message = message + self.from_ = from_ self.parents = parents self.file_iter = file_iter self.lineno = lineno
--- a/fastimport/hgechoprocessor.py Fri Feb 29 12:19:18 2008 +0000 +++ b/fastimport/hgechoprocessor.py Fri Feb 29 17:58:31 2008 +0000 @@ -32,40 +32,24 @@ self.finished = False def progress_handler(self, cmd): - """Process a ProgressCommand.""" - self.ui.write("Cmd: %s\n" % repr(cmd)) + self.ui.write(cmd.dump_str(verbose=True) + "\n") def blob_handler(self, cmd): - """Process a BlobCommand.""" - self.ui.write("Cmd: %s\n" % repr(cmd)) + self.ui.write(cmd.dump_str(verbose=True) + "\n") def checkpoint_handler(self, cmd): - """Process a CheckpointCommand.""" - self.ui.write("Cmd: %s\n" % repr(cmd)) + self.ui.write(cmd.dump_str(verbose=True) + "\n") def commit_handler(self, cmd): - """Process a CommitCommand.""" - self.ui.write("Commit: %s\n" % repr(cmd)) commit_handler = HgEchoCommitHandler(cmd, self.ui, self.repo, **self.opts) commit_handler.process() - self.ui.write("Done commit\n") + self.ui.write(cmd.dump_str(verbose=True) + "\n") def reset_handler(self, cmd): - """Process a ResetCommand.""" - self.ui.write("Cmd: %s\n" % repr(cmd)) + self.ui.write(cmd.dump_str(verbose=True) + "\n") def tag_handler(self, cmd): - """Process a TagCommand.""" - self.ui.write("Cmd: %s\n" % repr(cmd)) - - def finished(self): - self.ui.write("Finished") - - def pre_handler(self, cmd): - self.ui.write("Pre-handler: %s\n" % repr(cmd)) - - def post_handler(self, cmd): - self.ui.write("Post-handler: %s\n" % repr(cmd)) + self.ui.write(cmd.dump_str(verbose=True) + "\n") class HgEchoCommitHandler(processor.CommitHandler): @@ -75,41 +59,17 @@ self.repo = repo self.opts = opts - def process(self): - self.pre_process_files() - for fc in self.command.file_iter(): - try: - handler = self.__class__.__dict__[fc.name[4:] + "_handler"] - except KeyError: - raise errors.MissingHandler(fc.name) - else: - handler(self, fc) - self.post_process_files() - - def pre_process_files(self): - """Prepare for committing.""" - pass - - def post_process_files(self): - """Save the revision.""" - pass - def modify_handler(self, filecmd): - """Handle a filemodify command.""" - self.ui.write("Cmd: %s\n" % repr(filecmd)) + self.ui.write(filecmd.dump_str(verbose=True) + "\n") def delete_handler(self, filecmd): - """Handle a filedelete command.""" - self.ui.write("Cmd: %s\n" % repr(filecmd)) + self.ui.write(filecmd.dump_str(verbose=True) + "\n") def copy_handler(self, filecmd): - """Handle a filecopy command.""" - self.ui.write("Cmd: %s\n" % repr(filecmd)) + self.ui.write(filecmd.dump_str(verbose=True) + "\n") def rename_handler(self, filecmd): - """Handle a filerename command.""" - self.ui.write("Cmd: %s\n" % repr(filecmd)) + self.ui.write(filecmd.dump_str(verbose=True) + "\n") def deleteall_handler(self, filecmd): - """Handle a filedeleteall command.""" - self.ui.write("Cmd: %s\n" % repr(filecmd)) + self.ui.write(filecmd.dump_str(verbose=True) + "\n")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fastimport/hgimport.py Fri Feb 29 17:58:31 2008 +0000 @@ -0,0 +1,157 @@ +# Copyright (C) 2008 Canonical Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""Processor of import commands. + +This module provides core processing functionality including an abstract class +for basing real processors on. See the processors package for examples. +""" + +import os +import os.path +import mercurial.hg +import mercurial.commands +from mercurial.node import nullrev +import processor + +import hgechoprocessor + +class HgImportProcessor(processor.ImportProcessor): + + def __init__(self, ui, repo, **opts): + self.ui = ui + self.repo = repo + self.opts = opts + self.last_mark = None + self.mark_map = {} + self.branch_map = {} + #self.tag_map = {} + #self.tag_back_map = {} + self.finished = False + + def progress_handler(self, cmd): + self.ui.write("Progress: %s\n" % cmd.message) + + # We can't handle blobs - fail + #def blob_handler(self, cmd): + + def checkpoint_handler(self, cmd): + # This command means nothing to us + pass + + def committish_rev(self, committish): + if committish.startswith(":"): + return self.mark_map[committish] + else: + return self.branch_map[committish] + + def commit_handler(self, cmd): + if cmd.ref == "refs/heads/TAG.FIXUP": + #self.tag_back_map[cmd.mark] == first_parent + commit_handler = hgechoprocessor.HgEchoCommitHandler(cmd, self.ui, self.repo, **self.opts) + commit_handler.process() + return + if cmd.from_: + first_parent = self.committish_rev(cmd.from_) + else: + first_parent = self.branch_map.get(cmd.ref, nullrev) + # Update to the first parent + mercurial.hg.clean(self.repo, self.repo.lookup(first_parent)) + if cmd.parents: + if len(cmd.parents) > 1: + raise NotImplementedError("Can't handle more than two parents") + second_parent = cmd.parents[0] + mercurial.commands.debugsetparents(self.ui, self.repo, + first_parent, second_parent) + if cmd.ref == "refs/heads/master": + branch = "default" + else: + branch = cmd.ref[len("refs/heads/"):] + self.repo.dirstate.setbranch(branch) + #print "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + commit_handler = HgImportCommitHandler(cmd, self.ui, self.repo, **self.opts) + commit_handler.process() + #print "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" + node = self.repo.rawcommit(files = commit_handler.filelist(), + text = cmd.message, + user = cmd.committer[1], + date = self.convert_date(cmd.committer)) + rev = self.repo.changelog.rev(node) + self.mark_map[cmd.mark] = rev + self.branch_map[cmd.ref] = rev + self.ui.write("Done commit of rev %d\n" % rev) + + def convert_date(self, c): + res = (int(c[2]), int(c[3])) + #print c, res + #print type((0, 0)), type(res), len(res), type(res) is type((0, 0)) + #if type(res) is type((0, 0)) and len(res) == 2: + # print "go for it" + #return res + return "%d %d" % res + + def reset_handler(self, cmd): + #self.ui.write("Cmd: %s\n" % repr(cmd)) + if cmd.from_ is not None: + self.branch_map[cmd.from_] = self.committish_rev(cmd.ref) + + def tag_handler(self, cmd): + # self.tag_map[cmd.id] = self.tag_back_map[cmd.from_] + pass + +class HgImportCommitHandler(processor.CommitHandler): + + def __init__(self, command, ui, repo, **opts): + self.command = command + self.ui = ui + self.repo = repo + self.opts = opts + self.files = set() + + def _make_container(self, path): + if '/' in path: + d = os.path.dirname(path) + if not os.path.isdir(d): + os.makedirs(d) + + def modify_handler(self, filecmd): + #print "============================" + filecmd.path + # FIXME: handle mode + self.files.add(filecmd.path) + self._make_container(filecmd.path) + #print "made dirs, writing file" + f = open(filecmd.path, "w") + f.write(filecmd.data) + f.close() + #print self.repo.add([filecmd.path]) + #print "Done:", filecmd.path + + #def delete_handler(self, filecmd): + # self.files.add(filecmd.path) + # os.remove(filecmd.path) + + #def copy_handler(self, filecmd): + # self.files.add(filecmd.path) + # """Handle a filecopy command.""" + # self.ui.write("Cmd: %s\n" % repr(filecmd)) + + #def rename_handler(self, filecmd): + # self.files.add(filecmd.path) + # """Handle a filerename command.""" + # self.ui.write("Cmd: %s\n" % repr(filecmd)) + + def filelist(self): + return list(self.files)
--- a/fastimport/parser.py Fri Feb 29 12:19:18 2008 +0000 +++ b/fastimport/parser.py Fri Feb 29 17:58:31 2008 +0000 @@ -268,7 +268,6 @@ self.output = output # We auto-detect the date format when a date is first encountered self.date_parser = None - self.last_mark = None def iter_commands(self): """Iterator returning ImportCommand objects.""" @@ -292,7 +291,7 @@ elif line.startswith('checkpoint'): yield commands.CheckpointCommand() else: - #print line + print line self.abort(errors.InvalidCommand, line) def iter_file_commands(self): @@ -340,20 +339,14 @@ committer = self._get_user_info('commit', 'committer') message = self._get_data('commit', 'message') from_ = self._get_from() - if from_ is None: - from_ = self.last_mark - self.last_mark = mark - if from_ is not None: - parents = [from_] - while True: - merge = self._get_merge() - if merge is not None: - parents.append(merge) - else: - break - else: - parents = [] - return commands.CommitCommand(ref, mark, author, committer, message, + parents = [] + while True: + merge = self._get_merge() + if merge is not None: + parents.append(merge) + else: + break + return commands.CommitCommand(ref, mark, author, committer, message, from_, parents, self.iter_file_commands, lineno) def _parse_file_modify(self, info): @@ -442,9 +435,12 @@ size = int(rest) res = self.read_bytes(size) # consume extra LF if present - line = self.next_line() - if line != '': - self.push_line(line) + while True: + line = self.next_line() + if line != '': + self.push_line(line) + break + return res else: self.abort(errors.MissingSection, required_for, section) @@ -474,9 +470,13 @@ """Parse a path.""" if s.startswith('"'): if s[-1] != '"': - self.abort(errors.BadFormat, cmd, section, s) + self.abort(errors.BadFormat) else: - return _unquote_c_string(s[1:-1]) + s = _unquote_c_string(s[1:-1]) + # Check path for sanity + sp = s.split("/") + if "" in sp or ".." in sp: + self.abort(errors.BadFormat) return s def _path_pair(self, s):
--- a/fastimport/processor.py Fri Feb 29 12:19:18 2008 +0000 +++ b/fastimport/processor.py Fri Feb 29 17:58:31 2008 +0000 @@ -46,6 +46,7 @@ def _process(self, command_iter): self.pre_process() for cmd in command_iter(): + #print cmd.dump_str(verbose=True) #print "starting" try: #print cmd.name @@ -121,6 +122,7 @@ def process(self): self.pre_process_files() for fc in self.command.file_iter(): + #print fc.dump_str(verbose=True) try: handler = self.__class__.__dict__[fc.name[4:] + "_handler"] except KeyError:
