1fd4e5da5Sopenharmony_ci#!/usr/bin/env python3 2fd4e5da5Sopenharmony_ci# Copyright 2014 Google Inc. 3fd4e5da5Sopenharmony_ci# 4fd4e5da5Sopenharmony_ci# Redistribution and use in source and binary forms, with or without 5fd4e5da5Sopenharmony_ci# modification, are permitted provided that the following conditions are 6fd4e5da5Sopenharmony_ci# met: 7fd4e5da5Sopenharmony_ci# 8fd4e5da5Sopenharmony_ci# * Redistributions of source code must retain the above copyright 9fd4e5da5Sopenharmony_ci# notice, this list of conditions and the following disclaimer. 10fd4e5da5Sopenharmony_ci# * Redistributions in binary form must reproduce the above 11fd4e5da5Sopenharmony_ci# copyright notice, this list of conditions and the following disclaimer 12fd4e5da5Sopenharmony_ci# in the documentation and/or other materials provided with the 13fd4e5da5Sopenharmony_ci# distribution. 14fd4e5da5Sopenharmony_ci# * Neither the name of Google Inc. nor the names of its 15fd4e5da5Sopenharmony_ci# contributors may be used to endorse or promote products derived from 16fd4e5da5Sopenharmony_ci# this software without specific prior written permission. 17fd4e5da5Sopenharmony_ci# 18fd4e5da5Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19fd4e5da5Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20fd4e5da5Sopenharmony_ci# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21fd4e5da5Sopenharmony_ci# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22fd4e5da5Sopenharmony_ci# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23fd4e5da5Sopenharmony_ci# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24fd4e5da5Sopenharmony_ci# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25fd4e5da5Sopenharmony_ci# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26fd4e5da5Sopenharmony_ci# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27fd4e5da5Sopenharmony_ci# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28fd4e5da5Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29fd4e5da5Sopenharmony_ci 30fd4e5da5Sopenharmony_ci"""Parse a DEPS file and git checkout all of the dependencies. 31fd4e5da5Sopenharmony_ci""" 32fd4e5da5Sopenharmony_ci 33fd4e5da5Sopenharmony_ciEXTRA_HELP = """ 34fd4e5da5Sopenharmony_ciEnvironment Variables: 35fd4e5da5Sopenharmony_ci GIT_EXECUTABLE: path to "git" binary; if unset, will look for one of 36fd4e5da5Sopenharmony_ci ['git', 'git.exe', 'git.bat'] in your default path. 37fd4e5da5Sopenharmony_ci 38fd4e5da5Sopenharmony_ci GIT_SYNC_DEPS_PATH: file to get the dependency list from; if unset, 39fd4e5da5Sopenharmony_ci will use the file ../DEPS relative to this script's directory. 40fd4e5da5Sopenharmony_ci 41fd4e5da5Sopenharmony_ci GIT_SYNC_DEPS_QUIET: if set to non-empty string, suppress messages. 42fd4e5da5Sopenharmony_ci 43fd4e5da5Sopenharmony_ciGit Config: 44fd4e5da5Sopenharmony_ci To disable syncing of a single repository: 45fd4e5da5Sopenharmony_ci cd path/to/repository 46fd4e5da5Sopenharmony_ci git config sync-deps.disable true 47fd4e5da5Sopenharmony_ci 48fd4e5da5Sopenharmony_ci To re-enable sync: 49fd4e5da5Sopenharmony_ci cd path/to/repository 50fd4e5da5Sopenharmony_ci git config --unset sync-deps.disable 51fd4e5da5Sopenharmony_ci""" 52fd4e5da5Sopenharmony_ci 53fd4e5da5Sopenharmony_ci 54fd4e5da5Sopenharmony_ciimport argparse 55fd4e5da5Sopenharmony_ciimport os 56fd4e5da5Sopenharmony_ciimport re 57fd4e5da5Sopenharmony_ciimport subprocess 58fd4e5da5Sopenharmony_ciimport sys 59fd4e5da5Sopenharmony_ciimport threading 60fd4e5da5Sopenharmony_cifrom builtins import bytes 61fd4e5da5Sopenharmony_ci 62fd4e5da5Sopenharmony_cidef git_executable(): 63fd4e5da5Sopenharmony_ci """Find the git executable. 64fd4e5da5Sopenharmony_ci 65fd4e5da5Sopenharmony_ci Returns: 66fd4e5da5Sopenharmony_ci A triple: 67fd4e5da5Sopenharmony_ci A string suitable for passing to subprocess functions, or None. 68fd4e5da5Sopenharmony_ci The major version number 69fd4e5da5Sopenharmony_ci The minor version number 70fd4e5da5Sopenharmony_ci """ 71fd4e5da5Sopenharmony_ci envgit = os.environ.get('GIT_EXECUTABLE') 72fd4e5da5Sopenharmony_ci searchlist = ['git', 'git.exe', 'git.bat'] 73fd4e5da5Sopenharmony_ci if envgit: 74fd4e5da5Sopenharmony_ci searchlist.insert(0, envgit) 75fd4e5da5Sopenharmony_ci with open(os.devnull, 'w') as devnull: 76fd4e5da5Sopenharmony_ci for git in searchlist: 77fd4e5da5Sopenharmony_ci major=None 78fd4e5da5Sopenharmony_ci minor=None 79fd4e5da5Sopenharmony_ci try: 80fd4e5da5Sopenharmony_ci version_info = subprocess.check_output([git, '--version']).decode('utf-8') 81fd4e5da5Sopenharmony_ci match = re.search("^git version (\d+)\.(\d+)",version_info) 82fd4e5da5Sopenharmony_ci print("Using {}".format(version_info)) 83fd4e5da5Sopenharmony_ci if match: 84fd4e5da5Sopenharmony_ci major = int(match.group(1)) 85fd4e5da5Sopenharmony_ci minor = int(match.group(2)) 86fd4e5da5Sopenharmony_ci else: 87fd4e5da5Sopenharmony_ci continue 88fd4e5da5Sopenharmony_ci except (OSError,): 89fd4e5da5Sopenharmony_ci continue 90fd4e5da5Sopenharmony_ci return (git,major,minor) 91fd4e5da5Sopenharmony_ci return (None,0,0) 92fd4e5da5Sopenharmony_ci 93fd4e5da5Sopenharmony_ci 94fd4e5da5Sopenharmony_ciDEFAULT_DEPS_PATH = os.path.normpath( 95fd4e5da5Sopenharmony_ci os.path.join(os.path.dirname(__file__), os.pardir, 'DEPS')) 96fd4e5da5Sopenharmony_ci 97fd4e5da5Sopenharmony_cidef get_deps_os_str(deps_file): 98fd4e5da5Sopenharmony_ci parsed_deps = parse_file_to_dict(deps_file) 99fd4e5da5Sopenharmony_ci parts = [] 100fd4e5da5Sopenharmony_ci if 'deps_os' in parsed_deps: 101fd4e5da5Sopenharmony_ci for deps_os in parsed_deps['deps_os']: 102fd4e5da5Sopenharmony_ci parts.append(' [{}]]'.format(deps_os)) 103fd4e5da5Sopenharmony_ci return "\n".join(parts) 104fd4e5da5Sopenharmony_ci 105fd4e5da5Sopenharmony_cidef looks_like_raw_commit(commit): 106fd4e5da5Sopenharmony_ci return re.match('^[a-f0-9]{40}$', commit) is not None 107fd4e5da5Sopenharmony_ci 108fd4e5da5Sopenharmony_cidef git_repository_sync_is_disabled(git, directory): 109fd4e5da5Sopenharmony_ci try: 110fd4e5da5Sopenharmony_ci disable = subprocess.check_output( 111fd4e5da5Sopenharmony_ci [git, 'config', 'sync-deps.disable'], cwd=directory) 112fd4e5da5Sopenharmony_ci return disable.lower().strip() in ['true', '1', 'yes', 'on'] 113fd4e5da5Sopenharmony_ci except subprocess.CalledProcessError: 114fd4e5da5Sopenharmony_ci return False 115fd4e5da5Sopenharmony_ci 116fd4e5da5Sopenharmony_ci 117fd4e5da5Sopenharmony_cidef is_git_toplevel(git, directory): 118fd4e5da5Sopenharmony_ci """Return true iff the directory is the top level of a Git repository. 119fd4e5da5Sopenharmony_ci 120fd4e5da5Sopenharmony_ci Args: 121fd4e5da5Sopenharmony_ci git (string) the git executable 122fd4e5da5Sopenharmony_ci 123fd4e5da5Sopenharmony_ci directory (string) the path into which the repository 124fd4e5da5Sopenharmony_ci is expected to be checked out. 125fd4e5da5Sopenharmony_ci """ 126fd4e5da5Sopenharmony_ci try: 127fd4e5da5Sopenharmony_ci toplevel = subprocess.check_output( 128fd4e5da5Sopenharmony_ci [git, 'rev-parse', '--show-toplevel'], cwd=directory).strip() 129fd4e5da5Sopenharmony_ci return os.path.realpath(bytes(directory, 'utf8')) == os.path.realpath(toplevel) 130fd4e5da5Sopenharmony_ci except subprocess.CalledProcessError: 131fd4e5da5Sopenharmony_ci return False 132fd4e5da5Sopenharmony_ci 133fd4e5da5Sopenharmony_ci 134fd4e5da5Sopenharmony_cidef status(directory, checkoutable): 135fd4e5da5Sopenharmony_ci def truncate(s, length): 136fd4e5da5Sopenharmony_ci return s if len(s) <= length else '...' + s[-(length - 3):] 137fd4e5da5Sopenharmony_ci dlen = 36 138fd4e5da5Sopenharmony_ci directory = truncate(directory, dlen) 139fd4e5da5Sopenharmony_ci checkoutable = truncate(checkoutable, 40) 140fd4e5da5Sopenharmony_ci sys.stdout.write('%-*s @ %s\n' % (dlen, directory, checkoutable)) 141fd4e5da5Sopenharmony_ci 142fd4e5da5Sopenharmony_ci 143fd4e5da5Sopenharmony_cidef git_checkout_to_directory(git, repo, checkoutable, directory, verbose, treeless): 144fd4e5da5Sopenharmony_ci """Checkout (and clone if needed) a Git repository. 145fd4e5da5Sopenharmony_ci 146fd4e5da5Sopenharmony_ci Args: 147fd4e5da5Sopenharmony_ci git (string) the git executable 148fd4e5da5Sopenharmony_ci 149fd4e5da5Sopenharmony_ci repo (string) the location of the repository, suitable 150fd4e5da5Sopenharmony_ci for passing to `git clone`. 151fd4e5da5Sopenharmony_ci 152fd4e5da5Sopenharmony_ci checkoutable (string) a tag, branch, or commit, suitable for 153fd4e5da5Sopenharmony_ci passing to `git checkout` 154fd4e5da5Sopenharmony_ci 155fd4e5da5Sopenharmony_ci directory (string) the path into which the repository 156fd4e5da5Sopenharmony_ci should be checked out. 157fd4e5da5Sopenharmony_ci 158fd4e5da5Sopenharmony_ci verbose (boolean): emit status info to stdout 159fd4e5da5Sopenharmony_ci 160fd4e5da5Sopenharmony_ci treeless (boolean): when true, clone without any trees. 161fd4e5da5Sopenharmony_ci 162fd4e5da5Sopenharmony_ci Raises an exception if any calls to git fail. 163fd4e5da5Sopenharmony_ci """ 164fd4e5da5Sopenharmony_ci if not os.path.isdir(directory): 165fd4e5da5Sopenharmony_ci # Use blobless or treeless checkouts for faster downloads. 166fd4e5da5Sopenharmony_ci # This defers some work to checkout time. 167fd4e5da5Sopenharmony_ci # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ 168fd4e5da5Sopenharmony_ci filter = ['--filter=tree:0'] if treeless else ['--filter=blob:none'] 169fd4e5da5Sopenharmony_ci # If the thing to check out looks like a tag (and not like a commit), 170fd4e5da5Sopenharmony_ci # then limit the checkout to that branch. 171fd4e5da5Sopenharmony_ci branch = [] if looks_like_raw_commit(checkoutable) else ['--branch={}'.format(checkoutable)] 172fd4e5da5Sopenharmony_ci subprocess.check_call( 173fd4e5da5Sopenharmony_ci [git, 'clone', '--quiet', '--single-branch'] + filter + branch + [repo, directory]) 174fd4e5da5Sopenharmony_ci 175fd4e5da5Sopenharmony_ci if not is_git_toplevel(git, directory): 176fd4e5da5Sopenharmony_ci # if the directory exists, but isn't a git repo, you will modify 177fd4e5da5Sopenharmony_ci # the parent repostory, which isn't what you want. 178fd4e5da5Sopenharmony_ci sys.stdout.write('%s\n IS NOT TOP-LEVEL GIT DIRECTORY.\n' % directory) 179fd4e5da5Sopenharmony_ci return 180fd4e5da5Sopenharmony_ci 181fd4e5da5Sopenharmony_ci # Check to see if this repo is disabled. Quick return. 182fd4e5da5Sopenharmony_ci if git_repository_sync_is_disabled(git, directory): 183fd4e5da5Sopenharmony_ci sys.stdout.write('%s\n SYNC IS DISABLED.\n' % directory) 184fd4e5da5Sopenharmony_ci return 185fd4e5da5Sopenharmony_ci 186fd4e5da5Sopenharmony_ci with open(os.devnull, 'w') as devnull: 187fd4e5da5Sopenharmony_ci # If this fails, we will fetch before trying again. Don't spam user 188fd4e5da5Sopenharmony_ci # with error information. 189fd4e5da5Sopenharmony_ci if 0 == subprocess.call([git, 'checkout', '--quiet', checkoutable], 190fd4e5da5Sopenharmony_ci cwd=directory, stderr=devnull): 191fd4e5da5Sopenharmony_ci # if this succeeds, skip slow `git fetch`. 192fd4e5da5Sopenharmony_ci if verbose: 193fd4e5da5Sopenharmony_ci status(directory, checkoutable) # Success. 194fd4e5da5Sopenharmony_ci return 195fd4e5da5Sopenharmony_ci 196fd4e5da5Sopenharmony_ci # If the repo has changed, always force use of the correct repo. 197fd4e5da5Sopenharmony_ci # If origin already points to repo, this is a quick no-op. 198fd4e5da5Sopenharmony_ci subprocess.check_call( 199fd4e5da5Sopenharmony_ci [git, 'remote', 'set-url', 'origin', repo], cwd=directory) 200fd4e5da5Sopenharmony_ci 201fd4e5da5Sopenharmony_ci subprocess.check_call([git, 'fetch', '--quiet'], cwd=directory) 202fd4e5da5Sopenharmony_ci 203fd4e5da5Sopenharmony_ci subprocess.check_call([git, 'checkout', '--quiet', checkoutable], cwd=directory) 204fd4e5da5Sopenharmony_ci 205fd4e5da5Sopenharmony_ci if verbose: 206fd4e5da5Sopenharmony_ci status(directory, checkoutable) # Success. 207fd4e5da5Sopenharmony_ci 208fd4e5da5Sopenharmony_ci 209fd4e5da5Sopenharmony_cidef parse_file_to_dict(path): 210fd4e5da5Sopenharmony_ci dictionary = {} 211fd4e5da5Sopenharmony_ci contents = open(path).read() 212fd4e5da5Sopenharmony_ci # Need to convert Var() to vars[], so that the DEPS is actually Python. Var() 213fd4e5da5Sopenharmony_ci # comes from Autoroller using gclient which has a slightly different DEPS 214fd4e5da5Sopenharmony_ci # format. 215fd4e5da5Sopenharmony_ci contents = re.sub(r"Var\((.*?)\)", r"vars[\1]", contents) 216fd4e5da5Sopenharmony_ci exec(contents, dictionary) 217fd4e5da5Sopenharmony_ci return dictionary 218fd4e5da5Sopenharmony_ci 219fd4e5da5Sopenharmony_ci 220fd4e5da5Sopenharmony_cidef git_sync_deps(deps_file_path, command_line_os_requests, verbose, treeless): 221fd4e5da5Sopenharmony_ci """Grab dependencies, with optional platform support. 222fd4e5da5Sopenharmony_ci 223fd4e5da5Sopenharmony_ci Args: 224fd4e5da5Sopenharmony_ci deps_file_path (string) Path to the DEPS file. 225fd4e5da5Sopenharmony_ci 226fd4e5da5Sopenharmony_ci command_line_os_requests (list of strings) Can be empty list. 227fd4e5da5Sopenharmony_ci List of strings that should each be a key in the deps_os 228fd4e5da5Sopenharmony_ci dictionary in the DEPS file. 229fd4e5da5Sopenharmony_ci 230fd4e5da5Sopenharmony_ci verbose (boolean): emit status info to stdout 231fd4e5da5Sopenharmony_ci 232fd4e5da5Sopenharmony_ci treeless (boolean): when true, clone as treeless instead of blobless 233fd4e5da5Sopenharmony_ci 234fd4e5da5Sopenharmony_ci Raises git Exceptions. 235fd4e5da5Sopenharmony_ci """ 236fd4e5da5Sopenharmony_ci (git,git_major,git_minor) = git_executable() 237fd4e5da5Sopenharmony_ci assert git 238fd4e5da5Sopenharmony_ci 239fd4e5da5Sopenharmony_ci # --filter=tree:0 is available in git 2.20 and later 240fd4e5da5Sopenharmony_ci if (git_major,git_minor) < (2,20): 241fd4e5da5Sopenharmony_ci print("disabling --treeless: git is older than v2.20") 242fd4e5da5Sopenharmony_ci treeless = False 243fd4e5da5Sopenharmony_ci 244fd4e5da5Sopenharmony_ci deps_file_directory = os.path.dirname(deps_file_path) 245fd4e5da5Sopenharmony_ci deps_file = parse_file_to_dict(deps_file_path) 246fd4e5da5Sopenharmony_ci dependencies = deps_file['deps'].copy() 247fd4e5da5Sopenharmony_ci os_specific_dependencies = deps_file.get('deps_os', dict()) 248fd4e5da5Sopenharmony_ci if 'all' in command_line_os_requests: 249fd4e5da5Sopenharmony_ci for value in list(os_specific_dependencies.values()): 250fd4e5da5Sopenharmony_ci dependencies.update(value) 251fd4e5da5Sopenharmony_ci else: 252fd4e5da5Sopenharmony_ci for os_name in command_line_os_requests: 253fd4e5da5Sopenharmony_ci # Add OS-specific dependencies 254fd4e5da5Sopenharmony_ci if os_name in os_specific_dependencies: 255fd4e5da5Sopenharmony_ci dependencies.update(os_specific_dependencies[os_name]) 256fd4e5da5Sopenharmony_ci for directory in dependencies: 257fd4e5da5Sopenharmony_ci for other_dir in dependencies: 258fd4e5da5Sopenharmony_ci if directory.startswith(other_dir + '/'): 259fd4e5da5Sopenharmony_ci raise Exception('%r is parent of %r' % (other_dir, directory)) 260fd4e5da5Sopenharmony_ci list_of_arg_lists = [] 261fd4e5da5Sopenharmony_ci for directory in sorted(dependencies): 262fd4e5da5Sopenharmony_ci if '@' in dependencies[directory]: 263fd4e5da5Sopenharmony_ci repo, checkoutable = dependencies[directory].split('@', 1) 264fd4e5da5Sopenharmony_ci else: 265fd4e5da5Sopenharmony_ci raise Exception("please specify commit or tag") 266fd4e5da5Sopenharmony_ci 267fd4e5da5Sopenharmony_ci relative_directory = os.path.join(deps_file_directory, directory) 268fd4e5da5Sopenharmony_ci 269fd4e5da5Sopenharmony_ci list_of_arg_lists.append( 270fd4e5da5Sopenharmony_ci (git, repo, checkoutable, relative_directory, verbose, treeless)) 271fd4e5da5Sopenharmony_ci 272fd4e5da5Sopenharmony_ci multithread(git_checkout_to_directory, list_of_arg_lists) 273fd4e5da5Sopenharmony_ci 274fd4e5da5Sopenharmony_ci for directory in deps_file.get('recursedeps', []): 275fd4e5da5Sopenharmony_ci recursive_path = os.path.join(deps_file_directory, directory, 'DEPS') 276fd4e5da5Sopenharmony_ci git_sync_deps(recursive_path, command_line_os_requests, verbose) 277fd4e5da5Sopenharmony_ci 278fd4e5da5Sopenharmony_ci 279fd4e5da5Sopenharmony_cidef multithread(function, list_of_arg_lists): 280fd4e5da5Sopenharmony_ci # for args in list_of_arg_lists: 281fd4e5da5Sopenharmony_ci # function(*args) 282fd4e5da5Sopenharmony_ci # return 283fd4e5da5Sopenharmony_ci threads = [] 284fd4e5da5Sopenharmony_ci for args in list_of_arg_lists: 285fd4e5da5Sopenharmony_ci thread = threading.Thread(None, function, None, args) 286fd4e5da5Sopenharmony_ci thread.start() 287fd4e5da5Sopenharmony_ci threads.append(thread) 288fd4e5da5Sopenharmony_ci for thread in threads: 289fd4e5da5Sopenharmony_ci thread.join() 290fd4e5da5Sopenharmony_ci 291fd4e5da5Sopenharmony_ci 292fd4e5da5Sopenharmony_cidef main(argv): 293fd4e5da5Sopenharmony_ci argparser = argparse.ArgumentParser( 294fd4e5da5Sopenharmony_ci prog = "git-sync-deps", 295fd4e5da5Sopenharmony_ci description = "Checkout git-based dependencies as specified by the DEPS file", 296fd4e5da5Sopenharmony_ci add_help=False # Because we want to print deps_os with -h option 297fd4e5da5Sopenharmony_ci ) 298fd4e5da5Sopenharmony_ci argparser.add_argument("--help", "-h", 299fd4e5da5Sopenharmony_ci action='store_true', 300fd4e5da5Sopenharmony_ci help="show this help message and exit") 301fd4e5da5Sopenharmony_ci argparser.add_argument("--deps", 302fd4e5da5Sopenharmony_ci default = os.environ.get('GIT_SYNC_DEPS_PATH', DEFAULT_DEPS_PATH), 303fd4e5da5Sopenharmony_ci help="location of the the DEPS file") 304fd4e5da5Sopenharmony_ci argparser.add_argument("--verbose", 305fd4e5da5Sopenharmony_ci default=not bool(os.environ.get('GIT_SYNC_DEPS_QUIET', False)), 306fd4e5da5Sopenharmony_ci action='store_true', 307fd4e5da5Sopenharmony_ci help="be verbose: print status messages") 308fd4e5da5Sopenharmony_ci argparser.add_argument("--treeless", 309fd4e5da5Sopenharmony_ci default=False, 310fd4e5da5Sopenharmony_ci action='store_true', 311fd4e5da5Sopenharmony_ci help=""" 312fd4e5da5Sopenharmony_ci Clone repos without trees (--filter=tree:0). 313fd4e5da5Sopenharmony_ci This is the fastest option for a build machine, 314fd4e5da5Sopenharmony_ci when you only need a single commit. 315fd4e5da5Sopenharmony_ci Defers getting objects until checking out a commit. 316fd4e5da5Sopenharmony_ci 317fd4e5da5Sopenharmony_ci The default is to clone with trees but without blobs. 318fd4e5da5Sopenharmony_ci 319fd4e5da5Sopenharmony_ci Only takes effect if using git 2.20 or later. 320fd4e5da5Sopenharmony_ci 321fd4e5da5Sopenharmony_ci See https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ 322fd4e5da5Sopenharmony_ci """) 323fd4e5da5Sopenharmony_ci argparser.add_argument("os_requests",nargs="*", 324fd4e5da5Sopenharmony_ci help="OS requests, as keys in the deps_os dictionariy in the DEPS file") 325fd4e5da5Sopenharmony_ci 326fd4e5da5Sopenharmony_ci args = argparser.parse_args() 327fd4e5da5Sopenharmony_ci if args.help: 328fd4e5da5Sopenharmony_ci print(argparser.format_help()) 329fd4e5da5Sopenharmony_ci print(EXTRA_HELP) 330fd4e5da5Sopenharmony_ci print(get_deps_os_str(args.deps)) 331fd4e5da5Sopenharmony_ci return 0 332fd4e5da5Sopenharmony_ci 333fd4e5da5Sopenharmony_ci git_sync_deps(args.deps, args.os_requests, args.verbose, args.treeless) 334fd4e5da5Sopenharmony_ci return 0 335fd4e5da5Sopenharmony_ci 336fd4e5da5Sopenharmony_ci 337fd4e5da5Sopenharmony_ciif __name__ == '__main__': 338fd4e5da5Sopenharmony_ci exit(main(sys.argv[1:])) 339