]> thyrsus.com Git - rcs-fast-import.git/commitdiff
Now seems to be issuing reasonable-looking commands.
authorEric S. Raymond <esr@thyrsus.com>
Wed, 10 Nov 2010 21:03:23 +0000 (16:03 -0500)
committerEric S. Raymond <esr@thyrsus.com>
Wed, 10 Nov 2010 21:03:23 +0000 (16:03 -0500)
rcs-fast-import

index 25d8f2a9bb843f33534c3548a6595e078b2b0669..d247f887a6bd412d9a8dbb3a93f81fba6687898b 100755 (executable)
@@ -53,6 +53,8 @@ DEBUG_SHUFFLE   = 2    # Debug directory handling
 DEBUG_DELETE    = 2    # Debug canonicalization after deletes
 DEBUG_COMMANDS  = 2    # Show commands as they are executed
 
+dryrun = False
+
 class Baton:
     "Ship progress indications to stdout."
     def __init__(self, prompt, endmsg='done', enable=False):
@@ -512,12 +514,43 @@ def complain(msg):
 def announce(msg):
     print "rcs-fast-import:", msg
 
+class popen_or_die:
+    "Read or write from a subordinate process."
+    def __init__(self, cmd, legend="", mode="r"):
+        assert mode in ("r", "w")
+        self.cmd = cmd
+        self.legend = legend
+        self.mode = mode
+        if self.legend:
+            self.legend = " "  + self.legend
+    def __enter__(self):
+        if verbose >= DEBUG_COMMANDS:
+            if self.mode == "r":
+                announce("reading from '%s'%s" % (self.cmd, self.legend))
+            else:
+                announce("writing to '%s'%s" % (self.cmd, self.legend))
+        if dryrun:
+            self.fp = file("/dev/null", self.mode)
+            return self.fp
+        try:
+            self.fp = os.popen(self.cmd, self.mode)
+            return self.fp
+        except OSError, e:
+            raise FatalException("execution of %s%s failed: %s" \
+                                 % (self.cmd, self.legend, e))
+    def __exit__(self, type, value, traceback):
+        if self.fp.close() is not None:
+            raise FatalException("%s%s returned error." \
+                                 % (self.cmd, self.legend))
+        return False
 def do_or_die(cmd, legend=""):
     "Either execute a command or raise a fatal exception."
     if legend:
         legend = " "  + legend
     if verbose >= DEBUG_COMMANDS:
         announce("executing '%s'%s" % (cmd, legend))
+    if dryrun:
+        return
     try:
         retcode = subprocess.call(cmd, shell=True)
         if retcode < 0:
@@ -541,24 +574,31 @@ class RCS:
     @staticmethod
     def master(filename):
         "Return the master file corresponding to a specified filename."
-        parts = os.path.split(filename)
+        parts = list(os.path.split(filename))
         parts.insert(-1, "RCS")
-        return os.path.join(parts)
-    def modify(self, event, path, mode, copyfile):
+        return os.path.join(*parts)
+    def commit(self, event, committables):
         "Perform RCS file checkins and modifications,"
-        rcsdir = os.path.join(os.path.dirname(path), "RCS")
-        if not os.path.exists(rcsdir):
-            try:
-                os.makdirs(rcsdir)
-            except OSError:
-                raise FatalException("can't create %s." % rcsdir)
-        workdir = os.path.dirname(filename)
-        masterfile = RCS.master(filename)
-        exists = os.path.exists(path)
-        shutil.copy(copyfile, workdir)
-        exists = os.path.exists(path)
-        if exists:
-            fp = do_or_die("ci -m '%s'" % (event.comment))
+        inargs = []
+        for (path, mode, copyfile) in committables:
+            if mode == "160000":
+                announce("ignoring a submodule link %s", path)
+                continue
+            else:
+                inargs.append(RCS.master(path))
+                rcsdir = os.path.join(os.path.dirname(path), "RCS")
+                if not os.path.exists(rcsdir):
+                    try:
+                        os.makedirs(rcsdir)
+                    except OSError:
+                        raise FatalException("can't create %s." % rcsdir)
+                if verbose >= DEBUG_SHUFFLE:
+                    announce("copying %s to %s" \
+                             % (copyfile, os.path.dirname(path) or '.'))
+                if not dryrun:
+                    shutil.copy(copyfile, os.path.dirname(path))
+            with popen_or_die("ci " + " ".join(inargs), "checkin", "w") as fp:
+                fp.write(event.comment)
     def rename(self, source, target):
         "Perform RCS renames."
         # Dodgy, but since user is more likely to be
@@ -583,7 +623,6 @@ if __name__ == '__main__':
     (options, arguments) = getopt.getopt(sys.argv[1:], "dlnuvV?")
     do_unlocked_checkouts = False
     checkout_mode = None
-    dryrun = False
     for (switch, val) in options:
        if (switch == '-?'):
            print __doc__
@@ -612,13 +651,12 @@ if __name__ == '__main__':
                     announce("Tagging %s with %s" % (event.committish, event.name))
                 vcs.tag(event)
             elif isinstance(event, Commit):
+                committables = []
                 for op in event.fileops:
                     if op.op == "M":
                         if verbose:
                             announce("%5d M %s" % (i+1, op.path))
-                        if not dryrun:
-                            vcs.modify_file(event,
-                                            op.path, op.mode, op.copyname)
+                        committables.append((op.path, op.mode, op.copyname))
                     elif op.op in ("D", "deleteall"):
                         # If we delete masters, we lose ability to
                         # retrieve old versions.
@@ -641,6 +679,7 @@ if __name__ == '__main__':
                             vcs.copy(ops.source, op.target)
                     else:
                         raise FatalException("unknown op type %s" % op.op)
+                    vcs.commit(event, committables)
         vcs.checkout(checkout_mode)
         raise SystemExit, 0
     except FatalException, e: