# # # patch "ChangeLog" # from [716957e41c1f04ae4755a0648c7516e3b7970306] # to [c19d5a4aa54ccbb20f776b2b282f8e17f68b6d2e] # # patch "mtn.py" # from [24bdc6cf0f2935b5768da503135c11c50f86e267] # to [60dee430345a7183b092fd315c003468ffd86e33] # # patch "release.py" # from [02cc0da3565aacac95c45cd3cfbf493253e14f59] # to [49ec725bbbc7ba5b5ab6dc30de45b0c612bf7190] # # patch "release.sh" # from [391895b5a7b99a5cd10b6f2cc0af4a51165c1e28] # to [ec43a21a12b704c364720958c4ad72bd931b7d9f] # # patch "viewmtn.py" # from [937a0bd5668fef8dee7cb44f7c1584d7052812f3] # to [7b4da2d6e174dbee0d81e4460856e7779773ad31] # ============================================================ --- ChangeLog 716957e41c1f04ae4755a0648c7516e3b7970306 +++ ChangeLog c19d5a4aa54ccbb20f776b2b282f8e17f68b6d2e @@ -1,3 +1,10 @@ +2008-02-14 Grahame Bowland + + * implement optional arguments, use this to + disable ignoring of suspend certs + * don't link to empty revisions (for revisions + without an ancestor) + 2008-01-16 Grahame Bowland * fix a #filter.. #end filter error affecting ============================================================ --- mtn.py 24bdc6cf0f2935b5768da503135c11c50f86e267 +++ mtn.py 60dee430345a7183b092fd315c003468ffd86e33 @@ -43,7 +43,8 @@ class Revision(str): # special case that must be handled: empty (initial) revision ID '' str.__init__(v) self.obj_type = "revision" - if v != '' and not (revision_re_c.match(self) and len(self) == sha1_len): + self.is_empty = (v == '') + if not self.is_empty and not (revision_re_c.match(self) and len(self) == sha1_len): raise MonotoneException("Not a valid revision ID: %s" % (repr(v))) def abbrev(self): return '[' + self[:8] + '..]' @@ -139,9 +140,25 @@ class Automate(Runner): return CleanRequest(self.__run(*args, **kwargs)) - def __run(self, command, args): - enc = "l%d:%s" % (len(command), command) - enc += ''.join(["%d:%s" % (len(x), x) for x in args]) + 'e' + def __run(self, command, args, **kwargs): + def str_with_len(l, s): + l.append(str(len(s))) + l.append(":") + l.append(s) + parts = [] + for k in kwargs: + # can't use a '-' as a named function argument + kd = k.replace('_', '-') + parts.append("o") + str_with_len(parts, kd) + str_with_len(parts, kwargs[k]) + parts.append("e") + parts.append("l") + str_with_len(parts, command) + for x in args: + str_with_len(parts, x) + parts.append("e") + enc = ''.join(parts) # number of tries to get a working mtn going.. for i in xrange(2): @@ -155,7 +172,6 @@ class Automate(Runner): debug("exception writing to child process; attempting restart: %s" % format_exc()) self.stop() - import sys def read_result_packets(): buffer = "" while True: @@ -372,7 +388,7 @@ class Operations: yield Tag(stanza[1], stanza[3], stanza[5], branches) def branches(self): - for line in (t.strip() for t in self.automate.run('branches', [])): + for line in (t.strip() for t in self.automate.run('branches', [], ignore_suspend_certs="")): if not line: continue yield apply(Branch, (line,)) ============================================================ --- release.py 02cc0da3565aacac95c45cd3cfbf493253e14f59 +++ release.py 49ec725bbbc7ba5b5ab6dc30de45b0c612bf7190 @@ -1,4 +1,4 @@ -version='0.08' +version='0.09' authors=''' Authors: ============================================================ --- release.sh 391895b5a7b99a5cd10b6f2cc0af4a51165c1e28 +++ release.sh ec43a21a12b704c364720958c4ad72bd931b7d9f @@ -11,7 +11,7 @@ OUT="release.py" # generate the help file data OUT="release.py" -RELEASE="0.08" +RELEASE="0.09" echo -n > "$OUT" echo "version='$RELEASE'" > "$OUT" ============================================================ --- viewmtn.py 937a0bd5668fef8dee7cb44f7c1584d7052812f3 +++ viewmtn.py 7b4da2d6e174dbee0d81e4460856e7779773ad31 @@ -180,8 +180,16 @@ class DiffLink(Link): else: mode = "diff" self.relative_uri = 'revision/%s/' % (mode) + diff.from_rev + '/with/' + diff.to_rev - if diff.fname: - self.relative_uri += '/'+urllib.quote(diff.fname) + if isinstance(diff.fname, list): + # TODO: figure out a linking scheme for diffs of multiple files. + if len(diff.fname) > 0: + fname = diff.fname[0] + else: + fname = None + else: + fname = diff.fname + if fname is not None: + self.relative_uri += '/'+urllib.quote(fname) self.description = "diff" class DirLink(Link): @@ -267,8 +275,11 @@ def revisions_for_template(revision, rev value = "Patch file %s (%s)" % (link(mtn.File(fname, revision)).html(), diff_links) elif stanza_type == "old_revision": old_revision = mtn.Revision(stanza[1]) - old_revisions.append(old_revision) - value = "Old revision is: %s (%s)" % (link(old_revision).html(), link(Diff(old_revision, revision)).html()) + if old_revision.is_empty: + value = "This revision is has no ancestor." + else: + old_revisions.append(old_revision) + value = "Old revision is: %s (%s)" % (link(old_revision).html(), link(Diff(old_revision, revision)).html()) elif stanza_type == "add_file": fname = stanza[1] value = "Add file: %s" % (link(mtn.File(fname, revision)).html()) @@ -315,7 +326,7 @@ class ComparisonRev: class ComparisonRev: def __init__(self, ops, revision): self.revision = revision - self.certs = map (None, ops.certs(self.revision)) + self.certs = list(ops.certs(self.revision)) self.date = None for cert in self.certs: if cert[4] == 'name' and cert[5] == 'date': @@ -427,7 +438,7 @@ class Index: class Index: def GET(self): - branches = map(None, ops.branches ()) + branches = list(ops.branches ()) divisions.calculate_divisions (branches) def division_iter(): bitter = iter(branches) @@ -467,7 +478,7 @@ class Tags: class Tags: def GET(self, restrict_branch=None): # otherwise we couldn't use automate again.. - tags = map(None, ops.tags()) + tags = list(ops.tags()) if restrict_branch != None: restrict_branch = mtn.Branch(restrict_branch) def tag_in(tag): @@ -633,15 +644,15 @@ class Changes: def file_get_last_changes(self, from_change, to_change, revision, path): def content_changed_fn(start_revision, start_path, in_revision, pathinfo): uniq = set() - parents = map(None, ops.parents(in_revision)) + parents = list(ops.parents(in_revision)) for parent in parents: - stanza = map(None, ops.get_corresponding_path(start_revision, start_path, parent)) + stanza = list(ops.get_corresponding_path(start_revision, start_path, parent)) # file does not exist in this revision; skip! if not stanza: continue # follow the white rabbit current_path = stanza[0][1] - stanza = map(None, ops.get_content_changed(parent, current_path)) + stanza = list(ops.get_content_changed(parent, current_path)) to_add = stanza[0][1] uniq.add(to_add) pathinfo[to_add] = current_path @@ -915,7 +926,7 @@ class RevisionBrowse(RevisionPage): page_title += " of %s %s" % (branch_plural, ', '.join(branches)) def cut_manifest_to_subdir(): - manifest = map(None, ops.get_manifest_of(revision)) + manifest = list(ops.get_manifest_of(revision)) in_the_dir = False for stanza in manifest: stanza_type = stanza[0] @@ -955,7 +966,7 @@ class RevisionBrowse(RevisionPage): if not certs.has_key(revision): # subtle bug slipped in here; ops.cert() is a generator # so we can't just store it in a cache! - certs[revision] = map(None, ops.certs(revision)) + certs[revision] = list(ops.certs(revision)) return certs[revision] def _get_certinfo(revision): @@ -1165,6 +1176,8 @@ def ancestry_graph(revision): dot_data = ancestry_dot(revision) # okay, let's output the graph graph_sha = sha.new(dot_data).hexdigest() + if not os.access(config.graphopts['directory'], os.R_OK): + os.mkdir(config.graphopts['directory']) output_directory = os.path.join(config.graphopts['directory'], revision) if not os.access(output_directory, os.R_OK): os.mkdir(output_directory)