diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt index a7bb1561..e5f5ee18 100644 --- a/docs/manifest-format.txt +++ b/docs/manifest-format.txt @@ -43,12 +43,17 @@ following DTD: - + + + + + + @@ -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 "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 ---------------------- diff --git a/manifest_xml.py b/manifest_xml.py index a250382f..9b804da9 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -203,6 +203,13 @@ class XmlManifest(object): if 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: root.appendChild(doc.createTextNode('')) e = doc.createElement('repo-hooks') @@ -545,6 +552,8 @@ class XmlManifest(object): for n in node.childNodes: if n.nodeName == 'copyfile': self._ParseCopyFile(project, n) + if n.nodeName == 'annotation': + self._ParseAnnotation(project, n) return project @@ -556,6 +565,17 @@ class XmlManifest(object): # dest is relative to the top of the tree 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): name = node.getAttribute('remote') if not name: diff --git a/project.py b/project.py index 49fef2f7..e297926d 100644 --- a/project.py +++ b/project.py @@ -213,6 +213,11 @@ class DiffColoring(Coloring): Coloring.__init__(self, config, 'diff') 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: def __init__(self, src, dest, abssrc, absdest): @@ -529,6 +534,7 @@ class Project(object): self.snapshots = {} self.copyfiles = [] + self.annotations = [] self.config = GitConfig.ForRepository( gitdir = self.gitdir, defaults = self.manifest.globalConfig) @@ -1175,6 +1181,9 @@ class Project(object): abssrc = os.path.join(self.worktree, src) 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): """Download a single patch set of a single change to FETCH_HEAD. """ diff --git a/subcmds/forall.py b/subcmds/forall.py index d3e70ae1..9436f4e5 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py @@ -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 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 following . @@ -162,6 +167,8 @@ terminal and are not redirected. setenv('REPO_REMOTE', project.remote.name) setenv('REPO_LREV', project.GetRevisionId()) setenv('REPO_RREV', project.revisionExpr) + for a in project.annotations: + setenv("REPO__%s" % (a.name), a.value) if mirror: setenv('GIT_DIR', project.gitdir)