Compare commits

..

2 Commits

Author SHA1 Message Date
5cc6679fb8 Support user supplied custom .repo/local_manifest.xml files
By creating a .repo/local_manifest.xml the user can add extra
projects into their client space, without touching the main
manifest script.

For example:

  $ cat .repo/local_manifest.xml
  <?xml version="1.0" encoding="UTF-8"?>
  <manifest>
   <project path="android-build"
            name="platform/build"
            remote="korg"
            revision="android-1.0" />
  </manifest>

Signed-off-by: Shawn O. Pearce <sop@google.com>
2008-10-23 16:20:14 -07:00
632768bc65 Teach repo how to download changes to the local checkout
Now `repo download . 1402` would download the change numbered 1402
into the current project and check it out for the user, using a
detached HEAD.  `repo sync .` would back out of the change and
return to the upstream version.

Multiple projects can be fetched at once by listing them out on
the command line as different arguments.

Individual patch sets can be selected by adding a '/n' to indicate
the n-th patch set should be downloaded instead of the default of
patch set 1.

Signed-off-by: Shawn O. Pearce <sop@google.com>
2008-10-23 14:43:28 -07:00
3 changed files with 137 additions and 5 deletions

View File

@ -26,6 +26,7 @@ from remote import Remote
from error import ManifestParseError from error import ManifestParseError
MANIFEST_FILE_NAME = 'manifest.xml' MANIFEST_FILE_NAME = 'manifest.xml'
LOCAL_MANIFEST_NAME = 'local_manifest.xml'
class _Default(object): class _Default(object):
"""Project defaults within the manifest.""" """Project defaults within the manifest."""
@ -108,10 +109,20 @@ class Manifest(object):
def _Load(self): def _Load(self):
if not self._loaded: if not self._loaded:
self._ParseManifest() self._ParseManifest(True)
local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME)
if os.path.exists(local):
try:
real = self.manifestFile
self.manifestFile = local
self._ParseManifest(False)
finally:
self.manifestFile = real
self._loaded = True self._loaded = True
def _ParseManifest(self): def _ParseManifest(self, is_root_file):
root = xml.dom.minidom.parse(self.manifestFile) root = xml.dom.minidom.parse(self.manifestFile)
if not root or not root.childNodes: if not root or not root.childNodes:
raise ManifestParseError, \ raise ManifestParseError, \
@ -124,9 +135,10 @@ class Manifest(object):
"no <manifest> in %s" % \ "no <manifest> in %s" % \
self.manifestFile self.manifestFile
self.branch = config.getAttribute('branch') if is_root_file:
if not self.branch: self.branch = config.getAttribute('branch')
self.branch = 'default' if not self.branch:
self.branch = 'default'
for node in config.childNodes: for node in config.childNodes:
if node.nodeName == 'remote': if node.nodeName == 'remote':

View File

@ -45,6 +45,31 @@ def _info(fmt, *args):
def not_rev(r): def not_rev(r):
return '^' + r return '^' + r
class DownloadedChange(object):
_commit_cache = None
def __init__(self, project, base, change_id, ps_id, commit):
self.project = project
self.base = base
self.change_id = change_id
self.ps_id = ps_id
self.commit = commit
@property
def commits(self):
if self._commit_cache is None:
self._commit_cache = self.project.bare_git.rev_list(
'--abbrev=8',
'--abbrev-commit',
'--pretty=oneline',
'--reverse',
'--date-order',
not_rev(self.base),
self.commit,
'--')
return self._commit_cache
class ReviewableBranch(object): class ReviewableBranch(object):
_commit_cache = None _commit_cache = None
@ -612,6 +637,23 @@ class Project(object):
src = os.path.join(self.worktree, src) src = os.path.join(self.worktree, src)
self.copyfiles.append(_CopyFile(src, dest)) self.copyfiles.append(_CopyFile(src, dest))
def DownloadPatchSet(self, change_id, patch_id):
"""Download a single patch set of a single change to FETCH_HEAD.
"""
remote = self.GetRemote(self.remote.name)
cmd = ['fetch', remote.name]
cmd.append('refs/changes/%2.2d/%d/%d' \
% (change_id % 100, change_id, patch_id))
cmd.extend(map(lambda x: str(x), remote.fetch))
if GitCommand(self, cmd, bare=True).Wait() != 0:
return None
return DownloadedChange(self,
remote.ToLocal(self.revision),
change_id,
patch_id,
self.bare_git.rev_parse('FETCH_HEAD'))
## Branch Management ## ## Branch Management ##

78
subcmds/download.py Normal file
View File

@ -0,0 +1,78 @@
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import re
import sys
from command import Command
CHANGE_RE = re.compile(r'^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$')
class Download(Command):
common = True
helpSummary = "Download and checkout a change"
helpUsage = """
%prog {project change[/patchset]}...
"""
helpDescription = """
The '%prog' command downloads a change from the review system and
makes it available in your project's local working directory.
"""
def _Options(self, p):
pass
def _ParseChangeIds(self, args):
to_get = []
project = None
for a in args:
m = CHANGE_RE.match(a)
if m:
if not project:
self.Usage()
chg_id = int(m.group(1))
if m.group(2):
ps_id = int(m.group(2))
else:
ps_id = 1
to_get.append((project, chg_id, ps_id))
else:
project = self.GetProjects([a])[0]
return to_get
def Execute(self, opt, args):
for project, change_id, ps_id in self._ParseChangeIds(args):
dl = project.DownloadPatchSet(change_id, ps_id)
if not dl:
print >>sys.stderr, \
'[%s] change %d/%d not found' \
% (project.name, change_id, ps_id)
sys.exit(1)
if not dl.commits:
print >>sys.stderr, \
'[%s] change %d/%d has already been merged' \
% (project.name, change_id, ps_id)
continue
if len(dl.commits) > 1:
print >>sys.stderr, \
'[%s] %d/%d depends on %d unmerged changes:' \
% (project.name, change_id, ps_id, len(dl.commits))
for c in dl.commits:
print >>sys.stderr, ' %s' % (c)
project._Checkout(dl.commit)