]> thyrsus.com Git - rcs-fast-import.git/commitdiff
Journal actions to a secret file.
authorEric S. Raymond <esr@thyrsus.com>
Fri, 12 Nov 2010 01:48:26 +0000 (20:48 -0500)
committerEric S. Raymond <esr@thyrsus.com>
Fri, 12 Nov 2010 01:48:26 +0000 (20:48 -0500)
rcs-fast-import

index b57ef3c7d59e06eeee723925ced5cc9b7581ceb8..4a31bbefdde4d5e6ed035562c101a7e4ecef8fe2 100755 (executable)
@@ -546,9 +546,15 @@ def do_or_die(cmd, legend=""):
 
 class RCS:
     "Class encapsulating RCS version-control operations."
+    historyfile = ".HISTORY"
     def __init__(self):
         # Rev-to-branch map will go here
-        pass
+        if not os.path.exists("RCS"):
+            try:
+                os.makedirs("RCS")
+            except OSError:
+                raise FatalException("can't create RCS directory.")
+        file(RCS.historyfile, "w").close()
     @staticmethod
     def master(filename):
         "Return the master file corresponding to a specified filename."
@@ -564,38 +570,62 @@ class RCS:
                 for name in files:
                     res.append(os.path.join(root, name))
         return res
-    def commit(self, event, committables, roundtrip):
+    @staticmethod
+    def gethdr(path, header):
+        "Retrieve a required header from a master file"
+        master = RCS.master(path)
+        for line in file(master):
+            if line.startswith(header):
+                value = line.split()[1].strip()
+                if value.endswith(";"):
+                    value = value[:-1]
+                return value
+        raise FatalException("missing '%s' in %s" % (header, master))
+    @staticmethod
+    def record(code, path=None):
+        "Record an action."
+        with file(RCS.historyfile, "a") as fp:
+            fp.write(code)
+            if path:
+                fp.write(" ")
+                fp.write(RCS.gethdr(path, "head\t") + " ")
+                fp.write(path)
+            fp.write("\n")
+    def precommit(self, event):
+        RCS.record("commit")
+    def modify(self, event, path, mode, copyfile, roundtrip):
         "Perform RCS file checkins and modifications,"
-        for (path, mode, copyfile) in committables:
-            if mode == "160000":
-                raise FatalException("ignoring a submodule link %s", path)
+        if mode == "160000":
+            raise FatalException("ignoring a submodule link %s", path)
+        else:
+            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("linking %s to %s" % (os.path.relpath(copyfile), path))
+            if not dryrun:
+                try:
+                    os.link(copyfile, path)
+                except OSError:
+                    raise FatalException("refusing to step on %s." % path)
+            if roundtrip:
+                comment = event.email_out()
             else:
-                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("linking %s to %s" % (os.path.relpath(copyfile), path))
-                if not dryrun:
-                    try:
-                        os.link(copyfile, path)
-                    except OSError:
-                        raise FatalException("refusing to step on %s." % path)
-                if roundtrip:
-                    comment = event.email_out()
-                else:
-                    comment = event.comment
-                command = "ci -l"
-                command += " -d'%s'" % event.committer.date.rfc822()
-                command += ' -m"%s"' % comment.replace('"', '\\"')
-                command += " " + path + " " + RCS.master(path)
-                do_or_die(command, "checkin")
-                if verbose >= DEBUG_SHUFFLE:
-                    announce("removing %s" % (path,))
-                if not dryrun:
-                    os.remove(path)
+                comment = event.comment
+            command = "ci -l"
+            command += " -d'%s'" % event.committer.date.rfc822()
+            command += ' -m"%s"' % comment.replace('"', '\\"')
+            command += " " + path + " " + RCS.master(path)
+            do_or_die(command, "checkin")
+            RCS.record("M", path)
+            if verbose >= DEBUG_SHUFFLE:
+                announce("removing %s" % (path,))
+            if not dryrun:
+                os.remove(path)
+    def postcommit(self, event):
         # Save annotated tags for round-tripping
         for tag in event.taglist:
             with file("ANNOTATED-TAGS", "w") as fp:
@@ -616,6 +646,7 @@ class RCS:
         command += ' -m"%s of %s"' % (legend, path)
         command += " " + path + " " + RCS.master(path)
         do_or_die(command, legend.lower())
+        RCS.record("D", path)
         os.remove(path)
     def copy(self, source, target):
         "Perform RCS copies. Start the copy with no history."
@@ -625,10 +656,14 @@ class RCS:
         do_or_die("ci -i -m'Copy of %s' -l %s %s"
                   % (source, uphere, RCS.master(target)),
                   "copy")
+        RCS.record("C", source)
+        RCS.record("T", target)
         os.remove(uphere)
     def rename(self, commit, source, target):
         "Perform RCS renames, carrying history with the rename."
-        shutil.copy(RCS.master(op.source), RCS.master(op.target))
+        shutil.copy(RCS.master(source), RCS.master(target))
+        RCS.record("R", source)
+        RCS.record("U", target)
         # History is *not* removed from the source
         self.delete(commit, source, legend="Rename")
     def checkout(self, switch):
@@ -637,6 +672,7 @@ class RCS:
             do_or_die("rcs -u %s" % (" ".join(RCS.rcsfiles()),))
             if switch == '-u':
                 do_or_die("co -u %s" % (" ".join(RCS.rcsfiles()),))
+        os.rename(RCS.historyfile, os.path.join("RCS", RCS.historyfile))
 
 if __name__ == '__main__':
     (options, arguments) = getopt.getopt(sys.argv[1:], "lnpuvV?")
@@ -663,7 +699,7 @@ if __name__ == '__main__':
         with Repository() as repo:
             repo.fast_import(sys.stdin, progress=verbose>0)
             for event in repo.commits():
-                committables = []
+                vcs.precommit(event)
                 for op in event.fileops:
                     if op.op == "M":
                         if verbose:
@@ -671,7 +707,7 @@ if __name__ == '__main__':
                         if op.mode == "160000":
                             complain("cannot represent a submodule link in RCS")
                         else:
-                            committables.append((op.path, op.mode, op.copyname))
+                            vcs.modify(event, op.path, op.mode, op.copyname, roundtrip)
                     elif op.op in ("D", "deleteall"):
                         if verbose:
                             announce("%5s D %s" % (event.mark, op.path))
@@ -689,7 +725,7 @@ if __name__ == '__main__':
                             vcs.copy(ops.source, op.target)
                     else:
                         raise FatalException("unknown op type %s" % op.op)
-                vcs.commit(event, committables, roundtrip)
+                vcs.postcommit(event)
             vcs.checkout(checkout_mode)
         raise SystemExit, 0
     except FatalException, e: