Просмотр исходного кода

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>
James W. Mills 14 лет назад
Родитель
Сommit
24c1308840
4 измененных файлов с 53 добавлено и 1 удалено
  1. 17 1
      docs/manifest-format.txt
  2. 20 0
      manifest_xml.py
  3. 9 0
      project.py
  4. 7 0
      subcmds/forall.py

+ 17 - 1
docs/manifest-format.txt

@@ -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
 ----------------------
 ----------------------
 
 

+ 20 - 0
manifest_xml.py

@@ -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:

+ 9 - 0
project.py

@@ -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.
     """
     """

+ 7 - 0
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
 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)