git-sync-deps 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #!/usr/bin/env python3
  2. # Copyright 2023 The Effcee Authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import os
  16. import subprocess
  17. def run(cmd, directory, fail_ok=False, verbose=False):
  18. """Runs a command in a directory and returns its standard output stream.
  19. Captures and returns the standard error stream.
  20. Raises a RuntimeError if the command fails to launch or otherwise fails.
  21. """
  22. if verbose:
  23. print(cmd)
  24. p = subprocess.Popen(cmd,
  25. cwd=directory,
  26. stdout=subprocess.PIPE)
  27. (stdout, _) = p.communicate()
  28. if p.returncode != 0 and not fail_ok:
  29. raise RuntimeError('Failed to run {} in {}'.format(cmd, directory))
  30. return stdout
  31. # This is needed for interpreting the contents of the DEPS file.
  32. def Var(key):
  33. """Returns the value for the given key in the 'vars' dictionary"""
  34. return vars[key]
  35. # Get deps dictionary from the DEPS file
  36. with open('DEPS', mode='r', encoding='utf-8') as f:
  37. exec(''.join(f.readlines()))
  38. # Now 'deps' is a dictionary mapping relative subdirectory name
  39. # to a repo-and-commit string such as 'https://github.com/google/[email protected]'
  40. for d in sorted(deps.keys()):
  41. (repo,commit) = deps[d].split('@')
  42. print("{} <-- {} {}".format(d,repo,commit))
  43. os.makedirs(d, exist_ok=True)
  44. # Clone afresh if needed
  45. if not os.path.exists(os.path.join(d, '.git')):
  46. run(['git', 'clone', '--single-branch', repo,'.'], d, verbose=True)
  47. # Ensure there is a known-good remote
  48. if len(run(['git', 'remote', 'get-url', 'known-good'], d, fail_ok=True)) == 0:
  49. run(['git', 'remote', 'add', 'known-good', repo], d)
  50. # And it has the right remote URL
  51. run(['git', 'remote', 'set-url', 'known-good', repo], d)
  52. # Fetch if the commit isn't yet present
  53. if len(run(['git', 'rev-parse', '--verify', '--quiet', commit + '^{commit}'],
  54. d,
  55. fail_ok=True)) == 0:
  56. run(['git', 'fetch', 'known-good'], d, verbose=True)
  57. # Checkout the commit
  58. run(['git', 'checkout', commit], d)
  59. print()
  60. # vim: expandtab ts=4 sw=4