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."
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:
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."
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):
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?")
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:
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))
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: