Enable remotes to define their own revision

Some projects use multiple remotes.
In some cases these remotes have different naming conventions.
Add an option to define a revision in the remote configuration.

The `project` revision takes precedence over `remote` and `default`.
The `remote` revision takes precedence over `default`.
The `default` revision acts as a fall back as it originally did.

Change-Id: I2b376160d45d48b0bab840c02a3eef1a1e32cf6d
This commit is contained in:
Anthony King 2014-05-06 11:54:01 +01:00
parent 666d534636
commit 36ea2fb6ee
3 changed files with 28 additions and 9 deletions

View File

@ -35,6 +35,7 @@ following DTD:
<!ATTLIST remote alias CDATA #IMPLIED> <!ATTLIST remote alias CDATA #IMPLIED>
<!ATTLIST remote fetch CDATA #REQUIRED> <!ATTLIST remote fetch CDATA #REQUIRED>
<!ATTLIST remote review CDATA #IMPLIED> <!ATTLIST remote review CDATA #IMPLIED>
<!ATTLIST remote revision CDATA #IMPLIED>
<!ELEMENT default (EMPTY)> <!ELEMENT default (EMPTY)>
<!ATTLIST default remote IDREF #IMPLIED> <!ATTLIST default remote IDREF #IMPLIED>
@ -112,6 +113,10 @@ Attribute `review`: Hostname of the Gerrit server where reviews
are uploaded to by `repo upload`. This attribute is optional; are uploaded to by `repo upload`. This attribute is optional;
if not specified then `repo upload` will not function. if not specified then `repo upload` will not function.
Attribute `revision`: Name of a Git branch (e.g. `master` or
`refs/heads/master`). Remotes with their own revision will override
the default revision.
Element default Element default
--------------- ---------------
@ -208,7 +213,8 @@ to track for this project. Names can be relative to refs/heads
(e.g. just "master") or absolute (e.g. "refs/heads/master"). (e.g. just "master") or absolute (e.g. "refs/heads/master").
Tags and/or explicit SHA-1s should work in theory, but have not 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 remote element is used if applicable, else the default
element is used.
Attribute `dest-branch`: Name of a Git branch (e.g. `master`). Attribute `dest-branch`: Name of a Git branch (e.g. `master`).
When using `repo upload`, changes will be submitted for code When using `repo upload`, changes will be submitted for code

View File

@ -63,12 +63,14 @@ class _XmlRemote(object):
alias=None, alias=None,
fetch=None, fetch=None,
manifestUrl=None, manifestUrl=None,
review=None): review=None,
revision=None):
self.name = name self.name = name
self.fetchUrl = fetch self.fetchUrl = fetch
self.manifestUrl = manifestUrl self.manifestUrl = manifestUrl
self.remoteAlias = alias self.remoteAlias = alias
self.reviewUrl = review self.reviewUrl = review
self.revision = revision
self.resolvedFetchUrl = self._resolveFetchUrl() self.resolvedFetchUrl = self._resolveFetchUrl()
def __eq__(self, other): def __eq__(self, other):
@ -159,6 +161,8 @@ class XmlManifest(object):
e.setAttribute('alias', r.remoteAlias) e.setAttribute('alias', r.remoteAlias)
if r.reviewUrl is not None: if r.reviewUrl is not None:
e.setAttribute('review', r.reviewUrl) e.setAttribute('review', r.reviewUrl)
if r.revision is not None:
e.setAttribute('revision', r.revision)
def Save(self, fd, peg_rev=False, peg_rev_upstream=True): def Save(self, fd, peg_rev=False, peg_rev_upstream=True):
"""Write the current manifest out to the given file descriptor. """Write the current manifest out to the given file descriptor.
@ -240,7 +244,8 @@ class XmlManifest(object):
if d.remote: if d.remote:
remoteName = d.remote.remoteAlias or d.remote.name remoteName = d.remote.remoteAlias or d.remote.name
if not d.remote or p.remote.name != remoteName: if not d.remote or p.remote.name != remoteName:
e.setAttribute('remote', p.remote.name) remoteName = p.remote.name
e.setAttribute('remote', remoteName)
if peg_rev: if peg_rev:
if self.IsMirror: if self.IsMirror:
value = p.bare_git.rev_parse(p.revisionExpr + '^0') value = p.bare_git.rev_parse(p.revisionExpr + '^0')
@ -252,8 +257,10 @@ class XmlManifest(object):
# isn't our value, and the if the default doesn't already have that # isn't our value, and the if the default doesn't already have that
# covered. # covered.
e.setAttribute('upstream', p.revisionExpr) e.setAttribute('upstream', p.revisionExpr)
elif not d.revisionExpr or p.revisionExpr != d.revisionExpr: else:
e.setAttribute('revision', p.revisionExpr) revision = self.remotes[remoteName].revision or d.revisionExpr
if not revision or revision != p.revisionExpr:
e.setAttribute('revision', p.revisionExpr)
for c in p.copyfiles: for c in p.copyfiles:
ce = doc.createElement('copyfile') ce = doc.createElement('copyfile')
@ -592,8 +599,11 @@ class XmlManifest(object):
review = node.getAttribute('review') review = node.getAttribute('review')
if review == '': if review == '':
review = None review = None
revision = node.getAttribute('revision')
if revision == '':
revision = None
manifestUrl = self.manifestProject.config.GetString('remote.origin.url') manifestUrl = self.manifestProject.config.GetString('remote.origin.url')
return _XmlRemote(name, alias, fetch, manifestUrl, review) return _XmlRemote(name, alias, fetch, manifestUrl, review, revision)
def _ParseDefault(self, node): def _ParseDefault(self, node):
""" """
@ -686,7 +696,7 @@ class XmlManifest(object):
raise ManifestParseError("no remote for project %s within %s" % raise ManifestParseError("no remote for project %s within %s" %
(name, self.manifestFile)) (name, self.manifestFile))
revisionExpr = node.getAttribute('revision') revisionExpr = node.getAttribute('revision') or remote.revision
if not revisionExpr: if not revisionExpr:
revisionExpr = self._default.revisionExpr revisionExpr = self._default.revisionExpr
if not revisionExpr: if not revisionExpr:

View File

@ -259,10 +259,12 @@ class RemoteSpec(object):
def __init__(self, def __init__(self,
name, name,
url = None, url = None,
review = None): review = None,
revision = None):
self.name = name self.name = name
self.url = url self.url = url
self.review = review self.review = review
self.revision = revision
class RepoHook(object): class RepoHook(object):
"""A RepoHook contains information about a script to run as a hook. """A RepoHook contains information about a script to run as a hook.
@ -1657,7 +1659,8 @@ class Project(object):
remote = RemoteSpec(self.remote.name, remote = RemoteSpec(self.remote.name,
url = url, url = url,
review = self.remote.review) review = self.remote.review,
revision = self.remote.revision)
subproject = Project(manifest = self.manifest, subproject = Project(manifest = self.manifest,
name = name, name = name,
remote = remote, remote = remote,