debug = 0
DEBUG_COMMANDS = 1 # Show commands as they are executed
+DEBUG_PARSE = 2 # Debug logfile parse
def do_or_die(dcmd, legend=b"", loud=False):
"Either execute a command or raise a fatal exception."
class RCSRevisionItem:
"Capture the state of an RCS revision item in the log."
- def __init__(self, revno):
+ def __init__(self, master, revno):
+ self.master = master
self.revno = revno;
self.revision = None
self.log = ""
self.date = None
+ def selected(self):
+ return self.revision == self.master.lockrevs[0]
class RCSLog:
"Encapsulate a revision list and some methods on it"
self.revlist = []
with popen_or_die("cd .src >/dev/null; rlog %s; cd ..>/dev/null" % name) as fp:
self.revlist = []
+ self.lockrevs = []
maxrevno = 0
- state = "initial"
+ if debug >= DEBUG_PARSE:
+ sys.stdout.write("\t-> init\n")
+ state = "init"
for line in fp:
- if line.startswith("----------------------------"):
+ if debug >= DEBUG_PARSE:
+ sys.stdout.write("in: %s\n" % repr(line))
+ if state == "init":
+ if line.startswith("locks:"):
+ if debug >= DEBUG_PARSE:
+ sys.stdout.write("\t-> locks\n")
+ state = "locks"
+ elif line.startswith("----------------------------"):
+ if debug >= DEBUG_PARSE:
+ sys.stdout.write("\t-> logheader\n")
state = "logheader"
- self.revlist.append(RCSRevisionItem(maxrevno))
+ self.revlist.append(RCSRevisionItem(self, maxrevno))
maxrevno += 1
- elif state == "logheader" and line.startswith("revision"):
- fields = line.split()
- self.revlist[-1].revision = fields[1]
- elif state == "logheader" and line.startswith("date"):
- fields = line.split()
- date = fields[1] + " " + fields[2]
- if date.endswith(";"):
- date = date[:-1]
- date = date.replace("/", "-").replace(" ", "T") + "Z"
- self.revlist[-1].date = date
- elif line.startswith("======================="):
- if not self.revlist[-1].log.endswith("\n"):
- self.revlist[-1].log += "\n"
- break
- elif self.revlist:
- self.revlist[-1].log += line[1:]
+ elif state == "locks":
+ if not line[0].isspace():
+ if debug >= DEBUG_PARSE:
+ sys.stdout.write("\t-> init\n")
+ state = "init"
+ else:
+ fields = line.strip().split()
+ self.lockrevs.append(fields[1])
+ elif state == "logheader":
+ if line.startswith("revision"):
+ fields = line.split()
+ self.revlist[-1].revision = fields[1]
+ elif line.startswith("date"):
+ fields = line.split()
+ date = fields[1] + " " + fields[2]
+ if date.endswith(";"):
+ date = date[:-1]
+ date = date.replace("/", "-").replace(" ", "T") + "Z"
+ self.revlist[-1].date = date
+ elif line.startswith("======================="):
+ if not self.revlist[-1].log.endswith("\n"):
+ self.revlist[-1].log += "\n"
+ break
+ elif self.revlist:
+ self.revlist[-1].log += line[1:]
for item in self.revlist:
item.revno = maxrevno - item.revno
+ if debug >= DEBUG_PARSE:
+ print "\tlockrevs:", self.lockrevs
def __len__(self):
return len(self.revlist)
def __getitem__(self, i):
- "Use 1-origin indices, lowest oldest."
- return self.revlist[len(self.revlist) - i]
-
-def log_capture(fn):
- "Capture and parse the metadata for a specified file."
- return revlist
+ return self.revlist[i]
+ def rcs_to_revno(self, revision):
+ "Map an RCS ID to a revno"
+ for item in self.revlist:
+ if item.revision == revision:
+ return item.revno
+ return None
+ def revno_to_rcs(self, revno):
+ "Map a revno to an RCS ID"
+ for item in self.revlist:
+ if item.revno == revno:
+ return item.revision
+ return None
def help_method(*args):
"Summarize src commands, or (with argument) show help for a single command."
for item in RCSLog(arg):
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))
+ summary = item.log.strip()[:width - 34]
+ if item.selected():
+ mark = "*"
+ else:
+ mark = "-"
+ sys.stdout.write("%-4d %s %s %s\n" \
+ % (item.revno, mark, item.date, summary))
def log_method(*args):
"Report revision logs"