Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: recipe_engine/package.py

Issue 1997023002: recipe engine: add remote_run command (Closed) Base URL: https://github.com/luci/recipes-py.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import ast 5 import ast
6 import collections 6 import collections
7 import contextlib 7 import contextlib
8 import copy 8 import copy
9 import difflib 9 import difflib
10 import functools 10 import functools
11 import itertools 11 import itertools
12 import logging 12 import logging
13 import operator 13 import operator
14 import os 14 import os
15 import subprocess 15 import subprocess
16 import sys 16 import sys
17 import tempfile 17 import tempfile
18 18
19 from .third_party.google.protobuf import text_format 19 from .third_party.google.protobuf import text_format
20 from . import package_pb2 20 from . import package_pb2
21 21 from . import fetch
22
23 class UncleanFilesystemError(Exception):
24 pass
25
26
27 class FetchNotAllowedError(Exception):
28 pass
29 22
30 23
31 class InconsistentDependencyGraphError(Exception): 24 class InconsistentDependencyGraphError(Exception):
32 def __init__(self, project_id, specs): 25 def __init__(self, project_id, specs):
33 self.project_id = project_id 26 self.project_id = project_id
34 self.specs = specs 27 self.specs = specs
35 28
36 def __str__(self): 29 def __str__(self):
37 return 'Package specs for %s do not match: %s vs %s' % ( 30 return 'Package specs for %s do not match: %s vs %s' % (
38 project_id, self.specs[0], self.specs[1]) 31 project_id, self.specs[0], self.specs[1])
39 32
40 33
41 class CyclicDependencyError(Exception): 34 class CyclicDependencyError(Exception):
42 pass 35 pass
43 36
44 37
45 def cleanup_pyc(path):
46 """Removes any .pyc files from |path|'s directory tree.
47 This ensures we always use the fresh code.
48 """
49 for root, dirs, files in os.walk(path):
50 for f in files:
51 if f.endswith('.pyc'):
52 os.unlink(os.path.join(root, f))
53
54
55 class InfraRepoConfig(object): 38 class InfraRepoConfig(object):
56 def to_recipes_cfg(self, repo_root): 39 def to_recipes_cfg(self, repo_root):
57 # TODO(luqui): This is not always correct. It can be configured in 40 # TODO(luqui): This is not always correct. It can be configured in
58 # infra/config:refs.cfg. 41 # infra/config:refs.cfg.
59 return os.path.join(repo_root, 'infra', 'config', 'recipes.cfg') 42 return os.path.join(repo_root, 'infra', 'config', 'recipes.cfg')
60 43
61 def from_recipes_cfg(self, recipes_cfg): 44 def from_recipes_cfg(self, recipes_cfg):
62 return os.path.dirname( # <repo root> 45 return os.path.dirname( # <repo root>
63 os.path.dirname( # infra 46 os.path.dirname( # infra
64 os.path.dirname( # config 47 os.path.dirname( # config
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 def run_git(self, context, *args): 199 def run_git(self, context, *args):
217 cmd = [self._git] 200 cmd = [self._git]
218 if context is not None: 201 if context is not None:
219 cmd += ['-C', self._dep_dir(context)] 202 cmd += ['-C', self._dep_dir(context)]
220 cmd += list(args) 203 cmd += list(args)
221 204
222 logging.info('Running: %s', cmd) 205 logging.info('Running: %s', cmd)
223 return subprocess.check_output(cmd) 206 return subprocess.check_output(cmd)
224 207
225 def checkout(self, context): 208 def checkout(self, context):
226 dep_dir = self._dep_dir(context) 209 fetch.fetch_from_git(
227 logging.info('Freshening repository %s', dep_dir) 210 self.repo, self.revision, self._dep_dir(context), context.allow_fetch)
228
229 if not os.path.isdir(dep_dir):
230 if context.allow_fetch:
231 self.run_git(None, 'clone', '-q', self.repo, dep_dir)
232 else:
233 raise FetchNotAllowedError(
234 'need to clone %s but fetch not allowed' % self.repo)
235 elif not os.path.isdir(os.path.join(dep_dir, '.git')):
236 raise UncleanFilesystemError('%s exists but is not a git repo' % dep_dir)
237
238 try:
239 self.run_git(context, 'rev-parse', '-q', '--verify',
240 '%s^{commit}' % self.revision)
241 except subprocess.CalledProcessError:
242 if context.allow_fetch:
243 self.run_git(context, 'fetch')
244 else:
245 raise FetchNotAllowedError(
246 'need to fetch %s but fetch not allowed' % self.repo)
247 self.run_git(context, 'reset', '-q', '--hard', self.revision)
248 cleanup_pyc(dep_dir)
249 211
250 def repo_root(self, context): 212 def repo_root(self, context):
251 return os.path.join(self._dep_dir(context), self.path) 213 return os.path.join(self._dep_dir(context), self.path)
252 214
253 def dump(self): 215 def dump(self):
254 buf = package_pb2.DepSpec( 216 buf = package_pb2.DepSpec(
255 project_id=self.project_id, 217 project_id=self.project_id,
256 url=self.repo, 218 url=self.repo,
257 branch=self.branch, 219 branch=self.branch,
258 revision=self.revision) 220 revision=self.revision)
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 >>> d = { 'x': 1, 'y': 2 } 663 >>> d = { 'x': 1, 'y': 2 }
702 >>> sorted(_updated(d, { 'y': 3, 'z': 4 }).items()) 664 >>> sorted(_updated(d, { 'y': 3, 'z': 4 }).items())
703 [('x', 1), ('y', 3), ('z', 4)] 665 [('x', 1), ('y', 3), ('z', 4)]
704 >>> sorted(d.items()) 666 >>> sorted(d.items())
705 [('x', 1), ('y', 2)] 667 [('x', 1), ('y', 2)]
706 """ 668 """
707 669
708 d = copy.copy(d) 670 d = copy.copy(d)
709 d.update(updates) 671 d.update(updates)
710 return d 672 return d
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698