diff options
| author | Jason Chang <jasonnc@google.com> | 2023-05-26 12:44:50 -0700 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-08-15 22:14:52 +0000 |
| commit | 8914b1f86db3903e507b26979f6f137907ea3398 (patch) | |
| tree | 6ee19bd7e0f81cccc681729b309a14486787969f | |
| parent | 082487dcd135463313d772cff19b685ea8623793 (diff) | |
| download | git-repo-8914b1f86db3903e507b26979f6f137907ea3398.tar.gz | |
gitc: drop support
Bug: b/282775958
Change-Id: Ib6383d6fd82a017d0a6670d6558a905d41be321f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/375314
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Jason Chang <jasonnc@google.com>
Commit-Queue: Jason Chang <jasonnc@google.com>
| -rw-r--r-- | command.py | 8 | ||||
| -rw-r--r-- | error.py | 4 | ||||
| -rw-r--r-- | gitc_utils.py | 166 | ||||
| -rwxr-xr-x | main.py | 29 | ||||
| -rw-r--r-- | manifest_xml.py | 32 | ||||
| -rwxr-xr-x | repo | 44 | ||||
| -rw-r--r-- | subcmds/gitc_delete.py | 52 | ||||
| -rw-r--r-- | subcmds/gitc_init.py | 87 | ||||
| -rw-r--r-- | subcmds/help.py | 22 | ||||
| -rw-r--r-- | subcmds/init.py | 4 | ||||
| -rw-r--r-- | subcmds/start.py | 44 | ||||
| -rw-r--r-- | subcmds/sync.py | 46 | ||||
| -rw-r--r-- | tests/test_wrapper.py | 8 |
13 files changed, 23 insertions, 523 deletions
| @@ -75,7 +75,6 @@ class Command(object): | |||
| 75 | repodir=None, | 75 | repodir=None, |
| 76 | client=None, | 76 | client=None, |
| 77 | manifest=None, | 77 | manifest=None, |
| 78 | gitc_manifest=None, | ||
| 79 | git_event_log=None, | 78 | git_event_log=None, |
| 80 | outer_client=None, | 79 | outer_client=None, |
| 81 | outer_manifest=None, | 80 | outer_manifest=None, |
| @@ -84,7 +83,6 @@ class Command(object): | |||
| 84 | self.client = client | 83 | self.client = client |
| 85 | self.outer_client = outer_client or client | 84 | self.outer_client = outer_client or client |
| 86 | self.manifest = manifest | 85 | self.manifest = manifest |
| 87 | self.gitc_manifest = gitc_manifest | ||
| 88 | self.git_event_log = git_event_log | 86 | self.git_event_log = git_event_log |
| 89 | self.outer_manifest = outer_manifest | 87 | self.outer_manifest = outer_manifest |
| 90 | 88 | ||
| @@ -506,11 +504,5 @@ class MirrorSafeCommand(object): | |||
| 506 | """ | 504 | """ |
| 507 | 505 | ||
| 508 | 506 | ||
| 509 | class GitcAvailableCommand(object): | ||
| 510 | """Command that requires GITC to be available, but does not require the | ||
| 511 | local client to be a GITC client. | ||
| 512 | """ | ||
| 513 | |||
| 514 | |||
| 515 | class GitcClientCommand(object): | 507 | class GitcClientCommand(object): |
| 516 | """Command that requires the local client to be a GITC client.""" | 508 | """Command that requires the local client to be a GITC client.""" |
| @@ -107,6 +107,10 @@ class GitError(RepoError): | |||
| 107 | return self.message | 107 | return self.message |
| 108 | 108 | ||
| 109 | 109 | ||
| 110 | class GitcUnsupportedError(RepoExitError): | ||
| 111 | """Gitc no longer supported.""" | ||
| 112 | |||
| 113 | |||
| 110 | class UploadError(RepoError): | 114 | class UploadError(RepoError): |
| 111 | """A bundle upload to Gerrit did not succeed.""" | 115 | """A bundle upload to Gerrit did not succeed.""" |
| 112 | 116 | ||
diff --git a/gitc_utils.py b/gitc_utils.py deleted file mode 100644 index 7b72048f..00000000 --- a/gitc_utils.py +++ /dev/null | |||
| @@ -1,166 +0,0 @@ | |||
| 1 | # Copyright (C) 2015 The Android Open Source Project | ||
| 2 | # | ||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | # you may not use this file except in compliance with the License. | ||
| 5 | # You may obtain a copy of the License at | ||
| 6 | # | ||
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | # | ||
| 9 | # Unless required by applicable law or agreed to in writing, software | ||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | # See the License for the specific language governing permissions and | ||
| 13 | # limitations under the License. | ||
| 14 | |||
| 15 | import os | ||
| 16 | import multiprocessing | ||
| 17 | import re | ||
| 18 | import sys | ||
| 19 | import time | ||
| 20 | |||
| 21 | import git_command | ||
| 22 | import git_config | ||
| 23 | import wrapper | ||
| 24 | |||
| 25 | from error import ManifestParseError | ||
| 26 | |||
| 27 | NUM_BATCH_RETRIEVE_REVISIONID = 32 | ||
| 28 | |||
| 29 | |||
| 30 | def get_gitc_manifest_dir(): | ||
| 31 | return wrapper.Wrapper().get_gitc_manifest_dir() | ||
| 32 | |||
| 33 | |||
| 34 | def parse_clientdir(gitc_fs_path): | ||
| 35 | return wrapper.Wrapper().gitc_parse_clientdir(gitc_fs_path) | ||
| 36 | |||
| 37 | |||
| 38 | def _get_project_revision(args): | ||
| 39 | """Worker for _set_project_revisions to lookup one project remote.""" | ||
| 40 | (i, url, expr) = args | ||
| 41 | gitcmd = git_command.GitCommand( | ||
| 42 | None, ["ls-remote", url, expr], capture_stdout=True, cwd="/tmp" | ||
| 43 | ) | ||
| 44 | rc = gitcmd.Wait() | ||
| 45 | return (i, rc, gitcmd.stdout.split("\t", 1)[0]) | ||
| 46 | |||
| 47 | |||
| 48 | def _set_project_revisions(projects): | ||
| 49 | """Sets the revisionExpr for a list of projects. | ||
| 50 | |||
| 51 | Because of the limit of open file descriptors allowed, length of projects | ||
| 52 | should not be overly large. Recommend calling this function multiple times | ||
| 53 | with each call not exceeding NUM_BATCH_RETRIEVE_REVISIONID projects. | ||
| 54 | |||
| 55 | Args: | ||
| 56 | projects: List of project objects to set the revionExpr for. | ||
| 57 | """ | ||
| 58 | # Retrieve the commit id for each project based off of its current | ||
| 59 | # revisionExpr and it is not already a commit id. | ||
| 60 | with multiprocessing.Pool(NUM_BATCH_RETRIEVE_REVISIONID) as pool: | ||
| 61 | results_iter = pool.imap_unordered( | ||
| 62 | _get_project_revision, | ||
| 63 | ( | ||
| 64 | (i, project.remote.url, project.revisionExpr) | ||
| 65 | for i, project in enumerate(projects) | ||
| 66 | if not git_config.IsId(project.revisionExpr) | ||
| 67 | ), | ||
| 68 | chunksize=8, | ||
| 69 | ) | ||
| 70 | for i, rc, revisionExpr in results_iter: | ||
| 71 | project = projects[i] | ||
| 72 | if rc: | ||
| 73 | print( | ||
| 74 | "FATAL: Failed to retrieve revisionExpr for %s" | ||
| 75 | % project.name | ||
| 76 | ) | ||
| 77 | pool.terminate() | ||
| 78 | sys.exit(1) | ||
| 79 | if not revisionExpr: | ||
| 80 | pool.terminate() | ||
| 81 | raise ManifestParseError( | ||
| 82 | "Invalid SHA-1 revision project %s (%s)" | ||
| 83 | % (project.remote.url, project.revisionExpr) | ||
| 84 | ) | ||
| 85 | project.revisionExpr = revisionExpr | ||
| 86 | |||
| 87 | |||
| 88 | def generate_gitc_manifest(gitc_manifest, manifest, paths=None): | ||
| 89 | """Generate a manifest for shafsd to use for this GITC client. | ||
| 90 | |||
| 91 | Args: | ||
| 92 | gitc_manifest: Current gitc manifest, or None if there isn't one yet. | ||
| 93 | manifest: A GitcManifest object loaded with the current repo manifest. | ||
| 94 | paths: List of project paths we want to update. | ||
| 95 | """ | ||
| 96 | |||
| 97 | print( | ||
| 98 | "Generating GITC Manifest by fetching revision SHAs for each " | ||
| 99 | "project." | ||
| 100 | ) | ||
| 101 | if paths is None: | ||
| 102 | paths = list(manifest.paths.keys()) | ||
| 103 | |||
| 104 | groups = [x for x in re.split(r"[,\s]+", manifest.GetGroupsStr()) if x] | ||
| 105 | |||
| 106 | # Convert the paths to projects, and filter them to the matched groups. | ||
| 107 | projects = [manifest.paths[p] for p in paths] | ||
| 108 | projects = [p for p in projects if p.MatchesGroups(groups)] | ||
| 109 | |||
| 110 | if gitc_manifest is not None: | ||
| 111 | for path, proj in manifest.paths.items(): | ||
| 112 | if not proj.MatchesGroups(groups): | ||
| 113 | continue | ||
| 114 | |||
| 115 | if not proj.upstream and not git_config.IsId(proj.revisionExpr): | ||
| 116 | proj.upstream = proj.revisionExpr | ||
| 117 | |||
| 118 | if path not in gitc_manifest.paths: | ||
| 119 | # Any new projects need their first revision, even if we weren't | ||
| 120 | # asked for them. | ||
| 121 | projects.append(proj) | ||
| 122 | elif path not in paths: | ||
| 123 | # And copy revisions from the previous manifest if we're not | ||
| 124 | # updating them now. | ||
| 125 | gitc_proj = gitc_manifest.paths[path] | ||
| 126 | if gitc_proj.old_revision: | ||
| 127 | proj.revisionExpr = None | ||
| 128 | proj.old_revision = gitc_proj.old_revision | ||
| 129 | else: | ||
| 130 | proj.revisionExpr = gitc_proj.revisionExpr | ||
| 131 | |||
| 132 | _set_project_revisions(projects) | ||
| 133 | |||
| 134 | if gitc_manifest is not None: | ||
| 135 | for path, proj in gitc_manifest.paths.items(): | ||
| 136 | if proj.old_revision and path in paths: | ||
| 137 | # If we updated a project that has been started, keep the | ||
| 138 | # old-revision updated. | ||
| 139 | repo_proj = manifest.paths[path] | ||
| 140 | repo_proj.old_revision = repo_proj.revisionExpr | ||
| 141 | repo_proj.revisionExpr = None | ||
| 142 | |||
| 143 | # Convert URLs from relative to absolute. | ||
| 144 | for _name, remote in manifest.remotes.items(): | ||
| 145 | remote.fetchUrl = remote.resolvedFetchUrl | ||
| 146 | |||
| 147 | # Save the manifest. | ||
| 148 | save_manifest(manifest) | ||
| 149 | |||
| 150 | |||
| 151 | def save_manifest(manifest, client_dir=None): | ||
| 152 | """Save the manifest file in the client_dir. | ||
| 153 | |||
| 154 | Args: | ||
| 155 | manifest: Manifest object to save. | ||
| 156 | client_dir: Client directory to save the manifest in. | ||
| 157 | """ | ||
| 158 | if not client_dir: | ||
| 159 | manifest_file = manifest.manifestFile | ||
| 160 | else: | ||
| 161 | manifest_file = os.path.join(client_dir, ".manifest") | ||
| 162 | with open(manifest_file, "w") as f: | ||
| 163 | manifest.Save(f, groups=manifest.GetGroupsStr()) | ||
| 164 | # TODO(sbasi/jorg): Come up with a solution to remove the sleep below. | ||
| 165 | # Give the GITC filesystem time to register the manifest changes. | ||
| 166 | time.sleep(3) | ||
| @@ -45,7 +45,6 @@ from git_config import RepoConfig | |||
| 45 | from git_trace2_event_log import EventLog | 45 | from git_trace2_event_log import EventLog |
| 46 | from command import InteractiveCommand | 46 | from command import InteractiveCommand |
| 47 | from command import MirrorSafeCommand | 47 | from command import MirrorSafeCommand |
| 48 | from command import GitcAvailableCommand, GitcClientCommand | ||
| 49 | from subcmds.version import Version | 48 | from subcmds.version import Version |
| 50 | from editor import Editor | 49 | from editor import Editor |
| 51 | from error import DownloadError | 50 | from error import DownloadError |
| @@ -58,8 +57,8 @@ from error import RepoExitError | |||
| 58 | from error import RepoUnhandledExceptionError | 57 | from error import RepoUnhandledExceptionError |
| 59 | from error import RepoError | 58 | from error import RepoError |
| 60 | from error import SilentRepoExitError | 59 | from error import SilentRepoExitError |
| 61 | import gitc_utils | 60 | from error import GitcUnsupportedError |
| 62 | from manifest_xml import GitcClient, RepoClient | 61 | from manifest_xml import RepoClient |
| 63 | from pager import RunPager, TerminatePager | 62 | from pager import RunPager, TerminatePager |
| 64 | from wrapper import WrapperPath, Wrapper | 63 | from wrapper import WrapperPath, Wrapper |
| 65 | 64 | ||
| @@ -304,11 +303,10 @@ class _Repo(object): | |||
| 304 | submanifest_path=gopts.submanifest_path, | 303 | submanifest_path=gopts.submanifest_path, |
| 305 | outer_client=outer_client, | 304 | outer_client=outer_client, |
| 306 | ) | 305 | ) |
| 307 | gitc_manifest = None | 306 | |
| 308 | gitc_client_name = gitc_utils.parse_clientdir(os.getcwd()) | 307 | if Wrapper().gitc_parse_clientdir(os.getcwd()): |
| 309 | if gitc_client_name: | 308 | print("GITC is not supported.", file=sys.stderr) |
| 310 | gitc_manifest = GitcClient(self.repodir, gitc_client_name) | 309 | raise GitcUnsupportedError() |
| 311 | repo_client.isGitcClient = True | ||
| 312 | 310 | ||
| 313 | try: | 311 | try: |
| 314 | cmd = self.commands[name]( | 312 | cmd = self.commands[name]( |
| @@ -317,7 +315,6 @@ class _Repo(object): | |||
| 317 | manifest=repo_client.manifest, | 315 | manifest=repo_client.manifest, |
| 318 | outer_client=outer_client, | 316 | outer_client=outer_client, |
| 319 | outer_manifest=outer_client.manifest, | 317 | outer_manifest=outer_client.manifest, |
| 320 | gitc_manifest=gitc_manifest, | ||
| 321 | git_event_log=git_trace2_event_log, | 318 | git_event_log=git_trace2_event_log, |
| 322 | ) | 319 | ) |
| 323 | except KeyError: | 320 | except KeyError: |
| @@ -336,20 +333,6 @@ class _Repo(object): | |||
| 336 | ) | 333 | ) |
| 337 | return 1 | 334 | return 1 |
| 338 | 335 | ||
| 339 | if ( | ||
| 340 | isinstance(cmd, GitcAvailableCommand) | ||
| 341 | and not gitc_utils.get_gitc_manifest_dir() | ||
| 342 | ): | ||
| 343 | print( | ||
| 344 | "fatal: '%s' requires GITC to be available" % name, | ||
| 345 | file=sys.stderr, | ||
| 346 | ) | ||
| 347 | return 1 | ||
| 348 | |||
| 349 | if isinstance(cmd, GitcClientCommand) and not gitc_client_name: | ||
| 350 | print("fatal: '%s' requires a GITC client" % name, file=sys.stderr) | ||
| 351 | return 1 | ||
| 352 | |||
| 353 | try: | 336 | try: |
| 354 | copts, cargs = cmd.OptionParser.parse_args(argv) | 337 | copts, cargs = cmd.OptionParser.parse_args(argv) |
| 355 | copts = cmd.ReadEnvironmentOptions(copts) | 338 | copts = cmd.ReadEnvironmentOptions(copts) |
diff --git a/manifest_xml.py b/manifest_xml.py index 73be1b6e..80e563a5 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
| @@ -21,7 +21,6 @@ import sys | |||
| 21 | import xml.dom.minidom | 21 | import xml.dom.minidom |
| 22 | import urllib.parse | 22 | import urllib.parse |
| 23 | 23 | ||
| 24 | import gitc_utils | ||
| 25 | from git_config import GitConfig | 24 | from git_config import GitConfig |
| 26 | from git_refs import R_HEADS, HEAD | 25 | from git_refs import R_HEADS, HEAD |
| 27 | from git_superproject import Superproject | 26 | from git_superproject import Superproject |
| @@ -2248,21 +2247,6 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 2248 | return diff | 2247 | return diff |
| 2249 | 2248 | ||
| 2250 | 2249 | ||
| 2251 | class GitcManifest(XmlManifest): | ||
| 2252 | """Parser for GitC (git-in-the-cloud) manifests.""" | ||
| 2253 | |||
| 2254 | def _ParseProject(self, node, parent=None): | ||
| 2255 | """Override _ParseProject and add support for GITC specific attributes.""" # noqa: E501 | ||
| 2256 | return super()._ParseProject( | ||
| 2257 | node, parent=parent, old_revision=node.getAttribute("old-revision") | ||
| 2258 | ) | ||
| 2259 | |||
| 2260 | def _output_manifest_project_extras(self, p, e): | ||
| 2261 | """Output GITC Specific Project attributes""" | ||
| 2262 | if p.old_revision: | ||
| 2263 | e.setAttribute("old-revision", str(p.old_revision)) | ||
| 2264 | |||
| 2265 | |||
| 2266 | class RepoClient(XmlManifest): | 2250 | class RepoClient(XmlManifest): |
| 2267 | """Manages a repo client checkout.""" | 2251 | """Manages a repo client checkout.""" |
| 2268 | 2252 | ||
| @@ -2315,19 +2299,3 @@ class RepoClient(XmlManifest): | |||
| 2315 | 2299 | ||
| 2316 | # TODO: Completely separate manifest logic out of the client. | 2300 | # TODO: Completely separate manifest logic out of the client. |
| 2317 | self.manifest = self | 2301 | self.manifest = self |
| 2318 | |||
| 2319 | |||
| 2320 | class GitcClient(RepoClient, GitcManifest): | ||
| 2321 | """Manages a GitC client checkout.""" | ||
| 2322 | |||
| 2323 | def __init__(self, repodir, gitc_client_name): | ||
| 2324 | """Initialize the GitcManifest object.""" | ||
| 2325 | self.gitc_client_name = gitc_client_name | ||
| 2326 | self.gitc_client_dir = os.path.join( | ||
| 2327 | gitc_utils.get_gitc_manifest_dir(), gitc_client_name | ||
| 2328 | ) | ||
| 2329 | |||
| 2330 | super().__init__( | ||
| 2331 | repodir, os.path.join(self.gitc_client_dir, ".manifest") | ||
| 2332 | ) | ||
| 2333 | self.isGitcClient = True | ||
| @@ -149,7 +149,7 @@ if not REPO_REV: | |||
| 149 | BUG_URL = 'https://issues.gerritcodereview.com/issues/new?component=1370071' | 149 | BUG_URL = 'https://issues.gerritcodereview.com/issues/new?component=1370071' |
| 150 | 150 | ||
| 151 | # increment this whenever we make important changes to this script | 151 | # increment this whenever we make important changes to this script |
| 152 | VERSION = (2, 35) | 152 | VERSION = (2, 36) |
| 153 | 153 | ||
| 154 | # increment this if the MAINTAINER_KEYS block is modified | 154 | # increment this if the MAINTAINER_KEYS block is modified |
| 155 | KEYRING_VERSION = (2, 3) | 155 | KEYRING_VERSION = (2, 3) |
| @@ -273,16 +273,16 @@ gpg_dir = os.path.join(home_dot_repo, 'gnupg') | |||
| 273 | def GetParser(gitc_init=False): | 273 | def GetParser(gitc_init=False): |
| 274 | """Setup the CLI parser.""" | 274 | """Setup the CLI parser.""" |
| 275 | if gitc_init: | 275 | if gitc_init: |
| 276 | usage = 'repo gitc-init -c client [options] [-u] url' | 276 | sys.exit('repo: fatal: GITC not supported.') |
| 277 | else: | 277 | else: |
| 278 | usage = 'repo init [options] [-u] url' | 278 | usage = 'repo init [options] [-u] url' |
| 279 | 279 | ||
| 280 | parser = optparse.OptionParser(usage=usage) | 280 | parser = optparse.OptionParser(usage=usage) |
| 281 | InitParser(parser, gitc_init=gitc_init) | 281 | InitParser(parser) |
| 282 | return parser | 282 | return parser |
| 283 | 283 | ||
| 284 | 284 | ||
| 285 | def InitParser(parser, gitc_init=False): | 285 | def InitParser(parser): |
| 286 | """Setup the CLI parser.""" | 286 | """Setup the CLI parser.""" |
| 287 | # NB: Keep in sync with command.py:_CommonOptions(). | 287 | # NB: Keep in sync with command.py:_CommonOptions(). |
| 288 | 288 | ||
| @@ -325,12 +325,8 @@ def InitParser(parser, gitc_init=False): | |||
| 325 | # Options that only affect manifest project, and not any of the projects | 325 | # Options that only affect manifest project, and not any of the projects |
| 326 | # specified in the manifest itself. | 326 | # specified in the manifest itself. |
| 327 | group = parser.add_option_group('Manifest (only) checkout options') | 327 | group = parser.add_option_group('Manifest (only) checkout options') |
| 328 | cbr_opts = ['--current-branch'] | 328 | |
| 329 | # The gitc-init subcommand allocates -c itself, but a lot of init users | 329 | group.add_option('--current-branch', '-c', default=True, |
| 330 | # want -c, so try to satisfy both as best we can. | ||
| 331 | if not gitc_init: | ||
| 332 | cbr_opts += ['-c'] | ||
| 333 | group.add_option(*cbr_opts, default=True, | ||
| 334 | dest='current_branch_only', action='store_true', | 330 | dest='current_branch_only', action='store_true', |
| 335 | help='fetch only current manifest branch from server (default)') | 331 | help='fetch only current manifest branch from server (default)') |
| 336 | group.add_option('--no-current-branch', | 332 | group.add_option('--no-current-branch', |
| @@ -411,14 +407,6 @@ def InitParser(parser, gitc_init=False): | |||
| 411 | action='store_true', default=False, | 407 | action='store_true', default=False, |
| 412 | help='Always prompt for name/e-mail') | 408 | help='Always prompt for name/e-mail') |
| 413 | 409 | ||
| 414 | # gitc-init specific settings. | ||
| 415 | if gitc_init: | ||
| 416 | group = parser.add_option_group('GITC options') | ||
| 417 | group.add_option('-f', '--manifest-file', | ||
| 418 | help='Optional manifest file to use for this GITC client.') | ||
| 419 | group.add_option('-c', '--gitc-client', | ||
| 420 | help='Name of the gitc_client instance to create or modify.') | ||
| 421 | |||
| 422 | return parser | 410 | return parser |
| 423 | 411 | ||
| 424 | 412 | ||
| @@ -582,26 +570,6 @@ def _Init(args, gitc_init=False): | |||
| 582 | rev = opt.repo_rev or REPO_REV | 570 | rev = opt.repo_rev or REPO_REV |
| 583 | 571 | ||
| 584 | try: | 572 | try: |
| 585 | if gitc_init: | ||
| 586 | gitc_manifest_dir = get_gitc_manifest_dir() | ||
| 587 | if not gitc_manifest_dir: | ||
| 588 | print('fatal: GITC filesystem is not available. Exiting...', | ||
| 589 | file=sys.stderr) | ||
| 590 | sys.exit(1) | ||
| 591 | gitc_client = opt.gitc_client | ||
| 592 | if not gitc_client: | ||
| 593 | gitc_client = gitc_parse_clientdir(os.getcwd()) | ||
| 594 | if not gitc_client: | ||
| 595 | print('fatal: GITC client (-c) is required.', file=sys.stderr) | ||
| 596 | sys.exit(1) | ||
| 597 | client_dir = os.path.join(gitc_manifest_dir, gitc_client) | ||
| 598 | if not os.path.exists(client_dir): | ||
| 599 | os.makedirs(client_dir) | ||
| 600 | os.chdir(client_dir) | ||
| 601 | if os.path.exists(repodir): | ||
| 602 | # This GITC Client has already initialized repo so continue. | ||
| 603 | return | ||
| 604 | |||
| 605 | os.mkdir(repodir) | 573 | os.mkdir(repodir) |
| 606 | except OSError as e: | 574 | except OSError as e: |
| 607 | if e.errno != errno.EEXIST: | 575 | if e.errno != errno.EEXIST: |
diff --git a/subcmds/gitc_delete.py b/subcmds/gitc_delete.py deleted file mode 100644 index ae9d4d1f..00000000 --- a/subcmds/gitc_delete.py +++ /dev/null | |||
| @@ -1,52 +0,0 @@ | |||
| 1 | # Copyright (C) 2015 The Android Open Source Project | ||
| 2 | # | ||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | # you may not use this file except in compliance with the License. | ||
| 5 | # You may obtain a copy of the License at | ||
| 6 | # | ||
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | # | ||
| 9 | # Unless required by applicable law or agreed to in writing, software | ||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | # See the License for the specific language governing permissions and | ||
| 13 | # limitations under the License. | ||
| 14 | |||
| 15 | import sys | ||
| 16 | |||
| 17 | from command import Command, GitcClientCommand | ||
| 18 | import platform_utils | ||
| 19 | |||
| 20 | |||
| 21 | class GitcDelete(Command, GitcClientCommand): | ||
| 22 | COMMON = True | ||
| 23 | visible_everywhere = False | ||
| 24 | helpSummary = "Delete a GITC Client." | ||
| 25 | helpUsage = """ | ||
| 26 | %prog | ||
| 27 | """ | ||
| 28 | helpDescription = """ | ||
| 29 | This subcommand deletes the current GITC client, deleting the GITC manifest | ||
| 30 | and all locally downloaded sources. | ||
| 31 | """ | ||
| 32 | |||
| 33 | def _Options(self, p): | ||
| 34 | p.add_option( | ||
| 35 | "-f", | ||
| 36 | "--force", | ||
| 37 | dest="force", | ||
| 38 | action="store_true", | ||
| 39 | help="force the deletion (no prompt)", | ||
| 40 | ) | ||
| 41 | |||
| 42 | def Execute(self, opt, args): | ||
| 43 | if not opt.force: | ||
| 44 | prompt = ( | ||
| 45 | "This will delete GITC client: %s\nAre you sure? (yes/no) " | ||
| 46 | % self.gitc_manifest.gitc_client_name | ||
| 47 | ) | ||
| 48 | response = input(prompt).lower() | ||
| 49 | if not response == "yes": | ||
| 50 | print('Response was not "yes"\n Exiting...') | ||
| 51 | sys.exit(1) | ||
| 52 | platform_utils.rmtree(self.gitc_manifest.gitc_client_dir) | ||
diff --git a/subcmds/gitc_init.py b/subcmds/gitc_init.py deleted file mode 100644 index 54791d58..00000000 --- a/subcmds/gitc_init.py +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | # Copyright (C) 2015 The Android Open Source Project | ||
| 2 | # | ||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | # you may not use this file except in compliance with the License. | ||
| 5 | # You may obtain a copy of the License at | ||
| 6 | # | ||
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | # | ||
| 9 | # Unless required by applicable law or agreed to in writing, software | ||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | # See the License for the specific language governing permissions and | ||
| 13 | # limitations under the License. | ||
| 14 | |||
| 15 | import os | ||
| 16 | import sys | ||
| 17 | |||
| 18 | import gitc_utils | ||
| 19 | from command import GitcAvailableCommand | ||
| 20 | from manifest_xml import GitcManifest | ||
| 21 | from subcmds import init | ||
| 22 | import wrapper | ||
| 23 | |||
| 24 | |||
| 25 | class GitcInit(init.Init, GitcAvailableCommand): | ||
| 26 | COMMON = True | ||
| 27 | MULTI_MANIFEST_SUPPORT = False | ||
| 28 | helpSummary = "Initialize a GITC Client." | ||
| 29 | helpUsage = """ | ||
| 30 | %prog [options] [client name] | ||
| 31 | """ | ||
| 32 | helpDescription = """ | ||
| 33 | The '%prog' command is ran to initialize a new GITC client for use | ||
| 34 | with the GITC file system. | ||
| 35 | |||
| 36 | This command will setup the client directory, initialize repo, just | ||
| 37 | like repo init does, and then downloads the manifest collection | ||
| 38 | and installs it in the .repo/directory of the GITC client. | ||
| 39 | |||
| 40 | Once this is done, a GITC manifest is generated by pulling the HEAD | ||
| 41 | SHA for each project and generates the properly formatted XML file | ||
| 42 | and installs it as .manifest in the GITC client directory. | ||
| 43 | |||
| 44 | The -c argument is required to specify the GITC client name. | ||
| 45 | |||
| 46 | The optional -f argument can be used to specify the manifest file to | ||
| 47 | use for this GITC client. | ||
| 48 | """ | ||
| 49 | |||
| 50 | def _Options(self, p): | ||
| 51 | super()._Options(p, gitc_init=True) | ||
| 52 | |||
| 53 | def Execute(self, opt, args): | ||
| 54 | gitc_client = gitc_utils.parse_clientdir(os.getcwd()) | ||
| 55 | if not gitc_client or ( | ||
| 56 | opt.gitc_client and gitc_client != opt.gitc_client | ||
| 57 | ): | ||
| 58 | print( | ||
| 59 | "fatal: Please update your repo command. See go/gitc for " | ||
| 60 | "instructions.", | ||
| 61 | file=sys.stderr, | ||
| 62 | ) | ||
| 63 | sys.exit(1) | ||
| 64 | self.client_dir = os.path.join( | ||
| 65 | gitc_utils.get_gitc_manifest_dir(), gitc_client | ||
| 66 | ) | ||
| 67 | super().Execute(opt, args) | ||
| 68 | |||
| 69 | manifest_file = self.manifest.manifestFile | ||
| 70 | if opt.manifest_file: | ||
| 71 | if not os.path.exists(opt.manifest_file): | ||
| 72 | print( | ||
| 73 | "fatal: Specified manifest file %s does not exist." | ||
| 74 | % opt.manifest_file | ||
| 75 | ) | ||
| 76 | sys.exit(1) | ||
| 77 | manifest_file = opt.manifest_file | ||
| 78 | |||
| 79 | manifest = GitcManifest( | ||
| 80 | self.repodir, os.path.join(self.client_dir, ".manifest") | ||
| 81 | ) | ||
| 82 | manifest.Override(manifest_file) | ||
| 83 | gitc_utils.generate_gitc_manifest(None, manifest) | ||
| 84 | print( | ||
| 85 | "Please run `cd %s` to view your GITC client." | ||
| 86 | % os.path.join(wrapper.Wrapper().GITC_FS_ROOT_DIR, gitc_client) | ||
| 87 | ) | ||
diff --git a/subcmds/help.py b/subcmds/help.py index 593bf676..0d7b664e 100644 --- a/subcmds/help.py +++ b/subcmds/help.py | |||
| @@ -21,10 +21,7 @@ from color import Coloring | |||
| 21 | from command import ( | 21 | from command import ( |
| 22 | PagedCommand, | 22 | PagedCommand, |
| 23 | MirrorSafeCommand, | 23 | MirrorSafeCommand, |
| 24 | GitcAvailableCommand, | ||
| 25 | GitcClientCommand, | ||
| 26 | ) | 24 | ) |
| 27 | import gitc_utils | ||
| 28 | from wrapper import Wrapper | 25 | from wrapper import Wrapper |
| 29 | from error import RepoExitError | 26 | from error import RepoExitError |
| 30 | 27 | ||
| @@ -79,26 +76,9 @@ Displays detailed usage information about a command. | |||
| 79 | def PrintCommonCommandsBody(self): | 76 | def PrintCommonCommandsBody(self): |
| 80 | print("The most commonly used repo commands are:") | 77 | print("The most commonly used repo commands are:") |
| 81 | 78 | ||
| 82 | def gitc_supported(cmd): | ||
| 83 | if not isinstance(cmd, GitcAvailableCommand) and not isinstance( | ||
| 84 | cmd, GitcClientCommand | ||
| 85 | ): | ||
| 86 | return True | ||
| 87 | if self.client.isGitcClient: | ||
| 88 | return True | ||
| 89 | if isinstance(cmd, GitcClientCommand): | ||
| 90 | return False | ||
| 91 | if gitc_utils.get_gitc_manifest_dir(): | ||
| 92 | return True | ||
| 93 | return False | ||
| 94 | |||
| 95 | commandNames = list( | 79 | commandNames = list( |
| 96 | sorted( | 80 | sorted( |
| 97 | [ | 81 | name for name, command in all_commands.items() if command.COMMON |
| 98 | name | ||
| 99 | for name, command in all_commands.items() | ||
| 100 | if command.COMMON and gitc_supported(command) | ||
| 101 | ] | ||
| 102 | ) | 82 | ) |
| 103 | ) | 83 | ) |
| 104 | self._PrintCommands(commandNames) | 84 | self._PrintCommands(commandNames) |
diff --git a/subcmds/init.py b/subcmds/init.py index 868d339e..c5a2c54c 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
| @@ -84,8 +84,8 @@ to update the working directory files. | |||
| 84 | def _CommonOptions(self, p): | 84 | def _CommonOptions(self, p): |
| 85 | """Disable due to re-use of Wrapper().""" | 85 | """Disable due to re-use of Wrapper().""" |
| 86 | 86 | ||
| 87 | def _Options(self, p, gitc_init=False): | 87 | def _Options(self, p): |
| 88 | Wrapper().InitParser(p, gitc_init=gitc_init) | 88 | Wrapper().InitParser(p) |
| 89 | m = p.add_option_group("Multi-manifest") | 89 | m = p.add_option_group("Multi-manifest") |
| 90 | m.add_option( | 90 | m.add_option( |
| 91 | "--outer-manifest", | 91 | "--outer-manifest", |
diff --git a/subcmds/start.py b/subcmds/start.py index 67ac7df9..481d9ef2 100644 --- a/subcmds/start.py +++ b/subcmds/start.py | |||
| @@ -13,15 +13,13 @@ | |||
| 13 | # limitations under the License. | 13 | # limitations under the License. |
| 14 | 14 | ||
| 15 | import functools | 15 | import functools |
| 16 | import os | ||
| 17 | import sys | 16 | import sys |
| 18 | 17 | ||
| 19 | from command import Command, DEFAULT_LOCAL_JOBS | 18 | from command import Command, DEFAULT_LOCAL_JOBS |
| 20 | from git_config import IsImmutable | 19 | from git_config import IsImmutable |
| 21 | from git_command import git | 20 | from git_command import git |
| 22 | import gitc_utils | ||
| 23 | from progress import Progress | 21 | from progress import Progress |
| 24 | from project import SyncBuffer, Project | 22 | from project import Project |
| 25 | from typing import NamedTuple | 23 | from typing import NamedTuple |
| 26 | from error import RepoExitError | 24 | from error import RepoExitError |
| 27 | 25 | ||
| @@ -115,49 +113,9 @@ revision specified in the manifest. | |||
| 115 | 113 | ||
| 116 | all_projects = self.GetProjects( | 114 | all_projects = self.GetProjects( |
| 117 | projects, | 115 | projects, |
| 118 | missing_ok=bool(self.gitc_manifest), | ||
| 119 | all_manifests=not opt.this_manifest_only, | 116 | all_manifests=not opt.this_manifest_only, |
| 120 | ) | 117 | ) |
| 121 | 118 | ||
| 122 | # This must happen after we find all_projects, since GetProjects may | ||
| 123 | # need the local directory, which will disappear once we save the GITC | ||
| 124 | # manifest. | ||
| 125 | if self.gitc_manifest: | ||
| 126 | gitc_projects = self.GetProjects( | ||
| 127 | projects, manifest=self.gitc_manifest, missing_ok=True | ||
| 128 | ) | ||
| 129 | for project in gitc_projects: | ||
| 130 | if project.old_revision: | ||
| 131 | project.already_synced = True | ||
| 132 | else: | ||
| 133 | project.already_synced = False | ||
| 134 | project.old_revision = project.revisionExpr | ||
| 135 | project.revisionExpr = None | ||
| 136 | # Save the GITC manifest. | ||
| 137 | gitc_utils.save_manifest(self.gitc_manifest) | ||
| 138 | |||
| 139 | # Make sure we have a valid CWD. | ||
| 140 | if not os.path.exists(os.getcwd()): | ||
| 141 | os.chdir(self.manifest.topdir) | ||
| 142 | |||
| 143 | pm = Progress("Syncing %s" % nb, len(all_projects), quiet=opt.quiet) | ||
| 144 | for project in all_projects: | ||
| 145 | gitc_project = self.gitc_manifest.paths[project.relpath] | ||
| 146 | # Sync projects that have not been opened. | ||
| 147 | if not gitc_project.already_synced: | ||
| 148 | proj_localdir = os.path.join( | ||
| 149 | self.gitc_manifest.gitc_client_dir, project.relpath | ||
| 150 | ) | ||
| 151 | project.worktree = proj_localdir | ||
| 152 | if not os.path.exists(proj_localdir): | ||
| 153 | os.makedirs(proj_localdir) | ||
| 154 | project.Sync_NetworkHalf() | ||
| 155 | sync_buf = SyncBuffer(self.manifest.manifestProject.config) | ||
| 156 | project.Sync_LocalHalf(sync_buf) | ||
| 157 | project.revisionId = gitc_project.old_revision | ||
| 158 | pm.update(msg="") | ||
| 159 | pm.end() | ||
| 160 | |||
| 161 | def _ProcessResults(_pool, pm, results): | 119 | def _ProcessResults(_pool, pm, results): |
| 162 | for result in results: | 120 | for result in results: |
| 163 | if result.error: | 121 | if result.error: |
diff --git a/subcmds/sync.py b/subcmds/sync.py index 3fa6efa5..df536892 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -54,7 +54,6 @@ from git_command import git_require | |||
| 54 | from git_config import GetUrlCookieFile | 54 | from git_config import GetUrlCookieFile |
| 55 | from git_refs import R_HEADS, HEAD | 55 | from git_refs import R_HEADS, HEAD |
| 56 | import git_superproject | 56 | import git_superproject |
| 57 | import gitc_utils | ||
| 58 | from project import Project | 57 | from project import Project |
| 59 | from project import RemoteSpec | 58 | from project import RemoteSpec |
| 60 | from command import ( | 59 | from command import ( |
| @@ -77,7 +76,6 @@ from progress import Progress, elapsed_str, jobs_str | |||
| 77 | from repo_trace import Trace | 76 | from repo_trace import Trace |
| 78 | import ssh | 77 | import ssh |
| 79 | from wrapper import Wrapper | 78 | from wrapper import Wrapper |
| 80 | from manifest_xml import GitcManifest | ||
| 81 | 79 | ||
| 82 | _ONE_DAY_S = 24 * 60 * 60 | 80 | _ONE_DAY_S = 24 * 60 * 60 |
| 83 | 81 | ||
| @@ -1678,50 +1676,6 @@ later is required to fix a server side protocol bug. | |||
| 1678 | opt, args, superproject_logging_data, manifest | 1676 | opt, args, superproject_logging_data, manifest |
| 1679 | ) | 1677 | ) |
| 1680 | 1678 | ||
| 1681 | if self.gitc_manifest: | ||
| 1682 | gitc_manifest_projects = self.GetProjects(args, missing_ok=True) | ||
| 1683 | gitc_projects = [] | ||
| 1684 | opened_projects = [] | ||
| 1685 | for project in gitc_manifest_projects: | ||
| 1686 | if ( | ||
| 1687 | project.relpath in self.gitc_manifest.paths | ||
| 1688 | and self.gitc_manifest.paths[project.relpath].old_revision | ||
| 1689 | ): | ||
| 1690 | opened_projects.append(project.relpath) | ||
| 1691 | else: | ||
| 1692 | gitc_projects.append(project.relpath) | ||
| 1693 | |||
| 1694 | if not args: | ||
| 1695 | gitc_projects = None | ||
| 1696 | |||
| 1697 | if gitc_projects != [] and not opt.local_only: | ||
| 1698 | print( | ||
| 1699 | "Updating GITC client: %s" | ||
| 1700 | % self.gitc_manifest.gitc_client_name | ||
| 1701 | ) | ||
| 1702 | manifest = GitcManifest( | ||
| 1703 | self.repodir, self.gitc_manifest.gitc_client_name | ||
| 1704 | ) | ||
| 1705 | if manifest_name: | ||
| 1706 | manifest.Override(manifest_name) | ||
| 1707 | else: | ||
| 1708 | manifest.Override(manifest.manifestFile) | ||
| 1709 | gitc_utils.generate_gitc_manifest( | ||
| 1710 | self.gitc_manifest, manifest, gitc_projects | ||
| 1711 | ) | ||
| 1712 | print("GITC client successfully synced.") | ||
| 1713 | |||
| 1714 | # The opened projects need to be synced as normal, therefore we | ||
| 1715 | # generate a new args list to represent the opened projects. | ||
| 1716 | # TODO: make this more reliable -- if there's a project name/path | ||
| 1717 | # overlap, this may choose the wrong project. | ||
| 1718 | args = [ | ||
| 1719 | os.path.relpath(manifest.paths[path].worktree, os.getcwd()) | ||
| 1720 | for path in opened_projects | ||
| 1721 | ] | ||
| 1722 | if not args: | ||
| 1723 | return | ||
| 1724 | |||
| 1725 | all_projects = self.GetProjects( | 1679 | all_projects = self.GetProjects( |
| 1726 | args, | 1680 | args, |
| 1727 | missing_ok=True, | 1681 | missing_ok=True, |
diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 21fa094d..4e8263b2 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py | |||
| @@ -76,11 +76,9 @@ class RepoWrapperUnitTest(RepoWrapperTestCase): | |||
| 76 | self.assertIsNone(opts.manifest_url) | 76 | self.assertIsNone(opts.manifest_url) |
| 77 | 77 | ||
| 78 | def test_gitc_init_parser(self): | 78 | def test_gitc_init_parser(self): |
| 79 | """Make sure 'gitc-init' GetParser works.""" | 79 | """Make sure 'gitc-init' GetParser raises.""" |
| 80 | parser = self.wrapper.GetParser(gitc_init=True) | 80 | with self.assertRaises(SystemExit): |
| 81 | opts, args = parser.parse_args([]) | 81 | self.wrapper.GetParser(gitc_init=True) |
| 82 | self.assertEqual([], args) | ||
| 83 | self.assertIsNone(opts.manifest_file) | ||
| 84 | 82 | ||
| 85 | def test_get_gitc_manifest_dir_no_gitc(self): | 83 | def test_get_gitc_manifest_dir_no_gitc(self): |
| 86 | """ | 84 | """ |
