Add project annotation handling to repo

Allow the optional addition of "annotation" nodes nested under
projects.  Each annotation node must have "name" and "value"
attributes.  These name/value pairs will be exported into the
environment during any forall command, prefixed with "REPO__"

In addition, an optional "keep" attribute with case insensitive "true"
or "false" values can be included to determine whether the annotation
will be exported with 'repo manifest'

Change-Id: Icd7540afaae02c958f769ce3d25661aa721a9de8
Signed-off-by: James W. Mills <jameswmills@gmail.com>
This commit is contained in:
James W. Mills 2012-04-12 15:04:13 -05:00 committed by Shawn O. Pearce
parent b962a1f5e0
commit 24c1308840
4 changed files with 53 additions and 1 deletions

View File

@ -43,12 +43,17 @@ following DTD:
<!ELEMENT manifest-server (EMPTY)> <!ELEMENT manifest-server (EMPTY)>
<!ATTLIST url CDATA #REQUIRED> <!ATTLIST url CDATA #REQUIRED>
<!ELEMENT project (EMPTY)> <!ELEMENT project (annotation?)>
<!ATTLIST project name CDATA #REQUIRED> <!ATTLIST project name CDATA #REQUIRED>
<!ATTLIST project path CDATA #IMPLIED> <!ATTLIST project path CDATA #IMPLIED>
<!ATTLIST project remote IDREF #IMPLIED> <!ATTLIST project remote IDREF #IMPLIED>
<!ATTLIST project revision CDATA #IMPLIED> <!ATTLIST project revision CDATA #IMPLIED>
<!ATTLIST project groups CDATA #IMPLIED> <!ATTLIST project groups CDATA #IMPLIED>
<!ELEMENT annotation (EMPTY)>
<!ATTLIST annotation name CDATA #REQUIRED>
<!ATTLIST annotation value CDATA #REQUIRED>
<!ATTLIST annotation keep CDATA "true">
<!ELEMENT remove-project (EMPTY)> <!ELEMENT remove-project (EMPTY)>
<!ATTLIST remove-project name CDATA #REQUIRED> <!ATTLIST remove-project name CDATA #REQUIRED>
@ -163,6 +168,17 @@ Attribute `groups`: List of groups to which this project belongs,
whitespace or comma separated. All projects are part of the group whitespace or comma separated. All projects are part of the group
"default" unless "-default" is specified in the list of groups. "default" unless "-default" is specified in the list of groups.
Element annotation
------------------
Zero or more annotation elements may be specified as children of a
project element. Each element describes a name-value pair that will be
exported into each project's environment during a 'forall' command,
prefixed with REPO__. In addition, there is an optional attribute
"keep" which accepts the case insensitive values "true" (default) or
"false". This attribute determines whether or not the annotation will
be kept when exported with the manifest subcommand.
Element remove-project Element remove-project
---------------------- ----------------------

View File

@ -203,6 +203,13 @@ class XmlManifest(object):
if p.groups: if p.groups:
e.setAttribute('groups', ','.join(p.groups)) e.setAttribute('groups', ','.join(p.groups))
for a in p.annotations:
if a.keep == "true":
ae = doc.createElement('annotation')
ae.setAttribute('name', a.name)
ae.setAttribute('value', a.value)
e.appendChild(ae)
if self._repo_hooks_project: if self._repo_hooks_project:
root.appendChild(doc.createTextNode('')) root.appendChild(doc.createTextNode(''))
e = doc.createElement('repo-hooks') e = doc.createElement('repo-hooks')
@ -545,6 +552,8 @@ class XmlManifest(object):
for n in node.childNodes: for n in node.childNodes:
if n.nodeName == 'copyfile': if n.nodeName == 'copyfile':
self._ParseCopyFile(project, n) self._ParseCopyFile(project, n)
if n.nodeName == 'annotation':
self._ParseAnnotation(project, n)
return project return project
@ -556,6 +565,17 @@ class XmlManifest(object):
# dest is relative to the top of the tree # dest is relative to the top of the tree
project.AddCopyFile(src, dest, os.path.join(self.topdir, dest)) project.AddCopyFile(src, dest, os.path.join(self.topdir, dest))
def _ParseAnnotation(self, project, node):
name = self._reqatt(node, 'name')
value = self._reqatt(node, 'value')
try:
keep = self._reqatt(node, 'keep').lower()
except ManifestParseError:
keep = "true"
if keep != "true" and keep != "false":
raise ManifestParseError, "optional \"keep\" attribute must be \"true\" or \"false\""
project.AddAnnotation(name, value, keep)
def _get_remote(self, node): def _get_remote(self, node):
name = node.getAttribute('remote') name = node.getAttribute('remote')
if not name: if not name:

View File

@ -213,6 +213,11 @@ class DiffColoring(Coloring):
Coloring.__init__(self, config, 'diff') Coloring.__init__(self, config, 'diff')
self.project = self.printer('header', attr = 'bold') self.project = self.printer('header', attr = 'bold')
class _Annotation:
def __init__(self, name, value, keep):
self.name = name
self.value = value
self.keep = keep
class _CopyFile: class _CopyFile:
def __init__(self, src, dest, abssrc, absdest): def __init__(self, src, dest, abssrc, absdest):
@ -529,6 +534,7 @@ class Project(object):
self.snapshots = {} self.snapshots = {}
self.copyfiles = [] self.copyfiles = []
self.annotations = []
self.config = GitConfig.ForRepository( self.config = GitConfig.ForRepository(
gitdir = self.gitdir, gitdir = self.gitdir,
defaults = self.manifest.globalConfig) defaults = self.manifest.globalConfig)
@ -1175,6 +1181,9 @@ class Project(object):
abssrc = os.path.join(self.worktree, src) abssrc = os.path.join(self.worktree, src)
self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest)) self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest))
def AddAnnotation(self, name, value, keep):
self.annotations.append(_Annotation(name, value, keep))
def DownloadPatchSet(self, change_id, patch_id): def DownloadPatchSet(self, change_id, patch_id):
"""Download a single patch set of a single change to FETCH_HEAD. """Download a single patch set of a single change to FETCH_HEAD.
""" """

View File

@ -82,6 +82,11 @@ revision to a locally executed git command, use REPO_LREV.
REPO_RREV is the name of the revision from the manifest, exactly REPO_RREV is the name of the revision from the manifest, exactly
as written in the manifest. as written in the manifest.
REPO__* are any extra environment variables, specified by the
"annotation" element under any project element. This can be useful
for differentiating trees based on user-specific criteria, or simply
annotating tree details.
shell positional arguments ($1, $2, .., $#) are set to any arguments shell positional arguments ($1, $2, .., $#) are set to any arguments
following <command>. following <command>.
@ -162,6 +167,8 @@ terminal and are not redirected.
setenv('REPO_REMOTE', project.remote.name) setenv('REPO_REMOTE', project.remote.name)
setenv('REPO_LREV', project.GetRevisionId()) setenv('REPO_LREV', project.GetRevisionId())
setenv('REPO_RREV', project.revisionExpr) setenv('REPO_RREV', project.revisionExpr)
for a in project.annotations:
setenv("REPO__%s" % (a.name), a.value)
if mirror: if mirror:
setenv('GIT_DIR', project.gitdir) setenv('GIT_DIR', project.gitdir)