mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-03 23:33:41 +00:00 
			
		
		
		
	bug: limit amount of fetches used for changes
The issue appears in case if - somehow - unknown commit sha has been stored. In this scenario it would try to fetch infinitely
This commit is contained in:
		@ -64,8 +64,9 @@ class Sources(LazyLogging):
 | 
				
			|||||||
            return None  # no previous reference found
 | 
					            return None  # no previous reference found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        instance = Sources()
 | 
					        instance = Sources()
 | 
				
			||||||
        instance.fetch_until(source_dir, commit_sha=last_commit_sha)
 | 
					        if instance.fetch_until(source_dir, commit_sha=last_commit_sha) is not None:
 | 
				
			||||||
            return instance.diff(source_dir, last_commit_sha)
 | 
					            return instance.diff(source_dir, last_commit_sha)
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def extend_architectures(sources_dir: Path, architecture: str) -> list[PkgbuildPatch]:
 | 
					    def extend_architectures(sources_dir: Path, architecture: str) -> list[PkgbuildPatch]:
 | 
				
			||||||
@ -298,7 +299,8 @@ class Sources(LazyLogging):
 | 
				
			|||||||
            args.append(sha)
 | 
					            args.append(sha)
 | 
				
			||||||
        return check_output(*self.git(), "diff", *args, cwd=sources_dir, logger=self.logger)
 | 
					        return check_output(*self.git(), "diff", *args, cwd=sources_dir, logger=self.logger)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def fetch_until(self, sources_dir: Path, *, branch: str | None = None, commit_sha: str | None = None) -> None:
 | 
					    def fetch_until(self, sources_dir: Path, *, branch: str | None = None, commit_sha: str | None = None,
 | 
				
			||||||
 | 
					                    max_depth: int = 10) -> str | None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        fetch repository until commit sha
 | 
					        fetch repository until commit sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -307,11 +309,16 @@ class Sources(LazyLogging):
 | 
				
			|||||||
            branch(str | None, optional): use specified branch (Default value = None)
 | 
					            branch(str | None, optional): use specified branch (Default value = None)
 | 
				
			||||||
            commit_sha(str | None, optional): commit hash to fetch. If none set, only one will be fetched
 | 
					            commit_sha(str | None, optional): commit hash to fetch. If none set, only one will be fetched
 | 
				
			||||||
                (Default value = None)
 | 
					                (Default value = None)
 | 
				
			||||||
 | 
					            max_depth(int, optional): maximal amount of commits to fetch if ``commit_sha`` is set (Default value = 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            str | None: fetched ``commit_sha`` (if set) and ``None`` in case if commit wasn't found or
 | 
				
			||||||
 | 
					            ``commit_sha`` is not set
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        commit_sha = commit_sha or "HEAD"  # if none set we just fetch the last commit
 | 
					        commit_sha = commit_sha or "HEAD"  # if none set we just fetch the last commit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        commits_count = 1
 | 
					        commits_count = 1
 | 
				
			||||||
        while commit_sha is not None:
 | 
					        while commits_count <= max_depth:
 | 
				
			||||||
            command = self.git() + ["fetch", "--quiet", "--depth", str(commits_count)]
 | 
					            command = self.git() + ["fetch", "--quiet", "--depth", str(commits_count)]
 | 
				
			||||||
            if branch is not None:
 | 
					            if branch is not None:
 | 
				
			||||||
                command += ["origin", branch]
 | 
					                command += ["origin", branch]
 | 
				
			||||||
@ -320,10 +327,13 @@ class Sources(LazyLogging):
 | 
				
			|||||||
            try:
 | 
					            try:
 | 
				
			||||||
                # check if there is an object in current git directory
 | 
					                # check if there is an object in current git directory
 | 
				
			||||||
                check_output(*self.git(), "cat-file", "-e", commit_sha, cwd=sources_dir, logger=self.logger)
 | 
					                check_output(*self.git(), "cat-file", "-e", commit_sha, cwd=sources_dir, logger=self.logger)
 | 
				
			||||||
                commit_sha = None  # reset search
 | 
					                return commit_sha  # found the required commit
 | 
				
			||||||
            except CalledProcessError:
 | 
					            except CalledProcessError:
 | 
				
			||||||
                commits_count += 1  # increase depth
 | 
					                commits_count += 1  # increase depth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # no commits found at the requested depth
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def git(self, gitconfig: dict[str, str] | None = None) -> list[str]:
 | 
					    def git(self, gitconfig: dict[str, str] | None = None) -> list[str]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        git command prefix
 | 
					        git command prefix
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,17 @@ def test_changes_skip(mocker: MockerFixture) -> None:
 | 
				
			|||||||
    diff_mock.assert_not_called()
 | 
					    diff_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_changes_unknown_commit(mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must return none in case if commit sha wasn't found at the required depth
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.build_tools.sources.Sources.fetch_until", return_value=None)
 | 
				
			||||||
 | 
					    diff_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.diff")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert Sources.changes(Path("local"), "sha") is None
 | 
				
			||||||
 | 
					    diff_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_extend_architectures(mocker: MockerFixture) -> None:
 | 
					def test_extend_architectures(mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must update available architecture list
 | 
					    must update available architecture list
 | 
				
			||||||
@ -435,16 +446,17 @@ def test_fetch_until(sources: Sources, mocker: MockerFixture) -> None:
 | 
				
			|||||||
        "",
 | 
					        "",
 | 
				
			||||||
        "",
 | 
					        "",
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					 | 
				
			||||||
    local = Path("local")
 | 
					    local = Path("local")
 | 
				
			||||||
    sources.fetch_until(local, branch="master", commit_sha="sha")
 | 
					    last_commit_sha = "sha"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert sources.fetch_until(local, branch="master", commit_sha="sha") == last_commit_sha
 | 
				
			||||||
    check_output_mock.assert_has_calls([
 | 
					    check_output_mock.assert_has_calls([
 | 
				
			||||||
        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", "origin", "master",
 | 
					        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", "origin", "master",
 | 
				
			||||||
                 cwd=local, logger=sources.logger),
 | 
					                 cwd=local, logger=sources.logger),
 | 
				
			||||||
        MockCall(*sources.git(), "cat-file", "-e", "sha", cwd=local, logger=sources.logger),
 | 
					        MockCall(*sources.git(), "cat-file", "-e", last_commit_sha, cwd=local, logger=sources.logger),
 | 
				
			||||||
        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "2", "origin", "master",
 | 
					        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "2", "origin", "master",
 | 
				
			||||||
                 cwd=local, logger=sources.logger),
 | 
					                 cwd=local, logger=sources.logger),
 | 
				
			||||||
        MockCall(*sources.git(), "cat-file", "-e", "sha", cwd=local, logger=sources.logger),
 | 
					        MockCall(*sources.git(), "cat-file", "-e", last_commit_sha, cwd=local, logger=sources.logger),
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -453,9 +465,9 @@ def test_fetch_until_first(sources: Sources, mocker: MockerFixture) -> None:
 | 
				
			|||||||
    must fetch first commit only
 | 
					    must fetch first commit only
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output")
 | 
				
			||||||
 | 
					 | 
				
			||||||
    local = Path("local")
 | 
					    local = Path("local")
 | 
				
			||||||
    sources.fetch_until(local, branch="master")
 | 
					
 | 
				
			||||||
 | 
					    assert sources.fetch_until(local, branch="master") == "HEAD"
 | 
				
			||||||
    check_output_mock.assert_has_calls([
 | 
					    check_output_mock.assert_has_calls([
 | 
				
			||||||
        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", "origin", "master",
 | 
					        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", "origin", "master",
 | 
				
			||||||
                 cwd=local, logger=sources.logger),
 | 
					                 cwd=local, logger=sources.logger),
 | 
				
			||||||
@ -468,15 +480,28 @@ def test_fetch_until_all_branches(sources: Sources, mocker: MockerFixture) -> No
 | 
				
			|||||||
    must fetch all branches
 | 
					    must fetch all branches
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output")
 | 
				
			||||||
 | 
					 | 
				
			||||||
    local = Path("local")
 | 
					    local = Path("local")
 | 
				
			||||||
    sources.fetch_until(local)
 | 
					
 | 
				
			||||||
 | 
					    assert sources.fetch_until(local) == "HEAD"
 | 
				
			||||||
    check_output_mock.assert_has_calls([
 | 
					    check_output_mock.assert_has_calls([
 | 
				
			||||||
        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", cwd=local, logger=sources.logger),
 | 
					        MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", cwd=local, logger=sources.logger),
 | 
				
			||||||
        MockCall(*sources.git(), "cat-file", "-e", "HEAD", cwd=local, logger=sources.logger),
 | 
					        MockCall(*sources.git(), "cat-file", "-e", "HEAD", cwd=local, logger=sources.logger),
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_fetch_until_not_found(sources: Sources, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must return None in case if no commit found at the required maximal depth
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.build_tools.sources.check_output", side_effect=[
 | 
				
			||||||
 | 
					        "",
 | 
				
			||||||
 | 
					        CalledProcessError(1, ["command"], "error"),
 | 
				
			||||||
 | 
					        "",
 | 
				
			||||||
 | 
					        CalledProcessError(1, ["command"], "error"),
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					    assert sources.fetch_until(Path("local"), branch="master", commit_sha="sha", max_depth=2) is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_git(sources: Sources) -> None:
 | 
					def test_git(sources: Sources) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must correctly generate git command
 | 
					    must correctly generate git command
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user