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.
This commit is contained in:
Doug Anderson 2010-11-01 15:08:06 -07:00
parent 5df6de075e
commit 2b8db3ce3e
3 changed files with 71 additions and 1 deletions

View File

@ -20,12 +20,15 @@ A manifest XML file (e.g. 'default.xml') roughly conforms to the
following DTD: following DTD:
<!DOCTYPE manifest [ <!DOCTYPE manifest [
<!ELEMENT manifest (remote*, <!ELEMENT manifest (notice?,
remote*,
default?, default?,
manifest-server?, manifest-server?,
remove-project*, remove-project*,
project*)> project*)>
<!ELEMENT notice (#PCDATA)>
<!ELEMENT remote (EMPTY)> <!ELEMENT remote (EMPTY)>
<!ATTLIST remote name ID #REQUIRED> <!ATTLIST remote name ID #REQUIRED>
<!ATTLIST remote fetch CDATA #REQUIRED> <!ATTLIST remote fetch CDATA #REQUIRED>

View File

@ -107,6 +107,15 @@ class XmlManifest(object):
root = doc.createElement('manifest') root = doc.createElement('manifest')
doc.appendChild(root) 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 d = self.default
sort_remotes = list(self.remotes.keys()) sort_remotes = list(self.remotes.keys())
sort_remotes.sort() sort_remotes.sort()
@ -179,6 +188,11 @@ class XmlManifest(object):
self._Load() self._Load()
return self._default return self._default
@property
def notice(self):
self._Load()
return self._notice
@property @property
def manifest_server(self): def manifest_server(self):
self._Load() self._Load()
@ -193,6 +207,7 @@ class XmlManifest(object):
self._projects = {} self._projects = {}
self._remotes = {} self._remotes = {}
self._default = None self._default = None
self._notice = None
self.branch = None self.branch = None
self._manifest_server = None self._manifest_server = None
@ -263,6 +278,14 @@ class XmlManifest(object):
if self._default is None: if self._default is None:
self._default = _Default() 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: for node in config.childNodes:
if node.nodeName == 'manifest-server': if node.nodeName == 'manifest-server':
url = self._reqatt(node, 'url') url = self._reqatt(node, 'url')
@ -338,6 +361,45 @@ class XmlManifest(object):
d.revisionExpr = None d.revisionExpr = None
return d 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): def _ParseProject(self, node):
""" """
reads a <project> element from the manifest file reads a <project> element from the manifest file

View File

@ -361,6 +361,11 @@ uncommitted changes are present' % project.relpath
if not syncbuf.Finish(): if not syncbuf.Finish():
sys.exit(1) 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): def _PostRepoUpgrade(manifest):
for project in manifest.projects.values(): for project in manifest.projects.values():
if project.Exists: if project.Exists: