Refine groups functionality

Every project is in group "default".  "-default" does not remove
it from this project.  All group names specified in the manifest
are positive names as opposed to a mix of negative and positive.

Specified groups are resolved in order.  If init is supplied with
--groups="group1,-group2", the following describes the project
selection when syncing:

  * all projects in "group1" will be added, and
  * all projects in "group2" will be removed.

Change-Id: I1df3dcdb64bbd4cd80d675f9b2d3becbf721f661
diff --git a/manifest_xml.py b/manifest_xml.py
index 9b804da..5ffc49e 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -122,8 +122,9 @@
     mp = self.manifestProject
 
     groups = mp.config.GetString('manifest.groups')
-    if groups:
-      groups = re.split('[,\s]+', groups)
+    if groups is None:
+      groups = 'default'
+    groups = [x for x in re.split(r'[,\s]+', groups) if x]
 
     doc = xml.dom.minidom.Document()
     root = doc.createElement('manifest')
@@ -200,8 +201,9 @@
         ce.setAttribute('dest', c.dest)
         e.appendChild(ce)
 
-      if p.groups:
-        e.setAttribute('groups', ','.join(p.groups))
+      egroups = [g for g in p.groups if g != 'default']
+      if egroups:
+        e.setAttribute('groups', ','.join(egroups))
 
       for a in p.annotations:
         if a.keep == "true":
@@ -524,11 +526,12 @@
     else:
       rebase = rebase.lower() in ("yes", "true", "1")
 
-    groups = node.getAttribute('groups')
-    if groups:
-      groups = re.split('[,\s]+', groups)
-    else:
-      groups = None
+    groups = ''
+    if node.hasAttribute('groups'):
+      groups = node.getAttribute('groups')
+    groups = [x for x in re.split('[,\s]+', groups) if x]
+    if 'default' not in groups:
+      groups.append('default')
 
     if self.IsMirror:
       relpath = None