From: Eric S. Raymond Date: Thu, 6 Nov 2014 22:38:51 +0000 (-0500) Subject: src cat is working. So is revspec parsing. X-Git-Tag: 0.1~21 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=26ff6263305d615565ac52f4fc67932abff4163c;p=src.git src cat is working. So is revspec parsing. --- diff --git a/src b/src index c046738..8350814 100755 --- a/src +++ b/src @@ -28,11 +28,11 @@ def croak(msg): debug = 0 DEBUG_COMMANDS = 1 # Show commands as they are executed -def do_or_die(dcmd, legend=b""): +def do_or_die(dcmd, legend=b"", loud=False): "Either execute a command or raise a fatal exception." if legend: legend = " " + legend - if debug == 0: + if debug == 0 and not loud: mute = " >/dev/null 2>&1" else: mute = "" @@ -77,6 +77,14 @@ class popen_or_die: complain(b"%s%s returned error." % (self.command, self.legend)) return False +class RCSRevisionItem: + "Capture the state of an RCS revision item in the log." + def __init__(self, revno): + self.revno = revno; + self.revision = None + self.log = "" + self.date = None + def log_capture(fn): "Capture and parse the metadata for a specified file." with popen_or_die("cd .src >/dev/null; rlog %s; cd ..>/dev/null" % fn) as fp: @@ -126,6 +134,9 @@ src commit ['revison-spec'] ['file'...] src checkout [revspec] ['file'...] Refresh the working copy of the file(s) from their history files. +src cat [revspec] ['file'...] + Send the specified revisions of the files to standard output. + src branch [delete] ['branchname'] Create, switch to, or delete a branch. With no arguments, list branches. @@ -159,18 +170,34 @@ def init_method(*args): def preamble(cmd, args): "Common setup code." - if args: - return list(args) - else: + args = list(args) + revspec = None + if args and args[0].isdigit(): + revspec = args.pop(0) + try: + if "-" in revspec: + (start, end) = revspec.split("-") + start = int(start) + end = int(end) + else: + start = int(revspec) + end = start + except ValueError: + croak("malformed revision spec: %s" % revspec) + revspec = range(start, end+1) + if not args: masters = os.listdir(".src") if len(masters) == 1: - return [masters[0][:-2]] + args += [master[:-2] for master in masters] else: croak("%s requires at least one file argument" % cmd) + return(revspec, args) def add_method(*args): "Register a file into src control." - args = preamble("add", args) + (revspec, args) = preamble("add", args) + if revspec is not None: + croak("add doesn't take a revision spec") for arg in args: if not os.path.exists(arg): complain("I see no '%s' here." % arg) @@ -182,7 +209,9 @@ def add_method(*args): def commit_method(*args): "Commit changes to files." - args = preamble("commit", args) + (revspec, args) = preamble("commit", args) + if revspec is not None: + croak("commit doesn't take a revision spec") for arg in args: if not os.path.exists(arg): complain("I see no '%s' here." % arg) @@ -198,41 +227,56 @@ def commit_method(*args): revlist = log_capture(arg) announce("%s -> %d" % (arg, len(revlist))) -class RCSRevisionItem: - "Capture the state of an RCS revision item in the log." - def __init__(self, revno): - self.revno = revno; - self.revision = None - self.log = "" - self.date = None - def list_method(*args): - args = preamble("list", args) + "Generate a summary listing of commits, one line per commit." + (revspec, args) = preamble("list", args) width = screenwidth() for arg in args: sys.stdout.write("= %s %s\n" % (arg, ((width - len(arg) - 5) * "="))) for item in log_capture(arg): - # Must allow enough room for revno and date - summary = item.log.strip()[:width - 32] - sys.stdout.write("%-4d %s %s\n" % (item.revno, item.date, summary)) + if not revspec or item.revno in revspec: + # Must allow enough room for revno and date + summary = item.log.strip()[:width - 32] + sys.stdout.write("%-4d %s %s\n" % (item.revno, item.date, summary)) def log_method(*args): - args = preamble("log", args) + "Report revision logs" + (revspec, args) = preamble("log", args) width = screenwidth() for arg in args: sys.stdout.write("= %s %s\n" % (arg, ((width - len(arg) - 5) * "="))) for item in log_capture(arg): - sys.stdout.write("%-4d | %s\n%s" % (item.revno, item.date, item.log)) - sys.stdout.write(("-" * (width - 1)) + "\n") + if not revspec or item.revno in revspec: + sys.stdout.write("%-4d | %s\n%s" % (item.revno, item.date, item.log)) + sys.stdout.write(("-" * (width - 1)) + "\n") def checkout_method(*args): - args = preamble("checkout", args) - width = screenwidth() + (revspec, args) = preamble("checkout", args) + if len(revspec) > 1: + croak("checkout needs an empty or singleton revision spec") for arg in args: revlist = log_capture(arg) - do_or_die("mv .src/{0},v . && rm {0} && co -l {0} && mv {0},v .src".format(arg)) + if revspec is None: + revision = "" + elif len(revspec) == 1: + revision = "-r" + revlist[revspec[0]-1].revision + else: + croak("checkout cannot take a range") + do_or_die("mv .src/{0},v . && rm {0} && co -l -r%s {0} && mv {0},v .src".format(arg, revision)) announce("%s <- %d" % (arg, len(revlist))) +def cat_method(*args): + (revspec, args) = preamble("cat", args) + for arg in args: + revlist = log_capture(arg) + if revspec is None: + revspec = range(1, len(revlist)+1) + do_or_die("mv .src/{0},v .".format(arg)) + for item in revlist: + if item.revno in revspec: + do_or_die("co -q -p -r{1} {0}".format(arg, item.revision), loud=True) + do_or_die("mv {0},v .src".format(arg)) + dispatch = { "help": help_method, "init": init_method, @@ -241,13 +285,19 @@ dispatch = { "list": list_method, "log": log_method, "checkout": checkout_method, + "cat": cat_method, } if __name__ == "__main__": + command = sys.argv[1:] if not command: help_method() else: + command = list(command) + while command[0] == "-d": + debug += 1 + command.pop(0) try: apply(dispatch[command[0]], command[1:]) except KeyError: