diff options
| -rw-r--r-- | docs/manifest-format.txt | 18 | ||||
| -rw-r--r-- | manifest_xml.py | 20 | ||||
| -rw-r--r-- | project.py | 9 | ||||
| -rw-r--r-- | subcmds/forall.py | 7 |
4 files changed, 53 insertions, 1 deletions
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: | |||
| 43 | <!ELEMENT manifest-server (EMPTY)> | 43 | <!ELEMENT manifest-server (EMPTY)> |
| 44 | <!ATTLIST url CDATA #REQUIRED> | 44 | <!ATTLIST url CDATA #REQUIRED> |
| 45 | 45 | ||
| 46 | <!ELEMENT project (EMPTY)> | 46 | <!ELEMENT project (annotation?)> |
| 47 | <!ATTLIST project name CDATA #REQUIRED> | 47 | <!ATTLIST project name CDATA #REQUIRED> |
| 48 | <!ATTLIST project path CDATA #IMPLIED> | 48 | <!ATTLIST project path CDATA #IMPLIED> |
| 49 | <!ATTLIST project remote IDREF #IMPLIED> | 49 | <!ATTLIST project remote IDREF #IMPLIED> |
| 50 | <!ATTLIST project revision CDATA #IMPLIED> | 50 | <!ATTLIST project revision CDATA #IMPLIED> |
| 51 | <!ATTLIST project groups CDATA #IMPLIED> | 51 | <!ATTLIST project groups CDATA #IMPLIED> |
| 52 | |||
| 53 | <!ELEMENT annotation (EMPTY)> | ||
| 54 | <!ATTLIST annotation name CDATA #REQUIRED> | ||
| 55 | <!ATTLIST annotation value CDATA #REQUIRED> | ||
| 56 | <!ATTLIST annotation keep CDATA "true"> | ||
| 52 | 57 | ||
| 53 | <!ELEMENT remove-project (EMPTY)> | 58 | <!ELEMENT remove-project (EMPTY)> |
| 54 | <!ATTLIST remove-project name CDATA #REQUIRED> | 59 | <!ATTLIST remove-project name CDATA #REQUIRED> |
| @@ -163,6 +168,17 @@ Attribute `groups`: List of groups to which this project belongs, | |||
| 163 | whitespace or comma separated. All projects are part of the group | 168 | whitespace or comma separated. All projects are part of the group |
| 164 | "default" unless "-default" is specified in the list of groups. | 169 | "default" unless "-default" is specified in the list of groups. |
| 165 | 170 | ||
| 171 | Element annotation | ||
| 172 | ------------------ | ||
| 173 | |||
| 174 | Zero or more annotation elements may be specified as children of a | ||
| 175 | project element. Each element describes a name-value pair that will be | ||
| 176 | exported into each project's environment during a 'forall' command, | ||
| 177 | prefixed with REPO__. In addition, there is an optional attribute | ||
| 178 | "keep" which accepts the case insensitive values "true" (default) or | ||
| 179 | "false". This attribute determines whether or not the annotation will | ||
| 180 | be kept when exported with the manifest subcommand. | ||
| 181 | |||
| 166 | Element remove-project | 182 | Element remove-project |
| 167 | ---------------------- | 183 | ---------------------- |
| 168 | 184 | ||
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): | |||
| 203 | if p.groups: | 203 | if p.groups: |
| 204 | e.setAttribute('groups', ','.join(p.groups)) | 204 | e.setAttribute('groups', ','.join(p.groups)) |
| 205 | 205 | ||
| 206 | for a in p.annotations: | ||
| 207 | if a.keep == "true": | ||
| 208 | ae = doc.createElement('annotation') | ||
| 209 | ae.setAttribute('name', a.name) | ||
| 210 | ae.setAttribute('value', a.value) | ||
| 211 | e.appendChild(ae) | ||
| 212 | |||
| 206 | if self._repo_hooks_project: | 213 | if self._repo_hooks_project: |
| 207 | root.appendChild(doc.createTextNode('')) | 214 | root.appendChild(doc.createTextNode('')) |
| 208 | e = doc.createElement('repo-hooks') | 215 | e = doc.createElement('repo-hooks') |
| @@ -545,6 +552,8 @@ class XmlManifest(object): | |||
| 545 | for n in node.childNodes: | 552 | for n in node.childNodes: |
| 546 | if n.nodeName == 'copyfile': | 553 | if n.nodeName == 'copyfile': |
| 547 | self._ParseCopyFile(project, n) | 554 | self._ParseCopyFile(project, n) |
| 555 | if n.nodeName == 'annotation': | ||
| 556 | self._ParseAnnotation(project, n) | ||
| 548 | 557 | ||
| 549 | return project | 558 | return project |
| 550 | 559 | ||
| @@ -556,6 +565,17 @@ class XmlManifest(object): | |||
| 556 | # dest is relative to the top of the tree | 565 | # dest is relative to the top of the tree |
| 557 | project.AddCopyFile(src, dest, os.path.join(self.topdir, dest)) | 566 | project.AddCopyFile(src, dest, os.path.join(self.topdir, dest)) |
| 558 | 567 | ||
| 568 | def _ParseAnnotation(self, project, node): | ||
| 569 | name = self._reqatt(node, 'name') | ||
| 570 | value = self._reqatt(node, 'value') | ||
| 571 | try: | ||
| 572 | keep = self._reqatt(node, 'keep').lower() | ||
| 573 | except ManifestParseError: | ||
| 574 | keep = "true" | ||
| 575 | if keep != "true" and keep != "false": | ||
| 576 | raise ManifestParseError, "optional \"keep\" attribute must be \"true\" or \"false\"" | ||
| 577 | project.AddAnnotation(name, value, keep) | ||
| 578 | |||
| 559 | def _get_remote(self, node): | 579 | def _get_remote(self, node): |
| 560 | name = node.getAttribute('remote') | 580 | name = node.getAttribute('remote') |
| 561 | if not name: | 581 | if not name: |
| @@ -213,6 +213,11 @@ class DiffColoring(Coloring): | |||
| 213 | Coloring.__init__(self, config, 'diff') | 213 | Coloring.__init__(self, config, 'diff') |
| 214 | self.project = self.printer('header', attr = 'bold') | 214 | self.project = self.printer('header', attr = 'bold') |
| 215 | 215 | ||
| 216 | class _Annotation: | ||
| 217 | def __init__(self, name, value, keep): | ||
| 218 | self.name = name | ||
| 219 | self.value = value | ||
| 220 | self.keep = keep | ||
| 216 | 221 | ||
| 217 | class _CopyFile: | 222 | class _CopyFile: |
| 218 | def __init__(self, src, dest, abssrc, absdest): | 223 | def __init__(self, src, dest, abssrc, absdest): |
| @@ -529,6 +534,7 @@ class Project(object): | |||
| 529 | 534 | ||
| 530 | self.snapshots = {} | 535 | self.snapshots = {} |
| 531 | self.copyfiles = [] | 536 | self.copyfiles = [] |
| 537 | self.annotations = [] | ||
| 532 | self.config = GitConfig.ForRepository( | 538 | self.config = GitConfig.ForRepository( |
| 533 | gitdir = self.gitdir, | 539 | gitdir = self.gitdir, |
| 534 | defaults = self.manifest.globalConfig) | 540 | defaults = self.manifest.globalConfig) |
| @@ -1175,6 +1181,9 @@ class Project(object): | |||
| 1175 | abssrc = os.path.join(self.worktree, src) | 1181 | abssrc = os.path.join(self.worktree, src) |
| 1176 | self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest)) | 1182 | self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest)) |
| 1177 | 1183 | ||
| 1184 | def AddAnnotation(self, name, value, keep): | ||
| 1185 | self.annotations.append(_Annotation(name, value, keep)) | ||
| 1186 | |||
| 1178 | def DownloadPatchSet(self, change_id, patch_id): | 1187 | def DownloadPatchSet(self, change_id, patch_id): |
| 1179 | """Download a single patch set of a single change to FETCH_HEAD. | 1188 | """Download a single patch set of a single change to FETCH_HEAD. |
| 1180 | """ | 1189 | """ |
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. | |||
| 82 | REPO_RREV is the name of the revision from the manifest, exactly | 82 | REPO_RREV is the name of the revision from the manifest, exactly |
| 83 | as written in the manifest. | 83 | as written in the manifest. |
| 84 | 84 | ||
| 85 | REPO__* are any extra environment variables, specified by the | ||
| 86 | "annotation" element under any project element. This can be useful | ||
| 87 | for differentiating trees based on user-specific criteria, or simply | ||
| 88 | annotating tree details. | ||
| 89 | |||
| 85 | shell positional arguments ($1, $2, .., $#) are set to any arguments | 90 | shell positional arguments ($1, $2, .., $#) are set to any arguments |
| 86 | following <command>. | 91 | following <command>. |
| 87 | 92 | ||
| @@ -162,6 +167,8 @@ terminal and are not redirected. | |||
| 162 | setenv('REPO_REMOTE', project.remote.name) | 167 | setenv('REPO_REMOTE', project.remote.name) |
| 163 | setenv('REPO_LREV', project.GetRevisionId()) | 168 | setenv('REPO_LREV', project.GetRevisionId()) |
| 164 | setenv('REPO_RREV', project.revisionExpr) | 169 | setenv('REPO_RREV', project.revisionExpr) |
| 170 | for a in project.annotations: | ||
| 171 | setenv("REPO__%s" % (a.name), a.value) | ||
| 165 | 172 | ||
| 166 | if mirror: | 173 | if mirror: |
| 167 | setenv('GIT_DIR', project.gitdir) | 174 | setenv('GIT_DIR', project.gitdir) |
