diff options
| author | Gavin Mak <gavinmak@google.com> | 2026-08-25 09:04:41 -0700 |
|---|---|---|
| committer | gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2026-09-02 17:41:05 -0700 |
| commit | 948abc85bcfd3f73d6cec4160506af325f721b71 (patch) | |
| tree | eac286d41867ca68089f940191ae2b8c19e81e61 | |
| parent | c63a2f92fa9c01b1a58608a35f968da827b9ac3e (diff) | |
| download | git-repo-948abc85bcfd3f73d6cec4160506af325f721b71.tar.gz git-repo-948abc85bcfd3f73d6cec4160506af325f721b71.zip | |
git_config: recognize only complete object IDs
Full Git object IDs are exactly 40 hexadecimal digits for SHA-1 or 64
for SHA-256. Stop treating every intermediate length as immutable, which
could bypass normal ref resolution for invalid revision strings.
Bug: 553599402
Change-Id: I41b4ce6b2bfe2a2d8b351c7f040ec0cf469b474b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623901
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
| -rw-r--r-- | git_config.py | 2 | ||||
| -rw-r--r-- | tests/test_git_config.py | 4 | ||||
| -rw-r--r-- | tests/test_project.py | 52 |
3 files changed, 55 insertions, 3 deletions
diff --git a/git_config.py b/git_config.py index 888ae888c..84d347b1a 100644 --- a/git_config.py +++ b/git_config.py @@ -40,7 +40,7 @@ from repo_trace import Trace # that is saved in the config. SYNC_STATE_PREFIX = "repo.syncstate." -ID_RE = re.compile(r"^[0-9a-f]{40,64}$") +ID_RE = re.compile(r"^(?:[0-9a-f]{40}|[0-9a-f]{64})$") REVIEW_CACHE = {} diff --git a/tests/test_git_config.py b/tests/test_git_config.py index 9583f3e9f..4b4e4cabb 100644 --- a/tests/test_git_config.py +++ b/tests/test_git_config.py @@ -256,8 +256,8 @@ def test_remote_save_with_push_url_without_projectname( ("0" * 64, True), ("f" * 64, True), ("a" * 39, False), - ("a" * 41, True), - ("a" * 63, True), + ("a" * 41, False), + ("a" * 63, False), ("a" * 65, False), ("g" * 40, False), ("g" * 64, False), diff --git a/tests/test_project.py b/tests/test_project.py index 57bb8c10c..3be80c5c2 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -1039,6 +1039,58 @@ class ProjectTests(unittest.TestCase): self._get_derived_subproject_url(submodule_url), ) + def test_set_revision_object_id_lengths(self) -> None: + """SetRevision only treats exact 40- or 64-char hex as immutable IDs.""" + with utils_for_test.TempGitTree() as tempdir: + proj = _create_mock_project(tempdir) + + # SHA-1 (40 hex chars) is recorded as revisionId directly. + sha1 = "a" * 40 + proj.SetRevision(sha1) + self.assertEqual(proj.revisionId, sha1) + + # SHA-256 (64 hex chars) is recorded as revisionId directly. + sha256 = "b" * 64 + proj.SetRevision(sha256) + self.assertEqual(proj.revisionId, sha256) + + # Intermediate hex strings (41-63 chars) must not be treated + # as commit IDs. + for length in (41, 48, 63): + proj.SetRevision("c" * length) + self.assertIsNone(proj.revisionId) + + def test_remote_fetch_intermediate_hex_not_fetched_as_commit_id( + self, + ) -> None: + """41-char hex revisions are not fetched as raw commit IDs on shallow + fetch.""" + with utils_for_test.TempGitTree() as tempdir: + proj = _create_mock_project(tempdir) + proj.config.GetRemote("origin").ResetFetch() + hex41 = "a" * 41 + proj.SetRevision(hex41) + + with mock.patch("project.GitCommand") as mock_git: + mock_cmd = mock.MagicMock() + mock_cmd.Wait.return_value = 0 + mock_git.return_value = mock_cmd + + proj._RemoteFetch(depth=1, current_branch_only=True) + + fetch_args = mock_git.call_args[0][1] + # When depth is set, commit IDs are passed directly to + # git fetch. + # Since 41 hex chars is not an ID, it must not appear as a + # standalone argument. + self.assertNotIn(hex41, fetch_args) + # Instead, it is treated as a branch ref and formatted + # as a refspec. + self.assertIn( + f"+refs/heads/{hex41}:refs/remotes/origin/{hex41}", + fetch_args, + ) + class CopyLinkTestCase(unittest.TestCase): """TestCase for stub repo client checkouts. |
