Add manifest groups

Allows specifying a list of groups with a -g argument to repo init.
The groups act on a group= attribute specified on projects in the
manifest.
All projects are implicitly labelled with "default" unless they are
explicitly labelled "-default".
Prefixing a group with "-" removes matching projects from the list
of projects to sync.
If any non-inverted manifest groups are specified, the default label
is ignored.

Change-Id: I3a0dd7a93a8a1756205de1d03eee8c00906af0e5
Reviewed-on: https://gerrit-review.googlesource.com/34570
Reviewed-by: Shawn Pearce <sop@google.com>
Tested-by: Shawn Pearce <sop@google.com>
diff --git a/subcmds/init.py b/subcmds/init.py
index 1cba366..6cf39d1 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -86,6 +86,10 @@
     g.add_option('--depth', type='int', default=None,
                  dest='depth',
                  help='create a shallow clone with given depth; see git clone')
+    g.add_option('-g', '--groups',
+                 dest='groups', default="",
+                 help='restrict manifest projects to ones with a specified group',
+                 metavar='GROUP')
 
     # Tool
     g = p.add_option_group('repo Version options')
@@ -135,6 +139,8 @@
       r.ResetFetch()
       r.Save()
 
+    m.config.SetString('manifest.groups', opt.groups)
+
     if opt.reference:
       m.config.SetString('repo.reference', opt.reference)
 
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 74b3f18..63227af 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -277,7 +277,7 @@
 
   def UpdateProjectList(self):
     new_project_paths = []
-    for project in self.manifest.projects.values():
+    for project in self.GetProjects(None, missing_ok=True):
       if project.relpath:
         new_project_paths.append(project.relpath)
     file_name = 'project.list'
@@ -306,7 +306,8 @@
                              worktree = os.path.join(self.manifest.topdir, path),
                              relpath = path,
                              revisionExpr = 'HEAD',
-                             revisionId = None)
+                             revisionId = None,
+                             groups = None)
 
               if project.IsDirty():
                 print >>sys.stderr, 'error: Cannot remove project "%s": \