summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--command.py8
-rw-r--r--error.py4
-rw-r--r--gitc_utils.py166
-rwxr-xr-xmain.py29
-rw-r--r--manifest_xml.py32
-rwxr-xr-xrepo44
-rw-r--r--subcmds/gitc_delete.py52
-rw-r--r--subcmds/gitc_init.py87
-rw-r--r--subcmds/help.py22
-rw-r--r--subcmds/init.py4
-rw-r--r--subcmds/start.py44
-rw-r--r--subcmds/sync.py46
-rw-r--r--tests/test_wrapper.py8
13 files changed, 23 insertions, 523 deletions
diff --git a/command.py b/command.py
index d2129381..0205932d 100644
--- a/command.py
+++ b/command.py
@@ -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
509class 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
515class GitcClientCommand(object): 507class 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."""
diff --git a/error.py b/error.py
index cee977f9..7958a0a1 100644
--- a/error.py
+++ b/error.py
@@ -107,6 +107,10 @@ class GitError(RepoError):
107 return self.message 107 return self.message
108 108
109 109
110class GitcUnsupportedError(RepoExitError):
111 """Gitc no longer supported."""
112
113
110class UploadError(RepoError): 114class 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
15import os
16import multiprocessing
17import re
18import sys
19import time
20
21import git_command
22import git_config
23import wrapper
24
25from error import ManifestParseError
26
27NUM_BATCH_RETRIEVE_REVISIONID = 32
28
29
30def get_gitc_manifest_dir():
31 return wrapper.Wrapper().get_gitc_manifest_dir()
32
33
34def parse_clientdir(gitc_fs_path):
35 return wrapper.Wrapper().gitc_parse_clientdir(gitc_fs_path)
36
37
38def _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
48def _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
88def 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
151def 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)
diff --git a/main.py b/main.py
index ffed0b72..126a4b61 100755
--- a/main.py
+++ b/main.py
@@ -45,7 +45,6 @@ from git_config import RepoConfig
45from git_trace2_event_log import EventLog 45from git_trace2_event_log import EventLog
46from command import InteractiveCommand 46from command import InteractiveCommand
47from command import MirrorSafeCommand 47from command import MirrorSafeCommand
48from command import GitcAvailableCommand, GitcClientCommand
49from subcmds.version import Version 48from subcmds.version import Version
50from editor import Editor 49from editor import Editor
51from error import DownloadError 50from error import DownloadError
@@ -58,8 +57,8 @@ from error import RepoExitError
58from error import RepoUnhandledExceptionError 57from error import RepoUnhandledExceptionError
59from error import RepoError 58from error import RepoError
60from error import SilentRepoExitError 59from error import SilentRepoExitError
61import gitc_utils 60from error import GitcUnsupportedError
62from manifest_xml import GitcClient, RepoClient 61from manifest_xml import RepoClient
63from pager import RunPager, TerminatePager 62from pager import RunPager, TerminatePager
64from wrapper import WrapperPath, Wrapper 63from 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
21import xml.dom.minidom 21import xml.dom.minidom
22import urllib.parse 22import urllib.parse
23 23
24import gitc_utils
25from git_config import GitConfig 24from git_config import GitConfig
26from git_refs import R_HEADS, HEAD 25from git_refs import R_HEADS, HEAD
27from git_superproject import Superproject 26from 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
2251class 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
2266class RepoClient(XmlManifest): 2250class 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
2320class 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
diff --git a/repo b/repo
index dbc96da7..b9b1928a 100755
--- a/repo
+++ b/repo
@@ -149,7 +149,7 @@ if not REPO_REV:
149BUG_URL = 'https://issues.gerritcodereview.com/issues/new?component=1370071' 149BUG_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
152VERSION = (2, 35) 152VERSION = (2, 36)
153 153
154# increment this if the MAINTAINER_KEYS block is modified 154# increment this if the MAINTAINER_KEYS block is modified
155KEYRING_VERSION = (2, 3) 155KEYRING_VERSION = (2, 3)
@@ -273,16 +273,16 @@ gpg_dir = os.path.join(home_dot_repo, 'gnupg')
273def GetParser(gitc_init=False): 273def 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
285def InitParser(parser, gitc_init=False): 285def 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
15import sys
16
17from command import Command, GitcClientCommand
18import platform_utils
19
20
21class GitcDelete(Command, GitcClientCommand):
22 COMMON = True
23 visible_everywhere = False
24 helpSummary = "Delete a GITC Client."
25 helpUsage = """
26%prog
27"""
28 helpDescription = """
29This subcommand deletes the current GITC client, deleting the GITC manifest
30and 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
15import os
16import sys
17
18import gitc_utils
19from command import GitcAvailableCommand
20from manifest_xml import GitcManifest
21from subcmds import init
22import wrapper
23
24
25class 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 = """
33The '%prog' command is ran to initialize a new GITC client for use
34with the GITC file system.
35
36This command will setup the client directory, initialize repo, just
37like repo init does, and then downloads the manifest collection
38and installs it in the .repo/directory of the GITC client.
39
40Once this is done, a GITC manifest is generated by pulling the HEAD
41SHA for each project and generates the properly formatted XML file
42and installs it as .manifest in the GITC client directory.
43
44The -c argument is required to specify the GITC client name.
45
46The optional -f argument can be used to specify the manifest file to
47use 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
21from command import ( 21from command import (
22 PagedCommand, 22 PagedCommand,
23 MirrorSafeCommand, 23 MirrorSafeCommand,
24 GitcAvailableCommand,
25 GitcClientCommand,
26) 24)
27import gitc_utils
28from wrapper import Wrapper 25from wrapper import Wrapper
29from error import RepoExitError 26from 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
15import functools 15import functools
16import os
17import sys 16import sys
18 17
19from command import Command, DEFAULT_LOCAL_JOBS 18from command import Command, DEFAULT_LOCAL_JOBS
20from git_config import IsImmutable 19from git_config import IsImmutable
21from git_command import git 20from git_command import git
22import gitc_utils
23from progress import Progress 21from progress import Progress
24from project import SyncBuffer, Project 22from project import Project
25from typing import NamedTuple 23from typing import NamedTuple
26from error import RepoExitError 24from 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
54from git_config import GetUrlCookieFile 54from git_config import GetUrlCookieFile
55from git_refs import R_HEADS, HEAD 55from git_refs import R_HEADS, HEAD
56import git_superproject 56import git_superproject
57import gitc_utils
58from project import Project 57from project import Project
59from project import RemoteSpec 58from project import RemoteSpec
60from command import ( 59from command import (
@@ -77,7 +76,6 @@ from progress import Progress, elapsed_str, jobs_str
77from repo_trace import Trace 76from repo_trace import Trace
78import ssh 77import ssh
79from wrapper import Wrapper 78from wrapper import Wrapper
80from 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 """