summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaman Tenneti <rtenneti@google.com>2021-02-07 16:30:27 -0800
committerRaman Tenneti <rtenneti@google.com>2021-02-08 17:34:55 +0000
commit8d43dea6ea4b7d1664632e555e207f617e54657b (patch)
tree5632d2a6e5d6e8ccff305e84734665f2f1b4fb04
parent1fd7bc24386dbba3a9454bb49c702a642f00e34c (diff)
downloadgit-repo-8d43dea6ea4b7d1664632e555e207f617e54657b.tar.gz
sync: pass --bare option when doing git clone of superproject.v2.12.1
Changed "git pull" to "git fetch" as we are using --bare option. Used the following command to fetch: git fetch origin +refs/heads/*:refs/heads/* --prune Pass --branch argument to Superproject's UpdateProjectsRevisionId function. Returned False/None when directories don't exist instead of raise GitError exception from _Fetch and _LsTree functions. The caller of Fetch does Clone if Fetch fails. Tested the code with the following commands. $ ./run_tests -v Tested the init and sync code by copying all the repo changes into my Android AOSP checkout and running repo sync with --use-superproject option. Bug: https://crbug.com/gerrit/13709 Bug: https://crbug.com/gerrit/13707 Tested-by: Raman Tenneti <rtenneti@google.com> Change-Id: I3e441ecdfc87c735f46eff0eb98efa63cc2eb22a Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/296222 Reviewed-by: Mike Frysinger <vapier@google.com>
-rw-r--r--git_superproject.py42
-rw-r--r--subcmds/sync.py19
-rw-r--r--tests/test_git_superproject.py8
3 files changed, 43 insertions, 26 deletions
diff --git a/git_superproject.py b/git_superproject.py
index 465d1f87..57a3a533 100644
--- a/git_superproject.py
+++ b/git_superproject.py
@@ -29,6 +29,9 @@ from error import BUG_REPORT_URL, GitError
29from git_command import GitCommand 29from git_command import GitCommand
30import platform_utils 30import platform_utils
31 31
32_SUPERPROJECT_GIT_NAME = 'superproject.git'
33_SUPERPROJECT_MANIFEST_NAME = 'superproject_override.xml'
34
32 35
33class Superproject(object): 36class Superproject(object):
34 """Get SHAs from superproject. 37 """Get SHAs from superproject.
@@ -48,8 +51,9 @@ class Superproject(object):
48 self._superproject_dir = superproject_dir 51 self._superproject_dir = superproject_dir
49 self._superproject_path = os.path.join(self._repodir, superproject_dir) 52 self._superproject_path = os.path.join(self._repodir, superproject_dir)
50 self._manifest_path = os.path.join(self._superproject_path, 53 self._manifest_path = os.path.join(self._superproject_path,
51 'superproject_override.xml') 54 _SUPERPROJECT_MANIFEST_NAME)
52 self._work_git = os.path.join(self._superproject_path, 'superproject') 55 self._work_git = os.path.join(self._superproject_path,
56 _SUPERPROJECT_GIT_NAME)
53 57
54 @property 58 @property
55 def project_shas(self): 59 def project_shas(self):
@@ -66,8 +70,9 @@ class Superproject(object):
66 Returns: 70 Returns:
67 True if 'git clone <url> <branch>' is successful, or False. 71 True if 'git clone <url> <branch>' is successful, or False.
68 """ 72 """
69 os.mkdir(self._superproject_path) 73 if not os.path.exists(self._superproject_path):
70 cmd = ['clone', url, '--filter', 'blob:none'] 74 os.mkdir(self._superproject_path)
75 cmd = ['clone', url, '--filter', 'blob:none', '--bare']
71 if branch: 76 if branch:
72 cmd += ['--branch', branch] 77 cmd += ['--branch', branch]
73 p = GitCommand(None, 78 p = GitCommand(None,
@@ -84,15 +89,17 @@ class Superproject(object):
84 return False 89 return False
85 return True 90 return True
86 91
87 def _Pull(self): 92 def _Fetch(self):
88 """Do a 'git pull' to to fetch the latest content. 93 """Do a 'git fetch' to to fetch the latest content.
89 94
90 Returns: 95 Returns:
91 True if 'git pull <branch>' is successful, or False. 96 True if 'git fetch' is successful, or False.
92 """ 97 """
93 if not os.path.exists(self._work_git): 98 if not os.path.exists(self._work_git):
94 raise GitError('git pull missing drectory: %s' % self._work_git) 99 print('git fetch missing drectory: %s' % self._work_git,
95 cmd = ['pull'] 100 file=sys.stderr)
101 return False
102 cmd = ['fetch', 'origin', '+refs/heads/*:refs/heads/*', '--prune']
96 p = GitCommand(None, 103 p = GitCommand(None,
97 cmd, 104 cmd,
98 cwd=self._work_git, 105 cwd=self._work_git,
@@ -100,7 +107,7 @@ class Superproject(object):
100 capture_stderr=True) 107 capture_stderr=True)
101 retval = p.Wait() 108 retval = p.Wait()
102 if retval: 109 if retval:
103 print('repo: error: git pull call failed with return code: %r, stderr: %r' % 110 print('repo: error: git fetch call failed with return code: %r, stderr: %r' %
104 (retval, p.stderr), file=sys.stderr) 111 (retval, p.stderr), file=sys.stderr)
105 return False 112 return False
106 return True 113 return True
@@ -114,7 +121,9 @@ class Superproject(object):
114 data: data returned from 'git ls-tree -r HEAD' instead of None. 121 data: data returned from 'git ls-tree -r HEAD' instead of None.
115 """ 122 """
116 if not os.path.exists(self._work_git): 123 if not os.path.exists(self._work_git):
117 raise GitError('git ls-tree. Missing drectory: %s' % self._work_git) 124 print('git ls-tree missing drectory: %s' % self._work_git,
125 file=sys.stderr)
126 return None
118 data = None 127 data = None
119 cmd = ['ls-tree', '-z', '-r', 'HEAD'] 128 cmd = ['ls-tree', '-z', '-r', 'HEAD']
120 p = GitCommand(None, 129 p = GitCommand(None,
@@ -136,18 +145,19 @@ class Superproject(object):
136 """Get SHAs for all projects from superproject and save them in _project_shas. 145 """Get SHAs for all projects from superproject and save them in _project_shas.
137 146
138 Args: 147 Args:
139 url: superproject's url to be passed to git clone or pull. 148 url: superproject's url to be passed to git clone or fetch.
140 branch: The branchname to be passed as argument to git clone or pull. 149 branch: The branchname to be passed as argument to git clone or fetch.
141 150
142 Returns: 151 Returns:
143 A dictionary with the projects/SHAs instead of None. 152 A dictionary with the projects/SHAs instead of None.
144 """ 153 """
145 if not url: 154 if not url:
146 raise ValueError('url argument is not supplied.') 155 raise ValueError('url argument is not supplied.')
156
147 do_clone = True 157 do_clone = True
148 if os.path.exists(self._superproject_path): 158 if os.path.exists(self._superproject_path):
149 if not self._Pull(): 159 if not self._Fetch():
150 # If pull fails due to a corrupted git directory, then do a git clone. 160 # If fetch fails due to a corrupted git directory, then do a git clone.
151 platform_utils.rmtree(self._superproject_path) 161 platform_utils.rmtree(self._superproject_path)
152 else: 162 else:
153 do_clone = False 163 do_clone = False
@@ -208,7 +218,7 @@ class Superproject(object):
208 manifest: A Manifest object that is to be written to a file. 218 manifest: A Manifest object that is to be written to a file.
209 projects: List of projects whose revisionId needs to be updated. 219 projects: List of projects whose revisionId needs to be updated.
210 url: superproject's url to be passed to git clone or fetch. 220 url: superproject's url to be passed to git clone or fetch.
211 branch: The branchname to be passed as argument to git clone or pull. 221 branch: The branchname to be passed as argument to git clone or fetch.
212 222
213 Returns: 223 Returns:
214 manifest_path: Path name of the overriding manfiest file instead of None. 224 manifest_path: Path name of the overriding manfiest file instead of None.
diff --git a/subcmds/sync.py b/subcmds/sync.py
index c0f605a8..5855af55 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -271,6 +271,15 @@ later is required to fix a server side protocol bug.
271 dest='repo_upgraded', action='store_true', 271 dest='repo_upgraded', action='store_true',
272 help=SUPPRESS_HELP) 272 help=SUPPRESS_HELP)
273 273
274 def _GetBranch(self):
275 """Returns the branch name for getting the approved manifest."""
276 p = self.manifest.manifestProject
277 b = p.GetBranch(p.CurrentBranch)
278 branch = b.merge
279 if branch.startswith(R_HEADS):
280 branch = branch[len(R_HEADS):]
281 return branch
282
274 def _UpdateProjectsRevisionId(self, opt, args): 283 def _UpdateProjectsRevisionId(self, opt, args):
275 """Update revisionId of every project with the SHA from superproject. 284 """Update revisionId of every project with the SHA from superproject.
276 285
@@ -302,9 +311,11 @@ later is required to fix a server side protocol bug.
302 all_projects = self.GetProjects(args, 311 all_projects = self.GetProjects(args,
303 missing_ok=True, 312 missing_ok=True,
304 submodules_ok=opt.fetch_submodules) 313 submodules_ok=opt.fetch_submodules)
314 branch = self._GetBranch()
305 manifest_path = superproject.UpdateProjectsRevisionId(self.manifest, 315 manifest_path = superproject.UpdateProjectsRevisionId(self.manifest,
306 all_projects, 316 all_projects,
307 url=superproject_url) 317 url=superproject_url,
318 branch=branch)
308 if not manifest_path: 319 if not manifest_path:
309 print('error: Update of revsionId from superproject has failed', 320 print('error: Update of revsionId from superproject has failed',
310 file=sys.stderr) 321 file=sys.stderr)
@@ -753,11 +764,7 @@ later is required to fix a server side protocol bug.
753 try: 764 try:
754 server = xmlrpc.client.Server(manifest_server, transport=transport) 765 server = xmlrpc.client.Server(manifest_server, transport=transport)
755 if opt.smart_sync: 766 if opt.smart_sync:
756 p = self.manifest.manifestProject 767 branch = self._GetBranch()
757 b = p.GetBranch(p.CurrentBranch)
758 branch = b.merge
759 if branch.startswith(R_HEADS):
760 branch = branch[len(R_HEADS):]
761 768
762 if 'SYNC_TARGET' in os.environ: 769 if 'SYNC_TARGET' in os.environ:
763 target = os.environ['SYNC_TARGET'] 770 target = os.environ['SYNC_TARGET']
diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py
index d2c2f501..fc9101dd 100644
--- a/tests/test_git_superproject.py
+++ b/tests/test_git_superproject.py
@@ -78,11 +78,11 @@ class SuperprojectTestCase(unittest.TestCase):
78 with mock.patch.object(self._superproject, '_Clone', return_value=False): 78 with mock.patch.object(self._superproject, '_Clone', return_value=False):
79 self._superproject._GetAllProjectsSHAs(url='localhost') 79 self._superproject._GetAllProjectsSHAs(url='localhost')
80 80
81 def test_superproject_get_project_shas_mock_pull(self): 81 def test_superproject_get_project_shas_mock_fetch(self):
82 """Test with _Pull failing.""" 82 """Test with _Fetch failing."""
83 with self.assertRaises(GitError): 83 with self.assertRaises(GitError):
84 with mock.patch.object(self._superproject, '_Clone', return_value=True): 84 with mock.patch.object(self._superproject, '_Clone', return_value=True):
85 with mock.patch.object(self._superproject, '_Pull', return_value=False): 85 with mock.patch.object(self._superproject, '_Fetch', return_value=False):
86 self._superproject._GetAllProjectsSHAs(url='localhost') 86 self._superproject._GetAllProjectsSHAs(url='localhost')
87 87
88 def test_superproject_get_project_shas_mock_ls_tree(self): 88 def test_superproject_get_project_shas_mock_ls_tree(self):
@@ -141,7 +141,7 @@ class SuperprojectTestCase(unittest.TestCase):
141 data = ('160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00' 141 data = ('160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00'
142 '160000 commit e9d25da64d8d365dbba7c8ee00fe8c4473fe9a06\tbootable/recovery\x00') 142 '160000 commit e9d25da64d8d365dbba7c8ee00fe8c4473fe9a06\tbootable/recovery\x00')
143 with mock.patch.object(self._superproject, '_Clone', return_value=True): 143 with mock.patch.object(self._superproject, '_Clone', return_value=True):
144 with mock.patch.object(self._superproject, '_Pull', return_value=True): 144 with mock.patch.object(self._superproject, '_Fetch', return_value=True):
145 with mock.patch.object(self._superproject, '_LsTree', return_value=data): 145 with mock.patch.object(self._superproject, '_LsTree', return_value=data):
146 # Create temporary directory so that it can write the file. 146 # Create temporary directory so that it can write the file.
147 os.mkdir(self._superproject._superproject_path) 147 os.mkdir(self._superproject._superproject_path)