OLD | NEW |
1 # Copyright 2014 Google Inc. All Rights Reserved. | 1 # Copyright 2014 Google Inc. All Rights Reserved. |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 if section != 'remote "origin"': | 267 if section != 'remote "origin"': |
268 continue | 268 continue |
269 | 269 |
270 m = _GIT_CONFIG_REMOTE_URL_RE.match(line) | 270 m = _GIT_CONFIG_REMOTE_URL_RE.match(line) |
271 if m: | 271 if m: |
272 return m.group(1).strip() | 272 return m.group(1).strip() |
273 | 273 |
274 return None | 274 return None |
275 | 275 |
276 | 276 |
277 def _GetGitHead(path): | 277 def _GetGitHead(repo): |
278 """Returns the hash of the head of the git repo in |path|. Raises an IOError | 278 """Returns the hash of the head of the git repo local checkout. |
279 if |path| doesn't exist or is not a git repo. | 279 |
| 280 Raises: |
| 281 IOError: if repo's checkout directory doesn't exist or not a git repository. |
280 """ | 282 """ |
281 return open(os.path.join(path, '.git', 'HEAD'), 'rb').read().strip() | 283 with open(os.path.join(repo.checkout_dir, '.git', 'HEAD'), 'rb') as head: |
| 284 return head.read().strip() |
| 285 |
| 286 |
| 287 def _GetGitFetchHead(repo): |
| 288 """Returns the hash of the latest fetched revision. |
| 289 |
| 290 Raises: |
| 291 IOError: if repo's checkout directory doesn't exist or not a git repository. |
| 292 KeyError: if the fetched head of the remote repository is not found in the |
| 293 local checkout. |
| 294 """ |
| 295 path = os.path.join(repo.checkout_dir, '.git', 'FETCH_HEAD') |
| 296 with open(path, 'rb') as heads_file: |
| 297 for line in heads_file.readlines(): |
| 298 if not line.strip(): |
| 299 continue |
| 300 head, repo_url = line.strip().split() |
| 301 if repo_url == repo.repository: |
| 302 return head |
| 303 raise KeyError('Did not find fetched head for %s in %s' % |
| 304 (repo.repository, path)) |
282 | 305 |
283 | 306 |
284 def _NormalizeGitPath(path): | 307 def _NormalizeGitPath(path): |
285 """Given a |path| in a GIT repository (relative to its root), normalizes it so | 308 """Given a |path| in a GIT repository (relative to its root), normalizes it so |
286 it will match only that exact path in a sparse checkout. | 309 it will match only that exact path in a sparse checkout. |
287 """ | 310 """ |
288 path = path.strip() | 311 path = path.strip() |
289 if not path.startswith('/'): | 312 if not path.startswith('/'): |
290 path = '/' + path | 313 path = '/' + path |
291 if not path.endswith('/'): | 314 if not path.endswith('/'): |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 with open(path, 'wb') as io: | 406 with open(path, 'wb') as io: |
384 io.write(contents) | 407 io.write(contents) |
385 | 408 |
386 | 409 |
387 def _UpdateCheckout(path, repo, dry_run): | 410 def _UpdateCheckout(path, repo, dry_run): |
388 """Updates a GIT checkout in |path| by pulling down a specific revision | 411 """Updates a GIT checkout in |path| by pulling down a specific revision |
389 from it, as configured by RepoOptions |repo|. Only actually runs if | 412 from it, as configured by RepoOptions |repo|. Only actually runs if |
390 |dry_run| is False. | 413 |dry_run| is False. |
391 """ | 414 """ |
392 try: | 415 try: |
393 # Try a checkout first. If this fails then we'll actually need to fetch | 416 # If the repo has a revision specified, try a checkout first. If this fails |
394 # the revision. | 417 # then we'll actually need to fetch. |
395 _LOGGER.info('Trying to checkout revision %s.', repo.revision) | 418 if _GIT_SHA1_RE.match(repo.revision): |
396 _Shell('git', 'checkout', repo.revision, cwd=path, | 419 _LOGGER.info('Trying to checkout revision %s.', repo.revision) |
397 dry_run=dry_run) | 420 _Shell('git', 'checkout', repo.revision, cwd=path, |
398 return | 421 dry_run=dry_run) |
| 422 return |
399 except RuntimeError: | 423 except RuntimeError: |
400 pass | 424 pass |
401 | 425 |
402 # Fetch the revision and then check it out. Let output go to screen rather | 426 # Fetch the revision and then check it out. Let output go to screen rather |
403 # than be buffered. | 427 # than be buffered. |
404 _LOGGER.info('Fetching and checking out revision %s.', repo.revision) | 428 _LOGGER.info('Fetching revision %s.', repo.revision) |
405 _Shell('git', 'fetch', '--depth=1', 'origin', repo.revision, | 429 _Shell('git', 'fetch', '--depth=1', 'origin', repo.revision, |
406 cwd=path, dry_run=dry_run, stdout=None, stderr=None) | 430 cwd=path, dry_run=dry_run, stdout=None, stderr=None) |
407 _Shell('git', 'checkout', repo.revision, cwd=path, | 431 new_rev = _GetGitFetchHead(repo) if repo.revision == 'HEAD' else repo.revision |
| 432 _LOGGER.info('Checking out revision %s.', new_rev) |
| 433 _Shell('git', 'checkout', new_rev, cwd=path, |
408 dry_run=dry_run, stdout=None, stderr=None) | 434 dry_run=dry_run, stdout=None, stderr=None) |
409 | 435 |
410 | 436 |
411 # Used by _GetJunctionInfo to extract information about junctions. | 437 # Used by _GetJunctionInfo to extract information about junctions. |
412 _DIR_JUNCTION_RE = re.compile(r'^.*<JUNCTION>\s+(.+)\s+\[(.+)\]$') | 438 _DIR_JUNCTION_RE = re.compile(r'^.*<JUNCTION>\s+(.+)\s+\[(.+)\]$') |
413 | 439 |
414 | 440 |
415 # TODO(chrisha): This is ugly, and there has to be a better way! | 441 # TODO(chrisha): This is ugly, and there has to be a better way! |
416 def _GetJunctionInfo(junction): | 442 def _GetJunctionInfo(junction): |
417 """Returns the target of a junction, if it exists, None otherwise.""" | 443 """Returns the target of a junction, if it exists, None otherwise.""" |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 if not options.force and _IsGitCheckoutRoot(repo.checkout_dir): | 534 if not options.force and _IsGitCheckoutRoot(repo.checkout_dir): |
509 # Get the repo origin. | 535 # Get the repo origin. |
510 repo_url = _GetGitOrigin(repo.checkout_dir) | 536 repo_url = _GetGitOrigin(repo.checkout_dir) |
511 if (repo_url == repo.repository and | 537 if (repo_url == repo.repository and |
512 _HasValidSparseCheckoutConfig(repo)): | 538 _HasValidSparseCheckoutConfig(repo)): |
513 _LOGGER.debug('Checkout is for correct repository and subdirectory.') | 539 _LOGGER.debug('Checkout is for correct repository and subdirectory.') |
514 keep_cache_dir = True | 540 keep_cache_dir = True |
515 create_checkout = False | 541 create_checkout = False |
516 | 542 |
517 # Get the checked out revision. | 543 # Get the checked out revision. |
518 revhash = _GetGitHead(repo.checkout_dir) | 544 revhash = _GetGitHead(repo) |
519 if revhash == repo.revision: | 545 if revhash == repo.revision: |
520 _LOGGER.debug('Checkout is already up to date.') | 546 _LOGGER.debug('Checkout is already up to date.') |
521 update_checkout = False | 547 update_checkout = False |
522 | 548 |
523 if not keep_cache_dir: | 549 if not keep_cache_dir: |
524 # The old checkout directory is renamed and erased in a separate thread | 550 # The old checkout directory is renamed and erased in a separate thread |
525 # so that the new checkout can start immediately. | 551 # so that the new checkout can start immediately. |
526 _LOGGER.info('Erasing stale checkout directory: %s', repo.checkout_dir) | 552 _LOGGER.info('Erasing stale checkout directory: %s', repo.checkout_dir) |
527 | 553 |
528 # Any existing junctions to this repo must be removed otherwise the | 554 # Any existing junctions to this repo must be removed otherwise the |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 continue | 944 continue |
919 if not checkout_dirs[repo.checkout_dir] and not options.force: | 945 if not checkout_dirs[repo.checkout_dir] and not options.force: |
920 continue | 946 continue |
921 _RecurseRepository(options, repo) | 947 _RecurseRepository(options, repo) |
922 | 948 |
923 return | 949 return |
924 | 950 |
925 | 951 |
926 if __name__ == '__main__': | 952 if __name__ == '__main__': |
927 main() | 953 main() |
OLD | NEW |