mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-06-28 20:17:26 +00:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
87636f2ac2 | |||
337aee0a9c | |||
7cf1b36bcd | |||
5e57234ec6 | |||
5d016502eb | |||
475a47d531 | |||
62d0b10a7b | |||
d666e93ecc | |||
3f61950f01 | |||
4fd38ecc3a | |||
9fae805e04 | |||
6a927c5d19 | |||
eca119e5d6 | |||
6ba6ba0ef3 | |||
23acdd3f14 | |||
2644874d9d | |||
3d125940f6 | |||
a94f162b9f | |||
e5a2122e64 | |||
ccf86432b3 | |||
79770d269e | |||
c39864f5e1 | |||
5465727e53 | |||
d21720db31 | |||
971de8ea7b | |||
24c1308840 | |||
b962a1f5e0 | |||
5acde75e5d | |||
d67872d2f4 | |||
e9d6b611c5 |
17
command.py
17
command.py
@ -15,9 +15,12 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import optparse
|
import optparse
|
||||||
|
import platform
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from error import NoSuchProjectError
|
from error import NoSuchProjectError
|
||||||
|
from error import InvalidProjectGroupsError
|
||||||
|
|
||||||
class Command(object):
|
class Command(object):
|
||||||
"""Base class for any command line action in repo.
|
"""Base class for any command line action in repo.
|
||||||
@ -56,16 +59,24 @@ class Command(object):
|
|||||||
"""Perform the action, after option parsing is complete.
|
"""Perform the action, after option parsing is complete.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def GetProjects(self, args, missing_ok=False):
|
def GetProjects(self, args, missing_ok=False):
|
||||||
"""A list of projects that match the arguments.
|
"""A list of projects that match the arguments.
|
||||||
"""
|
"""
|
||||||
all = self.manifest.projects
|
all = self.manifest.projects
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
|
mp = self.manifest.manifestProject
|
||||||
|
|
||||||
|
groups = mp.config.GetString('manifest.groups')
|
||||||
|
if not groups:
|
||||||
|
groups = 'default,platform-' + platform.system().lower()
|
||||||
|
groups = [x for x in re.split('[,\s]+', groups) if x]
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
for project in all.values():
|
for project in all.values():
|
||||||
if missing_ok or project.Exists:
|
if ((missing_ok or project.Exists) and
|
||||||
|
project.MatchesGroups(groups)):
|
||||||
result.append(project)
|
result.append(project)
|
||||||
else:
|
else:
|
||||||
by_path = None
|
by_path = None
|
||||||
@ -102,6 +113,8 @@ class Command(object):
|
|||||||
raise NoSuchProjectError(arg)
|
raise NoSuchProjectError(arg)
|
||||||
if not missing_ok and not project.Exists:
|
if not missing_ok and not project.Exists:
|
||||||
raise NoSuchProjectError(arg)
|
raise NoSuchProjectError(arg)
|
||||||
|
if not project.MatchesGroups(groups):
|
||||||
|
raise InvalidProjectGroupsError(arg)
|
||||||
|
|
||||||
result.append(project)
|
result.append(project)
|
||||||
|
|
||||||
|
@ -39,15 +39,23 @@ following DTD:
|
|||||||
<!ATTLIST default remote IDREF #IMPLIED>
|
<!ATTLIST default remote IDREF #IMPLIED>
|
||||||
<!ATTLIST default revision CDATA #IMPLIED>
|
<!ATTLIST default revision CDATA #IMPLIED>
|
||||||
<!ATTLIST default sync-j CDATA #IMPLIED>
|
<!ATTLIST default sync-j CDATA #IMPLIED>
|
||||||
|
<!ATTLIST default sync-c CDATA #IMPLIED>
|
||||||
|
|
||||||
<!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 sync-c 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>
|
||||||
@ -55,6 +63,9 @@ following DTD:
|
|||||||
<!ELEMENT repo-hooks (EMPTY)>
|
<!ELEMENT repo-hooks (EMPTY)>
|
||||||
<!ATTLIST repo-hooks in-project CDATA #REQUIRED>
|
<!ATTLIST repo-hooks in-project CDATA #REQUIRED>
|
||||||
<!ATTLIST repo-hooks enabled-list CDATA #REQUIRED>
|
<!ATTLIST repo-hooks enabled-list CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT include (EMPTY)>
|
||||||
|
<!ATTLIST include name CDATA #REQUIRED>
|
||||||
]>
|
]>
|
||||||
|
|
||||||
A description of the elements and their attributes follows.
|
A description of the elements and their attributes follows.
|
||||||
@ -158,6 +169,21 @@ Tags and/or explicit SHA-1s should work in theory, but have not
|
|||||||
been extensively tested. If not supplied the revision given by
|
been extensively tested. If not supplied the revision given by
|
||||||
the default element is used.
|
the default element is used.
|
||||||
|
|
||||||
|
Attribute `groups`: List of groups to which this project belongs,
|
||||||
|
whitespace or comma separated. All projects belong to the group
|
||||||
|
"default".
|
||||||
|
|
||||||
|
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
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
@ -169,6 +195,16 @@ This element is mostly useful in the local_manifest.xml, where
|
|||||||
the user can remove a project, and possibly replace it with their
|
the user can remove a project, and possibly replace it with their
|
||||||
own definition.
|
own definition.
|
||||||
|
|
||||||
|
Element include
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This element provides the capability of including another manifest
|
||||||
|
file into the originating manifest. Normal rules apply for the
|
||||||
|
target manifest to include- it must be a usable manifest on it's own.
|
||||||
|
|
||||||
|
Attribute `name`; the manifest to include, specified relative to
|
||||||
|
the manifest repositories root.
|
||||||
|
|
||||||
|
|
||||||
Local Manifest
|
Local Manifest
|
||||||
==============
|
==============
|
||||||
|
12
error.py
12
error.py
@ -77,6 +77,18 @@ class NoSuchProjectError(Exception):
|
|||||||
return 'in current directory'
|
return 'in current directory'
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidProjectGroupsError(Exception):
|
||||||
|
"""A specified project is not suitable for the specified groups
|
||||||
|
"""
|
||||||
|
def __init__(self, name=None):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.Name is None:
|
||||||
|
return 'in current directory'
|
||||||
|
return self.name
|
||||||
|
|
||||||
class RepoChangedException(Exception):
|
class RepoChangedException(Exception):
|
||||||
"""Thrown if 'repo sync' results in repo updating its internal
|
"""Thrown if 'repo sync' results in repo updating its internal
|
||||||
repo or manifest repositories. In this special case we must
|
repo or manifest repositories. In this special case we must
|
||||||
|
@ -147,6 +147,12 @@ class GitCommand(object):
|
|||||||
if ssh_proxy:
|
if ssh_proxy:
|
||||||
_setenv(env, 'REPO_SSH_SOCK', ssh_sock())
|
_setenv(env, 'REPO_SSH_SOCK', ssh_sock())
|
||||||
_setenv(env, 'GIT_SSH', _ssh_proxy())
|
_setenv(env, 'GIT_SSH', _ssh_proxy())
|
||||||
|
if 'http_proxy' in env and 'darwin' == sys.platform:
|
||||||
|
s = "'http.proxy=%s'" % (env['http_proxy'],)
|
||||||
|
p = env.get('GIT_CONFIG_PARAMETERS')
|
||||||
|
if p is not None:
|
||||||
|
s = p + ' ' + s
|
||||||
|
_setenv(env, 'GIT_CONFIG_PARAMETERS', s)
|
||||||
|
|
||||||
if project:
|
if project:
|
||||||
if not cwd:
|
if not cwd:
|
||||||
|
@ -38,6 +38,11 @@ elif test -x /usr/bin/pmset && /usr/bin/pmset -g batt |
|
|||||||
grep -q "Currently drawing from 'AC Power'"
|
grep -q "Currently drawing from 'AC Power'"
|
||||||
then
|
then
|
||||||
exit 0
|
exit 0
|
||||||
|
elif test -d /sys/bus/acpi/drivers/battery && test 0 = \
|
||||||
|
"$(find /sys/bus/acpi/drivers/battery/ -type l | wc -l)";
|
||||||
|
then
|
||||||
|
# No battery exists.
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Auto packing deferred; not on AC"
|
echo "Auto packing deferred; not on AC"
|
||||||
|
152
manifest_xml.py
152
manifest_xml.py
@ -13,6 +13,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import itertools
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
@ -35,6 +36,7 @@ class _Default(object):
|
|||||||
revisionExpr = None
|
revisionExpr = None
|
||||||
remote = None
|
remote = None
|
||||||
sync_j = 1
|
sync_j = 1
|
||||||
|
sync_c = False
|
||||||
|
|
||||||
class _XmlRemote(object):
|
class _XmlRemote(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -119,6 +121,13 @@ class XmlManifest(object):
|
|||||||
def Save(self, fd, peg_rev=False):
|
def Save(self, fd, peg_rev=False):
|
||||||
"""Write the current manifest out to the given file descriptor.
|
"""Write the current manifest out to the given file descriptor.
|
||||||
"""
|
"""
|
||||||
|
mp = self.manifestProject
|
||||||
|
|
||||||
|
groups = mp.config.GetString('manifest.groups')
|
||||||
|
if not groups:
|
||||||
|
groups = 'default'
|
||||||
|
groups = [x for x in re.split(r'[,\s]+', groups) if x]
|
||||||
|
|
||||||
doc = xml.dom.minidom.Document()
|
doc = xml.dom.minidom.Document()
|
||||||
root = doc.createElement('manifest')
|
root = doc.createElement('manifest')
|
||||||
doc.appendChild(root)
|
doc.appendChild(root)
|
||||||
@ -152,6 +161,9 @@ class XmlManifest(object):
|
|||||||
if d.sync_j > 1:
|
if d.sync_j > 1:
|
||||||
have_default = True
|
have_default = True
|
||||||
e.setAttribute('sync-j', '%d' % d.sync_j)
|
e.setAttribute('sync-j', '%d' % d.sync_j)
|
||||||
|
if d.sync_c:
|
||||||
|
have_default = True
|
||||||
|
e.setAttribute('sync-c', 'true')
|
||||||
if have_default:
|
if have_default:
|
||||||
root.appendChild(e)
|
root.appendChild(e)
|
||||||
root.appendChild(doc.createTextNode(''))
|
root.appendChild(doc.createTextNode(''))
|
||||||
@ -167,6 +179,10 @@ class XmlManifest(object):
|
|||||||
|
|
||||||
for p in sort_projects:
|
for p in sort_projects:
|
||||||
p = self.projects[p]
|
p = self.projects[p]
|
||||||
|
|
||||||
|
if not p.MatchesGroups(groups):
|
||||||
|
continue
|
||||||
|
|
||||||
e = doc.createElement('project')
|
e = doc.createElement('project')
|
||||||
root.appendChild(e)
|
root.appendChild(e)
|
||||||
e.setAttribute('name', p.name)
|
e.setAttribute('name', p.name)
|
||||||
@ -190,6 +206,20 @@ class XmlManifest(object):
|
|||||||
ce.setAttribute('dest', c.dest)
|
ce.setAttribute('dest', c.dest)
|
||||||
e.appendChild(ce)
|
e.appendChild(ce)
|
||||||
|
|
||||||
|
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":
|
||||||
|
ae = doc.createElement('annotation')
|
||||||
|
ae.setAttribute('name', a.name)
|
||||||
|
ae.setAttribute('value', a.value)
|
||||||
|
e.appendChild(ae)
|
||||||
|
|
||||||
|
if p.sync_c:
|
||||||
|
e.setAttribute('sync-c', 'true')
|
||||||
|
|
||||||
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')
|
||||||
@ -252,16 +282,15 @@ class XmlManifest(object):
|
|||||||
b = b[len(R_HEADS):]
|
b = b[len(R_HEADS):]
|
||||||
self.branch = b
|
self.branch = b
|
||||||
|
|
||||||
self._ParseManifest(True)
|
nodes = []
|
||||||
|
nodes.append(self._ParseManifestXml(self.manifestFile,
|
||||||
|
self.manifestProject.worktree))
|
||||||
|
|
||||||
local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME)
|
local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME)
|
||||||
if os.path.exists(local):
|
if os.path.exists(local):
|
||||||
try:
|
nodes.append(self._ParseManifestXml(local, self.repodir))
|
||||||
real = self.manifestFile
|
|
||||||
self.manifestFile = local
|
self._ParseManifest(nodes)
|
||||||
self._ParseManifest(False)
|
|
||||||
finally:
|
|
||||||
self.manifestFile = real
|
|
||||||
|
|
||||||
if self.IsMirror:
|
if self.IsMirror:
|
||||||
self._AddMetaProjectMirror(self.repoProject)
|
self._AddMetaProjectMirror(self.repoProject)
|
||||||
@ -269,35 +298,39 @@ class XmlManifest(object):
|
|||||||
|
|
||||||
self._loaded = True
|
self._loaded = True
|
||||||
|
|
||||||
def _ParseManifest(self, is_root_file):
|
def _ParseManifestXml(self, path, include_root):
|
||||||
root = xml.dom.minidom.parse(self.manifestFile)
|
root = xml.dom.minidom.parse(path)
|
||||||
if not root or not root.childNodes:
|
if not root or not root.childNodes:
|
||||||
raise ManifestParseError(
|
raise ManifestParseError("no root node in %s" % (path,))
|
||||||
"no root node in %s" %
|
|
||||||
self.manifestFile)
|
|
||||||
|
|
||||||
config = root.childNodes[0]
|
config = root.childNodes[0]
|
||||||
if config.nodeName != 'manifest':
|
if config.nodeName != 'manifest':
|
||||||
raise ManifestParseError(
|
raise ManifestParseError("no <manifest> in %s" % (path,))
|
||||||
"no <manifest> in %s" %
|
|
||||||
self.manifestFile)
|
|
||||||
|
|
||||||
|
nodes = []
|
||||||
for node in config.childNodes:
|
for node in config.childNodes:
|
||||||
if node.nodeName == 'remove-project':
|
if node.nodeName == 'include':
|
||||||
name = self._reqatt(node, 'name')
|
name = self._reqatt(node, 'name')
|
||||||
try:
|
fp = os.path.join(include_root, name)
|
||||||
del self._projects[name]
|
if not os.path.isfile(fp):
|
||||||
except KeyError:
|
raise ManifestParseError, \
|
||||||
raise ManifestParseError(
|
"include %s doesn't exist or isn't a file" % \
|
||||||
'project %s not found' %
|
(name,)
|
||||||
(name))
|
try:
|
||||||
|
nodes.extend(self._ParseManifestXml(fp, include_root))
|
||||||
|
# should isolate this to the exact exception, but that's
|
||||||
|
# tricky. actual parsing implementation may vary.
|
||||||
|
except (KeyboardInterrupt, RuntimeError, SystemExit):
|
||||||
|
raise
|
||||||
|
except Exception, e:
|
||||||
|
raise ManifestParseError(
|
||||||
|
"failed parsing included manifest %s: %s", (name, e))
|
||||||
|
else:
|
||||||
|
nodes.append(node)
|
||||||
|
return nodes
|
||||||
|
|
||||||
# If the manifest removes the hooks project, treat it as if it deleted
|
def _ParseManifest(self, node_list):
|
||||||
# the repo-hooks element too.
|
for node in itertools.chain(*node_list):
|
||||||
if self._repo_hooks_project and (self._repo_hooks_project.name == name):
|
|
||||||
self._repo_hooks_project = None
|
|
||||||
|
|
||||||
for node in config.childNodes:
|
|
||||||
if node.nodeName == 'remote':
|
if node.nodeName == 'remote':
|
||||||
remote = self._ParseRemote(node)
|
remote = self._ParseRemote(node)
|
||||||
if self._remotes.get(remote.name):
|
if self._remotes.get(remote.name):
|
||||||
@ -306,7 +339,7 @@ class XmlManifest(object):
|
|||||||
(remote.name, self.manifestFile))
|
(remote.name, self.manifestFile))
|
||||||
self._remotes[remote.name] = remote
|
self._remotes[remote.name] = remote
|
||||||
|
|
||||||
for node in config.childNodes:
|
for node in itertools.chain(*node_list):
|
||||||
if node.nodeName == 'default':
|
if node.nodeName == 'default':
|
||||||
if self._default is not None:
|
if self._default is not None:
|
||||||
raise ManifestParseError(
|
raise ManifestParseError(
|
||||||
@ -316,7 +349,7 @@ class XmlManifest(object):
|
|||||||
if self._default is None:
|
if self._default is None:
|
||||||
self._default = _Default()
|
self._default = _Default()
|
||||||
|
|
||||||
for node in config.childNodes:
|
for node in itertools.chain(*node_list):
|
||||||
if node.nodeName == 'notice':
|
if node.nodeName == 'notice':
|
||||||
if self._notice is not None:
|
if self._notice is not None:
|
||||||
raise ManifestParseError(
|
raise ManifestParseError(
|
||||||
@ -324,7 +357,7 @@ class XmlManifest(object):
|
|||||||
(self.manifestFile))
|
(self.manifestFile))
|
||||||
self._notice = self._ParseNotice(node)
|
self._notice = self._ParseNotice(node)
|
||||||
|
|
||||||
for node in config.childNodes:
|
for node in itertools.chain(*node_list):
|
||||||
if node.nodeName == 'manifest-server':
|
if node.nodeName == 'manifest-server':
|
||||||
url = self._reqatt(node, 'url')
|
url = self._reqatt(node, 'url')
|
||||||
if self._manifest_server is not None:
|
if self._manifest_server is not None:
|
||||||
@ -333,7 +366,7 @@ class XmlManifest(object):
|
|||||||
(self.manifestFile))
|
(self.manifestFile))
|
||||||
self._manifest_server = url
|
self._manifest_server = url
|
||||||
|
|
||||||
for node in config.childNodes:
|
for node in itertools.chain(*node_list):
|
||||||
if node.nodeName == 'project':
|
if node.nodeName == 'project':
|
||||||
project = self._ParseProject(node)
|
project = self._ParseProject(node)
|
||||||
if self._projects.get(project.name):
|
if self._projects.get(project.name):
|
||||||
@ -341,8 +374,6 @@ class XmlManifest(object):
|
|||||||
'duplicate project %s in %s' %
|
'duplicate project %s in %s' %
|
||||||
(project.name, self.manifestFile))
|
(project.name, self.manifestFile))
|
||||||
self._projects[project.name] = project
|
self._projects[project.name] = project
|
||||||
|
|
||||||
for node in config.childNodes:
|
|
||||||
if node.nodeName == 'repo-hooks':
|
if node.nodeName == 'repo-hooks':
|
||||||
# Get the name of the project and the (space-separated) list of enabled.
|
# Get the name of the project and the (space-separated) list of enabled.
|
||||||
repo_hooks_project = self._reqatt(node, 'in-project')
|
repo_hooks_project = self._reqatt(node, 'in-project')
|
||||||
@ -364,6 +395,20 @@ class XmlManifest(object):
|
|||||||
|
|
||||||
# Store the enabled hooks in the Project object.
|
# Store the enabled hooks in the Project object.
|
||||||
self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks
|
self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks
|
||||||
|
if node.nodeName == 'remove-project':
|
||||||
|
name = self._reqatt(node, 'name')
|
||||||
|
try:
|
||||||
|
del self._projects[name]
|
||||||
|
except KeyError:
|
||||||
|
raise ManifestParseError(
|
||||||
|
'project %s not found' %
|
||||||
|
(name))
|
||||||
|
|
||||||
|
# If the manifest removes the hooks project, treat it as if it deleted
|
||||||
|
# the repo-hooks element too.
|
||||||
|
if self._repo_hooks_project and (self._repo_hooks_project.name == name):
|
||||||
|
self._repo_hooks_project = None
|
||||||
|
|
||||||
|
|
||||||
def _AddMetaProjectMirror(self, m):
|
def _AddMetaProjectMirror(self, m):
|
||||||
name = None
|
name = None
|
||||||
@ -422,11 +467,18 @@ class XmlManifest(object):
|
|||||||
d.revisionExpr = node.getAttribute('revision')
|
d.revisionExpr = node.getAttribute('revision')
|
||||||
if d.revisionExpr == '':
|
if d.revisionExpr == '':
|
||||||
d.revisionExpr = None
|
d.revisionExpr = None
|
||||||
|
|
||||||
sync_j = node.getAttribute('sync-j')
|
sync_j = node.getAttribute('sync-j')
|
||||||
if sync_j == '' or sync_j is None:
|
if sync_j == '' or sync_j is None:
|
||||||
d.sync_j = 1
|
d.sync_j = 1
|
||||||
else:
|
else:
|
||||||
d.sync_j = int(sync_j)
|
d.sync_j = int(sync_j)
|
||||||
|
|
||||||
|
sync_c = node.getAttribute('sync-c')
|
||||||
|
if not sync_c:
|
||||||
|
d.sync_c = False
|
||||||
|
else:
|
||||||
|
d.sync_c = sync_c.lower() in ("yes", "true", "1")
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _ParseNotice(self, node):
|
def _ParseNotice(self, node):
|
||||||
@ -504,6 +556,19 @@ class XmlManifest(object):
|
|||||||
else:
|
else:
|
||||||
rebase = rebase.lower() in ("yes", "true", "1")
|
rebase = rebase.lower() in ("yes", "true", "1")
|
||||||
|
|
||||||
|
sync_c = node.getAttribute('sync-c')
|
||||||
|
if not sync_c:
|
||||||
|
sync_c = False
|
||||||
|
else:
|
||||||
|
sync_c = sync_c.lower() in ("yes", "true", "1")
|
||||||
|
|
||||||
|
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:
|
if self.IsMirror:
|
||||||
relpath = None
|
relpath = None
|
||||||
worktree = None
|
worktree = None
|
||||||
@ -520,11 +585,15 @@ class XmlManifest(object):
|
|||||||
relpath = path,
|
relpath = path,
|
||||||
revisionExpr = revisionExpr,
|
revisionExpr = revisionExpr,
|
||||||
revisionId = None,
|
revisionId = None,
|
||||||
rebase = rebase)
|
rebase = rebase,
|
||||||
|
groups = groups,
|
||||||
|
sync_c = sync_c)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@ -536,6 +605,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:
|
||||||
|
107
project.py
107
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):
|
||||||
@ -504,7 +509,9 @@ class Project(object):
|
|||||||
relpath,
|
relpath,
|
||||||
revisionExpr,
|
revisionExpr,
|
||||||
revisionId,
|
revisionId,
|
||||||
rebase = True):
|
rebase = True,
|
||||||
|
groups = None,
|
||||||
|
sync_c = False):
|
||||||
self.manifest = manifest
|
self.manifest = manifest
|
||||||
self.name = name
|
self.name = name
|
||||||
self.remote = remote
|
self.remote = remote
|
||||||
@ -524,9 +531,12 @@ class Project(object):
|
|||||||
self.revisionId = revisionId
|
self.revisionId = revisionId
|
||||||
|
|
||||||
self.rebase = rebase
|
self.rebase = rebase
|
||||||
|
self.groups = groups
|
||||||
|
self.sync_c = sync_c
|
||||||
|
|
||||||
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)
|
||||||
@ -645,6 +655,27 @@ class Project(object):
|
|||||||
|
|
||||||
return heads
|
return heads
|
||||||
|
|
||||||
|
def MatchesGroups(self, manifest_groups):
|
||||||
|
"""Returns true if the manifest groups specified at init should cause
|
||||||
|
this project to be synced.
|
||||||
|
Prefixing a manifest group with "-" inverts the meaning of a group.
|
||||||
|
All projects are implicitly labelled with "default".
|
||||||
|
|
||||||
|
labels are resolved in order. In the example case of
|
||||||
|
project_groups: "default,group1,group2"
|
||||||
|
manifest_groups: "-group1,group2"
|
||||||
|
the project will be matched.
|
||||||
|
"""
|
||||||
|
if self.groups is None:
|
||||||
|
return True
|
||||||
|
matched = False
|
||||||
|
for group in manifest_groups:
|
||||||
|
if group.startswith('-') and group[1:] in self.groups:
|
||||||
|
matched = False
|
||||||
|
elif group in self.groups:
|
||||||
|
matched = True
|
||||||
|
|
||||||
|
return matched
|
||||||
|
|
||||||
## Status Display ##
|
## Status Display ##
|
||||||
|
|
||||||
@ -749,7 +780,7 @@ class Project(object):
|
|||||||
|
|
||||||
return 'DIRTY'
|
return 'DIRTY'
|
||||||
|
|
||||||
def PrintWorkTreeDiff(self):
|
def PrintWorkTreeDiff(self, absolute_paths=False):
|
||||||
"""Prints the status of the repository to stdout.
|
"""Prints the status of the repository to stdout.
|
||||||
"""
|
"""
|
||||||
out = DiffColoring(self.config)
|
out = DiffColoring(self.config)
|
||||||
@ -757,6 +788,9 @@ class Project(object):
|
|||||||
if out.is_on:
|
if out.is_on:
|
||||||
cmd.append('--color')
|
cmd.append('--color')
|
||||||
cmd.append(HEAD)
|
cmd.append(HEAD)
|
||||||
|
if absolute_paths:
|
||||||
|
cmd.append('--src-prefix=a/%s/' % self.relpath)
|
||||||
|
cmd.append('--dst-prefix=b/%s/' % self.relpath)
|
||||||
cmd.append('--')
|
cmd.append('--')
|
||||||
p = GitCommand(self,
|
p = GitCommand(self,
|
||||||
cmd,
|
cmd,
|
||||||
@ -934,6 +968,15 @@ class Project(object):
|
|||||||
and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
|
and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
|
||||||
is_new = False
|
is_new = False
|
||||||
|
|
||||||
|
if not current_branch_only:
|
||||||
|
if self.sync_c:
|
||||||
|
current_branch_only = True
|
||||||
|
elif not self.manifest._loaded:
|
||||||
|
# Manifest cannot check defaults until it syncs.
|
||||||
|
current_branch_only = False
|
||||||
|
elif self.manifest.default.sync_c:
|
||||||
|
current_branch_only = True
|
||||||
|
|
||||||
if not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
|
if not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
|
||||||
current_branch_only=current_branch_only):
|
current_branch_only=current_branch_only):
|
||||||
return False
|
return False
|
||||||
@ -1001,12 +1044,15 @@ class Project(object):
|
|||||||
|
|
||||||
if head == revid:
|
if head == revid:
|
||||||
# No changes; don't do anything further.
|
# No changes; don't do anything further.
|
||||||
|
# Except if the head needs to be detached
|
||||||
#
|
#
|
||||||
return
|
if not syncbuf.detach_head:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
lost = self._revlist(not_rev(revid), HEAD)
|
||||||
|
if lost:
|
||||||
|
syncbuf.info(self, "discarding %d commits", len(lost))
|
||||||
|
|
||||||
lost = self._revlist(not_rev(revid), HEAD)
|
|
||||||
if lost:
|
|
||||||
syncbuf.info(self, "discarding %d commits", len(lost))
|
|
||||||
try:
|
try:
|
||||||
self._Checkout(revid, quiet=True)
|
self._Checkout(revid, quiet=True)
|
||||||
except GitError, e:
|
except GitError, e:
|
||||||
@ -1131,6 +1177,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.
|
||||||
"""
|
"""
|
||||||
@ -1352,9 +1401,11 @@ class Project(object):
|
|||||||
|
|
||||||
if is_sha1 or tag_name is not None:
|
if is_sha1 or tag_name is not None:
|
||||||
try:
|
try:
|
||||||
self.GetRevisionId()
|
# if revision (sha or tag) is not present then following function
|
||||||
|
# throws an error.
|
||||||
|
self.bare_git.rev_parse('--verify', '%s^0' % self.revisionExpr)
|
||||||
return True
|
return True
|
||||||
except ManifestInvalidRevisionError:
|
except GitError:
|
||||||
# There is no such persistent revision. We have to fetch it.
|
# There is no such persistent revision. We have to fetch it.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -1599,6 +1650,23 @@ class Project(object):
|
|||||||
if self._allrefs:
|
if self._allrefs:
|
||||||
raise GitError('%s checkout %s ' % (self.name, rev))
|
raise GitError('%s checkout %s ' % (self.name, rev))
|
||||||
|
|
||||||
|
def _CherryPick(self, rev, quiet=False):
|
||||||
|
cmd = ['cherry-pick']
|
||||||
|
cmd.append(rev)
|
||||||
|
cmd.append('--')
|
||||||
|
if GitCommand(self, cmd).Wait() != 0:
|
||||||
|
if self._allrefs:
|
||||||
|
raise GitError('%s cherry-pick %s ' % (self.name, rev))
|
||||||
|
|
||||||
|
def _Revert(self, rev, quiet=False):
|
||||||
|
cmd = ['revert']
|
||||||
|
cmd.append('--no-edit')
|
||||||
|
cmd.append(rev)
|
||||||
|
cmd.append('--')
|
||||||
|
if GitCommand(self, cmd).Wait() != 0:
|
||||||
|
if self._allrefs:
|
||||||
|
raise GitError('%s revert %s ' % (self.name, rev))
|
||||||
|
|
||||||
def _ResetHard(self, rev, quiet=True):
|
def _ResetHard(self, rev, quiet=True):
|
||||||
cmd = ['reset', '--hard']
|
cmd = ['reset', '--hard']
|
||||||
if quiet:
|
if quiet:
|
||||||
@ -1615,8 +1683,10 @@ class Project(object):
|
|||||||
if GitCommand(self, cmd).Wait() != 0:
|
if GitCommand(self, cmd).Wait() != 0:
|
||||||
raise GitError('%s rebase %s ' % (self.name, upstream))
|
raise GitError('%s rebase %s ' % (self.name, upstream))
|
||||||
|
|
||||||
def _FastForward(self, head):
|
def _FastForward(self, head, ffonly=False):
|
||||||
cmd = ['merge', head]
|
cmd = ['merge', head]
|
||||||
|
if ffonly:
|
||||||
|
cmd.append("--ff-only")
|
||||||
if GitCommand(self, cmd).Wait() != 0:
|
if GitCommand(self, cmd).Wait() != 0:
|
||||||
raise GitError('%s merge %s ' % (self.name, head))
|
raise GitError('%s merge %s ' % (self.name, head))
|
||||||
|
|
||||||
@ -2088,7 +2158,8 @@ class MetaProject(Project):
|
|||||||
remote = RemoteSpec('origin'),
|
remote = RemoteSpec('origin'),
|
||||||
relpath = '.repo/%s' % name,
|
relpath = '.repo/%s' % name,
|
||||||
revisionExpr = 'refs/heads/master',
|
revisionExpr = 'refs/heads/master',
|
||||||
revisionId = None)
|
revisionId = None,
|
||||||
|
groups = None)
|
||||||
|
|
||||||
def PreSync(self):
|
def PreSync(self):
|
||||||
if self.Exists:
|
if self.Exists:
|
||||||
@ -2099,6 +2170,22 @@ class MetaProject(Project):
|
|||||||
self.revisionExpr = base
|
self.revisionExpr = base
|
||||||
self.revisionId = None
|
self.revisionId = None
|
||||||
|
|
||||||
|
def MetaBranchSwitch(self, target):
|
||||||
|
""" Prepare MetaProject for manifest branch switch
|
||||||
|
"""
|
||||||
|
|
||||||
|
# detach and delete manifest branch, allowing a new
|
||||||
|
# branch to take over
|
||||||
|
syncbuf = SyncBuffer(self.config, detach_head = True)
|
||||||
|
self.Sync_LocalHalf(syncbuf)
|
||||||
|
syncbuf.Finish()
|
||||||
|
|
||||||
|
return GitCommand(self,
|
||||||
|
['branch', '-D', 'default'],
|
||||||
|
capture_stdout = True,
|
||||||
|
capture_stderr = True).Wait() == 0
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def LastFetch(self):
|
def LastFetch(self):
|
||||||
try:
|
try:
|
||||||
|
25
repo
25
repo
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## repo default configuration
|
## repo default configuration
|
||||||
##
|
##
|
||||||
REPO_URL='https://code.google.com/p/git-repo/'
|
REPO_URL='https://gerrit.googlesource.com/git-repo'
|
||||||
REPO_REV='stable'
|
REPO_REV='stable'
|
||||||
|
|
||||||
# Copyright (C) 2008 Google Inc.
|
# Copyright (C) 2008 Google Inc.
|
||||||
@ -28,7 +28,7 @@ if __name__ == '__main__':
|
|||||||
del magic
|
del magic
|
||||||
|
|
||||||
# increment this whenever we make important changes to this script
|
# increment this whenever we make important changes to this script
|
||||||
VERSION = (1, 14)
|
VERSION = (1, 17)
|
||||||
|
|
||||||
# increment this if the MAINTAINER_KEYS block is modified
|
# increment this if the MAINTAINER_KEYS block is modified
|
||||||
KEYRING_VERSION = (1,0)
|
KEYRING_VERSION = (1,0)
|
||||||
@ -125,6 +125,15 @@ group.add_option('--reference',
|
|||||||
group.add_option('--depth', type='int', default=None,
|
group.add_option('--depth', type='int', default=None,
|
||||||
dest='depth',
|
dest='depth',
|
||||||
help='create a shallow clone with given depth; see git clone')
|
help='create a shallow clone with given depth; see git clone')
|
||||||
|
group.add_option('-g', '--groups',
|
||||||
|
dest='groups', default='default',
|
||||||
|
help='restrict manifest projects to ones with a specified group',
|
||||||
|
metavar='GROUP')
|
||||||
|
group.add_option('-p', '--platform',
|
||||||
|
dest='platform', default="auto",
|
||||||
|
help='restrict manifest projects to ones with a specified'
|
||||||
|
'platform group [auto|all|none|linux|darwin|...]',
|
||||||
|
metavar='PLATFORM')
|
||||||
|
|
||||||
|
|
||||||
# Tool
|
# Tool
|
||||||
@ -211,7 +220,17 @@ def _Init(args):
|
|||||||
|
|
||||||
def _CheckGitVersion():
|
def _CheckGitVersion():
|
||||||
cmd = [GIT, '--version']
|
cmd = [GIT, '--version']
|
||||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
try:
|
||||||
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||||
|
except OSError, e:
|
||||||
|
print >>sys.stderr
|
||||||
|
print >>sys.stderr, "fatal: '%s' is not available" % GIT
|
||||||
|
print >>sys.stderr, 'fatal: %s' % e
|
||||||
|
print >>sys.stderr
|
||||||
|
print >>sys.stderr, 'Please make sure %s is installed'\
|
||||||
|
' and in your path.' % GIT
|
||||||
|
raise CloneFailure()
|
||||||
|
|
||||||
ver_str = proc.stdout.read().strip()
|
ver_str = proc.stdout.read().strip()
|
||||||
proc.stdout.close()
|
proc.stdout.close()
|
||||||
proc.wait()
|
proc.wait()
|
||||||
|
@ -20,8 +20,21 @@ class Diff(PagedCommand):
|
|||||||
helpSummary = "Show changes between commit and working tree"
|
helpSummary = "Show changes between commit and working tree"
|
||||||
helpUsage = """
|
helpUsage = """
|
||||||
%prog [<project>...]
|
%prog [<project>...]
|
||||||
|
|
||||||
|
The -u option causes '%prog' to generate diff output with file paths
|
||||||
|
relative to the repository root, so the output can be applied
|
||||||
|
to the Unix 'patch' command.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def _Options(self, p):
|
||||||
|
def cmd(option, opt_str, value, parser):
|
||||||
|
setattr(parser.values, option.dest, list(parser.rargs))
|
||||||
|
while parser.rargs:
|
||||||
|
del parser.rargs[0]
|
||||||
|
p.add_option('-u', '--absolute',
|
||||||
|
dest='absolute', action='store_true',
|
||||||
|
help='Paths are relative to the repository root')
|
||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
for project in self.GetProjects(args):
|
for project in self.GetProjects(args):
|
||||||
project.PrintWorkTreeDiff()
|
project.PrintWorkTreeDiff(opt.absolute)
|
||||||
|
@ -33,7 +33,15 @@ makes it available in your project's local working directory.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def _Options(self, p):
|
def _Options(self, p):
|
||||||
pass
|
p.add_option('-c','--cherry-pick',
|
||||||
|
dest='cherrypick', action='store_true',
|
||||||
|
help="cherry-pick instead of checkout")
|
||||||
|
p.add_option('-r','--revert',
|
||||||
|
dest='revert', action='store_true',
|
||||||
|
help="revert instead of checkout")
|
||||||
|
p.add_option('-f','--ff-only',
|
||||||
|
dest='ffonly', action='store_true',
|
||||||
|
help="force fast-forward merge")
|
||||||
|
|
||||||
def _ParseChangeIds(self, args):
|
def _ParseChangeIds(self, args):
|
||||||
if not args:
|
if not args:
|
||||||
@ -66,7 +74,7 @@ makes it available in your project's local working directory.
|
|||||||
% (project.name, change_id, ps_id)
|
% (project.name, change_id, ps_id)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not dl.commits:
|
if not opt.revert and not dl.commits:
|
||||||
print >>sys.stderr, \
|
print >>sys.stderr, \
|
||||||
'[%s] change %d/%d has already been merged' \
|
'[%s] change %d/%d has already been merged' \
|
||||||
% (project.name, change_id, ps_id)
|
% (project.name, change_id, ps_id)
|
||||||
@ -78,4 +86,11 @@ makes it available in your project's local working directory.
|
|||||||
% (project.name, change_id, ps_id, len(dl.commits))
|
% (project.name, change_id, ps_id, len(dl.commits))
|
||||||
for c in dl.commits:
|
for c in dl.commits:
|
||||||
print >>sys.stderr, ' %s' % (c)
|
print >>sys.stderr, ' %s' % (c)
|
||||||
project._Checkout(dl.commit)
|
if opt.cherrypick:
|
||||||
|
project._CherryPick(dl.commit)
|
||||||
|
elif opt.revert:
|
||||||
|
project._Revert(dl.commit)
|
||||||
|
elif opt.ffonly:
|
||||||
|
project._FastForward(dl.commit, ffonly=True)
|
||||||
|
else:
|
||||||
|
project._Checkout(dl.commit)
|
||||||
|
@ -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)
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -86,6 +88,15 @@ to update the working directory files.
|
|||||||
g.add_option('--depth', type='int', default=None,
|
g.add_option('--depth', type='int', default=None,
|
||||||
dest='depth',
|
dest='depth',
|
||||||
help='create a shallow clone with given depth; see git clone')
|
help='create a shallow clone with given depth; see git clone')
|
||||||
|
g.add_option('-g', '--groups',
|
||||||
|
dest='groups', default='default',
|
||||||
|
help='restrict manifest projects to ones with a specified group',
|
||||||
|
metavar='GROUP')
|
||||||
|
g.add_option('-p', '--platform',
|
||||||
|
dest='platform', default='auto',
|
||||||
|
help='restrict manifest projects to ones with a specified'
|
||||||
|
'platform group [auto|all|none|linux|darwin|...]',
|
||||||
|
metavar='PLATFORM')
|
||||||
|
|
||||||
# Tool
|
# Tool
|
||||||
g = p.add_option_group('repo Version options')
|
g = p.add_option_group('repo Version options')
|
||||||
@ -135,6 +146,27 @@ to update the working directory files.
|
|||||||
r.ResetFetch()
|
r.ResetFetch()
|
||||||
r.Save()
|
r.Save()
|
||||||
|
|
||||||
|
groups = re.split('[,\s]+', opt.groups)
|
||||||
|
all_platforms = ['linux', 'darwin']
|
||||||
|
platformize = lambda x: 'platform-' + x
|
||||||
|
if opt.platform == 'auto':
|
||||||
|
if (not opt.mirror and
|
||||||
|
not m.config.GetString('repo.mirror') == 'true'):
|
||||||
|
groups.append(platformize(platform.system().lower()))
|
||||||
|
elif opt.platform == 'all':
|
||||||
|
groups.extend(map(platformize, all_platforms))
|
||||||
|
elif opt.platform in all_platforms:
|
||||||
|
groups.extend(platformize(opt.platform))
|
||||||
|
elif opt.platform != 'none':
|
||||||
|
print >>sys.stderr, 'fatal: invalid platform flag'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
groups = [x for x in groups if x]
|
||||||
|
groupstr = ','.join(groups)
|
||||||
|
if opt.platform == 'auto' and groupstr == 'default,platform-' + platform.system().lower():
|
||||||
|
groupstr = None
|
||||||
|
m.config.SetString('manifest.groups', groupstr)
|
||||||
|
|
||||||
if opt.reference:
|
if opt.reference:
|
||||||
m.config.SetString('repo.reference', opt.reference)
|
m.config.SetString('repo.reference', opt.reference)
|
||||||
|
|
||||||
@ -155,6 +187,9 @@ to update the working directory files.
|
|||||||
shutil.rmtree(m.gitdir)
|
shutil.rmtree(m.gitdir)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if opt.manifest_branch:
|
||||||
|
m.MetaBranchSwitch(opt.manifest_branch)
|
||||||
|
|
||||||
syncbuf = SyncBuffer(m.config)
|
syncbuf = SyncBuffer(m.config)
|
||||||
m.Sync_LocalHalf(syncbuf)
|
m.Sync_LocalHalf(syncbuf)
|
||||||
syncbuf.Finish()
|
syncbuf.Finish()
|
||||||
|
@ -52,6 +52,9 @@ branch but need to incorporate new upstream changes "underneath" them.
|
|||||||
p.add_option('--whitespace',
|
p.add_option('--whitespace',
|
||||||
dest='whitespace', action='store', metavar='WS',
|
dest='whitespace', action='store', metavar='WS',
|
||||||
help='Pass --whitespace to git rebase')
|
help='Pass --whitespace to git rebase')
|
||||||
|
p.add_option('--auto-stash',
|
||||||
|
dest='auto_stash', action='store_true',
|
||||||
|
help='Stash local modifications before starting')
|
||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
all = self.GetProjects(args)
|
all = self.GetProjects(args)
|
||||||
@ -103,5 +106,23 @@ branch but need to incorporate new upstream changes "underneath" them.
|
|||||||
print >>sys.stderr, '# %s: rebasing %s -> %s' % \
|
print >>sys.stderr, '# %s: rebasing %s -> %s' % \
|
||||||
(project.relpath, cb, upbranch.LocalMerge)
|
(project.relpath, cb, upbranch.LocalMerge)
|
||||||
|
|
||||||
|
needs_stash = False
|
||||||
|
if opt.auto_stash:
|
||||||
|
stash_args = ["update-index", "--refresh", "-q"]
|
||||||
|
|
||||||
|
if GitCommand(project, stash_args).Wait() != 0:
|
||||||
|
needs_stash = True
|
||||||
|
# Dirty index, requires stash...
|
||||||
|
stash_args = ["stash"]
|
||||||
|
|
||||||
|
if GitCommand(project, stash_args).Wait() != 0:
|
||||||
|
return -1
|
||||||
|
|
||||||
if GitCommand(project, args).Wait() != 0:
|
if GitCommand(project, args).Wait() != 0:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
if needs_stash:
|
||||||
|
stash_args.append('pop')
|
||||||
|
stash_args.append('--quiet')
|
||||||
|
if GitCommand(project, stash_args).Wait() != 0:
|
||||||
|
return -1
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
from command import Command
|
from command import Command
|
||||||
|
from git_config import IsId
|
||||||
from git_command import git
|
from git_command import git
|
||||||
from progress import Progress
|
from progress import Progress
|
||||||
|
|
||||||
@ -56,6 +57,10 @@ revision specified in the manifest.
|
|||||||
pm = Progress('Starting %s' % nb, len(all))
|
pm = Progress('Starting %s' % nb, len(all))
|
||||||
for project in all:
|
for project in all:
|
||||||
pm.update()
|
pm.update()
|
||||||
|
# If the current revision is a specific SHA1 then we can't push back
|
||||||
|
# to it so substitute the manifest default revision instead.
|
||||||
|
if IsId(project.revisionExpr):
|
||||||
|
project.revisionExpr = self.manifest.default.revisionExpr
|
||||||
if not project.StartBranch(nb):
|
if not project.StartBranch(nb):
|
||||||
err.append(project)
|
err.append(project)
|
||||||
pm.end()
|
pm.end()
|
||||||
|
@ -111,14 +111,21 @@ the following meanings:
|
|||||||
threads_and_output = []
|
threads_and_output = []
|
||||||
for project in all:
|
for project in all:
|
||||||
sem.acquire()
|
sem.acquire()
|
||||||
output = StringIO.StringIO()
|
|
||||||
|
class BufList(StringIO.StringIO):
|
||||||
|
def dump(self, ostream):
|
||||||
|
for entry in self.buflist:
|
||||||
|
ostream.write(entry)
|
||||||
|
|
||||||
|
output = BufList()
|
||||||
|
|
||||||
t = _threading.Thread(target=self._StatusHelper,
|
t = _threading.Thread(target=self._StatusHelper,
|
||||||
args=(project, counter, sem, output))
|
args=(project, counter, sem, output))
|
||||||
threads_and_output.append((t, output))
|
threads_and_output.append((t, output))
|
||||||
t.start()
|
t.start()
|
||||||
for (t, output) in threads_and_output:
|
for (t, output) in threads_and_output:
|
||||||
t.join()
|
t.join()
|
||||||
sys.stdout.write(output.getvalue())
|
output.dump(sys.stdout)
|
||||||
output.close()
|
output.close()
|
||||||
if len(all) == counter.next():
|
if len(all) == counter.next():
|
||||||
print 'nothing to commit (working directory clean)'
|
print 'nothing to commit (working directory clean)'
|
||||||
|
@ -277,7 +277,7 @@ later is required to fix a server side protocol bug.
|
|||||||
|
|
||||||
def UpdateProjectList(self):
|
def UpdateProjectList(self):
|
||||||
new_project_paths = []
|
new_project_paths = []
|
||||||
for project in self.manifest.projects.values():
|
for project in self.GetProjects(None, missing_ok=True):
|
||||||
if project.relpath:
|
if project.relpath:
|
||||||
new_project_paths.append(project.relpath)
|
new_project_paths.append(project.relpath)
|
||||||
file_name = 'project.list'
|
file_name = 'project.list'
|
||||||
@ -306,7 +306,8 @@ later is required to fix a server side protocol bug.
|
|||||||
worktree = os.path.join(self.manifest.topdir, path),
|
worktree = os.path.join(self.manifest.topdir, path),
|
||||||
relpath = path,
|
relpath = path,
|
||||||
revisionExpr = 'HEAD',
|
revisionExpr = 'HEAD',
|
||||||
revisionId = None)
|
revisionId = None,
|
||||||
|
groups = None)
|
||||||
|
|
||||||
if project.IsDirty():
|
if project.IsDirty():
|
||||||
print >>sys.stderr, 'error: Cannot remove project "%s": \
|
print >>sys.stderr, 'error: Cannot remove project "%s": \
|
||||||
|
@ -103,6 +103,14 @@ or in the .git/config within the project. For example:
|
|||||||
autoupload = true
|
autoupload = true
|
||||||
autocopy = johndoe@company.com,my-team-alias@company.com
|
autocopy = johndoe@company.com,my-team-alias@company.com
|
||||||
|
|
||||||
|
review.URL.uploadtopic:
|
||||||
|
|
||||||
|
To add a topic branch whenever uploading a commit, you can set a
|
||||||
|
per-project or global Git option to do so. If review.URL.uploadtopic
|
||||||
|
is set to "true" then repo will assume you always want the equivalent
|
||||||
|
of the -t option to the repo command. If unset or set to "false" then
|
||||||
|
repo will make use of only the command line option.
|
||||||
|
|
||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -123,6 +131,9 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
|||||||
p.add_option('--br',
|
p.add_option('--br',
|
||||||
type='string', action='store', dest='branch',
|
type='string', action='store', dest='branch',
|
||||||
help='Branch to upload.')
|
help='Branch to upload.')
|
||||||
|
p.add_option('--cbr', '--current-branch',
|
||||||
|
dest='current_branch', action='store_true',
|
||||||
|
help='Upload current git branch.')
|
||||||
|
|
||||||
# Options relating to upload hook. Note that verify and no-verify are NOT
|
# Options relating to upload hook. Note that verify and no-verify are NOT
|
||||||
# opposites of each other, which is why they store to different locations.
|
# opposites of each other, which is why they store to different locations.
|
||||||
@ -308,6 +319,11 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
|||||||
branch.error = 'User aborted'
|
branch.error = 'User aborted'
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Check if topic branches should be sent to the server during upload
|
||||||
|
if opt.auto_topic is not True:
|
||||||
|
key = 'review.%s.uploadtopic' % branch.project.remote.review
|
||||||
|
opt.auto_topic = branch.project.config.GetBoolean(key)
|
||||||
|
|
||||||
branch.UploadForReview(people, auto_topic=opt.auto_topic)
|
branch.UploadForReview(people, auto_topic=opt.auto_topic)
|
||||||
branch.uploaded = True
|
branch.uploaded = True
|
||||||
except UploadError, e:
|
except UploadError, e:
|
||||||
@ -351,7 +367,11 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
|||||||
branch = opt.branch
|
branch = opt.branch
|
||||||
|
|
||||||
for project in project_list:
|
for project in project_list:
|
||||||
avail = project.GetUploadableBranches(branch)
|
if opt.current_branch:
|
||||||
|
cbr = project.CurrentBranch
|
||||||
|
avail = [project.GetUploadableBranch(cbr)] if cbr else None
|
||||||
|
else:
|
||||||
|
avail = project.GetUploadableBranches(branch)
|
||||||
if avail:
|
if avail:
|
||||||
pending.append((project, avail))
|
pending.append((project, avail))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user