@@ -475,102 +475,43 @@ def test_commit_sha_from_registry_pr(logger):
475475 assert r ._commit_sha_from_registry_pr ("v4.5.6" , "def" ) == "sha"
476476
477477
478- def test_commit_sha_of_tree_from_branch ():
479- r = _repo ()
480- r ._repo .get_commits = Mock (return_value = [Mock (sha = "abc" ), Mock (sha = "sha" )])
481- r ._repo .get_commits .return_value [1 ].commit .tree .sha = "tree"
482- assert r ._commit_sha_of_tree_from_branch ("master" , "tree" ) == "sha"
483- r ._repo .get_commits .assert_called_with (sha = "master" )
484- r ._repo .get_commits .return_value .pop ()
485- assert r ._commit_sha_of_tree_from_branch ("master" , "tree" ) is None
486-
487-
488- @patch ("tagbot.action.repo.logger" )
489- def test_commit_sha_of_tree_from_branch_subdir (logger ):
490- r = _repo (subdir = "path/to/package" )
491- commits = [Mock (sha = "abc" ), Mock (sha = "sha" )]
492- r ._repo .get_commits = Mock (return_value = commits )
493- r ._git .command = Mock (side_effect = ["other" , "tree_hash" ])
494-
495- assert r ._commit_sha_of_tree_from_branch ("master" , "tree_hash" ) == "sha"
496-
497- r ._repo .get_commits .assert_called_with (sha = "master" )
498- r ._git .command .assert_has_calls (
499- [
500- call ("rev-parse" , "abc:path/to/package" ),
501- call ("rev-parse" , "sha:path/to/package" ),
502- ]
503- )
504- logger .debug .assert_not_called ()
505-
506-
507- @patch ("tagbot.action.repo.logger" )
508- def test_commit_sha_of_tree_from_branch_subdir_rev_parse_failure (logger ):
509- r = _repo (subdir = "path/to/package" )
510- commits = [Mock (sha = "abc" ), Mock (sha = "sha" )]
511- r ._repo .get_commits = Mock (return_value = commits )
512- r ._git .command = Mock (side_effect = [Abort ("missing" ), "tree_hash" ])
513-
514- assert r ._commit_sha_of_tree_from_branch ("master" , "tree_hash" ) == "sha"
515-
516- r ._repo .get_commits .assert_called_with (sha = "master" )
517- logger .debug .assert_called_with (
518- "rev-parse failed while inspecting %s" , "abc:path/to/package"
519- )
520- r ._git .command .assert_has_calls (
521- [
522- call ("rev-parse" , "abc:path/to/package" ),
523- call ("rev-parse" , "sha:path/to/package" ),
524- ]
525- )
526-
527-
528478def test_commit_sha_of_tree ():
479+ """Test tree→commit lookup using git log cache."""
529480 r = _repo ()
530- r ._repo = Mock (default_branch = "master" )
531- branches = r ._repo .get_branches .return_value = [Mock (), Mock ()]
532- branches [0 ].name = "foo"
533- branches [1 ].name = "master"
534- r ._commit_sha_of_tree_from_branch = Mock (side_effect = ["sha1" , None , "sha2" ])
535- assert r ._commit_sha_of_tree ("tree" ) == "sha1"
536- r ._repo .get_branches .assert_not_called ()
537- r ._commit_sha_of_tree_from_branch .assert_called_once_with ("master" , "tree" )
538- assert r ._commit_sha_of_tree ("tree" ) == "sha2"
539- r ._commit_sha_of_tree_from_branch .assert_called_with ("foo" , "tree" )
540- r ._commit_sha_of_tree_from_branch .side_effect = None
541- r ._commit_sha_of_tree_from_branch .return_value = None
542- r ._git .commit_sha_of_tree = Mock (side_effect = ["sha" , None ])
543- assert r ._commit_sha_of_tree ("tree" ) == "sha"
544- assert r ._commit_sha_of_tree ("tree" ) is None
481+ # Mock git command to return commit:tree pairs
482+ r ._git .command = Mock (return_value = "sha1 tree1\n sha2 tree2\n sha3 tree3" )
483+ # First lookup builds cache and finds match
484+ assert r ._commit_sha_of_tree ("tree1" ) == "sha1"
485+ r ._git .command .assert_called_once_with ("log" , "--all" , "--format=%H %T" )
486+ # Second lookup uses cache (no additional git command)
487+ assert r ._commit_sha_of_tree ("tree2" ) == "sha2"
488+ assert r ._git .command .call_count == 1 # Still just one call
489+ # Non-existent tree returns None
490+ assert r ._commit_sha_of_tree ("nonexistent" ) is None
545491
546492
547493def test_commit_sha_of_tree_subdir_fallback ():
548- """Test subdirectory fallback when branch lookups fail ."""
494+ """Test subdirectory tree→commit cache ."""
549495 r = _repo (subdir = "path/to/package" )
550- r ._repo = Mock (default_branch = "master" )
551- branches = r ._repo .get_branches .return_value = [Mock ()]
552- branches [0 ].name = "master"
553- # Branch lookups return None (fail)
554- r ._commit_sha_of_tree_from_branch = Mock (return_value = None )
555496 # git log returns commit SHAs
556497 r ._git .command = Mock (return_value = "abc123\n def456\n ghi789" )
557- # _subdir_tree_hash called via helper, simulate finding match on second commit
558- with patch .object (r , "_subdir_tree_hash" , side_effect = [None , "tree_hash" , "other" ]):
498+ # _subdir_tree_hash called for each commit, match on second
499+ with patch .object (
500+ r , "_subdir_tree_hash" , side_effect = ["other" , "tree_hash" , "another" ]
501+ ):
559502 assert r ._commit_sha_of_tree ("tree_hash" ) == "def456"
560- # Verify it iterated through commits
561- assert r ._subdir_tree_hash .call_count == 2
503+ r ._git .command .assert_called_once_with ("log" , "--all" , "--format=%H" )
504+ # Cache is built, so subsequent lookups don't call git again
505+ assert r ._commit_sha_of_tree ("other" ) == "abc123"
506+ assert r ._git .command .call_count == 1
562507
563508
564509def test_commit_sha_of_tree_subdir_fallback_no_match ():
565- """Test subdirectory fallback returns None when no match found."""
510+ """Test subdirectory cache returns None when no match found."""
566511 r = _repo (subdir = "path/to/package" )
567- r ._repo = Mock (default_branch = "master" )
568- branches = r ._repo .get_branches .return_value = [Mock ()]
569- branches [0 ].name = "master"
570- r ._commit_sha_of_tree_from_branch = Mock (return_value = None )
571512 r ._git .command = Mock (return_value = "abc123\n def456" )
572- # No matches found
573- with patch .object (r , "_subdir_tree_hash" , return_value = None ):
513+ # No matching subdir tree hash
514+ with patch .object (r , "_subdir_tree_hash" , return_value = "other_tree" ):
574515 assert r ._commit_sha_of_tree ("tree_hash" ) is None
575516 assert r ._subdir_tree_hash .call_count == 2
576517
@@ -740,21 +681,28 @@ def test_filter_map_versions(logger):
740681 r = _repo ()
741682 # Mock the caches to avoid real API calls
742683 r ._build_tags_cache = Mock (return_value = {})
743- r ._build_registry_prs_cache = Mock (return_value = {})
744684 r ._commit_sha_from_registry_pr = Mock (return_value = None )
745685 r ._commit_sha_of_tree = Mock (return_value = None )
686+ # No registry PR or tree found - should skip
746687 assert not r ._filter_map_versions ({"1.2.3" : "tree1" })
747- logger .warning .assert_called_with (
748- "No matching commit was found for version v1.2.3 (tree1) "
688+ logger .debug .assert_called_with (
689+ "Skipping v1.2.3: no registry PR or matching tree found "
749690 )
750- r ._commit_sha_of_tree .return_value = "sha"
751- r ._commit_sha_of_tag = Mock (return_value = "sha" )
752- # Tag exists - skip it (no validation of commit SHA for performance)
753- assert not r ._filter_map_versions ({"2.3.4" : "tree2" })
754- logger .info .assert_called_with ("Tag v2.3.4 already exists" )
755- # Tag doesn't exist - should be included
756- r ._commit_sha_of_tag .return_value = None
691+ # Tree lookup fallback should be called when PR not found
692+ r ._commit_sha_of_tree .assert_called_with ("tree1" )
693+ # Registry PR found - should include (no tree lookup needed)
694+ r ._commit_sha_from_registry_pr .return_value = "sha"
695+ r ._commit_sha_of_tree .reset_mock ()
757696 assert r ._filter_map_versions ({"4.5.6" : "tree4" }) == {"v4.5.6" : "sha" }
697+ r ._commit_sha_of_tree .assert_not_called ()
698+ # Tag exists - skip it silently (no per-version logging for performance)
699+ r ._build_tags_cache .return_value = {"v2.3.4" : "existing_sha" }
700+ assert not r ._filter_map_versions ({"2.3.4" : "tree2" })
701+ # Tree fallback works when PR not found
702+ r ._build_tags_cache .return_value = {}
703+ r ._commit_sha_from_registry_pr .return_value = None
704+ r ._commit_sha_of_tree .return_value = "tree_sha"
705+ assert r ._filter_map_versions ({"5.6.7" : "tree5" }) == {"v5.6.7" : "tree_sha" }
758706
759707
760708@patch ("tagbot.action.repo.logger" )
0 commit comments