Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """ | 6 """ |
| 7 Tool to perform checkouts in one easy command line! | 7 Tool to perform checkouts in one easy command line! |
| 8 | 8 |
| 9 Usage: | 9 Usage: |
| 10 fetch <recipe> [--property=value [--property2=value2 ...]] | 10 fetch <recipe> [--property=value [--property2=value2 ...]] |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 | 59 |
| 60 class GclientCheckout(Checkout): | 60 class GclientCheckout(Checkout): |
| 61 | 61 |
| 62 def run_gclient(self, *cmd, **kwargs): | 62 def run_gclient(self, *cmd, **kwargs): |
| 63 print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd) | 63 print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd) |
| 64 if not self.dryrun: | 64 if not self.dryrun: |
| 65 return subprocess.check_call( | 65 return subprocess.check_call( |
| 66 (sys.executable, os.path.join(SCRIPT_PATH, 'gclient.py')) + cmd, | 66 (sys.executable, os.path.join(SCRIPT_PATH, 'gclient.py')) + cmd, |
| 67 **kwargs) | 67 **kwargs) |
| 68 | 68 |
| 69 def exists(self): | |
|
Dirk Pranke
2013/04/06 01:45:25
I know this name was already chosen, but it's not
| |
| 70 return os.path.exists(os.path.join(os.getcwd(), self.root)) | |
|
iannucci
2013/04/06 01:38:18
Let's make self.root abspath from the initial set.
| |
| 71 | |
| 69 | 72 |
| 70 class GitCheckout(Checkout): | 73 class GitCheckout(Checkout): |
| 71 | 74 |
| 72 def run_git(self, *cmd, **kwargs): | 75 def run_git(self, *cmd, **kwargs): |
| 73 print 'Running: git %s' % ' '.join(pipes.quote(x) for x in cmd) | 76 print 'Running: git %s' % ' '.join(pipes.quote(x) for x in cmd) |
| 74 if not self.dryrun: | 77 if not self.dryrun: |
| 75 return subprocess.check_call(('git',) + cmd, **kwargs) | 78 return subprocess.check_call(('git',) + cmd, **kwargs) |
| 76 | 79 |
| 77 | 80 |
| 78 class SvnCheckout(Checkout): | 81 class SvnCheckout(Checkout): |
| 79 | 82 |
| 80 def run_svn(self, *cmd, **kwargs): | 83 def run_svn(self, *cmd, **kwargs): |
| 81 print 'Running: svn %s' % ' '.join(pipes.quote(x) for x in cmd) | 84 print 'Running: svn %s' % ' '.join(pipes.quote(x) for x in cmd) |
| 82 if not self.dryrun: | 85 if not self.dryrun: |
| 83 return subprocess.check_call(('svn',) + cmd, **kwargs) | 86 return subprocess.check_call(('svn',) + cmd, **kwargs) |
| 84 | 87 |
| 85 | 88 |
| 89 class GclientGitCheckout(GclientCheckout, GitCheckout): | |
| 90 | |
| 91 def __init__(self, dryrun, spec, root): | |
| 92 super(GclientGitCheckout, self).__init__(dryrun, spec, root) | |
| 93 assert 'solutions' in self.spec | |
| 94 keys = ['solutions', 'target_os', 'target_os_only'] | |
| 95 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key]) | |
| 96 for key in self.spec if key in keys) | |
|
iannucci
2013/04/06 01:38:18
This should be a function (spec'ifying a dict).
| |
| 97 self.spec['gclient_spec'] = gclient_spec | |
| 98 | |
| 99 def init(self): | |
|
iannucci
2013/04/06 01:38:18
This should call super.
| |
| 100 # TODO(dpranke): Work around issues w/ delta compression on big repos. | |
| 101 self.run_git('config', '--global', 'core.deltaBaseCacheLimit', '1G') | |
|
iannucci
2013/04/06 01:38:18
*grumble*
| |
| 102 | |
| 103 # Configure and do the gclient checkout. | |
| 104 self.run_gclient('config', '--spec', self.spec['gclient_spec']) | |
| 105 self.run_gclient('sync') | |
| 106 | |
| 107 # Configure git. | |
| 108 wd = os.path.join(self.base, self.root) | |
| 109 if self.dryrun: | |
| 110 print 'cd %s' % wd | |
| 111 self.run_git( | |
|
iannucci
2013/04/06 01:38:18
run_git should print cwd on dryrun... don't need t
| |
| 112 'submodule', 'foreach', | |
| 113 'git config -f $toplevel/.git/config submodule.$name.ignore all', | |
| 114 cwd=wd) | |
| 115 self.run_git('config', 'diff.ignoreSubmodules', 'all', cwd=wd) | |
| 116 | |
| 117 | |
| 86 class GclientGitSvnCheckout(GclientCheckout, GitCheckout, SvnCheckout): | 118 class GclientGitSvnCheckout(GclientCheckout, GitCheckout, SvnCheckout): |
|
Dirk Pranke
2013/04/06 01:45:25
Should this inherit from GclientGitCheckout instea
| |
| 87 | 119 |
| 88 def __init__(self, dryrun, spec, root): | 120 def __init__(self, dryrun, spec, root): |
| 89 super(GclientGitSvnCheckout, self).__init__(dryrun, spec, root) | 121 super(GclientGitSvnCheckout, self).__init__(dryrun, spec, root) |
| 90 assert 'solutions' in self.spec | 122 assert 'solutions' in self.spec |
| 91 keys = ['solutions', 'target_os', 'target_os_only'] | 123 keys = ['solutions', 'target_os', 'target_os_only'] |
| 92 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key]) | 124 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key]) |
| 93 for key in self.spec if key in keys) | 125 for key in self.spec if key in keys) |
| 94 self.spec['gclient_spec'] = gclient_spec | 126 self.spec['gclient_spec'] = gclient_spec |
| 95 assert 'svn_url' in self.spec | 127 assert 'svn_url' in self.spec |
| 96 assert 'svn_branch' in self.spec | 128 assert 'svn_branch' in self.spec |
| 97 assert 'svn_ref' in self.spec | 129 assert 'svn_ref' in self.spec |
| 98 | 130 |
| 99 def exists(self): | |
| 100 return os.path.exists(os.path.join(os.getcwd(), self.root)) | |
| 101 | |
| 102 def init(self): | 131 def init(self): |
| 103 # Ensure we are authenticated with subversion for all submodules. | |
| 104 git_svn_dirs = json.loads(self.spec.get('submodule_git_svn_spec', '{}')) | |
| 105 git_svn_dirs.update({self.root: self.spec}) | |
| 106 for _, svn_spec in git_svn_dirs.iteritems(): | |
| 107 try: | |
| 108 self.run_svn('ls', '--non-interactive', svn_spec['svn_url']) | |
| 109 except subprocess.CalledProcessError: | |
| 110 print 'Please run `svn ls %s`' % svn_spec['svn_url'] | |
| 111 return 1 | |
| 112 | |
| 113 # TODO(dpranke): Work around issues w/ delta compression on big repos. | 132 # TODO(dpranke): Work around issues w/ delta compression on big repos. |
| 114 self.run_git('config', '--global', 'core.deltaBaseCacheLimit', '1G') | 133 self.run_git('config', '--global', 'core.deltaBaseCacheLimit', '1G') |
| 115 | 134 |
| 116 # Configure and do the gclient checkout. | 135 # Configure and do the gclient checkout. |
| 117 self.run_gclient('config', '--spec', self.spec['gclient_spec']) | 136 self.run_gclient('config', '--spec', self.spec['gclient_spec']) |
| 118 self.run_gclient('sync') | 137 self.run_gclient('sync') |
| 119 | 138 |
| 120 # Configure git. | 139 # Configure git. |
| 121 wd = os.path.join(self.base, self.root) | 140 wd = os.path.join(self.base, self.root) |
| 122 if self.dryrun: | 141 if self.dryrun: |
| 123 print 'cd %s' % wd | 142 print 'cd %s' % wd |
| 124 self.run_git( | 143 self.run_git( |
| 125 'submodule', 'foreach', | 144 'submodule', 'foreach', |
| 126 'git config -f $toplevel/.git/config submodule.$name.ignore all', | 145 'git config -f $toplevel/.git/config submodule.$name.ignore all', |
| 127 cwd=wd) | 146 cwd=wd) |
| 128 self.run_git('config', 'diff.ignoreSubmodules', 'all', cwd=wd) | 147 self.run_git('config', 'diff.ignoreSubmodules', 'all', cwd=wd) |
|
iannucci
2013/04/06 01:38:18
This should be a call to super
| |
| 129 | 148 |
| 130 # Configure git-svn. | 149 # Configure git-svn. |
| 150 git_svn_dirs = json.loads(self.spec.get('submodule_git_svn_spec', '{}')) | |
| 151 git_svn_dirs.update({self.root: self.spec}) | |
| 131 for path, svn_spec in git_svn_dirs.iteritems(): | 152 for path, svn_spec in git_svn_dirs.iteritems(): |
| 132 real_path = os.path.join(*path.split('/')) | 153 real_path = os.path.join(*path.split('/')) |
| 133 if real_path != self.root: | 154 if real_path != self.root: |
| 134 real_path = os.path.join(self.root, real_path) | 155 real_path = os.path.join(self.root, real_path) |
| 135 wd = os.path.join(self.base, real_path) | 156 wd = os.path.join(self.base, real_path) |
| 136 if self.dryrun: | 157 if self.dryrun: |
| 137 print 'cd %s' % wd | 158 print 'cd %s' % wd |
| 138 self.run_git('svn', 'init', '--prefix=origin/', '-T', | 159 self.run_git('svn', 'init', '--prefix=origin/', '-T', |
| 139 svn_spec['svn_branch'], svn_spec['svn_url'], cwd=wd) | 160 svn_spec['svn_branch'], svn_spec['svn_url'], cwd=wd) |
| 140 self.run_git('config', '--replace', 'svn-remote.svn.fetch', | 161 self.run_git('config', '--replace', 'svn-remote.svn.fetch', |
| 141 svn_spec['svn_branch'] + ':refs/remotes/origin/' + | 162 svn_spec['svn_branch'] + ':refs/remotes/origin/' + |
| 142 svn_spec['svn_ref'], cwd=wd) | 163 svn_spec['svn_ref'], cwd=wd) |
| 143 self.run_git('svn', 'fetch', cwd=wd) | 164 self.run_git('svn', 'fetch', cwd=wd) |
| 144 | 165 |
| 145 | 166 |
| 146 | |
| 147 CHECKOUT_TYPE_MAP = { | 167 CHECKOUT_TYPE_MAP = { |
| 148 'gclient': GclientCheckout, | 168 'gclient': GclientCheckout, |
| 169 'gclient_git': GclientGitCheckout, | |
| 149 'gclient_git_svn': GclientGitSvnCheckout, | 170 'gclient_git_svn': GclientGitSvnCheckout, |
| 150 'git': GitCheckout, | 171 'git': GitCheckout, |
| 151 } | 172 } |
| 152 | 173 |
| 153 | 174 |
| 154 def CheckoutFactory(type_name, dryrun, spec, root): | 175 def CheckoutFactory(type_name, dryrun, spec, root): |
| 155 """Factory to build Checkout class instances.""" | 176 """Factory to build Checkout class instances.""" |
| 156 class_ = CHECKOUT_TYPE_MAP.get(type_name) | 177 class_ = CHECKOUT_TYPE_MAP.get(type_name) |
| 157 if not class_: | 178 if not class_: |
| 158 raise KeyError('unrecognized checkout type: %s' % type_name) | 179 raise KeyError('unrecognized checkout type: %s' % type_name) |
| 159 return class_(dryrun, spec, root) | 180 return class_(dryrun, spec, root) |
| 160 | 181 |
| 161 | 182 |
| 162 ################################################# | 183 ################################################# |
| 163 # Utility function and file entry point. | 184 # Utility function and file entry point. |
| 164 ################################################# | 185 ################################################# |
| 165 def usage(msg=None): | 186 def usage(msg=None): |
| 166 """Print help and exit.""" | 187 """Print help and exit.""" |
| 167 if msg: | 188 if msg: |
| 168 print 'Error:', msg | 189 print 'Error:', msg |
| 169 | 190 |
| 170 print ( | 191 print ( |
| 171 """ | 192 """ |
| 172 usage: %s [-n|--dry-run] <recipe> [--property=value [--property2=value2 ...]] | 193 usage: %s [-n|--dry-run] <recipe> [--property=value [--property2=value2 ...]] |
| 173 """ % os.path.basename(sys.argv[0])) | 194 """ % os.path.basename(sys.argv[0])) |
|
Dirk Pranke
2013/04/06 01:45:25
Since we're hacking here, we should add in a comme
| |
| 174 sys.exit(bool(msg)) | 195 sys.exit(bool(msg)) |
| 175 | 196 |
| 176 | 197 |
| 177 def handle_args(argv): | 198 def handle_args(argv): |
| 178 """Gets the recipe name from the command line arguments.""" | 199 """Gets the recipe name from the command line arguments.""" |
| 179 if len(argv) <= 1: | 200 if len(argv) <= 1: |
| 180 usage('Must specify a recipe.') | 201 usage('Must specify a recipe.') |
| 181 if argv[1] in ('-h', '--help', 'help'): | 202 if argv[1] in ('-h', '--help', 'help'): |
| 182 usage() | 203 usage() |
| 183 | 204 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 | 265 |
| 245 | 266 |
| 246 def main(): | 267 def main(): |
| 247 dryrun, recipe, props = handle_args(sys.argv) | 268 dryrun, recipe, props = handle_args(sys.argv) |
| 248 spec, root = run_recipe_fetch(recipe, props) | 269 spec, root = run_recipe_fetch(recipe, props) |
| 249 return run(dryrun, spec, root) | 270 return run(dryrun, spec, root) |
| 250 | 271 |
| 251 | 272 |
| 252 if __name__ == '__main__': | 273 if __name__ == '__main__': |
| 253 sys.exit(main()) | 274 sys.exit(main()) |
| OLD | NEW |