Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | """Script that resets your Chrome GIT checkout.""" |
| 7 | |
Chris Sosa | 4f6ffaf | 2012-05-01 17:05:44 -0700 | [diff] [blame] | 8 | import logging |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 9 | import optparse |
| 10 | import os |
Ryan Cui | 7d7c88b | 2011-11-01 22:11:55 -0700 | [diff] [blame] | 11 | import re |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 12 | |
Brian Harring | 503f3ab | 2012-03-09 21:39:41 -0800 | [diff] [blame] | 13 | from chromite.buildbot import repository |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 14 | from chromite.lib import cros_build_lib |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 15 | from chromite.lib import git |
Brian Harring | af019fb | 2012-05-10 15:06:13 -0700 | [diff] [blame] | 16 | from chromite.lib import osutils |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 17 | |
| 18 | |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 19 | _CHROMIUM_ROOT = 'chromium' |
| 20 | _CHROMIUM_SRC_ROOT = os.path.join(_CHROMIUM_ROOT, 'src') |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 21 | _CHROMIUM_SRC_INTERNAL = os.path.join(_CHROMIUM_ROOT, 'src-internal') |
Ben Chan | 84ff118 | 2012-07-02 16:17:10 -0700 | [diff] [blame] | 22 | _CHROMIUM_SRC_DEPS = os.path.join(_CHROMIUM_SRC_ROOT, 'DEPS') |
| 23 | _CHROMIUM_CROS_DEP_KEYS = [ 'src/third_party/cros_system_api' ] |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 24 | |
| 25 | |
| 26 | def _LoadDEPS(deps_content): |
| 27 | """Load contents of DEPS file into a dictionary. |
| 28 | |
| 29 | Arguments: |
| 30 | deps_content: The contents of the .DEPS.git file. |
| 31 | |
| 32 | Returns: |
| 33 | A dictionary indexed by the top level items in the structure - i.e., |
| 34 | 'hooks', 'deps', 'os_deps'. |
| 35 | """ |
| 36 | class FromImpl: |
| 37 | """From syntax is not supported.""" |
| 38 | def __init__(self, module_name, var_name): |
| 39 | raise NotImplementedError('The From() syntax is not supported in' |
| 40 | 'chrome_set_ver.') |
| 41 | |
| 42 | class _VarImpl: |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 43 | def __init__(self, custom_vars, local_scope): |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 44 | self._custom_vars = custom_vars |
| 45 | self._local_scope = local_scope |
| 46 | |
| 47 | def Lookup(self, var_name): |
| 48 | """Implements the Var syntax.""" |
| 49 | if var_name in self._custom_vars: |
| 50 | return self._custom_vars[var_name] |
| 51 | elif var_name in self._local_scope.get('vars', {}): |
| 52 | return self._local_scope['vars'][var_name] |
| 53 | raise Exception('Var is not defined: %s' % var_name) |
| 54 | |
David James | 43e14f4 | 2012-12-14 13:44:16 -0800 | [diff] [blame^] | 55 | my_locals = {} |
| 56 | var = _VarImpl({}, my_locals) |
| 57 | my_globals = {'From': FromImpl, 'Var': var.Lookup, 'deps_os': {}} |
| 58 | exec(deps_content) in my_globals, my_locals |
| 59 | return my_locals |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 60 | |
| 61 | |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 62 | def _CreateCrosSymlink(repo_root): |
| 63 | """Create symlinks to CrOS projects specified in the cros_DEPS/DEPS file.""" |
Ben Chan | 84ff118 | 2012-07-02 16:17:10 -0700 | [diff] [blame] | 64 | deps_file = os.path.join(repo_root, _CHROMIUM_SRC_DEPS) |
| 65 | _, merged_deps = GetParsedDeps(deps_file) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 66 | chromium_root = os.path.join(repo_root, _CHROMIUM_ROOT) |
Ryan Cui | af3e2eb | 2011-09-30 16:43:03 -0700 | [diff] [blame] | 67 | |
Ben Chan | 84ff118 | 2012-07-02 16:17:10 -0700 | [diff] [blame] | 68 | # TODO(rcui): Infer Chromium OS dependencies from the Chromium DEPS file. |
| 69 | cros_merged_deps = dict((k, v) for (k, v) in merged_deps.iteritems() |
| 70 | if k in _CHROMIUM_CROS_DEP_KEYS) |
| 71 | mappings = GetPathToProjectMappings(cros_merged_deps) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 72 | for rel_path, project in mappings.iteritems(): |
| 73 | link_dir = os.path.join(chromium_root, rel_path) |
| 74 | target_dir = os.path.join(repo_root, |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 75 | git.GetProjectDir(repo_root, project)) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 76 | path_to_target = os.path.relpath(target_dir, os.path.dirname(link_dir)) |
| 77 | if not os.path.exists(link_dir): |
| 78 | os.symlink(path_to_target, link_dir) |
| 79 | |
| 80 | |
| 81 | def _ExtractProjectFromUrl(repo_url): |
| 82 | """Get the Gerrit project name from an url.""" |
Ryan Cui | 7d7c88b | 2011-11-01 22:11:55 -0700 | [diff] [blame] | 83 | # Example: 'ssh://gerrit-int.chromium.org:12121/my/project.git' would parse to |
| 84 | # 'my/project'. See unit test for more examples. For 'URL's like |
| 85 | # '../abc/efg' leave as-is to support unit tests. |
| 86 | mo = re.match(r'(?:[\w\+]+://[^/]+/)?(.*)', repo_url) |
| 87 | return os.path.splitext(mo.group(1))[0] |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 88 | |
| 89 | |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 90 | def _ExtractProjectFromEntry(entry): |
| 91 | """From a deps entry extract the Gerrit project name. |
| 92 | |
| 93 | Arguments: |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 94 | entry: The deps entry in the format ${url_prefix}/${project_name}@${hash}. |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 95 | """ |
| 96 | # We only support Gerrit urls, where the path is the project name. |
| 97 | repo_url = entry.partition('@')[0] |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 98 | return _ExtractProjectFromUrl(repo_url) |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 99 | |
| 100 | |
| 101 | def GetPathToProjectMappings(deps): |
| 102 | """Get dictionary relating path to Gerrit project names. |
| 103 | |
| 104 | Arguments: |
| 105 | deps: a dictionary indexed by repo paths. The same format as the 'deps' |
| 106 | entry in the '.DEPS.git' file. |
| 107 | """ |
| 108 | mappings = {} |
| 109 | for rel_path, entry in deps.iteritems(): |
| 110 | mappings[rel_path] = _ExtractProjectFromEntry(entry) |
| 111 | |
| 112 | return mappings |
| 113 | |
| 114 | |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 115 | class ProjectException(Exception): |
| 116 | """Raised by Project class when a Pin error """ |
| 117 | pass |
Ryan Cui | b75c303 | 2011-08-10 16:19:39 -0700 | [diff] [blame] | 118 | |
| 119 | |
Brian Harring | 609dc4e | 2012-05-07 02:17:44 -0700 | [diff] [blame] | 120 | def _IsGitStoreInRepo(path): |
| 121 | """Checks if the git repo rooted at a directory is in repo's storage. |
| 122 | |
| 123 | Note that just because a pathway is in .repo, does *not* mean that |
| 124 | repo can actually use it (the git repo must be in the manifest for |
| 125 | that to be true). |
| 126 | """ |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 127 | repo_dir = os.path.realpath(git.FindRepoDir(path)) |
Brian Harring | 609dc4e | 2012-05-07 02:17:44 -0700 | [diff] [blame] | 128 | git_objects_dir = os.path.realpath(os.path.join(path, '.git/objects')) |
| 129 | return git_objects_dir.startswith(repo_dir) |
| 130 | |
| 131 | |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 132 | class Project(object): |
| 133 | """Encapsulates functionality to pin a project to a specific commit.""" |
| 134 | def __init__(self, repo_root, project_url, rel_path): |
| 135 | """Construct the class. |
| 136 | |
| 137 | Arguments: |
| 138 | repo_root: The root of the repo checkout. |
| 139 | project_url: The Gerrit url of the project. |
| 140 | rel_path: The path the project is expected to be checked out to. Relative |
| 141 | to <repo_root>/chromium. |
| 142 | """ |
| 143 | self.repo_root = repo_root |
| 144 | self.chromium_root = os.path.join(self.repo_root, _CHROMIUM_ROOT) |
| 145 | self.project_url = project_url |
| 146 | self.rel_path = rel_path |
| 147 | self.abs_path = os.path.join(self.chromium_root, self.rel_path) |
| 148 | self.manifest_rel_path = os.path.join(_CHROMIUM_ROOT, self.rel_path) |
| 149 | self.project_name = _ExtractProjectFromUrl(self.project_url) |
| 150 | |
| 151 | def _ResetProject(self, commit_hash): |
| 152 | """Actually pin project to the specified commit hash.""" |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 153 | if not git.DoesCommitExistInRepo(self.abs_path, commit_hash): |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 154 | cros_build_lib.Die( |
| 155 | 'Commit %s not found in %s.\n' |
| 156 | "You probably need to run 'repo sync --jobs=<jobs>' " |
| 157 | 'to update your checkout.' |
| 158 | % (commit_hash, self.abs_path)) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 159 | |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 160 | result = cros_build_lib.RunCommand(['git', 'checkout', commit_hash], |
| 161 | error_code_ok=True, cwd=self.abs_path) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 162 | if result.returncode != 0: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 163 | cros_build_lib.Warning('Failed to pin project %s.\n' |
| 164 | 'You probably have uncommited local changes.' |
| 165 | % self.abs_path) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 166 | |
| 167 | def _PrepareProject(self): |
| 168 | """Make sure the project is synced properly and is ready for pinning.""" |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 169 | handler = git.ManifestCheckout.Cached(self.repo_root) |
David James | 1bd7fae | 2012-04-22 10:14:38 -0700 | [diff] [blame] | 170 | path_to_project_dict = dict(([attrs['path'], project]) for project, attrs |
| 171 | in handler.projects.iteritems()) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 172 | |
| 173 | # TODO(rcui): Handle case where a dependency never makes it to the manifest |
| 174 | # (i.e., dep path added as double checkout, and then gets deleted). We need |
| 175 | # to delete those. crosbug/22123. |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 176 | if not git.IsGitRepo(self.abs_path): |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 177 | if self.manifest_rel_path in path_to_project_dict: |
| 178 | raise ProjectException('%s in full layout manifest but not in working ' |
| 179 | "tree. Please run 'repo sync %s'" |
| 180 | % (self.manifest_rel_path, |
| 181 | path_to_project_dict[self.manifest_rel_path])) |
| 182 | else: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 183 | cros_build_lib.Warning( |
| 184 | 'Project %s is not in the manifest. Automatically checking out ' |
| 185 | 'to %s.\n' % (self.project_url, self.abs_path)) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 186 | repository.CloneGitRepo(self.abs_path, self.project_url) |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 187 | cros_build_lib.RunCommand( |
| 188 | ['git', 'checkout', |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 189 | git.GetGitRepoRevision(self.abs_path)], |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 190 | cwd=self.abs_path) |
Brian Harring | 609dc4e | 2012-05-07 02:17:44 -0700 | [diff] [blame] | 191 | elif not _IsGitStoreInRepo(self.abs_path): |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 192 | if self.manifest_rel_path in path_to_project_dict: |
| 193 | # If path is now in the manifest, tell user to manually delete our |
| 194 | # managed checkout and re-sync. |
| 195 | raise ProjectException('%s needs to be replaced. Please remove the ' |
| 196 | "directory and run 'repo sync %s'" |
| 197 | % (self.manifest_rel_path, |
| 198 | path_to_project_dict[self.manifest_rel_path])) |
| 199 | else: |
| 200 | # If not managed by Repo we need to perform sync. |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 201 | cros_build_lib.RunCommand(['git', 'pull', '--rebase', self.project_url], |
| 202 | cwd=self.abs_path) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 203 | elif not os.path.islink(self.abs_path): |
| 204 | # Skip symlinks - we don't want to error out for the cros.DEPS projects. |
| 205 | if self.manifest_rel_path not in path_to_project_dict: |
| 206 | # If it is 'managed by repo' but not in the manifest, repo tried |
| 207 | # deleting it but failed because of local changes. |
| 208 | raise ProjectException('%s is no longer in the manifest but has local ' |
| 209 | 'changes. Please remove and try again.' |
| 210 | % self.manifest_rel_path) |
| 211 | elif self.project_name != path_to_project_dict[self.manifest_rel_path]: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 212 | cros_build_lib.Die( |
| 213 | '.DEPS.git for %s conflicts with manifest.xml! Running with ' |
| 214 | 'older .DEPS.git files are not yet supported. ' |
| 215 | "Please run'repo sync --jobs=<jobs>' to sync everything up." |
| 216 | % self.manifest_rel_path) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 217 | |
| 218 | def Pin(self, commit_hash): |
| 219 | """Attempt to pin the project to the specified commit hash. |
| 220 | |
| 221 | Arguments: |
| 222 | commit_hash: The commit to pin the project to. |
| 223 | |
| 224 | Raises: |
| 225 | ProjectException when an error occurs. |
| 226 | """ |
| 227 | self._PrepareProject() |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 228 | if git.GetCurrentBranch(self.abs_path): |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 229 | cros_build_lib.Warning("Not pinning project %s that's checked out to a " |
| 230 | 'development branch.' % self.rel_path) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 231 | elif (commit_hash and |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 232 | (commit_hash != git.GetGitRepoRevision(self.abs_path))): |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 233 | print 'Pinning project %s' % self.rel_path |
| 234 | self._ResetProject(commit_hash) |
| 235 | else: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 236 | cros_build_lib.Debug('Skipping project %s, already pinned' |
| 237 | % self.rel_path) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 238 | |
| 239 | |
| 240 | def _ResetGitCheckout(repo_root, deps): |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 241 | """Reset chrome repos to hashes specified in the DEPS file. |
| 242 | |
| 243 | Arguments: |
| 244 | chromium_root: directory where chromium is checked out - level above 'src'. |
| 245 | deps: a dictionary indexed by repo paths. The same format as the 'deps' |
| 246 | entry in the '.DEPS.git' file. |
| 247 | """ |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 248 | errors = [] |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 249 | for rel_path, project_hash in deps.iteritems(): |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 250 | repo_url, _, commit_hash = project_hash.partition('@') |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 251 | project = Project(repo_root, repo_url, rel_path) |
| 252 | try: |
| 253 | project.Pin(commit_hash) |
| 254 | except ProjectException as e: |
| 255 | errors.append(str(e)) |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 256 | |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 257 | if errors: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 258 | cros_build_lib.Die('Errors encountered:\n* ' + '\n* '.join(errors)) |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 259 | |
| 260 | |
| 261 | def _RunHooks(chromium_root, hooks): |
| 262 | """Run the hooks contained in the DEPS file. |
| 263 | |
| 264 | Arguments: |
| 265 | chromium_root: directory where chromium is checked out - level above 'src'. |
| 266 | hooks: a list of hook dictionaries. The same format as the 'hooks' entry |
| 267 | in the '.DEPS.git' file. |
| 268 | """ |
| 269 | for hook in hooks: |
Ryan Cui | af3e2eb | 2011-09-30 16:43:03 -0700 | [diff] [blame] | 270 | print '[running hook] %s' % ' '.join(hook['action']) |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 271 | cros_build_lib.RunCommand(hook['action'], cwd=chromium_root) |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 272 | |
| 273 | |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 274 | def _MergeDeps(dest, update): |
| 275 | """Merge the dependencies specified in two dictionaries. |
| 276 | |
| 277 | Arguments: |
| 278 | dest: The dictionary that will be merged into. |
| 279 | update: The dictionary whose elements will be merged into dest. |
| 280 | """ |
| 281 | assert(not set(dest.keys()).intersection(set(update.keys()))) |
| 282 | dest.update(update) |
| 283 | return dest |
| 284 | |
| 285 | |
Ryan Cui | 97b2f30 | 2011-10-24 17:34:05 -0700 | [diff] [blame] | 286 | def GetParsedDeps(deps_file): |
Ryan Cui | 6c85111 | 2011-08-11 21:51:37 -0700 | [diff] [blame] | 287 | """Returns the full parsed DEPS file dictionary, and merged deps. |
| 288 | |
| 289 | Arguments: |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 290 | deps_file: Path to the .DEPS.git file. |
Ryan Cui | 6c85111 | 2011-08-11 21:51:37 -0700 | [diff] [blame] | 291 | |
| 292 | Returns: |
| 293 | An (x,y) tuple. x is a dictionary containing the contents of the DEPS file, |
| 294 | and y is a dictionary containing the result of merging unix and common deps. |
| 295 | """ |
Brian Harring | af019fb | 2012-05-10 15:06:13 -0700 | [diff] [blame] | 296 | deps = _LoadDEPS(osutils.ReadFile(deps_file, 'rU')) |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 297 | merged_deps = deps.get('deps', {}) |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 298 | unix_deps = deps.get('deps_os', {}).get('unix', {}) |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 299 | merged_deps = _MergeDeps(merged_deps, unix_deps) |
Ryan Cui | 6c85111 | 2011-08-11 21:51:37 -0700 | [diff] [blame] | 300 | return deps, merged_deps |
| 301 | |
| 302 | |
Brian Harring | 3067505 | 2012-02-29 12:18:22 -0800 | [diff] [blame] | 303 | def main(argv): |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 304 | |
Ryan Cui | 9ef7c92 | 2011-08-17 11:48:02 -0700 | [diff] [blame] | 305 | usage = 'usage: %prog [-d <DEPS.git file>] [command]' |
| 306 | parser = optparse.OptionParser(usage=usage) |
Ryan Cui | 6c85111 | 2011-08-11 21:51:37 -0700 | [diff] [blame] | 307 | |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 308 | # TODO(rcui): have -d accept a URL. |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 309 | parser.add_option('-d', '--deps', default=None, |
| 310 | help=('DEPS file to use. Defaults to ' |
| 311 | '<chrome_src_root>/.DEPS.git')) |
| 312 | parser.add_option('--internal', action='store_false', dest='internal', |
| 313 | default=True, help='Allow chrome-internal URLs') |
Ryan Cui | 9ef7c92 | 2011-08-17 11:48:02 -0700 | [diff] [blame] | 314 | parser.add_option('--runhooks', action='store_true', dest='runhooks', |
| 315 | default=False, help="Run hooks as well.") |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 316 | parser.add_option('-v', '--verbose', default=False, action='store_true', |
| 317 | help='Run with debug output.') |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 318 | (options, _inputs) = parser.parse_args(argv) |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 319 | |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 320 | # Set cros_build_lib debug level to hide RunCommand spew. |
| 321 | if options.verbose: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 322 | cros_build_lib.logger.setLevel(logging.DEBUG) |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 323 | else: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 324 | cros_build_lib.logger.setLevel(logging.WARNING) |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 325 | |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 326 | if cros_build_lib.IsInsideChroot(): |
Ryan Cui | e52602e | 2011-11-03 15:54:35 -0700 | [diff] [blame] | 327 | ssh_path = '/usr/bin/ssh_no_update' |
| 328 | if os.path.isfile(ssh_path): |
| 329 | os.environ['GIT_SSH'] = ssh_path |
| 330 | else: |
Brian Harring | 1b8c4c8 | 2012-05-29 23:03:04 -0700 | [diff] [blame] | 331 | cros_build_lib.Warning( |
| 332 | "Can't find %s. Run build_packages or setup_board to update " |
| 333 | "your choot." % ssh_path) |
Ryan Cui | e52602e | 2011-11-03 15:54:35 -0700 | [diff] [blame] | 334 | |
David James | 97d9587 | 2012-11-16 15:09:56 -0800 | [diff] [blame] | 335 | repo_root = git.FindRepoCheckoutRoot() |
Ryan Cui | b75c303 | 2011-08-10 16:19:39 -0700 | [diff] [blame] | 336 | chromium_src_root = os.path.join(repo_root, _CHROMIUM_SRC_ROOT) |
Ryan Cui | 4f492d9 | 2012-09-20 16:36:00 -0700 | [diff] [blame] | 337 | if not os.path.isdir(os.path.join(chromium_src_root, '.git')): |
| 338 | error_msg = 'chromium checkout not found at %s.\n' % chromium_src_root |
| 339 | |
| 340 | manifest = os.path.join(repo_root, '.repo', 'manifest.xml') |
| 341 | if os.path.basename(os.path.realpath(manifest)) == 'gerrit-source.xml': |
| 342 | error_msg += ("Please run repo sync and try again.") |
| 343 | else: |
| 344 | link = 'http://www.chromium.org/chromium-os/new-chrome-developer-workflow' |
| 345 | error_msg += ('Detected you are not using gerrit_source.xml. Follow ' |
| 346 | 'instructions at %s to use repo checkout of chrome.' % link) |
| 347 | |
| 348 | cros_build_lib.Die(error_msg) |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 349 | |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 350 | # Add DEPS files to parse. |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 351 | deps_files_to_parse = [] |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 352 | if options.deps: |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 353 | deps_files_to_parse.append(options.deps) |
| 354 | else: |
| 355 | deps_files_to_parse.append(os.path.join(chromium_src_root, '.DEPS.git')) |
Ryan Cui | b603c54 | 2011-07-27 16:00:11 -0700 | [diff] [blame] | 356 | |
Ryan Cui | d1024a8 | 2011-08-26 17:58:36 -0700 | [diff] [blame] | 357 | internal_deps = os.path.join(repo_root, _CHROMIUM_SRC_INTERNAL, '.DEPS.git') |
| 358 | if os.path.exists(internal_deps): |
| 359 | deps_files_to_parse.append(internal_deps) |
| 360 | |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 361 | # Prepare source tree for resetting. |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 362 | chromium_root = os.path.join(repo_root, _CHROMIUM_ROOT) |
Ryan Cui | b75c303 | 2011-08-10 16:19:39 -0700 | [diff] [blame] | 363 | _CreateCrosSymlink(repo_root) |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 364 | |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 365 | # Parse DEPS files and store hooks. |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 366 | hook_dicts = [] |
| 367 | for deps_file in deps_files_to_parse: |
Ryan Cui | 97b2f30 | 2011-10-24 17:34:05 -0700 | [diff] [blame] | 368 | deps, merged_deps = GetParsedDeps(deps_file) |
Ryan Cui | 446e8e7 | 2011-09-23 18:02:41 -0700 | [diff] [blame] | 369 | _ResetGitCheckout(repo_root, merged_deps) |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 370 | hook_dicts.append(deps.get('hooks', {})) |
| 371 | |
Ryan Cui | 65e1f9a | 2011-09-21 17:06:43 -0700 | [diff] [blame] | 372 | # Run hooks after checkout has been reset properly. |
Ryan Cui | 44360de | 2011-08-22 16:50:20 -0700 | [diff] [blame] | 373 | if options.runhooks: |
| 374 | for hooks in hook_dicts: |
| 375 | _RunHooks(chromium_root, hooks) |