mirror of https://github.com/Chizi123/Arch-autobuild-repo.git

cbc630823e875a56ef24775c064461d7b8f8c720..f250049cca24d7178cb52569c1da4273884e5aa8
23 hours ago Joel Grunbaum
Rebuild if in config repo
f25004 diff | tree
yesterday Joel Grunbaum
Try and account for multiple build outputs
621616 diff | tree
yesterday Joel Grunbaum
Allow rebuilding existing repo packages
ce77be diff | tree
5 files modified
116 ■■■■ changed files
src/archrepobuild/builder.py 18 ●●●●● patch | view | raw | blame | history
src/archrepobuild/cli.py 10 ●●●● patch | view | raw | blame | history
src/archrepobuild/repo.py 14 ●●●● patch | view | raw | blame | history
src/archrepobuild/resolver.py 20 ●●●● patch | view | raw | blame | history
tests/test_resolver.py 54 ●●●●● patch | view | raw | blame | history
src/archrepobuild/builder.py
@@ -494,11 +494,12 @@
                error=str(e),
            )
    async def add_package(self, package: str) -> BuildResult:
    async def add_package(self, package: str, include_repo: bool = False) -> BuildResult:
        """Add and build (or download) a new package with dependencies.
        Args:
            package: Package name
            include_repo: Whether to check the managed repository for existing packages
        Returns:
            BuildResult for the main package
@@ -506,7 +507,8 @@
        logger.info(f"Adding package: {package}")
        # Resolve dependencies
        build_order = await self.resolver.resolve([package])
        exclude_repo = None if include_repo else self.config.repository.name
        build_order = await self.resolver.resolve([package], exclude_repo=exclude_repo)
        # Filter build order: skip managed repo, download others, build AUR
        final_results: list[BuildResult] = []
@@ -514,10 +516,14 @@
            repo = self.resolver.is_in_repos(pkg_name)
            
            if repo == self.config.repository.name:
                logger.info(f"Package {pkg_name} already in managed repository, skipping")
                if pkg_name == package:
                    return BuildResult(package=package, status=BuildStatus.SKIPPED)
                continue
                if include_repo:
                    logger.info(f"Package {pkg_name} already in managed repository, skipping")
                    if pkg_name == package:
                        return BuildResult(package=package, status=BuildStatus.SKIPPED)
                    continue
                else:
                    # Treat as not in repo to force rebuild from AUR
                    repo = None
            if repo:
                logger.info(f"Package {pkg_name} found in {repo}, downloading...")
src/archrepobuild/cli.py
@@ -117,8 +117,14 @@
@cli.command()
@click.argument("packages", nargs=-1, required=True)
@click.option(
    "--include-repo",
    is_flag=True,
    default=False,
    help="Check managed repository for existing packages (skip if present)",
)
@pass_context
def add(ctx: Context, packages: tuple[str, ...]) -> None:
def add(ctx: Context, packages: tuple[str, ...], include_repo: bool) -> None:
    """Add and build new packages from the AUR."""
    config = ctx.config
@@ -129,7 +135,7 @@
                results = []
                for package in packages:
                    console.print(f"[bold blue]Adding package:[/] {package}")
                    result = await builder.add_package(package)
                    result = await builder.add_package(package, include_repo=include_repo)
                    results.append(result)
                    if result.status == BuildStatus.SUCCESS:
src/archrepobuild/repo.py
@@ -211,8 +211,16 @@
            # Remove package files
            removed = 0
            for f in self.config.repository.path.glob(f"{package}-*.pkg.tar.*"):
                f.unlink()
                removed += 1
                if f.name.endswith(".sig"):
                    continue
                name, _, _ = self._parse_pkg_filename(f.name)
                if name == package:
                    f.unlink()
                    removed += 1
                    # Also remove signature
                    sig = f.with_suffix(f.suffix + ".sig")
                    if sig.exists():
                        sig.unlink()
            logger.info(f"Removed {package} ({removed} files)")
            return True
@@ -232,6 +240,8 @@
        # Find all package files
        files = list(self.config.repository.path.glob(pattern))
        files = [f for f in files if not f.name.endswith(".sig")]
        # Filter to ensure exact package name match (to avoid matching sub-packages)
        files = [f for f in files if self._parse_pkg_filename(f.name)[0] == package]
        if len(files) <= keep_versions:
            return 0
src/archrepobuild/resolver.py
@@ -221,11 +221,9 @@
            dep_parsed = Dependency.parse(dep)
            base_name = dep_parsed.name
            # Skip if in repos or already installed
            # Skip if in repos
            if self.is_in_repos(base_name):
                continue
            if self.is_installed(base_name):
                continue
            aur_deps.append(base_name)
            graph[package.name].add(base_name)
@@ -325,11 +323,12 @@
        return cycles
    async def resolve(self, package_names: list[str]) -> BuildOrder:
    async def resolve(self, package_names: list[str], exclude_repo: str | None = None) -> BuildOrder:
        """Resolve dependencies and determine build order.
        Args:
            package_names: List of packages to resolve
            exclude_repo: Optional repository name to exclude from existence checks
        Returns:
            BuildOrder with packages in correct build order
@@ -340,12 +339,13 @@
        # Filter out packages already in repos or installed
        aur_package_names = []
        for name in package_names:
            if self.is_in_repos(name):
                logger.info(f"Package {name} found in repositories, skipping AUR lookup")
                continue
            if self.is_installed(name):
                logger.info(f"Package {name} is already installed, skipping AUR lookup")
                continue
            repo = self.is_in_repos(name)
            if repo:
                if exclude_repo and repo == exclude_repo:
                    logger.debug(f"Package {name} found in excluded repo {repo}, treating as not in repos")
                else:
                    logger.info(f"Package {name} found in {repo}, skipping AUR lookup")
                    continue
            aur_package_names.append(name)
        if not aur_package_names:
tests/test_resolver.py
@@ -145,6 +145,7 @@
        resolver = DependencyResolver(mock_aur_client)
        
        # Mock AUR response
        from datetime import datetime
        pkg = Package(
            name="test-pkg",
            version="1.0",
@@ -154,8 +155,9 @@
            votes=0,
            popularity=0.0,
            out_of_date=None,
            first_submitted=None,
            last_modified=None,
            first_submitted=datetime.now(),
            last_modified=datetime.now(),
            package_base="test-pkg",
            depends=[],
            makedepends=[],
            checkdepends=["check-dep"],
@@ -170,8 +172,9 @@
            votes=0,
            popularity=0.0,
            out_of_date=None,
            first_submitted=None,
            last_modified=None,
            first_submitted=datetime.now(),
            last_modified=datetime.now(),
            package_base="check-dep",
            depends=[],
            makedepends=[],
            checkdepends=[],
@@ -188,3 +191,46 @@
            assert "check-dep" in build_order.packages
            assert "check-dep" in [d.name for d in build_order.aur_dependencies["test-pkg"]]
            assert any(d.dep_type == DependencyType.CHECK for d in build_order.aur_dependencies["test-pkg"])
    @pytest.mark.asyncio
    async def test_resolve_with_exclude_repo(self, mock_aur_client):
        """Test that resolve correctly handles exclude_repo."""
        from archrepobuild.aur import Package
        resolver = DependencyResolver(mock_aur_client)
        from datetime import datetime
        # Mock AUR response
        pkg = Package(
            name="test-pkg",
            version="1.0",
            description="test",
            url=None,
            maintainer=None,
            votes=0,
            popularity=0.0,
            out_of_date=None,
            first_submitted=datetime.now(),
            last_modified=datetime.now(),
            package_base="test-pkg",
            depends=[],
            makedepends=[],
            checkdepends=[],
        )
        mock_aur_client.get_packages.return_value = [pkg]
        # Case 1: Package in repo, not excluded -> should be skipped
        with patch.object(resolver, "is_in_repos", return_value="myrepo"):
            build_order = await resolver.resolve(["test-pkg"])
            assert "test-pkg" not in build_order.packages
        # Case 2: Package in repo, excluded -> should be included (AUR lookup)
        with patch.object(resolver, "is_in_repos", return_value="myrepo"):
            build_order = await resolver.resolve(["test-pkg"], exclude_repo="myrepo")
            assert "test-pkg" in build_order.packages
        # Case 3: Package in different repo, not excluded -> should be skipped
        with patch.object(resolver, "is_in_repos", return_value="otherrepo"):
            build_order = await resolver.resolve(["test-pkg"], exclude_repo="myrepo")
            assert "test-pkg" not in build_order.packages