From 2b8db3ce3e7344b9f3b5216637c5af0d54be5656 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Mon, 1 Nov 2010 15:08:06 -0700 Subject: [PATCH] Added feature to print a from manifest at the end of a sync. This feature is used to convey information on a when a branch has ceased development or if it is an experimental branch with a few gotchas, etc. You add it to your manifest XML by doing something like this: NOTE TO DEVELOPERS: If you checkin code, you have to pinky-swear that it contains no bugs. Anyone who breaks their promise will have tomatoes thrown at them in the team meeting. Be sure to bring an extra set of clothes. ... Carriage returns and indentation are relevant for the text in this tag. This feature was requested by Anush Elangovan on the ChromiumOS team. --- docs/manifest-format.txt | 5 +++- manifest_xml.py | 62 ++++++++++++++++++++++++++++++++++++++++ subcmds/sync.py | 5 ++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt index 211344ee..2e1c8c35 100644 --- a/docs/manifest-format.txt +++ b/docs/manifest-format.txt @@ -20,12 +20,15 @@ A manifest XML file (e.g. 'default.xml') roughly conforms to the following DTD: + + diff --git a/manifest_xml.py b/manifest_xml.py index d0c9debe..9d68f09f 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -107,6 +107,15 @@ class XmlManifest(object): root = doc.createElement('manifest') doc.appendChild(root) + # Save out the notice. There's a little bit of work here to give it the + # right whitespace, which assumes that the notice is automatically indented + # by 4 by minidom. + if self.notice: + notice_element = root.appendChild(doc.createElement('notice')) + notice_lines = self.notice.splitlines() + indented_notice = ('\n'.join(" "*4 + line for line in notice_lines))[4:] + notice_element.appendChild(doc.createTextNode(indented_notice)) + d = self.default sort_remotes = list(self.remotes.keys()) sort_remotes.sort() @@ -179,6 +188,11 @@ class XmlManifest(object): self._Load() return self._default + @property + def notice(self): + self._Load() + return self._notice + @property def manifest_server(self): self._Load() @@ -193,6 +207,7 @@ class XmlManifest(object): self._projects = {} self._remotes = {} self._default = None + self._notice = None self.branch = None self._manifest_server = None @@ -263,6 +278,14 @@ class XmlManifest(object): if self._default is None: self._default = _Default() + for node in config.childNodes: + if node.nodeName == 'notice': + if self._notice is not None: + raise ManifestParseError, \ + 'duplicate notice in %s' % \ + (self.manifestFile) + self._notice = self._ParseNotice(node) + for node in config.childNodes: if node.nodeName == 'manifest-server': url = self._reqatt(node, 'url') @@ -338,6 +361,45 @@ class XmlManifest(object): d.revisionExpr = None return d + def _ParseNotice(self, node): + """ + reads a element from the manifest file + + The element is distinct from other tags in the XML in that the + data is conveyed between the start and end tag (it's not an empty-element + tag). + + The white space (carriage returns, indentation) for the notice element is + relevant and is parsed in a way that is based on how python docstrings work. + In fact, the code is remarkably similar to here: + http://www.python.org/dev/peps/pep-0257/ + """ + # Get the data out of the node... + notice = node.childNodes[0].data + + # Figure out minimum indentation, skipping the first line (the same line + # as the tag)... + minIndent = sys.maxint + lines = notice.splitlines() + for line in lines[1:]: + lstrippedLine = line.lstrip() + if lstrippedLine: + indent = len(line) - len(lstrippedLine) + minIndent = min(indent, minIndent) + + # Strip leading / trailing blank lines and also indentation. + cleanLines = [lines[0].strip()] + for line in lines[1:]: + cleanLines.append(line[minIndent:].rstrip()) + + # Clear completely blank lines from front and back... + while cleanLines and not cleanLines[0]: + del cleanLines[0] + while cleanLines and not cleanLines[-1]: + del cleanLines[-1] + + return '\n'.join(cleanLines) + def _ParseProject(self, node): """ reads a element from the manifest file diff --git a/subcmds/sync.py b/subcmds/sync.py index ca78467b..d6ea442a 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -361,6 +361,11 @@ uncommitted changes are present' % project.relpath if not syncbuf.Finish(): sys.exit(1) + # If there's a notice that's supposed to print at the end of the sync, print + # it now... + if self.manifest.notice: + print self.manifest.notice + def _PostRepoUpgrade(manifest): for project in manifest.projects.values(): if project.Exists: