From 0e4f1e7fba4770908235e136c5ed0a540854651e Mon Sep 17 00:00:00 2001 From: Joanna Wang Date: Thu, 8 Dec 2022 17:46:28 -0500 Subject: [PATCH] Use --negotiation-tip in superproject fetches. Bug: b/260645739 Change-Id: Ib0cdbb13f130b91ab14df9c60a510f1e27cca8e0 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/354354 Reviewed-by: Mike Frysinger Tested-by: Joanna Wang --- git_superproject.py | 12 ++++++++++- tests/test_git_superproject.py | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/git_superproject.py b/git_superproject.py index 8b6bbcf9..7a4ca16b 100644 --- a/git_superproject.py +++ b/git_superproject.py @@ -31,7 +31,7 @@ from typing import NamedTuple from git_command import git_require, GitCommand from git_config import RepoConfig -from git_refs import R_HEADS +from git_refs import R_HEADS, GitRefs _SUPERPROJECT_GIT_NAME = 'superproject.git' _SUPERPROJECT_MANIFEST_NAME = 'superproject_override.xml' @@ -181,6 +181,16 @@ class Superproject(object): return False cmd = ['fetch', self._remote_url, '--depth', '1', '--force', '--no-tags', '--filter', 'blob:none'] + + # Check if there is a local ref that we can pass to --negotiation-tip. + # If this is the first fetch, it does not exist yet. + # We use --negotiation-tip to speed up the fetch. Superproject branches do + # not share commits. So this lets git know it only needs to send commits + # reachable from the specified local refs. + rev_commit = GitRefs(self._work_git).get(f'refs/heads/{self.revision}') + if rev_commit: + cmd.extend(['--negotiation-tip', rev_commit]) + if self._branch: cmd += [self._branch + ':' + self._branch] p = GitCommand(None, diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py index 225e98c2..49295d83 100644 --- a/tests/test_git_superproject.py +++ b/tests/test_git_superproject.py @@ -21,6 +21,7 @@ import tempfile import unittest from unittest import mock +from git_command import GitCommand import git_superproject import git_trace2_event_log import manifest_xml @@ -364,3 +365,41 @@ class SuperprojectTestCase(unittest.TestCase): 'revision="52d3c9f7c107839ece2319d077de0cd922aa9d8f"/>' '' '') + + def test_Fetch(self): + manifest = self.getXmlManifest(""" + + + + + " /> +""") + self.maxDiff = None + self._superproject = git_superproject.Superproject( + manifest, name='superproject', + remote=manifest.remotes.get('default-remote').ToRemoteSpec('superproject'), + revision='refs/heads/main') + os.mkdir(self._superproject._superproject_path) + os.mkdir(self._superproject._work_git) + with mock.patch.object(self._superproject, '_Init', return_value=True): + with mock.patch('git_superproject.GitCommand', autospec=True) as mock_git_command: + with mock.patch('git_superproject.GitRefs.get', autospec=True) as mock_git_refs: + instance = mock_git_command.return_value + instance.Wait.return_value = 0 + mock_git_refs.side_effect = ['', '1234'] + + self.assertTrue(self._superproject._Fetch()) + self.assertEqual(mock_git_command.call_args.args,(None, [ + 'fetch', 'http://localhost/superproject', '--depth', '1', + '--force', '--no-tags', '--filter', 'blob:none', + 'refs/heads/main:refs/heads/main' + ])) + + # If branch for revision exists, set as --negotiation-tip. + self.assertTrue(self._superproject._Fetch()) + self.assertEqual(mock_git_command.call_args.args,(None, [ + 'fetch', 'http://localhost/superproject', '--depth', '1', + '--force', '--no-tags', '--filter', 'blob:none', + '--negotiation-tip', '1234', + 'refs/heads/main:refs/heads/main' + ]))