Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: ensure_dependencies.py

Issue 29408728: Issue 4906 - change cloning in ensure_dependecies (Closed)
Patch Set: Created April 10, 2017, 2:15 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 # This Source Code Form is subject to the terms of the Mozilla Public 3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 6
7 import sys 7 import sys
8 import os 8 import os
9 import posixpath 9 import posixpath
10 import re 10 import re
(...skipping 30 matching lines...) Expand all
41 41
42 SKIP_DEPENDENCY_UPDATES = os.environ.get( 42 SKIP_DEPENDENCY_UPDATES = os.environ.get(
43 'SKIP_DEPENDENCY_UPDATES', '' 43 'SKIP_DEPENDENCY_UPDATES', ''
44 ).lower() not in ('', '0', 'false') 44 ).lower() not in ('', '0', 'false')
45 45
46 46
47 class Mercurial(): 47 class Mercurial():
48 def istype(self, repodir): 48 def istype(self, repodir):
49 return os.path.exists(os.path.join(repodir, '.hg')) 49 return os.path.exists(os.path.join(repodir, '.hg'))
50 50
51 def clone(self, source, target): 51 def clone(self, source, target, revision):
52 if not source.endswith('/'): 52 if not source.endswith('/'):
53 source += '/' 53 source += '/'
54 subprocess.check_call(['hg', 'clone', '--quiet', '--noupdate', source, t arget]) 54 if not os.path.isdir(target):
55 os.makedirs(target)
56 subprocess.check_call(['hg', 'init', target])
57 config_path = os.path.join(target, '.hg', 'hgrc')
58 config = RawConfigParser()
59 config.add_section('paths')
60 config.set('paths', 'default', source)
61 with open(config_path, 'w') as stream:
62 config.write(stream)
63 self.pull(target)
55 64
56 def get_revision_id(self, repo, rev=None): 65 def get_revision_id(self, repo, rev=None):
57 command = ['hg', 'id', '--repository', repo, '--id'] 66 command = ['hg', 'id', '--repository', repo, '--id']
58 if rev: 67 if rev:
59 command.extend(['--rev', rev]) 68 command.extend(['--rev', rev])
60 69
61 # Ignore stderr output and return code here: if revision lookup failed w e 70 # Ignore stderr output and return code here: if revision lookup failed w e
62 # should simply return an empty string. 71 # should simply return an empty string.
63 result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subpro cess.PIPE).communicate()[0] 72 result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subpro cess.PIPE).communicate()[0]
64 return result.strip() 73 return result.strip()
(...skipping 23 matching lines...) Expand all
88 _ensure_line_exists(ignore_path, module) 97 _ensure_line_exists(ignore_path, module)
89 98
90 def postprocess_url(self, url): 99 def postprocess_url(self, url):
91 return url 100 return url
92 101
93 102
94 class Git(): 103 class Git():
95 def istype(self, repodir): 104 def istype(self, repodir):
96 return os.path.exists(os.path.join(repodir, '.git')) 105 return os.path.exists(os.path.join(repodir, '.git'))
97 106
98 def clone(self, source, target): 107 def clone(self, source, target, revision):
99 source = source.rstrip('/') 108 source = source.rstrip('/')
100 if not source.endswith('.git'): 109 if not source.endswith('.git'):
101 source += '.git' 110 source += '.git'
102 subprocess.check_call(['git', 'clone', '--quiet', source, target]) 111 if not os.path.isdir(target):
112 os.makedirs(target)
113 subprocess.check_call(['git', 'init', '--quiet'], cwd=target)
114 subprocess.check_call(['git', 'remote', 'add', 'origin', source], cwd=ta rget)
115 self.pull(target)
116 # Manual call of update here because if the revision is the HEAD of the
117 # repository then update_repo, which is called after this clone method,
118 # cannot understand that checking out is still required and skips it.
119 # As the result there are no files.
120 resolved_revision = self.get_revision_id(target, revision)
121 self.update(target, resolved_revision, revision)
103 122
104 def get_revision_id(self, repo, rev='HEAD'): 123 def get_revision_id(self, repo, rev='HEAD'):
105 command = ['git', 'rev-parse', '--revs-only', rev + '^{commit}'] 124 command = ['git', 'rev-parse', '--revs-only', rev + '^{commit}']
106 return subprocess.check_output(command, cwd=repo).strip() 125 return subprocess.check_output(command, cwd=repo).strip()
107 126
108 def pull(self, repo): 127 def pull(self, repo):
109 # Fetch tracked branches, new tags and the list of available remote bran ches 128 # Fetch tracked branches, new tags and the list of available remote bran ches
110 subprocess.check_call(['git', 'fetch', '--quiet', '--all', '--tags'], cw d=repo) 129 subprocess.check_call(['git', 'fetch', '--quiet', '--all', '--tags'], cw d=repo)
111 # Next we need to ensure all remote branches are tracked 130 # Next we need to ensure all remote branches are tracked
112 newly_tracked = False 131 newly_tracked = False
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 return os.path.join(path, *normpath.split(posixpath.sep)) 257 return os.path.join(path, *normpath.split(posixpath.sep))
239 258
240 259
241 def get_repo_type(repo): 260 def get_repo_type(repo):
242 for name, repotype in repo_types.iteritems(): 261 for name, repotype in repo_types.iteritems():
243 if repotype.istype(repo): 262 if repotype.istype(repo):
244 return name 263 return name
245 return 'hg' 264 return 'hg'
246 265
247 266
248 def ensure_repo(parentrepo, parenttype, target, type, root, sourcename): 267 def ensure_repo(parentrepo, parenttype, target, type, root, sourcename, revision ):
249 if os.path.exists(target): 268 repo = repo_types[type]
269 if repo.istype(target):
250 return 270 return
251 271
252 if SKIP_DEPENDENCY_UPDATES: 272 if SKIP_DEPENDENCY_UPDATES:
253 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, ' 273 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, '
254 '%s not cloned', target) 274 '%s not cloned', target)
255 return 275 return
256 276
257 postprocess_url = repo_types[type].postprocess_url 277 root = repo.postprocess_url(root)
258 root = postprocess_url(root) 278 sourcename = repo.postprocess_url(sourcename)
259 sourcename = postprocess_url(sourcename)
260 279
261 if os.path.exists(root): 280 if os.path.exists(root):
262 url = os.path.join(root, sourcename) 281 url = os.path.join(root, sourcename)
263 else: 282 else:
264 url = urlparse.urljoin(root, sourcename) 283 url = urlparse.urljoin(root, sourcename)
265 284
266 logging.info('Cloning repository %s into %s' % (url, target)) 285 logging.info('Cloning repository %s into %s' % (url, target))
267 repo_types[type].clone(url, target) 286 repo.clone(url, target, revision)
268 repo_types[parenttype].ignore(target, parentrepo) 287 repo_types[parenttype].ignore(target, parentrepo)
269 288
270 289
271 def update_repo(target, type, revision): 290 def update_repo(target, type, revision):
272 resolved_revision = repo_types[type].get_revision_id(target, revision) 291 resolved_revision = repo_types[type].get_revision_id(target, revision)
273 current_revision = repo_types[type].get_revision_id(target) 292 current_revision = repo_types[type].get_revision_id(target)
274 293
275 if resolved_revision != current_revision: 294 if resolved_revision != current_revision:
276 if SKIP_DEPENDENCY_UPDATES: 295 if SKIP_DEPENDENCY_UPDATES:
277 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, ' 296 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, '
(...skipping 17 matching lines...) Expand all
295 if level == 0: 314 if level == 0:
296 logging.warning('No dependencies file in directory %s, nothing to do ...\n%s' % (repodir, USAGE)) 315 logging.warning('No dependencies file in directory %s, nothing to do ...\n%s' % (repodir, USAGE))
297 return 316 return
298 if level >= 10: 317 if level >= 10:
299 logging.warning('Too much subrepository nesting, ignoring %s' % repo) 318 logging.warning('Too much subrepository nesting, ignoring %s' % repo)
300 return 319 return
301 320
302 if overrideroots is not None: 321 if overrideroots is not None:
303 config['_root'] = overrideroots 322 config['_root'] = overrideroots
304 323
305 for dir, sources in config.iteritems(): 324 for dir, sources in config.iteritems():
Wladimir Palant 2017/05/31 11:04:45 IMHO, sorting here should do: for dir, sources
sergei 2017/05/31 13:38:00 Tested, it does work in our case and it is suffici
Sebastian Noack 2017/05/31 14:46:09 Now where I understand the problem, I don't see wh
Wladimir Palant 2017/05/31 15:59:37 Absolutely. This is a classic example where an unn
306 if (dir.startswith('_') or 325 if (dir.startswith('_') or
307 skipdependencies.intersection([s[0] for s in sources if s[0]])): 326 skipdependencies.intersection([s[0] for s in sources if s[0]])):
308 continue 327 continue
309 328
310 target = safe_join(repodir, dir) 329 target = safe_join(repodir, dir)
311 parenttype = get_repo_type(repodir) 330 parenttype = get_repo_type(repodir)
312 _root = config.get('_root', {}) 331 _root = config.get('_root', {})
313 332
314 for key in sources.keys() + _root.keys(): 333 for key in sources.keys() + _root.keys():
315 if key == parenttype or key is None and vcs != '*': 334 if key == parenttype or key is None and vcs != '*':
316 vcs = key 335 vcs = key
317 source, rev = merge_seqs(sources.get('*'), sources.get(vcs)) 336 source, rev = merge_seqs(sources.get('*'), sources.get(vcs))
318 337
319 if not (vcs and source and rev): 338 if not (vcs and source and rev):
320 logging.warning('No valid source / revision found to create %s' % ta rget) 339 logging.warning('No valid source / revision found to create %s' % ta rget)
321 continue 340 continue
322 341
323 ensure_repo(repodir, parenttype, target, vcs, _root.get(vcs, ''), source ) 342 ensure_repo(repodir, parenttype, target, vcs, _root.get(vcs, ''), source , rev)
324 update_repo(target, vcs, rev) 343 update_repo(target, vcs, rev)
325 resolve_deps(target, level + 1, self_update=False, 344 resolve_deps(target, level + 1, self_update=False,
326 overrideroots=overrideroots, skipdependencies=skipdependenc ies) 345 overrideroots=overrideroots, skipdependencies=skipdependenc ies)
327 346
328 if self_update and '_self' in config and '*' in config['_self']: 347 if self_update and '_self' in config and '*' in config['_self']:
329 source = safe_join(repodir, config['_self']['*']) 348 source = safe_join(repodir, config['_self']['*'])
330 try: 349 try:
331 with io.open(source, 'rb') as handle: 350 with io.open(source, 'rb') as handle:
332 sourcedata = handle.read() 351 sourcedata = handle.read()
333 except IOError as e: 352 except IOError as e:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 args = parser.parse_args() 390 args = parser.parse_args()
372 391
373 if args.quiet: 392 if args.quiet:
374 logging.disable(logging.INFO) 393 logging.disable(logging.INFO)
375 394
376 repos = args.repos 395 repos = args.repos
377 if not len(repos): 396 if not len(repos):
378 repos = [os.path.dirname(__file__)] 397 repos = [os.path.dirname(__file__)]
379 for repo in repos: 398 for repo in repos:
380 resolve_deps(repo) 399 resolve_deps(repo)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld