Index: recipe_engine/fetch.py |
diff --git a/recipe_engine/fetch.py b/recipe_engine/fetch.py |
index e67c137c183d837b6c8bc4e952b07db7e519dbfd..e237b7948b59fcff0f652fd59db053cd206349b0 100644 |
--- a/recipe_engine/fetch.py |
+++ b/recipe_engine/fetch.py |
@@ -49,89 +49,97 @@ def _run_git(checkout_dir, *args): |
return subprocess42.check_output(cmd) |
-def ensure_git_checkout(repo, revision, checkout_dir, allow_fetch): |
- """Fetches given |repo| at |revision| to |checkout_dir| using git. |
- |
- Network operations are performed only if |allow_fetch| is True. |
- """ |
- logging.info('Freshening repository %s in %s', repo, checkout_dir) |
- |
- if not os.path.isdir(checkout_dir): |
- if not allow_fetch: |
- raise FetchNotAllowedError( |
- 'need to clone %s but fetch not allowed' % repo) |
- _run_git(None, 'clone', '-q', repo, checkout_dir) |
- elif not os.path.isdir(os.path.join(checkout_dir, '.git')): |
- raise UncleanFilesystemError( |
- '%s exists but is not a git repo' % checkout_dir) |
- |
- actual_origin = _run_git(checkout_dir, 'config', 'remote.origin.url').strip() |
- if actual_origin != repo: |
- raise UncleanFilesystemError( |
- ('workdir %r exists but uses a different origin url %r ' |
- 'than requested %r') % (checkout_dir, actual_origin, repo)) |
- |
- try: |
- _run_git(checkout_dir, 'rev-parse', '-q', '--verify', |
- '%s^{commit}' % revision) |
- except subprocess42.CalledProcessError: |
+class Backend(object): |
+ def checkout(self, repo, revision, checkout_dir, allow_fetch): |
+ """Checks out given |repo| at |revision| to |checkout_dir|. |
+ |
+ Network operations are performed only if |allow_fetch| is True. |
+ """ |
+ raise NotImplementedError() |
+ |
+ |
+class GitBackend(Backend): |
+ """GitBackend uses a local git checkout.""" |
+ |
+ def checkout(self, repo, revision, checkout_dir, allow_fetch): |
+ logging.info('Freshening repository %s in %s', repo, checkout_dir) |
+ |
+ if not os.path.isdir(checkout_dir): |
+ if not allow_fetch: |
+ raise FetchNotAllowedError( |
+ 'need to clone %s but fetch not allowed' % repo) |
+ _run_git(None, 'clone', '-q', repo, checkout_dir) |
+ elif not os.path.isdir(os.path.join(checkout_dir, '.git')): |
+ raise UncleanFilesystemError( |
+ '%s exists but is not a git repo' % checkout_dir) |
+ |
+ actual_origin = _run_git( |
+ checkout_dir, 'config', 'remote.origin.url').strip() |
+ if actual_origin != repo: |
+ raise UncleanFilesystemError( |
+ ('workdir %r exists but uses a different origin url %r ' |
+ 'than requested %r') % (checkout_dir, actual_origin, repo)) |
+ |
+ try: |
+ _run_git(checkout_dir, 'rev-parse', '-q', '--verify', |
+ '%s^{commit}' % revision) |
+ except subprocess42.CalledProcessError: |
+ if not allow_fetch: |
+ raise FetchNotAllowedError( |
+ 'need to fetch %s but fetch not allowed' % repo) |
+ _run_git(checkout_dir, 'fetch') |
+ _run_git(checkout_dir, 'reset', '-q', '--hard', revision) |
+ |
+ |
+class GitilesBackend(Backend): |
+ """GitilesBackend uses a repo served by Gitiles.""" |
+ |
+ def checkout(self, repo, revision, checkout_dir, allow_fetch): |
+ logging.info('Freshening repository %s in %s', repo, checkout_dir) |
+ |
+ # TODO(phajdan.jr): implement caching. |
if not allow_fetch: |
raise FetchNotAllowedError( |
- 'need to fetch %s but fetch not allowed' % repo) |
- _run_git(checkout_dir, 'fetch') |
- _run_git(checkout_dir, 'reset', '-q', '--hard', revision) |
- |
- |
-def ensure_gitiles_checkout(repo, revision, checkout_dir, allow_fetch): |
- """Fetches given |repo| at |revision| to |checkout_dir| using gitiles. |
- |
- Network operations are performed only if |allow_fetch| is True. |
- """ |
- logging.info('Freshening repository %s in %s', repo, checkout_dir) |
- |
- # TODO(phajdan.jr): implement caching. |
- if not allow_fetch: |
- raise FetchNotAllowedError( |
- 'need to download %s from gitiles but fetch not allowed' % repo) |
- |
- rev_url = '%s/+/%s?format=JSON' % (repo, requests.utils.quote(revision)) |
- logging.info('fetching %s', rev_url) |
- rev_raw = requests.get(rev_url).text |
- if not rev_raw.startswith(')]}\'\n'): |
- raise FetchError('Unexpected gitiles response: %s' % rev_raw) |
- rev_json = json.loads(rev_raw.split('\n', 1)[1]) |
- orig_revision = revision |
- revision = rev_json['commit'] |
- logging.info('resolved %s to %s', orig_revision, revision) |
- |
- shutil.rmtree(checkout_dir, ignore_errors=True) |
- |
- recipes_cfg_url = '%s/+/%s/infra/config/recipes.cfg?format=TEXT' % ( |
- repo, requests.utils.quote(revision)) |
- logging.info('fetching %s' % recipes_cfg_url) |
- recipes_cfg_request = requests.get(recipes_cfg_url) |
- recipes_cfg_text = base64.b64decode(recipes_cfg_request.text) |
- recipes_cfg_proto = package_pb2.Package() |
- text_format.Merge(recipes_cfg_text, recipes_cfg_proto) |
- recipes_path_rel = recipes_cfg_proto.recipes_path |
- |
- # Re-create recipes.cfg in |checkout_dir| so that the repo's recipes.py |
- # can look it up. |
- recipes_cfg_path = os.path.join( |
- checkout_dir, 'infra', 'config', 'recipes.cfg') |
- os.makedirs(os.path.dirname(recipes_cfg_path)) |
- with open(recipes_cfg_path, 'w') as f: |
- f.write(recipes_cfg_text) |
- |
- recipes_path = os.path.join(checkout_dir, recipes_path_rel) |
- os.makedirs(recipes_path) |
- |
- archive_url = '%s/+archive/%s/%s.tar.gz' % ( |
- repo, requests.utils.quote(revision), recipes_path_rel) |
- logging.info('fetching %s' % archive_url) |
- archive_request = requests.get(archive_url) |
- with tempfile.NamedTemporaryFile() as f: |
- f.write(archive_request.content) |
- f.flush() |
- with tarfile.open(f.name) as archive_tarfile: |
- archive_tarfile.extractall(recipes_path) |
+ 'need to download %s from gitiles but fetch not allowed' % repo) |
+ |
+ rev_url = '%s/+/%s?format=JSON' % (repo, requests.utils.quote(revision)) |
+ logging.info('fetching %s', rev_url) |
+ rev_raw = requests.get(rev_url).text |
+ if not rev_raw.startswith(')]}\'\n'): |
+ raise FetchError('Unexpected gitiles response: %s' % rev_raw) |
+ rev_json = json.loads(rev_raw.split('\n', 1)[1]) |
+ orig_revision = revision |
+ revision = rev_json['commit'] |
+ logging.info('resolved %s to %s', orig_revision, revision) |
+ |
+ shutil.rmtree(checkout_dir, ignore_errors=True) |
+ |
+ recipes_cfg_url = '%s/+/%s/infra/config/recipes.cfg?format=TEXT' % ( |
+ repo, requests.utils.quote(revision)) |
+ logging.info('fetching %s' % recipes_cfg_url) |
+ recipes_cfg_request = requests.get(recipes_cfg_url) |
+ recipes_cfg_text = base64.b64decode(recipes_cfg_request.text) |
+ recipes_cfg_proto = package_pb2.Package() |
+ text_format.Merge(recipes_cfg_text, recipes_cfg_proto) |
+ recipes_path_rel = recipes_cfg_proto.recipes_path |
+ |
+ # Re-create recipes.cfg in |checkout_dir| so that the repo's recipes.py |
+ # can look it up. |
+ recipes_cfg_path = os.path.join( |
+ checkout_dir, 'infra', 'config', 'recipes.cfg') |
+ os.makedirs(os.path.dirname(recipes_cfg_path)) |
+ with open(recipes_cfg_path, 'w') as f: |
+ f.write(recipes_cfg_text) |
+ |
+ recipes_path = os.path.join(checkout_dir, recipes_path_rel) |
+ os.makedirs(recipes_path) |
+ |
+ archive_url = '%s/+archive/%s/%s.tar.gz' % ( |
+ repo, requests.utils.quote(revision), recipes_path_rel) |
+ logging.info('fetching %s' % archive_url) |
+ archive_request = requests.get(archive_url) |
+ with tempfile.NamedTemporaryFile() as f: |
+ f.write(archive_request.content) |
+ f.flush() |
+ with tarfile.open(f.name) as archive_tarfile: |
+ archive_tarfile.extractall(recipes_path) |