# # # patch "mtn.py" # from [1f4c058e4f55b848c1c8195a38e6edaeb86310b6] # to [402aba6497fb89242b82920b3a3222fbf7088eaf] # # patch "templates/revisioninfo.html" # from [f78b63b0bea3ba8971396d33e0ce9e7b0477847d] # to [48136f1e28536c5dabbfa7754566e049aed42635] # # patch "viewmtn.py" # from [f64c08da43d7339e847ed1cddd44939c349bf9e7] # to [fb9d3d9fa86e7ae6b4e9ee3be5ac53fa944c6147] # ============================================================ --- mtn.py 1f4c058e4f55b848c1c8195a38e6edaeb86310b6 +++ mtn.py 402aba6497fb89242b82920b3a3222fbf7088eaf @@ -7,10 +7,6 @@ import popen2 import threading import popen2 -debugging = True - -debug = None - import web debug = web.debug @@ -86,15 +82,19 @@ class Automate(Runner): self.process.tochild, self.process.childerr ]) - def run(self, command, args): + def run(self, *args, **kwargs): if not self.lock.acquire(False): raise MonotoneException("Automate process can't be called: it is already locked.") - self.__process_required() + try: + rv = apply(self.__run, args, kwargs) + finally: + self.lock.release() + return rv - debug(command, args) + def __run(self, command, args): + self.__process_required() enc = "l%d:%s" % (len(command), command) enc += ''.join(map(lambda x: "%d:%s" % (len(x), x), args)) + 'e' - debug("wrote", enc) self.process.tochild.write(enc) self.process.tochild.flush() @@ -108,7 +108,6 @@ class Automate(Runner): if self.process.fromchild in r_stdin: data = self.process.fromchild.read() - debug("data", data) if data == "": break buffer += data @@ -148,7 +147,6 @@ class Automate(Runner): yield line + '\n' if code_max > 0: raise MonotoneException("error code %d in automate packet." % (code_max)) - self.lock.release() class Standalone(Runner): """Runs commands by running monotone. One monotone process @@ -182,6 +180,12 @@ class Branch(MtnObject): MtnObject.__init__(self, "branch") self.name = name +class File(MtnObject): + def __init__(self, name, in_revision): + MtnObject.__init__(self, "file") + self.name = name + self.in_revision = in_revision + basic_io_name_tok = re.compile(r'^(\S+)') def basic_io_from_stream(gen): @@ -277,9 +281,6 @@ class Operations: self.standalone = apply(Standalone, runner_args) self.automate = apply(Automate, runner_args) - def __del__(self): - debug("deleting Operations instance.") - def tags(self): for line in (t.strip() for t in self.standalone.run('ls', ['tags'])): if not line: ============================================================ --- templates/revisioninfo.html f78b63b0bea3ba8971396d33e0ce9e7b0477847d +++ templates/revisioninfo.html 48136f1e28536c5dabbfa7754566e049aed42635 @@ -24,18 +24,20 @@

Revision Details

-#for stanza_type, descr, value in $revisions - +#for grouping, stanzagroup in $revisions + #end for
#filter Filter - $descr + $grouping #filter WebSafe #filter Filter - $value + #for value in $stanzagroup + $value
+ #end for #filter WebSafe - +
============================================================ --- viewmtn.py f64c08da43d7339e847ed1cddd44939c349bf9e7 +++ viewmtn.py fb9d3d9fa86e7ae6b4e9ee3be5ac53fa944c6147 @@ -8,6 +8,9 @@ hq = cgi.escape import urlparse hq = cgi.escape +import web +debug = web.debug + # /about.psp -> /about # /branch.psp -> /branch/{branch}/ @@ -60,12 +63,19 @@ class DiffLink(Link): def __init__(self, diff, **kwargs): Link.__init__(*(self, ), **kwargs) self.relative_uri = 'revision/diff/' + diff.from_rev + '/with/' + diff.to_rev + if diff.fname: + self.relative_uri += '/'+urllib.quote(diff.fname) self.description = "diff" +class FileLink(Link): + def __init__(self, file, **kwargs): + Link.__init__(*(self, ), **kwargs) + self.relative_uri = 'revision/file/' + file.in_revision + '/' + urllib.quote("goat") + class Diff: - def __init__(self, from_rev, to_rev, file): + def __init__(self, from_rev, to_rev, fname=None): self.obj_type = 'diff' - self.file = file + self.fname = fname self.from_rev = from_rev self.to_rev = to_rev @@ -93,33 +103,55 @@ def certs_for_template(cert_gen): 'name' : prettify(name), 'value' : value } -def revisions_for_template(rev_gen): +def revisions_for_template(revision, rev_gen): + old_revisions = [] + stanzas = [] + grouping = None for stanza in rev_gen: stanza_type = stanza[0] description, value = prettify(stanza_type), None + if grouping == None: + grouping = description + if description != grouping: + if len(stanzas) > 0: + yield grouping, stanzas + grouping, stanzas = description, [] + if stanza_type == "format_version" or \ stanza_type == "new_manifest": continue elif stanza_type == "patch": fname, from_id, to_id = stanza[1], stanza[3], stanza[5] + debug(stanza) # if from_id is null, this is a new file # since we're showing that information under "Add", so # skip it here if not from_id: continue - value = "Patch file %s (%s)" % ("not yet", - link(Diff(from_id, to_id, fname)).html()) + diff_links = ','.join([link(Diff(old_revision, revision, fname)).html() for old_revision in old_revisions]) + value = "Patch file %s (%s)" % (hq(fname), diff_links) + elif stanza_type == "old_revision": + old_revision = mtn.Revision(stanza[1]) + old_revisions.append(old_revision) + value = "Old revision is: %s (%s)" % (old_revision.abbrev(), link(Diff(old_revision, revision)).html()) + elif stanza_type == "add_file": + fname = stanza + value = "Add file: %s" % (link(mtn.File(fname, revision))) else: value = "(this stanza type is not explicitly rendered; please report this.)\n%s" % hq(str(stanza)) if description != None: - yield stanza_type, description, value + stanzas.append(value) + if len(stanzas) > 0: + yield grouping, stanzas + type_to_link_class = { 'tag' : TagLink, 'branch' : BranchLink, 'diff' : DiffLink, + 'file' : FileLink, } def link(obj): @@ -185,7 +217,7 @@ class RevisionInfo: page_title="Revision %s" % revision.abbrev(), revision=revision, certs=certs_for_template(certs), - revisions=revisions_for_template(revisions)) + revisions=revisions_for_template(revision, revisions)) class RevisionDiff: def GET(self, revision_from, revision_to): @@ -227,6 +259,7 @@ urls = ( '/revision/browse/('+mtn.revision_re+')/(.*)', 'RevisionBrowse', '/revision/diff/('+mtn.revision_re+')/with/('+mtn.revision_re+')', 'RevisionDiff', + '/revision/diff/('+mtn.revision_re+')/with/('+mtn.revision_re+')'+'/(.*)', 'RevisionDiffWithFile', '/revision/file/('+mtn.revision_re+')/(.*)', 'RevisionFile', '/revision/info/('+mtn.revision_re+')', 'RevisionInfo', '/revision/tar/('+mtn.revision_re+')', 'RevisionTar',