From 5e5f9dc32b899e99431d7677f7e3666cd9c5a8fe Mon Sep 17 00:00:00 2001 From: Hal Canary Date: Fri, 1 Nov 2019 10:34:32 -0400 Subject: [PATCH] tools/git-sync-deps: enforce commit hash in DEPS, not tags or branches Change variable name to reflect that. Also, pass '--no-checkout' to git-clone to suppress "warning: remote HEAD refers to nonexistent ref, unable to checkout" error message. Also, change '@' to '>' in verbose output if anything changes in the repositories. Change-Id: I27d0b026d121c163e378f34ab2bbe81233ddba1a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252177 Reviewed-by: Eric Boren Commit-Queue: Hal Canary --- tools/git-sync-deps | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/tools/git-sync-deps b/tools/git-sync-deps index c7379c0b5c..ff121b1d9f 100755 --- a/tools/git-sync-deps +++ b/tools/git-sync-deps @@ -99,16 +99,17 @@ def is_git_toplevel(git, directory): return False -def status(directory, checkoutable): +def status(directory, commithash, change): def truncate(s, length): return s if len(s) <= length else s[:(length - 3)] + '...' dlen = 36 directory = truncate(directory, dlen) - checkoutable = truncate(checkoutable, 40) - sys.stdout.write('%-*s @ %s\n' % (dlen, directory, checkoutable)) + commithash = truncate(commithash, 40) + symbol = '>' if change else '@' + sys.stdout.write('%-*s %s %s\n' % (dlen, directory, symbol, commithash)) -def git_checkout_to_directory(git, repo, checkoutable, directory, verbose): +def git_checkout_to_directory(git, repo, commithash, directory, verbose): """Checkout (and clone if needed) a Git repository. Args: @@ -117,8 +118,7 @@ def git_checkout_to_directory(git, repo, checkoutable, directory, verbose): repo (string) the location of the repository, suitable for passing to `git clone`. - checkoutable (string) a tag, branch, or commit, suitable for - passing to `git checkout` + commithash (string) a commit, suitable for passing to `git checkout` directory (string) the path into which the repository should be checked out. @@ -129,7 +129,12 @@ def git_checkout_to_directory(git, repo, checkoutable, directory, verbose): """ if not os.path.isdir(directory): subprocess.check_call( - [git, 'clone', '--quiet', repo, directory]) + [git, 'clone', '--quiet', '--no-checkout', repo, directory]) + subprocess.check_call([git, 'checkout', '--quiet', commithash], + cwd=directory) + if verbose: + status(directory, commithash, True) + return if not is_git_toplevel(git, directory): # if the directory exists, but isn't a git repo, you will modify @@ -145,11 +150,11 @@ def git_checkout_to_directory(git, repo, checkoutable, directory, verbose): with open(os.devnull, 'w') as devnull: # If this fails, we will fetch before trying again. Don't spam user # with error infomation. - if 0 == subprocess.call([git, 'checkout', '--quiet', checkoutable], + if 0 == subprocess.call([git, 'checkout', '--quiet', commithash], cwd=directory, stderr=devnull): # if this succeeds, skip slow `git fetch`. if verbose: - status(directory, checkoutable) # Success. + status(directory, commithash, False) # Success. return # If the repo has changed, always force use of the correct repo. @@ -159,10 +164,10 @@ def git_checkout_to_directory(git, repo, checkoutable, directory, verbose): subprocess.check_call([git, 'fetch', '--quiet'], cwd=directory) - subprocess.check_call([git, 'checkout', '--quiet', checkoutable], cwd=directory) + subprocess.check_call([git, 'checkout', '--quiet', commithash], cwd=directory) if verbose: - status(directory, checkoutable) # Success. + status(directory, commithash, True) # Success. def parse_file_to_dict(path): @@ -171,6 +176,11 @@ def parse_file_to_dict(path): return dictionary +def is_sha1_sum(s): + """SHA1 sums are 160 bits, encoded as lowercase hexadecimal.""" + return len(s) == 40 and all(c in '0123456789abcdef' for c in s) + + def git_sync_deps(deps_file_path, command_line_os_requests, verbose): """Grab dependencies, with optional platform support. @@ -209,14 +219,16 @@ def git_sync_deps(deps_file_path, command_line_os_requests, verbose): print 'Skipping "%s".' % directory continue if '@' in dependencies[directory]: - repo, checkoutable = dependencies[directory].split('@', 1) + repo, commithash = dependencies[directory].split('@', 1) else: - raise Exception("please specify commit or tag") + raise Exception("please specify commit") + if not is_sha1_sum(commithash): + raise Exception("poorly formed commit hash: %r" % commithash) relative_directory = os.path.join(deps_file_directory, directory) list_of_arg_lists.append( - (git, repo, checkoutable, relative_directory, verbose)) + (git, repo, commithash, relative_directory, verbose)) multithread(git_checkout_to_directory, list_of_arg_lists)