blob: 8ff7699b8a7a6a0c49044d8920535d8d64f528c6 [file] [log] [blame]
Mike Frysingerf6013762019-06-13 02:30:51 -04001# -*- coding:utf-8 -*-
Simran Basibdb52712015-08-10 13:23:23 -07002#
3# Copyright (C) 2015 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17from __future__ import print_function
18import os
Dan Willemsen5ea32d12015-09-08 13:27:20 -070019import platform
20import re
David Pursehouse46496d82015-08-20 16:37:09 +090021import sys
Simran Basib9a1b732015-08-20 12:19:28 -070022import time
Simran Basibdb52712015-08-10 13:23:23 -070023
24import git_command
25import git_config
Simran Basi8ce50412015-08-28 14:25:44 -070026import wrapper
Simran Basibdb52712015-08-10 13:23:23 -070027
Xin Lif97e72e2016-06-24 12:17:14 -070028from error import ManifestParseError
29
Dan Willemsen39252ba2016-08-23 14:06:59 -070030NUM_BATCH_RETRIEVE_REVISIONID = 32
Simran Basibdb52712015-08-10 13:23:23 -070031
David Pursehouse819827a2020-02-12 15:20:19 +090032
Simran Basi8ce50412015-08-28 14:25:44 -070033def get_gitc_manifest_dir():
34 return wrapper.Wrapper().get_gitc_manifest_dir()
35
David Pursehouse819827a2020-02-12 15:20:19 +090036
Simran Basib9a1b732015-08-20 12:19:28 -070037def parse_clientdir(gitc_fs_path):
Dan Willemsen745b4ad2015-10-06 15:23:19 -070038 return wrapper.Wrapper().gitc_parse_clientdir(gitc_fs_path)
Simran Basib9a1b732015-08-20 12:19:28 -070039
David Pursehouse819827a2020-02-12 15:20:19 +090040
Simran Basibdb52712015-08-10 13:23:23 -070041def _set_project_revisions(projects):
42 """Sets the revisionExpr for a list of projects.
43
44 Because of the limit of open file descriptors allowed, length of projects
45 should not be overly large. Recommend calling this function multiple times
46 with each call not exceeding NUM_BATCH_RETRIEVE_REVISIONID projects.
47
Mike Frysinger0a849b62020-12-11 03:26:42 -050048 Args:
49 projects: List of project objects to set the revionExpr for.
Simran Basibdb52712015-08-10 13:23:23 -070050 """
51 # Retrieve the commit id for each project based off of it's current
52 # revisionExpr and it is not already a commit id.
53 project_gitcmds = [(
54 project, git_command.GitCommand(None,
55 ['ls-remote',
56 project.remote.url,
57 project.revisionExpr],
58 capture_stdout=True, cwd='/tmp'))
David Pursehouseabdf7502020-02-12 14:58:39 +090059 for project in projects if not git_config.IsId(project.revisionExpr)]
Simran Basibdb52712015-08-10 13:23:23 -070060 for proj, gitcmd in project_gitcmds:
61 if gitcmd.Wait():
David Pursehouse022a1d42015-08-20 16:41:04 +090062 print('FATAL: Failed to retrieve revisionExpr for %s' % proj)
Simran Basibdb52712015-08-10 13:23:23 -070063 sys.exit(1)
Xin Lif97e72e2016-06-24 12:17:14 -070064 revisionExpr = gitcmd.stdout.split('\t')[0]
65 if not revisionExpr:
Mike Frysinger31067c02019-06-13 02:13:23 -040066 raise ManifestParseError('Invalid SHA-1 revision project %s (%s)' %
67 (proj.remote.url, proj.revisionExpr))
Xin Lif97e72e2016-06-24 12:17:14 -070068 proj.revisionExpr = revisionExpr
Simran Basibdb52712015-08-10 13:23:23 -070069
David Pursehouse819827a2020-02-12 15:20:19 +090070
Dan Willemsen5ea32d12015-09-08 13:27:20 -070071def _manifest_groups(manifest):
72 """Returns the manifest group string that should be synced
73
74 This is the same logic used by Command.GetProjects(), which is used during
75 repo sync
76
Mike Frysinger0a849b62020-12-11 03:26:42 -050077 Args:
78 manifest: The XmlManifest object
Dan Willemsen5ea32d12015-09-08 13:27:20 -070079 """
80 mp = manifest.manifestProject
81 groups = mp.config.GetString('manifest.groups')
82 if not groups:
83 groups = 'default,platform-' + platform.system().lower()
84 return groups
85
David Pursehouse819827a2020-02-12 15:20:19 +090086
Dan Willemsen5ea32d12015-09-08 13:27:20 -070087def generate_gitc_manifest(gitc_manifest, manifest, paths=None):
Simran Basibdb52712015-08-10 13:23:23 -070088 """Generate a manifest for shafsd to use for this GITC client.
89
Mike Frysinger0a849b62020-12-11 03:26:42 -050090 Args:
91 gitc_manifest: Current gitc manifest, or None if there isn't one yet.
92 manifest: A GitcManifest object loaded with the current repo manifest.
93 paths: List of project paths we want to update.
Simran Basibdb52712015-08-10 13:23:23 -070094 """
Dan Willemsen5ea32d12015-09-08 13:27:20 -070095
Simran Basibdb52712015-08-10 13:23:23 -070096 print('Generating GITC Manifest by fetching revision SHAs for each '
97 'project.')
Dan Willemsen5ea32d12015-09-08 13:27:20 -070098 if paths is None:
Mike Frysinger31067c02019-06-13 02:13:23 -040099 paths = list(manifest.paths.keys())
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700100
101 groups = [x for x in re.split(r'[,\s]+', _manifest_groups(manifest)) if x]
102
103 # Convert the paths to projects, and filter them to the matched groups.
104 projects = [manifest.paths[p] for p in paths]
105 projects = [p for p in projects if p.MatchesGroups(groups)]
106
107 if gitc_manifest is not None:
Mike Frysinger31067c02019-06-13 02:13:23 -0400108 for path, proj in manifest.paths.items():
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700109 if not proj.MatchesGroups(groups):
110 continue
111
112 if not proj.upstream and not git_config.IsId(proj.revisionExpr):
113 proj.upstream = proj.revisionExpr
114
David Pursehouseeeff3532020-02-12 11:24:10 +0900115 if path not in gitc_manifest.paths:
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700116 # Any new projects need their first revision, even if we weren't asked
117 # for them.
118 projects.append(proj)
David Pursehouseeeff3532020-02-12 11:24:10 +0900119 elif path not in paths:
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700120 # And copy revisions from the previous manifest if we're not updating
121 # them now.
122 gitc_proj = gitc_manifest.paths[path]
123 if gitc_proj.old_revision:
124 proj.revisionExpr = None
125 proj.old_revision = gitc_proj.old_revision
126 else:
127 proj.revisionExpr = gitc_proj.revisionExpr
128
Simran Basibdb52712015-08-10 13:23:23 -0700129 index = 0
Simran Basib9a1b732015-08-20 12:19:28 -0700130 while index < len(projects):
Simran Basibdb52712015-08-10 13:23:23 -0700131 _set_project_revisions(
David Pursehouse54a4e602020-02-12 14:31:05 +0900132 projects[index:(index + NUM_BATCH_RETRIEVE_REVISIONID)])
Simran Basibdb52712015-08-10 13:23:23 -0700133 index += NUM_BATCH_RETRIEVE_REVISIONID
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700134
135 if gitc_manifest is not None:
Mike Frysinger31067c02019-06-13 02:13:23 -0400136 for path, proj in gitc_manifest.paths.items():
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700137 if proj.old_revision and path in paths:
138 # If we updated a project that has been started, keep the old-revision
139 # updated.
140 repo_proj = manifest.paths[path]
141 repo_proj.old_revision = repo_proj.revisionExpr
142 repo_proj.revisionExpr = None
143
144 # Convert URLs from relative to absolute.
Mike Frysinger31067c02019-06-13 02:13:23 -0400145 for _name, remote in manifest.remotes.items():
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700146 remote.fetchUrl = remote.resolvedFetchUrl
147
Simran Basibdb52712015-08-10 13:23:23 -0700148 # Save the manifest.
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700149 save_manifest(manifest)
Simran Basib9a1b732015-08-20 12:19:28 -0700150
David Pursehouse819827a2020-02-12 15:20:19 +0900151
Simran Basib9a1b732015-08-20 12:19:28 -0700152def save_manifest(manifest, client_dir=None):
153 """Save the manifest file in the client_dir.
154
Mike Frysinger0a849b62020-12-11 03:26:42 -0500155 Args:
156 manifest: Manifest object to save.
157 client_dir: Client directory to save the manifest in.
Simran Basib9a1b732015-08-20 12:19:28 -0700158 """
159 if not client_dir:
160 client_dir = manifest.gitc_client_dir
Simran Basibdb52712015-08-10 13:23:23 -0700161 with open(os.path.join(client_dir, '.manifest'), 'w') as f:
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700162 manifest.Save(f, groups=_manifest_groups(manifest))
Simran Basib9a1b732015-08-20 12:19:28 -0700163 # TODO(sbasi/jorg): Come up with a solution to remove the sleep below.
164 # Give the GITC filesystem time to register the manifest changes.
Dan Willemsen5ea32d12015-09-08 13:27:20 -0700165 time.sleep(3)