Permalink
Browse files

Added feature to print a <notice> 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:
<manifest>
  <notice>
    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.
  </notice>

  <remote ... />
  ...
</manifest>

Carriage returns and indentation are relevant for the text in this tag.

This feature was requested by Anush Elangovan on the ChromiumOS team.
  • Loading branch information...
1 parent 5df6de0 commit 2b8db3ce3e7344b9f3b5216637c5af0d54be5656 Doug Anderson committed Nov 1, 2010
Showing with 71 additions and 1 deletion.
  1. +4 −1 docs/manifest-format.txt
  2. +62 −0 manifest_xml.py
  3. +5 −0 subcmds/sync.py
@@ -20,12 +20,15 @@ A manifest XML file (e.g. 'default.xml') roughly conforms to the
following DTD:
<!DOCTYPE manifest [
- <!ELEMENT manifest (remote*,
+ <!ELEMENT manifest (notice?,
+ remote*,
default?,
manifest-server?,
remove-project*,
project*)>
+ <!ELEMENT notice (#PCDATA)>
+
<!ELEMENT remote (EMPTY)>
<!ATTLIST remote name ID #REQUIRED>
<!ATTLIST remote fetch CDATA #REQUIRED>
View
@@ -107,6 +107,15 @@ def Save(self, fd, peg_rev=False):
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()
@@ -180,6 +189,11 @@ def default(self):
return self._default
@property
+ def notice(self):
+ self._Load()
+ return self._notice
+
+ @property
def manifest_server(self):
self._Load()
return self._manifest_server
@@ -193,6 +207,7 @@ def _Unload(self):
self._projects = {}
self._remotes = {}
self._default = None
+ self._notice = None
self.branch = None
self._manifest_server = None
@@ -264,6 +279,14 @@ def _ParseManifest(self, is_root_file):
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')
if self._manifest_server is not None:
@@ -338,6 +361,45 @@ def _ParseDefault(self, node):
d.revisionExpr = None
return d
+ def _ParseNotice(self, node):
+ """
+ reads a <notice> element from the manifest file
+
+ The <notice> 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 <notice> 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 <project> element from the manifest file
View
@@ -361,6 +361,11 @@ def Execute(self, opt, args):
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:

0 comments on commit 2b8db3c

Please sign in to comment.