From 70fbd0736c5392fa10f42f82769160c64cc099a4 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Thu, 11 Nov 2010 20:48:26 -0500 Subject: [PATCH] Journal actions to a secret file. --- rcs-fast-import | 106 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 35 deletions(-) diff --git a/rcs-fast-import b/rcs-fast-import index b57ef3c..4a31bbe 100755 --- a/rcs-fast-import +++ b/rcs-fast-import @@ -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: -- 2.43.0