mirror of
https://github.com/Jguer/yay.git
synced 2025-06-25 00:03:32 -04:00
Compare commits
No commits in common. "next" and "v12.0.0" have entirely different histories.
@ -1,26 +0,0 @@
|
|||||||
# Use the jguer/yay-builder image as a parent image with archlinux
|
|
||||||
FROM docker.io/jguer/yay-builder
|
|
||||||
|
|
||||||
# Install extra packages (pacman-contrib and fish)
|
|
||||||
RUN sudo pacman -Syu --noconfirm pacman-contrib fish git-delta openssh bat go
|
|
||||||
|
|
||||||
# Set passwordless sudo for the docker user
|
|
||||||
RUN echo "docker ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/docker
|
|
||||||
|
|
||||||
# Create a non-root user and switch to it
|
|
||||||
USER docker
|
|
||||||
|
|
||||||
# Install xgotext
|
|
||||||
RUN go install github.com/leonelquinteros/gotext/cli/xgotext@latest
|
|
||||||
|
|
||||||
# Add /app/bin to the PATH
|
|
||||||
ENV PATH="/app/bin:$PATH"
|
|
||||||
|
|
||||||
# add /home/docker/go/bin to the PATH
|
|
||||||
ENV PATH="/home/docker/go/bin:$PATH"
|
|
||||||
|
|
||||||
# Set the working directory
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
# Command to run when starting the container
|
|
||||||
CMD ["bash"]
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Existing Dockerfile",
|
|
||||||
"build": {
|
|
||||||
"context": "..",
|
|
||||||
"dockerfile": "../.devcontainer/Dockerfile"
|
|
||||||
},
|
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": [
|
|
||||||
"golang.go"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -32,11 +32,6 @@ Example: `yay v8.1139.r0.g9ac4ab6 - libalpm v11.0.1` -->
|
|||||||
Include the FULL output of any relevant commands/configs
|
Include the FULL output of any relevant commands/configs
|
||||||
The current yay config can be printed with `yay -Pg`
|
The current yay config can be printed with `yay -Pg`
|
||||||
Paste services are only needed for excessive output (>500 lines)
|
Paste services are only needed for excessive output (>500 lines)
|
||||||
Use --debug to add pacman and yay debug logs
|
|
||||||
or add the following key to your ~/.config/yay/config.json to only get yay debug logs
|
|
||||||
{
|
|
||||||
"debug": true
|
|
||||||
}
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
15
.github/dependabot.yml
vendored
15
.github/dependabot.yml
vendored
@ -1,15 +0,0 @@
|
|||||||
# To get started with Dependabot version updates, you'll need to specify which
|
|
||||||
# package ecosystems to update and where the package manifests are located.
|
|
||||||
# Please see the documentation for all configuration options:
|
|
||||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "gomod" # See documentation for possible values
|
|
||||||
directory: "/" # Location of package manifests
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
groups:
|
|
||||||
go-all:
|
|
||||||
patterns:
|
|
||||||
- '*'
|
|
155
.github/workflows/builder-image.yml
vendored
155
.github/workflows/builder-image.yml
vendored
@ -1,143 +1,40 @@
|
|||||||
name: Builder Image
|
name: Builder image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 3 * * 1" # Every Monday at 3 AM
|
- cron: "0 3 * * 1"
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- "ci.Dockerfile"
|
- "ci.Dockerfile"
|
||||||
- ".github/workflows/builder-image.yml"
|
- "**/builder-image.yml"
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY_IMAGE: jguer/yay-builder
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
name: Push builder image to Docker Hub
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
platform:
|
|
||||||
- linux/amd64
|
|
||||||
- linux/arm/v7
|
|
||||||
- linux/arm64
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Login to DockerHub
|
||||||
- name: Login to Docker Hub
|
uses: docker/login-action@v1
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Push to Docker Hub
|
||||||
- name: Login to GitHub Container Registry
|
uses: docker/build-push-action@v2
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract metadata for Docker
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
${{ env.REGISTRY_IMAGE }}
|
|
||||||
ghcr.io/${{ env.REGISTRY_IMAGE }}
|
|
||||||
tags: |
|
|
||||||
type=raw,value=latest
|
|
||||||
type=sha,format=long
|
|
||||||
|
|
||||||
- name: Build and push by digest
|
|
||||||
id: build
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ci.Dockerfile
|
|
||||||
platforms: ${{ matrix.platform }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
||||||
|
|
||||||
- name: Export digest
|
|
||||||
run: |
|
|
||||||
mkdir -p /tmp/digests
|
|
||||||
digest="${{ steps.build.outputs.digest }}"
|
|
||||||
echo -n "$digest" > "/tmp/digests/$(echo "${{ matrix.platform }}" | tr '/' '_')"
|
|
||||||
|
|
||||||
- name: Upload digest
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: digest-${{ matrix.platform == 'linux/amd64' && 'amd64' || matrix.platform == 'linux/arm/v7' && 'armv7' || 'arm64' }}
|
|
||||||
path: /tmp/digests/*
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
merge:
|
|
||||||
needs: [build]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Download digests
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
pattern: digest-*
|
|
||||||
merge-multiple: true
|
|
||||||
path: /tmp/digests
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract metadata for Docker
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
${{ env.REGISTRY_IMAGE }}
|
|
||||||
ghcr.io/${{ env.REGISTRY_IMAGE }}
|
|
||||||
tags: |
|
|
||||||
type=raw,value=latest
|
|
||||||
type=sha,format=short
|
|
||||||
|
|
||||||
- name: Create and push manifest list
|
|
||||||
env:
|
env:
|
||||||
DOCKER_CLI_EXPERIMENTAL: enabled
|
DOCKER_BUILDKIT: 0
|
||||||
run: |
|
COMPOSE_DOCKER_CLI_BUILD: 0
|
||||||
# Extract Docker Hub tags
|
with:
|
||||||
DH_TAGS=$(echo '${{ steps.meta.outputs.tags }}' | grep -v "^ghcr.io" | xargs -I {} echo "-t {}")
|
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||||
|
file: ci.Dockerfile
|
||||||
# Extract GitHub Container Registry tags
|
push: true
|
||||||
GHCR_TAGS=$(echo '${{ steps.meta.outputs.tags }}' | grep "^ghcr.io" | xargs -I {} echo "-t {}")
|
tags: jguer/yay-builder:latest
|
||||||
|
secrets: |
|
||||||
# Create a manifest list using the image digests from /tmp/digests/*
|
DOCKER_BUILDKIT=0
|
||||||
DIGESTS=$(for file in /tmp/digests/*; do
|
COMPOSE_DOCKER_CLI_BUILD=0
|
||||||
echo -n "${{ env.REGISTRY_IMAGE }}@$(cat $file) "
|
cache-from: type=registry,ref=jguer/yay-builder:latest
|
||||||
done)
|
cache-to: type=inline
|
||||||
|
|
||||||
# Create the manifest list for Docker Hub
|
|
||||||
docker buildx imagetools create $DH_TAGS $DIGESTS
|
|
||||||
|
|
||||||
# Create the manifest list for GitHub Container Registry
|
|
||||||
docker buildx imagetools create $GHCR_TAGS $DIGESTS
|
|
||||||
|
|
||||||
- name: Inspect image
|
|
||||||
run: |
|
|
||||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:latest
|
|
||||||
|
106
.github/workflows/multiarch-build.yml
vendored
106
.github/workflows/multiarch-build.yml
vendored
@ -1,5 +1,4 @@
|
|||||||
name: Build Release
|
name: Build Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
@ -9,36 +8,31 @@ jobs:
|
|||||||
build-releases:
|
build-releases:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
arch: ["linux/amd64 x86_64", "linux/arm/v7 armv7h", "linux/arm64 aarch64"]
|
arch:
|
||||||
|
["linux/amd64 x86_64", "linux/arm/v7 armv7h", "linux/arm64 aarch64"]
|
||||||
name: Build ${{ matrix.arch }}
|
name: Build ${{ matrix.arch }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
platforms: all
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
- name: Read info
|
- name: Read info
|
||||||
id: tags
|
id: tags
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/v/}
|
||||||
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
|
||||||
arch="${{ matrix.arch }}"
|
arch="${{ matrix.arch }}"
|
||||||
echo "PLATFORM=${arch%% *}" >> $GITHUB_OUTPUT
|
echo ::set-output name=PLATFORM::${arch%% *}
|
||||||
echo "ARCH=${arch##* }" >> $GITHUB_OUTPUT
|
echo ::set-output name=ARCH::${arch##* }
|
||||||
|
|
||||||
- name: Build ${{ matrix.arch }} release
|
- name: Build ${{ matrix.arch }} release
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
@ -49,44 +43,74 @@ jobs:
|
|||||||
-t yay:${{ steps.tags.outputs.arch }} . --load
|
-t yay:${{ steps.tags.outputs.arch }} . --load
|
||||||
make docker-release ARCH=${{ steps.tags.outputs.arch }} VERSION=${{ steps.tags.outputs.version }} PREFIX="/usr"
|
make docker-release ARCH=${{ steps.tags.outputs.arch }} VERSION=${{ steps.tags.outputs.version }} PREFIX="/usr"
|
||||||
mv *.tar.gz artifacts
|
mv *.tar.gz artifacts
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: yay_${{ steps.tags.outputs.arch }}
|
name: yay_${{ steps.tags.outputs.arch }}
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
||||||
create_release:
|
create_release:
|
||||||
name: Create release from this build
|
name: Create release from this build
|
||||||
needs: [build-releases]
|
needs: [build-releases]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Read info
|
- name: Read info
|
||||||
id: tags
|
id: tags
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/v/}
|
||||||
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
pattern: yay_*
|
name: yay_x86_64
|
||||||
merge-multiple: true
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: yay_armv7h
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: yay_aarch64
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@master
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
with:
|
||||||
gh release create ${{ steps.tags.outputs.tag }} \
|
tag_name: ${{ steps.tags.outputs.tag }}
|
||||||
--title "${{ steps.tags.outputs.tag }}" \
|
release_name: ${{ steps.tags.outputs.tag }}
|
||||||
--generate-notes \
|
draft: false
|
||||||
./yay_${{ steps.tags.outputs.version }}_*.tar.gz
|
prerelease: false
|
||||||
|
- name: Upload x86_64 asset
|
||||||
|
id: upload-release-asset-x86_64
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./yay_${{ steps.tags.outputs.version }}_x86_64.tar.gz
|
||||||
|
asset_name: yay_${{ steps.tags.outputs.version }}_x86_64.tar.gz
|
||||||
|
asset_content_type: application/tar+gzip
|
||||||
|
- name: Upload armv7h asset
|
||||||
|
id: upload-release-asset-armv7h
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./yay_${{ steps.tags.outputs.version }}_armv7h.tar.gz
|
||||||
|
asset_name: yay_${{ steps.tags.outputs.version }}_armv7h.tar.gz
|
||||||
|
asset_content_type: application/tar+gzip
|
||||||
|
- name: Upload aarch64 asset
|
||||||
|
id: upload-release-asset-aarch64
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./yay_${{ steps.tags.outputs.version }}_aarch64.tar.gz
|
||||||
|
asset_name: yay_${{ steps.tags.outputs.version }}_aarch64.tar.gz
|
||||||
|
asset_content_type: application/tar+gzip
|
||||||
- name: Release Notary Action
|
- name: Release Notary Action
|
||||||
uses: docker://aevea/release-notary:latest
|
uses: docker://aevea/release-notary:latest
|
||||||
env:
|
env:
|
||||||
|
7
.github/workflows/testing-git.yml
vendored
7
.github/workflows/testing-git.yml
vendored
@ -12,9 +12,9 @@ jobs:
|
|||||||
name: Lint and test yay (-git)
|
name: Lint and test yay (-git)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/jguer/yay-builder:latest
|
image: jguer/yay-builder:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: ~/go/pkg/mod
|
||||||
@ -35,5 +35,4 @@ jobs:
|
|||||||
chmod -R 777 pacman-git
|
chmod -R 777 pacman-git
|
||||||
su github -c 'cd pacman-git; yes | makepkg -i --nocheck'
|
su github -c 'cd pacman-git; yes | makepkg -i --nocheck'
|
||||||
- name: Run Build and Tests with pacman-git
|
- name: Run Build and Tests with pacman-git
|
||||||
run: |
|
run: make test
|
||||||
make test
|
|
||||||
|
28
.github/workflows/testing.yml
vendored
28
.github/workflows/testing.yml
vendored
@ -7,9 +7,9 @@ jobs:
|
|||||||
name: Lint and test yay
|
name: Lint and test yay
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/jguer/yay-builder:latest
|
image: jguer/yay-builder:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: ~/go/pkg/mod
|
||||||
@ -17,28 +17,6 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
- name: Lint
|
- name: Lint
|
||||||
env:
|
run: /app/bin/golangci-lint run ./...
|
||||||
GOFLAGS: -buildvcs=false -tags=next
|
|
||||||
run: /app/bin/golangci-lint run -v ./...
|
|
||||||
- name: Run Build and Tests
|
- name: Run Build and Tests
|
||||||
run: make test
|
run: make test
|
||||||
|
|
||||||
- name: Run Integration Tests
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
useradd -m yay &&
|
|
||||||
chown -R yay:yay . &&
|
|
||||||
cp -r ~/go/ /home/yay/go/ &&
|
|
||||||
chown -R yay:yay /home/yay/go/ &&
|
|
||||||
su yay -c "make test-integration"
|
|
||||||
- name: Build yay Artifact
|
|
||||||
env:
|
|
||||||
GOFLAGS: -buildvcs=false -tags=next
|
|
||||||
run: make
|
|
||||||
- name: Upload yay Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: yay
|
|
||||||
path: ./yay
|
|
||||||
if-no-files-found: error
|
|
||||||
overwrite: true
|
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -28,7 +28,3 @@ qemu-*
|
|||||||
*.pot
|
*.pot
|
||||||
*.po~
|
*.po~
|
||||||
*.pprof
|
*.pprof
|
||||||
|
|
||||||
node_modules/
|
|
||||||
xgotext
|
|
||||||
.devcontainer/
|
|
154
.golangci.yml
154
.golangci.yml
@ -1,18 +1,70 @@
|
|||||||
version: "2"
|
linters-settings:
|
||||||
run:
|
dupl:
|
||||||
go: "1.20"
|
threshold: 100
|
||||||
|
funlen:
|
||||||
|
lines: 100
|
||||||
|
statements: 50
|
||||||
|
goconst:
|
||||||
|
min-len: 3
|
||||||
|
min-occurrences: 4
|
||||||
|
gocritic:
|
||||||
|
enabled-tags:
|
||||||
|
- diagnostic
|
||||||
|
- experimental
|
||||||
|
- opinionated
|
||||||
|
- performance
|
||||||
|
- style
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 15
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/Jguer/yay/v12
|
||||||
|
gomnd:
|
||||||
|
checks:
|
||||||
|
- argument
|
||||||
|
- case
|
||||||
|
- condition
|
||||||
|
- return
|
||||||
|
ignored-numbers:
|
||||||
|
- "0"
|
||||||
|
- "1"
|
||||||
|
- "2"
|
||||||
|
- "3"
|
||||||
|
ignored-functions:
|
||||||
|
- strings.SplitN
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
lll:
|
||||||
|
line-length: 140
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
nolintlint:
|
||||||
|
allow-unused: false # report any unused nolint directives
|
||||||
|
require-explanation: false # don't require an explanation for nolint directives
|
||||||
|
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
default: none
|
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||||
|
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||||
|
disable-all: true
|
||||||
enable:
|
enable:
|
||||||
- bodyclose
|
- bodyclose
|
||||||
|
- depguard
|
||||||
- dogsled
|
- dogsled
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
|
||||||
- errorlint
|
- errorlint
|
||||||
|
- errcheck
|
||||||
|
- exportloopref
|
||||||
|
# - funlen # TOFIX
|
||||||
- gochecknoinits
|
- gochecknoinits
|
||||||
|
# - goconst # TOFIX
|
||||||
- gocritic
|
- gocritic
|
||||||
|
# - gocyclo # TOFIX
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
# - gomnd # TOFIX
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
- gosec
|
- gosec
|
||||||
|
- gosimple
|
||||||
- govet
|
- govet
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- lll
|
- lll
|
||||||
@ -21,74 +73,32 @@ linters:
|
|||||||
- noctx
|
- noctx
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- staticcheck
|
- staticcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- unused
|
- unused
|
||||||
- whitespace
|
- whitespace
|
||||||
settings:
|
|
||||||
dupl:
|
run:
|
||||||
threshold: 100
|
go: "1.18"
|
||||||
funlen:
|
timeout: "10m"
|
||||||
lines: 100
|
|
||||||
statements: 50
|
issues:
|
||||||
goconst:
|
exclude-rules:
|
||||||
min-len: 3
|
- path: (.+)_test.go
|
||||||
min-occurrences: 4
|
linters:
|
||||||
gocritic:
|
- lll
|
||||||
enabled-tags:
|
- revive
|
||||||
- diagnostic
|
- wsl
|
||||||
- experimental
|
- govet
|
||||||
- opinionated
|
- godot
|
||||||
- performance
|
- errcheck
|
||||||
- style
|
- stylecheck
|
||||||
gocyclo:
|
- dupl
|
||||||
min-complexity: 15
|
- gocritic
|
||||||
lll:
|
- gochecknoinits
|
||||||
line-length: 140
|
- errorlint
|
||||||
misspell:
|
|
||||||
locale: US
|
exclude:
|
||||||
nolintlint:
|
- G204
|
||||||
require-explanation: false
|
|
||||||
require-specific: false
|
|
||||||
allow-unused: false
|
|
||||||
exclusions:
|
|
||||||
generated: lax
|
|
||||||
presets:
|
|
||||||
- comments
|
|
||||||
- common-false-positives
|
|
||||||
- legacy
|
|
||||||
- std-error-handling
|
|
||||||
rules:
|
|
||||||
- linters:
|
|
||||||
- dupl
|
|
||||||
- errcheck
|
|
||||||
- errorlint
|
|
||||||
- gochecknoinits
|
|
||||||
- gocritic
|
|
||||||
- godot
|
|
||||||
- govet
|
|
||||||
- lll
|
|
||||||
- revive
|
|
||||||
- staticcheck
|
|
||||||
- wsl
|
|
||||||
path: (.+)_test.go
|
|
||||||
- path: (.+)\.go$
|
|
||||||
text: G204
|
|
||||||
paths:
|
|
||||||
- third_party$
|
|
||||||
- builtin$
|
|
||||||
- examples$
|
|
||||||
formatters:
|
|
||||||
enable:
|
|
||||||
- gofmt
|
|
||||||
- goimports
|
|
||||||
settings:
|
|
||||||
goimports:
|
|
||||||
local-prefixes:
|
|
||||||
- github.com/Jguer/yay/v12
|
|
||||||
exclusions:
|
|
||||||
generated: lax
|
|
||||||
paths:
|
|
||||||
- third_party$
|
|
||||||
- builtin$
|
|
||||||
- examples$
|
|
||||||
|
@ -5,17 +5,19 @@ repos:
|
|||||||
rev: v0.5.1
|
rev: v0.5.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: go-fmt
|
- id: go-fmt
|
||||||
|
- id: go-imports
|
||||||
|
args: [-local=github.com/Jguer/yay/v12/]
|
||||||
- id: golangci-lint
|
- id: golangci-lint
|
||||||
- id: go-unit-tests
|
- id: go-unit-tests
|
||||||
- id: go-build
|
- id: go-build
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
rev: v4.0.0-alpha.8 # Use the sha or tag you want to point at
|
rev: v3.0.0-alpha.4 # Use the sha or tag you want to point at
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.5.0 # Use the ref you want to point at
|
rev: v4.4.0 # Use the ref you want to point at
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: check-json
|
- id: check-json
|
||||||
@ -23,7 +25,7 @@ repos:
|
|||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
|
|
||||||
- repo: https://github.com/commitizen-tools/commitizen
|
- repo: https://github.com/commitizen-tools/commitizen
|
||||||
rev: v3.15.0
|
rev: v2.38.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: commitizen
|
- id: commitizen
|
||||||
stages: [commit-msg]
|
stages: [commit-msg]
|
||||||
|
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"go.lintTool": "golangci-lint",
|
|
||||||
"gopls": {
|
|
||||||
"formatting.gofumpt": true,
|
|
||||||
"formatting.local": "github.com/Jguer/yay/v12"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
FROM ghcr.io/jguer/yay-builder:latest
|
FROM docker.io/jguer/yay-builder:latest
|
||||||
LABEL maintainer="Jguer,docker@jguer.space"
|
LABEL maintainer="Jguer,joaogg3 at google mail"
|
||||||
|
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
ARG PREFIX
|
ARG PREFIX
|
||||||
|
16
Makefile
16
Makefile
@ -26,7 +26,8 @@ MOFILES := $(POFILES:.po=.mo)
|
|||||||
|
|
||||||
FLAGS ?= -trimpath -mod=readonly -modcacherw
|
FLAGS ?= -trimpath -mod=readonly -modcacherw
|
||||||
EXTRA_FLAGS ?= -buildmode=pie
|
EXTRA_FLAGS ?= -buildmode=pie
|
||||||
LDFLAGS := -X "main.yayVersion=${VERSION}" -X "main.localePath=${SYSTEMLOCALEPATH}" -linkmode=external -compressdwarf=false
|
LDFLAGS := -X "main.yayVersion=${VERSION}" -X "main.localePath=${SYSTEMLOCALEPATH}" -linkmode=external
|
||||||
|
FLAGS += $(shell pacman -T 'pacman-git' >/dev/null 2>&1 && echo "-tags next")
|
||||||
|
|
||||||
RELEASE_DIR := ${PKGNAME}_${VERSION}_${ARCH}
|
RELEASE_DIR := ${PKGNAME}_${VERSION}_${ARCH}
|
||||||
PACKAGE := $(RELEASE_DIR).tar.gz
|
PACKAGE := $(RELEASE_DIR).tar.gz
|
||||||
@ -52,10 +53,6 @@ test_lint: test lint
|
|||||||
test:
|
test:
|
||||||
$(GO) test -race -covermode=atomic $(FLAGS) ./...
|
$(GO) test -race -covermode=atomic $(FLAGS) ./...
|
||||||
|
|
||||||
.PHONY: test-integration
|
|
||||||
test-integration:
|
|
||||||
$(GO) test -tags=integration $(FLAGS) ./...
|
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(BIN)
|
build: $(BIN)
|
||||||
|
|
||||||
@ -69,7 +66,7 @@ docker-release-all:
|
|||||||
make docker-release-aarch64 ARCH=aarch64
|
make docker-release-aarch64 ARCH=aarch64
|
||||||
|
|
||||||
docker-release:
|
docker-release:
|
||||||
docker create --name yay-$(ARCH) yay:${ARCH} /bin/sh
|
docker create --name yay-$(ARCH) yay:${ARCH}
|
||||||
docker cp yay-$(ARCH):/app/${PACKAGE} $(PACKAGE)
|
docker cp yay-$(ARCH):/app/${PACKAGE} $(PACKAGE)
|
||||||
docker container rm yay-$(ARCH)
|
docker container rm yay-$(ARCH)
|
||||||
|
|
||||||
@ -82,7 +79,9 @@ docker-build:
|
|||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
GOFLAGS="$(FLAGS)" golangci-lint run ./...
|
$(GO) vet $(FLAGS) ./...
|
||||||
|
@test -z "$$(gofmt -l $(SOURCES))" || (echo "Files need to be linted. Use make fmt" && false)
|
||||||
|
golangci-lint run ./...
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt:
|
fmt:
|
||||||
@ -123,9 +122,8 @@ $(PACKAGE): $(BIN) $(RELEASE_DIR) ${MOFILES}
|
|||||||
|
|
||||||
locale:
|
locale:
|
||||||
xgotext -in . -out po
|
xgotext -in . -out po
|
||||||
mv po/default.pot po/en.po
|
|
||||||
for lang in ${LANGS}; do \
|
for lang in ${LANGS}; do \
|
||||||
test -f po/$$lang.po || msginit --no-translator -l po/$$lang.po -i po/${POTFILE} -o po/$$lang.po; \
|
test -f po/$$lang.po || msginit -l po/$$lang.po -i po/${POTFILE} -o po/$$lang.po \
|
||||||
msgmerge -U po/$$lang.po po/${POTFILE}; \
|
msgmerge -U po/$$lang.po po/${POTFILE}; \
|
||||||
touch po/$$lang.po; \
|
touch po/$$lang.po; \
|
||||||
done
|
done
|
||||||
|
65
README.md
65
README.md
@ -30,18 +30,15 @@ Yet Another Yogurt - An AUR Helper Written in Go
|
|||||||
|
|
||||||
If you are migrating from another AUR helper, you can simply install Yay with that helper.
|
If you are migrating from another AUR helper, you can simply install Yay with that helper.
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> We are using `sudo` in these examples, you can switch that out for a different privilege escalation tool.
|
|
||||||
|
|
||||||
### Source
|
### Source
|
||||||
|
|
||||||
The initial installation of Yay can be done by cloning the PKGBUILD and
|
The initial installation of Yay can be done by cloning the PKGBUILD and
|
||||||
building with makepkg:
|
building with makepkg:
|
||||||
|
|
||||||
We make sure we have the `base-devel` package group installed.
|
Before you begin, make sure you have the `base-devel` package group installed.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo pacman -S --needed git base-devel
|
pacman -S --needed git base-devel
|
||||||
git clone https://aur.archlinux.org/yay.git
|
git clone https://aur.archlinux.org/yay.git
|
||||||
cd yay
|
cd yay
|
||||||
makepkg -si
|
makepkg -si
|
||||||
@ -50,7 +47,7 @@ makepkg -si
|
|||||||
If you want to do all of this at once, we can chain the commands like so:
|
If you want to do all of this at once, we can chain the commands like so:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si
|
pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si
|
||||||
```
|
```
|
||||||
|
|
||||||
### Binary
|
### Binary
|
||||||
@ -59,18 +56,12 @@ If you do not want to compile yay yourself you can use the builds generated by
|
|||||||
GitHub Actions.
|
GitHub Actions.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo pacman -S --needed git base-devel
|
pacman -S --needed git base-devel
|
||||||
git clone https://aur.archlinux.org/yay-bin.git
|
git clone https://aur.archlinux.org/yay-bin.git
|
||||||
cd yay-bin
|
cd yay-bin
|
||||||
makepkg -si
|
makepkg -si
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to do all of this at once, we can chain the commands like so:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay-bin.git && cd yay-bin && makepkg -si
|
|
||||||
```
|
|
||||||
|
|
||||||
### Other distributions
|
### Other distributions
|
||||||
|
|
||||||
If you're using Manjaro or [another distribution that packages `yay`](https://repology.org/project/yay/versions)
|
If you're using Manjaro or [another distribution that packages `yay`](https://repology.org/project/yay/versions)
|
||||||
@ -79,8 +70,8 @@ you can simply install yay using pacman (as root):
|
|||||||
```sh
|
```sh
|
||||||
pacman -S --needed git base-devel yay
|
pacman -S --needed git base-devel yay
|
||||||
```
|
```
|
||||||
> [!WARNING]
|
|
||||||
> distributions sometimes lag updating yay on their repositories.
|
⚠️ distributions sometimes lag updating yay on their repositories.
|
||||||
|
|
||||||
## First Use
|
## First Use
|
||||||
|
|
||||||
@ -120,6 +111,17 @@ pacman -S --needed git base-devel yay
|
|||||||
Make sure you have the `Color` option in your `/etc/pacman.conf`
|
Make sure you have the `Color` option in your `/etc/pacman.conf`
|
||||||
(see issue [#123](https://github.com/Jguer/yay/issues/123)).
|
(see issue [#123](https://github.com/Jguer/yay/issues/123)).
|
||||||
|
|
||||||
|
- **Yay is not prompting to skip packages during system upgrade.**
|
||||||
|
|
||||||
|
The default behavior was changed after
|
||||||
|
[v8.918](https://github.com/Jguer/yay/releases/tag/v8.918)
|
||||||
|
(see [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)
|
||||||
|
and issue [#554](https://github.com/Jguer/yay/issues/554)).
|
||||||
|
To restore the package-skip behavior use `--combinedupgrade` (make
|
||||||
|
it permanent by appending `--save`). Note: skipping packages will leave your
|
||||||
|
system in a
|
||||||
|
[partially-upgraded state](https://wiki.archlinux.org/index.php/System_maintenance#Partial_upgrades_are_unsupported).
|
||||||
|
|
||||||
- **Sometimes diffs are printed to the terminal, and other times they are paged via less. How do I fix this?**
|
- **Sometimes diffs are printed to the terminal, and other times they are paged via less. How do I fix this?**
|
||||||
|
|
||||||
Yay uses `git diff` to display diffs, which by default tells less not to
|
Yay uses `git diff` to display diffs, which by default tells less not to
|
||||||
@ -128,14 +130,14 @@ pacman -S --needed git base-devel yay
|
|||||||
|
|
||||||
- **Yay is not asking me to edit PKGBUILDS, and I don't like the diff menu! What can I do?**
|
- **Yay is not asking me to edit PKGBUILDS, and I don't like the diff menu! What can I do?**
|
||||||
|
|
||||||
`yay --editmenu --diffmenu=false --save`
|
`yay --editmenu --nodiffmenu --save`
|
||||||
|
|
||||||
- **How can I tell Yay to act only on AUR packages, or only on repo packages?**
|
- **How can I tell Yay to act only on AUR packages, or only on repo packages?**
|
||||||
|
|
||||||
`yay -{OPERATION} --aur`
|
`yay -{OPERATION} --aur`
|
||||||
`yay -{OPERATION} --repo`
|
`yay -{OPERATION} --repo`
|
||||||
|
|
||||||
- **A `Flagged Out Of Date AUR Packages` message is displayed. Why doesn't Yay update them?**
|
- **An `Out Of Date AUR Packages` message is displayed. Why doesn't Yay update them?**
|
||||||
|
|
||||||
This message does not mean that updated AUR packages are available. It means
|
This message does not mean that updated AUR packages are available. It means
|
||||||
the packages have been flagged out of date on the AUR, but
|
the packages have been flagged out of date on the AUR, but
|
||||||
@ -150,13 +152,28 @@ pacman -S --needed git base-devel yay
|
|||||||
|
|
||||||
- **I know my `-git` package has updates but yay doesn't offer to update it**
|
- **I know my `-git` package has updates but yay doesn't offer to update it**
|
||||||
|
|
||||||
Yay uses a hash cache for development packages. Normally it is updated at the end of the package install with the message `Found git repo`.
|
Yay uses an hash cache for development packages. Normally it is updated at the end of the package install with the message `Found git repo`.
|
||||||
If you transition between aur helpers and did not install the devel package using yay at some point, it is possible it never got added to the cache. `yay -Y --gendb` will fix the current version of every devel package and start checking from there.
|
If you transition between aur helpers and did not install the devel package using yay at some point, it is possible it never got added to the cache. `yay -Y --gendb` will fix the current version of every devel package and start checking from there.
|
||||||
|
|
||||||
- **I want to help out!**
|
- **I want to help out!**
|
||||||
|
|
||||||
Check [CONTRIBUTING.md](./CONTRIBUTING.md) for more information.
|
Check [CONTRIBUTING.md](./CONTRIBUTING.md) for more information.
|
||||||
|
|
||||||
|
- **What settings do you use?**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yay -Y --devel --combinedupgrade --batchinstall --save
|
||||||
|
```
|
||||||
|
|
||||||
|
Pacman conf options:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
UseSyslog
|
||||||
|
Color
|
||||||
|
CheckSpace
|
||||||
|
VerbosePkgLists
|
||||||
|
```
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
All support related to Yay should be requested via GitHub issues. Since Yay is not
|
All support related to Yay should be requested via GitHub issues. Since Yay is not
|
||||||
@ -172,14 +189,14 @@ tools.
|
|||||||
|
|
||||||
## Images
|
## Images
|
||||||
|
|
||||||
<p align="center">
|
<p float="left">
|
||||||
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay.png" width="42%">
|
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay.png" width="42%"/>
|
||||||
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-s.png" width="42%">
|
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay-s.png" width="42%"/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p float="left">
|
||||||
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-y.png" width="42%">
|
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay-y.png" width="42%"/>
|
||||||
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-ps.png" width="42%">
|
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay-ps.png" width="42%"/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
### Other AUR helpers/tools
|
### Other AUR helpers/tools
|
||||||
|
13
SECURITY.md
13
SECURITY.md
@ -1,13 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
Thank you for helping keep yay secure!
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
We only provide security updates and support for the latest released version of yay. Please ensure you are using the most up-to-date version before reporting vulnerabilities.
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
If you discover a security vulnerability, please email us at [security@jguer.space](mailto:security@jguer.space). We will respond as quickly as possible and coordinate a fix.
|
|
||||||
|
|
||||||
We appreciate responsible disclosure and your help in making this project safe for everyone.
|
|
@ -1,4 +1,4 @@
|
|||||||
package build
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -27,39 +27,33 @@ type (
|
|||||||
exeCmd exe.ICmdBuilder
|
exeCmd exe.ICmdBuilder
|
||||||
vcsStore vcs.Store
|
vcsStore vcs.Store
|
||||||
targetMode parser.TargetMode
|
targetMode parser.TargetMode
|
||||||
rebuildMode parser.RebuildMode
|
|
||||||
origTargets mapset.Set[string]
|
|
||||||
downloadOnly bool
|
downloadOnly bool
|
||||||
log *text.Logger
|
log *text.Logger
|
||||||
|
|
||||||
manualConfirmRequired bool
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewInstaller(dbExecutor db.Executor,
|
func NewInstaller(dbExecutor db.Executor,
|
||||||
exeCmd exe.ICmdBuilder, vcsStore vcs.Store, targetMode parser.TargetMode,
|
exeCmd exe.ICmdBuilder, vcsStore vcs.Store, targetMode parser.TargetMode,
|
||||||
rebuildMode parser.RebuildMode, downloadOnly bool, logger *text.Logger,
|
downloadOnly bool, logger *text.Logger,
|
||||||
) *Installer {
|
) *Installer {
|
||||||
return &Installer{
|
return &Installer{
|
||||||
dbExecutor: dbExecutor,
|
dbExecutor: dbExecutor,
|
||||||
postInstallHooks: []PostInstallHookFunc{},
|
postInstallHooks: []PostInstallHookFunc{},
|
||||||
failedAndIgnored: map[string]error{},
|
failedAndIgnored: map[string]error{},
|
||||||
exeCmd: exeCmd,
|
exeCmd: exeCmd,
|
||||||
vcsStore: vcsStore,
|
vcsStore: vcsStore,
|
||||||
targetMode: targetMode,
|
targetMode: targetMode,
|
||||||
rebuildMode: rebuildMode,
|
downloadOnly: downloadOnly,
|
||||||
downloadOnly: downloadOnly,
|
log: logger,
|
||||||
log: logger,
|
|
||||||
manualConfirmRequired: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (installer *Installer) CompileFailedAndIgnored() (map[string]error, error) {
|
func (installer *Installer) CompileFailedAndIgnored() error {
|
||||||
if len(installer.failedAndIgnored) == 0 {
|
if len(installer.failedAndIgnored) == 0 {
|
||||||
return installer.failedAndIgnored, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return installer.failedAndIgnored, &FailedIgnoredPkgError{
|
return &FailedIgnoredPkgError{
|
||||||
pkgErrors: installer.failedAndIgnored,
|
pkgErrors: installer.failedAndIgnored,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,17 +83,7 @@ func (installer *Installer) Install(ctx context.Context,
|
|||||||
targets []map[string]*dep.InstallInfo,
|
targets []map[string]*dep.InstallInfo,
|
||||||
pkgBuildDirs map[string]string,
|
pkgBuildDirs map[string]string,
|
||||||
excluded []string,
|
excluded []string,
|
||||||
manualConfirmRequired bool,
|
|
||||||
) error {
|
) error {
|
||||||
installer.log.Debugln("manualConfirmRequired:", manualConfirmRequired)
|
|
||||||
installer.manualConfirmRequired = manualConfirmRequired
|
|
||||||
|
|
||||||
installer.origTargets = mapset.NewThreadUnsafeSet[string]()
|
|
||||||
for _, targetString := range cmdArgs.Targets {
|
|
||||||
installer.origTargets.Add(dep.ToTarget(targetString).Name)
|
|
||||||
}
|
|
||||||
installer.log.Debugln("origTargets:", installer.origTargets)
|
|
||||||
|
|
||||||
// Reorganize targets into layers of dependencies
|
// Reorganize targets into layers of dependencies
|
||||||
var errMulti multierror.MultiError
|
var errMulti multierror.MultiError
|
||||||
for i := len(targets) - 1; i >= 0; i-- {
|
for i := len(targets) - 1; i >= 0; i-- {
|
||||||
@ -133,10 +117,6 @@ func mergeLayers(layer1, layer2 map[string]*dep.InstallInfo) map[string]*dep.Ins
|
|||||||
return layer1
|
return layer1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (installer *Installer) appendNoConfirm() bool {
|
|
||||||
return !installer.manualConfirmRequired || settings.NoConfirm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (installer *Installer) handleLayer(ctx context.Context,
|
func (installer *Installer) handleLayer(ctx context.Context,
|
||||||
cmdArgs *parser.Arguments,
|
cmdArgs *parser.Arguments,
|
||||||
layer map[string]*dep.InstallInfo,
|
layer map[string]*dep.InstallInfo,
|
||||||
@ -145,20 +125,15 @@ func (installer *Installer) handleLayer(ctx context.Context,
|
|||||||
excluded []string,
|
excluded []string,
|
||||||
) error {
|
) error {
|
||||||
// Install layer
|
// Install layer
|
||||||
nameToBaseMap := make(map[string]string, len(layer))
|
nameToBaseMap := make(map[string]string, 0)
|
||||||
syncDeps, syncExp, syncGroups := mapset.NewThreadUnsafeSet[string](),
|
syncDeps, syncExp := mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()
|
||||||
mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()
|
aurDeps, aurExp := mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()
|
||||||
aurDeps, aurExp, aurOrigTargetBases := mapset.NewThreadUnsafeSet[string](),
|
|
||||||
mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()
|
|
||||||
|
|
||||||
upgradeSync := false
|
upgradeSync := false
|
||||||
for name, info := range layer {
|
for name, info := range layer {
|
||||||
switch info.Source {
|
switch info.Source {
|
||||||
case dep.AUR, dep.SrcInfo:
|
case dep.AUR, dep.SrcInfo:
|
||||||
nameToBaseMap[name] = *info.AURBase
|
nameToBaseMap[name] = *info.AURBase
|
||||||
if installer.origTargets.Contains(name) {
|
|
||||||
aurOrigTargetBases.Add(*info.AURBase)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch info.Reason {
|
switch info.Reason {
|
||||||
case dep.Explicit:
|
case dep.Explicit:
|
||||||
@ -177,11 +152,6 @@ func (installer *Installer) handleLayer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
compositePkgName := fmt.Sprintf("%s/%s", *info.SyncDBName, name)
|
compositePkgName := fmt.Sprintf("%s/%s", *info.SyncDBName, name)
|
||||||
|
|
||||||
if info.IsGroup {
|
|
||||||
syncGroups.Add(compositePkgName)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch info.Reason {
|
switch info.Reason {
|
||||||
case dep.Explicit:
|
case dep.Explicit:
|
||||||
if cmdArgs.ExistsArg("asdeps", "asdep") {
|
if cmdArgs.ExistsArg("asdeps", "asdep") {
|
||||||
@ -195,66 +165,52 @@ func (installer *Installer) handleLayer(ctx context.Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
installer.log.Debugln("syncDeps", syncDeps, "SyncExp", syncExp,
|
text.Debugln("syncDeps", syncDeps, "SyncExp", syncExp,
|
||||||
"aurDeps", aurDeps, "aurExp", aurExp, "upgrade", upgradeSync)
|
"aurDeps", aurDeps, "aurExp", aurExp, "upgrade", upgradeSync)
|
||||||
|
|
||||||
errShow := installer.installSyncPackages(ctx, cmdArgs, syncDeps, syncExp, syncGroups,
|
errShow := installer.installSyncPackages(ctx, cmdArgs, syncDeps, syncExp, excluded, upgradeSync)
|
||||||
excluded, upgradeSync, installer.appendNoConfirm())
|
|
||||||
if errShow != nil {
|
if errShow != nil {
|
||||||
return ErrInstallRepoPkgs
|
return ErrInstallRepoPkgs
|
||||||
}
|
}
|
||||||
|
|
||||||
errAur := installer.installAURPackages(ctx, cmdArgs, aurDeps, aurExp,
|
errAur := installer.installAURPackages(ctx, cmdArgs, aurDeps, aurExp,
|
||||||
aurOrigTargetBases, nameToBaseMap, pkgBuildDirs, true, lastLayer,
|
nameToBaseMap, pkgBuildDirs, true, lastLayer)
|
||||||
installer.appendNoConfirm())
|
|
||||||
|
|
||||||
return errAur
|
return errAur
|
||||||
}
|
}
|
||||||
|
|
||||||
func (installer *Installer) installAURPackages(ctx context.Context,
|
func (installer *Installer) installAURPackages(ctx context.Context,
|
||||||
cmdArgs *parser.Arguments,
|
cmdArgs *parser.Arguments,
|
||||||
aurDepNames, aurExpNames, aurOrigTargetBases mapset.Set[string],
|
aurDepNames, aurExpNames mapset.Set[string],
|
||||||
nameToBase, pkgBuildDirsByBase map[string]string,
|
nameToBase, pkgBuildDirsByBase map[string]string,
|
||||||
installIncompatible bool,
|
installIncompatible bool,
|
||||||
lastLayer bool,
|
lastLayer bool,
|
||||||
noConfirm bool,
|
|
||||||
) error {
|
) error {
|
||||||
all := aurDepNames.Union(aurExpNames).ToSlice()
|
all := aurDepNames.Union(aurExpNames).ToSlice()
|
||||||
if len(all) == 0 {
|
if len(all) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builtPkgDests := make(map[string]map[string]string)
|
deps, exps := make([]string, 0, aurDepNames.Cardinality()), make([]string, 0, aurExpNames.Cardinality())
|
||||||
deps := make([]string, 0, aurDepNames.Cardinality())
|
pkgArchives := make([]string, 0, len(exps)+len(deps))
|
||||||
exps := make([]string, 0, aurExpNames.Cardinality())
|
|
||||||
pkgArchives := make([]string, 0, len(all))
|
|
||||||
|
|
||||||
for _, name := range all {
|
for _, name := range all {
|
||||||
base := nameToBase[name]
|
base := nameToBase[name]
|
||||||
dir := pkgBuildDirsByBase[base]
|
dir := pkgBuildDirsByBase[base]
|
||||||
|
|
||||||
pkgdests, ok := builtPkgDests[base]
|
pkgdests, errMake := installer.buildPkg(ctx, dir, base, installIncompatible, cmdArgs.ExistsArg("needed"))
|
||||||
if ok {
|
if errMake != nil {
|
||||||
installer.log.Debugln("skipping built pkgbase", base, "package", name)
|
if !lastLayer {
|
||||||
} else {
|
return fmt.Errorf("%s - %w", gotext.Get("error making: %s", base), errMake)
|
||||||
var errMake error
|
|
||||||
installer.log.Debugln("building pkgbase", base, "package", name)
|
|
||||||
pkgdests, errMake = installer.buildPkg(ctx, dir, base,
|
|
||||||
installIncompatible, cmdArgs.ExistsArg("needed"), aurOrigTargetBases.Contains(base))
|
|
||||||
builtPkgDests[base] = pkgdests
|
|
||||||
if errMake != nil {
|
|
||||||
if !lastLayer {
|
|
||||||
return fmt.Errorf("%s - %w", gotext.Get("error making: %s", base), errMake)
|
|
||||||
}
|
|
||||||
|
|
||||||
installer.failedAndIgnored[name] = errMake
|
|
||||||
installer.log.Errorln(gotext.Get("error making: %s", base), "-", errMake)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installer.failedAndIgnored[name] = errMake
|
||||||
|
text.Errorln(gotext.Get("error making: %s", base), "-", errMake)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pkgdests) == 0 {
|
if len(pkgdests) == 0 {
|
||||||
installer.log.Warnln(gotext.Get("nothing to install for %s", text.Cyan(base)))
|
text.Warnln(gotext.Get("nothing to install for %s", text.Cyan(base)))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,8 +232,7 @@ func (installer *Installer) installAURPackages(ctx context.Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := installPkgArchive(ctx, installer.exeCmd, installer.targetMode,
|
if err := installPkgArchive(ctx, installer.exeCmd, installer.targetMode, installer.vcsStore, cmdArgs, pkgArchives); err != nil {
|
||||||
installer.vcsStore, cmdArgs, pkgArchives, noConfirm); err != nil {
|
|
||||||
return fmt.Errorf("%s - %w", fmt.Sprintf(gotext.Get("error installing:")+" %v", pkgArchives), err)
|
return fmt.Errorf("%s - %w", fmt.Sprintf(gotext.Get("error installing:")+" %v", pkgArchives), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,13 +245,9 @@ func (installer *Installer) installAURPackages(ctx context.Context,
|
|||||||
|
|
||||||
func (installer *Installer) buildPkg(ctx context.Context,
|
func (installer *Installer) buildPkg(ctx context.Context,
|
||||||
dir, base string,
|
dir, base string,
|
||||||
installIncompatible, needed, isTarget bool,
|
installIncompatible, needed bool,
|
||||||
) (map[string]string, error) {
|
) (map[string]string, error) {
|
||||||
args := []string{"--nobuild", "-f"}
|
args := []string{"--nobuild", "-fC"}
|
||||||
|
|
||||||
if !installer.exeCmd.GetKeepSrc() {
|
|
||||||
args = append(args, "-C")
|
|
||||||
}
|
|
||||||
|
|
||||||
if installIncompatible {
|
if installIncompatible {
|
||||||
args = append(args, "--ignorearch")
|
args = append(args, "--ignorearch")
|
||||||
@ -315,23 +266,19 @@ func (installer *Installer) buildPkg(ctx context.Context,
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case needed && installer.pkgsAreAlreadyInstalled(pkgdests, pkgVersion) || installer.downloadOnly:
|
case needed && installer.pkgsAreAlreadyInstalled(pkgdests, pkgVersion) || installer.downloadOnly:
|
||||||
args = []string{"--nobuild", "--noextract", "--ignorearch"}
|
args = []string{"-c", "--nobuild", "--noextract", "--ignorearch"}
|
||||||
pkgdests = map[string]string{}
|
pkgdests = map[string]string{}
|
||||||
installer.log.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(base+"-"+pkgVersion)))
|
text.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(base+"-"+pkgVersion)))
|
||||||
case installer.skipAlreadyBuiltPkg(isTarget, pkgdests):
|
case pkgsAreBuilt(pkgdests):
|
||||||
args = []string{"--nobuild", "--noextract", "--ignorearch"}
|
args = []string{"-c", "--nobuild", "--noextract", "--ignorearch"}
|
||||||
installer.log.Warnln(gotext.Get("%s already made -- skipping build", text.Cyan(base+"-"+pkgVersion)))
|
text.Warnln(gotext.Get("%s already made -- skipping build", text.Cyan(base+"-"+pkgVersion)))
|
||||||
default:
|
default:
|
||||||
args = []string{"-f", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
|
args = []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
|
||||||
if installIncompatible {
|
if installIncompatible {
|
||||||
args = append(args, "--ignorearch")
|
args = append(args, "--ignorearch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !installer.exeCmd.GetKeepSrc() {
|
|
||||||
args = append(args, "-c")
|
|
||||||
}
|
|
||||||
|
|
||||||
errMake := installer.exeCmd.Show(
|
errMake := installer.exeCmd.Show(
|
||||||
installer.exeCmd.BuildMakepkgCmd(ctx,
|
installer.exeCmd.BuildMakepkgCmd(ctx,
|
||||||
dir, args...))
|
dir, args...))
|
||||||
@ -356,10 +303,10 @@ func (installer *Installer) pkgsAreAlreadyInstalled(pkgdests map[string]string,
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func pkgsAreBuilt(logger *text.Logger, pkgdests map[string]string) bool {
|
func pkgsAreBuilt(pkgdests map[string]string) bool {
|
||||||
for _, pkgdest := range pkgdests {
|
for _, pkgdest := range pkgdests {
|
||||||
if _, err := os.Stat(pkgdest); err != nil {
|
if _, err := os.Stat(pkgdest); err != nil {
|
||||||
logger.Debugln("pkgIsBuilt:", pkgdest, "does not exist")
|
text.Debugln("pkgIsBuilt:", pkgdest, "does not exist")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,20 +314,6 @@ func pkgsAreBuilt(logger *text.Logger, pkgdests map[string]string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (installer *Installer) skipAlreadyBuiltPkg(isTarget bool, pkgdests map[string]string) bool {
|
|
||||||
switch installer.rebuildMode {
|
|
||||||
case parser.RebuildModeNo:
|
|
||||||
return pkgsAreBuilt(installer.log, pkgdests)
|
|
||||||
case parser.RebuildModeYes:
|
|
||||||
return !isTarget && pkgsAreBuilt(installer.log, pkgdests)
|
|
||||||
// case parser.RebuildModeTree: // TODO
|
|
||||||
// case parser.RebuildModeAll: // TODO
|
|
||||||
default:
|
|
||||||
// same as RebuildModeNo
|
|
||||||
return pkgsAreBuilt(installer.log, pkgdests)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Installer) isDep(cmdArgs *parser.Arguments, aurExpNames mapset.Set[string], name string) bool {
|
func (*Installer) isDep(cmdArgs *parser.Arguments, aurExpNames mapset.Set[string], name string) bool {
|
||||||
switch {
|
switch {
|
||||||
case cmdArgs.ExistsArg("asdeps", "asdep"):
|
case cmdArgs.ExistsArg("asdeps", "asdep"):
|
||||||
@ -426,12 +359,10 @@ func (installer *Installer) getNewTargets(pkgdests map[string]string, name strin
|
|||||||
func (installer *Installer) installSyncPackages(ctx context.Context, cmdArgs *parser.Arguments,
|
func (installer *Installer) installSyncPackages(ctx context.Context, cmdArgs *parser.Arguments,
|
||||||
syncDeps, // repo targets that are deps
|
syncDeps, // repo targets that are deps
|
||||||
syncExp mapset.Set[string], // repo targets that are exp
|
syncExp mapset.Set[string], // repo targets that are exp
|
||||||
syncGroups mapset.Set[string], // repo targets that are groups
|
|
||||||
excluded []string,
|
excluded []string,
|
||||||
upgrade bool, // run even without targets
|
upgrade bool, // run even without targets
|
||||||
noConfirm bool,
|
|
||||||
) error {
|
) error {
|
||||||
repoTargets := syncDeps.Union(syncExp).Union(syncGroups).ToSlice()
|
repoTargets := syncDeps.Union(syncExp).ToSlice()
|
||||||
if len(repoTargets) == 0 && !upgrade {
|
if len(repoTargets) == 0 && !upgrade {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -443,21 +374,12 @@ func (installer *Installer) installSyncPackages(ctx context.Context, cmdArgs *pa
|
|||||||
arguments.Op = "S"
|
arguments.Op = "S"
|
||||||
arguments.ClearTargets()
|
arguments.ClearTargets()
|
||||||
arguments.AddTarget(repoTargets...)
|
arguments.AddTarget(repoTargets...)
|
||||||
|
|
||||||
// Don't upgrade all repo packages if only AUR upgrades are specified
|
|
||||||
if installer.targetMode == parser.ModeAUR {
|
|
||||||
arguments.DelArg("u", "upgrades")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(excluded) > 0 {
|
if len(excluded) > 0 {
|
||||||
arguments.CreateOrAppendOption("ignore", excluded...)
|
arguments.CreateOrAppendOption("ignore", excluded...)
|
||||||
}
|
}
|
||||||
|
|
||||||
errShow := installer.exeCmd.Show(installer.exeCmd.BuildPacmanCmd(ctx,
|
errShow := installer.exeCmd.Show(installer.exeCmd.BuildPacmanCmd(ctx,
|
||||||
arguments, installer.targetMode, noConfirm))
|
arguments, installer.targetMode, settings.NoConfirm))
|
||||||
if errShow != nil {
|
|
||||||
return errShow
|
|
||||||
}
|
|
||||||
|
|
||||||
if errD := asdeps(ctx, installer.exeCmd, installer.targetMode, cmdArgs, syncDeps.ToSlice()); errD != nil {
|
if errD := asdeps(ctx, installer.exeCmd, installer.targetMode, cmdArgs, syncDeps.ToSlice()); errD != nil {
|
||||||
return errD
|
return errD
|
||||||
@ -467,5 +389,5 @@ func (installer *Installer) installSyncPackages(ctx context.Context, cmdArgs *pa
|
|||||||
return errE
|
return errE
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return errShow
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package build
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -21,9 +21,7 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/vcs"
|
"github.com/Jguer/yay/v12/pkg/vcs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestLogger() *text.Logger {
|
var testLogger = text.NewLogger(io.Discard, strings.NewReader(""), true, "test")
|
||||||
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
|
|
||||||
}
|
|
||||||
|
|
||||||
func ptrString(s string) *string {
|
func ptrString(s string) *string {
|
||||||
return &s
|
return &s
|
||||||
@ -56,8 +54,8 @@ func TestInstaller_InstallNeeded(t *testing.T) {
|
|||||||
isInstalled: false,
|
isInstalled: false,
|
||||||
isBuilt: false,
|
isBuilt: false,
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
"pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config -- yay",
|
"pacman -D -q --asexplicit --config -- yay",
|
||||||
},
|
},
|
||||||
@ -68,7 +66,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
|
|||||||
isInstalled: false,
|
isInstalled: false,
|
||||||
isBuilt: true,
|
isBuilt: true,
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
"pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config -- yay",
|
"pacman -D -q --asexplicit --config -- yay",
|
||||||
@ -80,7 +78,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
|
|||||||
isInstalled: true,
|
isInstalled: true,
|
||||||
isBuilt: false,
|
isBuilt: false,
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
},
|
},
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
wantCapture: []string{"makepkg --packagelist"},
|
||||||
@ -133,8 +131,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
|
|||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
cmdBuilder.Runner = mockRunner
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, false, testLogger)
|
||||||
parser.RebuildModeNo, false, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
cmdArgs.AddArg("needed")
|
cmdArgs.AddArg("needed")
|
||||||
@ -156,7 +153,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)
|
errI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{})
|
||||||
require.NoError(td, errI)
|
require.NoError(td, errI)
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
||||||
@ -212,8 +209,8 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"pacman -S --config /etc/pacman.conf -- core/linux",
|
"pacman -S --config /etc/pacman.conf -- core/linux",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- linux",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- linux",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
||||||
},
|
},
|
||||||
@ -241,8 +238,8 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"pacman -S --config /etc/pacman.conf -- core/linux",
|
"pacman -S --config /etc/pacman.conf -- core/linux",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- linux",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- linux",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
||||||
},
|
},
|
||||||
@ -293,10 +290,10 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
{
|
{
|
||||||
desc: "same layer -- aur",
|
desc: "same layer -- aur",
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
||||||
},
|
},
|
||||||
@ -323,12 +320,12 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
{
|
{
|
||||||
desc: "different layer -- aur",
|
desc: "different layer -- aur",
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.8-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.8-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay",
|
||||||
},
|
},
|
||||||
@ -374,13 +371,13 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
showOverride := func(cmd *exec.Cmd) error {
|
||||||
if strings.Contains(cmd.String(), "makepkg -f --noconfirm") && cmd.Dir == tmpDir {
|
if strings.Contains(cmd.String(), "makepkg -cf --noconfirm") && cmd.Dir == tmpDir {
|
||||||
f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
||||||
require.NoError(td, err)
|
require.NoError(td, err)
|
||||||
require.NoError(td, f.Close())
|
require.NoError(td, f.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(cmd.String(), "makepkg -f --noconfirm") && cmd.Dir == tmpDirJfin {
|
if strings.Contains(cmd.String(), "makepkg -cf --noconfirm") && cmd.Dir == tmpDirJfin {
|
||||||
f, err := os.OpenFile(jfinPkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
f, err := os.OpenFile(jfinPkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
||||||
require.NoError(td, err)
|
require.NoError(td, err)
|
||||||
require.NoError(td, f.Close())
|
require.NoError(td, f.Close())
|
||||||
@ -408,7 +405,7 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
cmdBuilder.Runner = mockRunner
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, parser.RebuildModeNo, false, newTestLogger())
|
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, false, testLogger)
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
cmdArgs.AddTarget("yay")
|
cmdArgs.AddTarget("yay")
|
||||||
@ -418,7 +415,7 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
|
|||||||
"jellyfin": tmpDirJfin,
|
"jellyfin": tmpDirJfin,
|
||||||
}
|
}
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)
|
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{})
|
||||||
require.NoError(td, errI)
|
require.NoError(td, errI)
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
||||||
@ -461,8 +458,7 @@ func TestInstaller_RunPostHooks(t *testing.T) {
|
|||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
cmdBuilder.Runner = mockRunner
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, false, testLogger)
|
||||||
parser.RebuildModeNo, false, newTestLogger())
|
|
||||||
|
|
||||||
called := false
|
called := false
|
||||||
hook := func(ctx context.Context) error {
|
hook := func(ctx context.Context) error {
|
||||||
@ -570,7 +566,7 @@ func TestInstaller_CompileFailed(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
showOverride := func(cmd *exec.Cmd) error {
|
||||||
if tc.failBuild && strings.Contains(cmd.String(), "makepkg -f --noconfirm") && cmd.Dir == tmpDir {
|
if tc.failBuild && strings.Contains(cmd.String(), "makepkg -cf --noconfirm") && cmd.Dir == tmpDir {
|
||||||
return errors.New("makepkg failed")
|
return errors.New("makepkg failed")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -592,8 +588,7 @@ func TestInstaller_CompileFailed(t *testing.T) {
|
|||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
cmdBuilder.Runner = mockRunner
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, false, testLogger)
|
||||||
parser.RebuildModeNo, false, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
cmdArgs.AddArg("needed")
|
cmdArgs.AddArg("needed")
|
||||||
@ -603,27 +598,16 @@ func TestInstaller_CompileFailed(t *testing.T) {
|
|||||||
"yay": tmpDir,
|
"yay": tmpDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)
|
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{})
|
||||||
if tc.wantErrInstall {
|
if tc.wantErrInstall {
|
||||||
require.Error(td, errI)
|
require.Error(td, errI)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(td, errI)
|
require.NoError(td, errI)
|
||||||
}
|
}
|
||||||
failed, err := installer.CompileFailedAndIgnored()
|
err := installer.CompileFailedAndIgnored()
|
||||||
if tc.wantErrCompile {
|
if tc.wantErrCompile {
|
||||||
require.Error(td, err)
|
require.Error(td, err)
|
||||||
for key := range failed {
|
assert.ErrorContains(td, err, "yay")
|
||||||
assert.ErrorContains(td, err, key)
|
|
||||||
}
|
|
||||||
uniqueBases := make(map[string]struct{})
|
|
||||||
for _, layer := range tc.targets {
|
|
||||||
for _, info := range layer {
|
|
||||||
if info.AURBase != nil {
|
|
||||||
uniqueBases[*info.AURBase] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require.Len(td, failed, len(uniqueBases))
|
|
||||||
} else {
|
} else {
|
||||||
require.NoError(td, err)
|
require.NoError(td, err)
|
||||||
}
|
}
|
||||||
@ -704,16 +688,18 @@ func TestInstaller_InstallSplitPackage(t *testing.T) {
|
|||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"pacman -S --config /etc/pacman.conf -- community/dotnet-runtime-6.0 community/aspnet-runtime community/dotnet-sdk-6.0",
|
"pacman -S --config /etc/pacman.conf -- community/dotnet-runtime-6.0 community/aspnet-runtime community/dotnet-sdk-6.0",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 aspnet-runtime dotnet-sdk-6.0",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 aspnet-runtime dotnet-sdk-6.0",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
|
||||||
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
|
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin",
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin",
|
||||||
},
|
},
|
||||||
wantCapture: []string{"makepkg --packagelist", "makepkg --packagelist"},
|
wantCapture: []string{"makepkg --packagelist", "makepkg --packagelist", "makepkg --packagelist"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,8 +746,7 @@ func TestInstaller_InstallSplitPackage(t *testing.T) {
|
|||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
cmdBuilder.Runner = mockRunner
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, false, testLogger)
|
||||||
parser.RebuildModeNo, false, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
cmdArgs.AddTarget("jellyfin")
|
cmdArgs.AddTarget("jellyfin")
|
||||||
@ -770,7 +755,7 @@ func TestInstaller_InstallSplitPackage(t *testing.T) {
|
|||||||
"jellyfin": tmpDir,
|
"jellyfin": tmpDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)
|
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{})
|
||||||
require.NoError(td, errI)
|
require.NoError(td, errI)
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
||||||
@ -826,7 +811,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
|
|||||||
isInstalled: false,
|
isInstalled: false,
|
||||||
isBuilt: false,
|
isBuilt: false,
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
},
|
},
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
wantCapture: []string{"makepkg --packagelist"},
|
||||||
@ -836,7 +821,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
|
|||||||
isInstalled: false,
|
isInstalled: false,
|
||||||
isBuilt: true,
|
isBuilt: true,
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
},
|
},
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
wantCapture: []string{"makepkg --packagelist"},
|
||||||
@ -846,7 +831,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
|
|||||||
isInstalled: true,
|
isInstalled: true,
|
||||||
isBuilt: false,
|
isBuilt: false,
|
||||||
wantShow: []string{
|
wantShow: []string{
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
},
|
},
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
wantCapture: []string{"makepkg --packagelist"},
|
||||||
@ -899,8 +884,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
|
|||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
cmdBuilder.Runner = mockRunner
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, true, testLogger)
|
||||||
parser.RebuildModeNo, true, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
cmdArgs.AddTarget("yay")
|
cmdArgs.AddTarget("yay")
|
||||||
@ -921,7 +905,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)
|
errI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{})
|
||||||
require.NoError(td, errI)
|
require.NoError(td, errI)
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
||||||
@ -948,504 +932,3 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstaller_InstallGroup(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
desc string
|
|
||||||
wantShow []string
|
|
||||||
wantCapture []string
|
|
||||||
}
|
|
||||||
|
|
||||||
testCases := []testCase{
|
|
||||||
{
|
|
||||||
desc: "group",
|
|
||||||
wantShow: []string{
|
|
||||||
"pacman -S --noconfirm --config -- community/kubernetes-tools",
|
|
||||||
},
|
|
||||||
wantCapture: []string{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.desc, func(td *testing.T) {
|
|
||||||
tmpDir := td.TempDir()
|
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mockDB := &mock.DBExecutor{}
|
|
||||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
|
||||||
parser.RebuildModeNo, true, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddTarget("kubernetes-tools")
|
|
||||||
|
|
||||||
pkgBuildDirs := map[string]string{}
|
|
||||||
|
|
||||||
targets := []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"kubernetes-tools": {
|
|
||||||
Source: dep.Sync,
|
|
||||||
Reason: dep.Explicit,
|
|
||||||
Version: "",
|
|
||||||
IsGroup: true,
|
|
||||||
SyncDBName: ptrString("community"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)
|
|
||||||
require.NoError(td, errI)
|
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
|
||||||
require.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))
|
|
||||||
require.Empty(td, installer.failedAndIgnored)
|
|
||||||
|
|
||||||
for i, call := range mockRunner.ShowCalls {
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
|
|
||||||
// options are in a different order on different systems and on CI root user is used
|
|
||||||
assert.Subset(td, strings.Split(show, " "), strings.Split(tc.wantShow[i], " "), show)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, call := range mockRunner.CaptureCalls {
|
|
||||||
capture := call.Args[0].(*exec.Cmd).String()
|
|
||||||
capture = strings.ReplaceAll(capture, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
capture = strings.ReplaceAll(capture, makepkgBin, "makepkg")
|
|
||||||
capture = strings.ReplaceAll(capture, pacmanBin, "pacman")
|
|
||||||
assert.Subset(td, strings.Split(capture, " "), strings.Split(tc.wantCapture[i], " "), capture)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstaller_InstallRebuild(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
desc string
|
|
||||||
rebuildOption parser.RebuildMode
|
|
||||||
isInstalled bool
|
|
||||||
isBuilt bool
|
|
||||||
wantShow []string
|
|
||||||
wantCapture []string
|
|
||||||
targets []map[string]*dep.InstallInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir := t.TempDir()
|
|
||||||
|
|
||||||
testCases := []testCase{
|
|
||||||
{
|
|
||||||
desc: "--norebuild(default) when built and not installed",
|
|
||||||
rebuildOption: parser.RebuildModeNo,
|
|
||||||
isBuilt: true,
|
|
||||||
isInstalled: false,
|
|
||||||
wantShow: []string{
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
|
||||||
"pacman -U --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config -- yay",
|
|
||||||
},
|
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
|
||||||
targets: []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"yay": {
|
|
||||||
Source: dep.AUR,
|
|
||||||
Reason: dep.Explicit,
|
|
||||||
Version: "91.0.0-1",
|
|
||||||
SrcinfoPath: ptrString(tmpDir + "/.SRCINFO"),
|
|
||||||
AURBase: ptrString("yay"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "--rebuild when built and not installed",
|
|
||||||
rebuildOption: parser.RebuildModeYes,
|
|
||||||
isBuilt: true,
|
|
||||||
isInstalled: false,
|
|
||||||
wantShow: []string{
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
|
||||||
"pacman -U --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config -- yay",
|
|
||||||
},
|
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
|
||||||
targets: []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"yay": {
|
|
||||||
Source: dep.AUR,
|
|
||||||
Reason: dep.Explicit,
|
|
||||||
Version: "91.0.0-1",
|
|
||||||
SrcinfoPath: ptrString(tmpDir + "/.SRCINFO"),
|
|
||||||
AURBase: ptrString("yay"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "--rebuild when built and installed",
|
|
||||||
rebuildOption: parser.RebuildModeYes,
|
|
||||||
isInstalled: true,
|
|
||||||
isBuilt: true,
|
|
||||||
wantShow: []string{
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
|
||||||
"pacman -U --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config -- yay",
|
|
||||||
},
|
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
|
||||||
targets: []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"yay": {
|
|
||||||
Source: dep.AUR,
|
|
||||||
Reason: dep.Explicit,
|
|
||||||
Version: "91.0.0-1",
|
|
||||||
SrcinfoPath: ptrString(tmpDir + "/.SRCINFO"),
|
|
||||||
AURBase: ptrString("yay"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "--rebuild when built and installed previously as dep",
|
|
||||||
rebuildOption: parser.RebuildModeYes,
|
|
||||||
isInstalled: true,
|
|
||||||
isBuilt: true,
|
|
||||||
wantShow: []string{
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
|
|
||||||
"pacman -U --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asdeps --config -- yay",
|
|
||||||
},
|
|
||||||
wantCapture: []string{"makepkg --packagelist"},
|
|
||||||
targets: []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"yay": {
|
|
||||||
Source: dep.AUR,
|
|
||||||
Reason: dep.Dep,
|
|
||||||
Version: "91.0.0-1",
|
|
||||||
SrcinfoPath: ptrString(tmpDir + "/.SRCINFO"),
|
|
||||||
AURBase: ptrString("yay"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.desc, func(td *testing.T) {
|
|
||||||
tmpDir := td.TempDir()
|
|
||||||
pkgTar := tmpDir + "/yay-91.0.0-1-x86_64.pkg.tar.zst"
|
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
|
||||||
return pkgTar, "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
|
||||||
i++
|
|
||||||
if i == 2 {
|
|
||||||
if !tc.isBuilt {
|
|
||||||
f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
|
||||||
require.NoError(td, err)
|
|
||||||
require.NoError(td, f.Close())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a mock file
|
|
||||||
if tc.isBuilt {
|
|
||||||
f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
|
||||||
require.NoError(td, err)
|
|
||||||
require.NoError(td, f.Close())
|
|
||||||
}
|
|
||||||
|
|
||||||
isCorrectInstalledOverride := func(string, string) bool {
|
|
||||||
return tc.isInstalled
|
|
||||||
}
|
|
||||||
|
|
||||||
mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}
|
|
||||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdBuilder.Runner = mockRunner
|
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
|
||||||
tc.rebuildOption, false, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddTarget("yay")
|
|
||||||
|
|
||||||
pkgBuildDirs := map[string]string{
|
|
||||||
"yay": tmpDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)
|
|
||||||
require.NoError(td, errI)
|
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
|
||||||
require.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))
|
|
||||||
|
|
||||||
for i, call := range mockRunner.ShowCalls {
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
|
|
||||||
// options are in a different order on different systems and on CI root user is used
|
|
||||||
assert.Subset(td, strings.Split(show, " "), strings.Split(tc.wantShow[i], " "), show)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, call := range mockRunner.CaptureCalls {
|
|
||||||
capture := call.Args[0].(*exec.Cmd).String()
|
|
||||||
capture = strings.ReplaceAll(capture, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
capture = strings.ReplaceAll(capture, makepkgBin, "makepkg")
|
|
||||||
capture = strings.ReplaceAll(capture, pacmanBin, "pacman")
|
|
||||||
assert.Subset(td, strings.Split(capture, " "), strings.Split(tc.wantCapture[i], " "), capture)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstaller_InstallUpgrade(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
desc string
|
|
||||||
targetMode parser.TargetMode
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir := t.TempDir()
|
|
||||||
|
|
||||||
testCases := []testCase{
|
|
||||||
{
|
|
||||||
desc: "target any",
|
|
||||||
targetMode: parser.ModeAny,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "target repo",
|
|
||||||
targetMode: parser.ModeRepo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "target aur",
|
|
||||||
targetMode: parser.ModeAUR,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.desc, func(td *testing.T) {
|
|
||||||
mockDB := &mock.DBExecutor{}
|
|
||||||
mockRunner := &exe.MockRunner{}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, tc.targetMode,
|
|
||||||
parser.RebuildModeNo, false, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddArg("u", "upgrades") // Make sure both args are removed
|
|
||||||
|
|
||||||
targets := []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"linux": {
|
|
||||||
Source: dep.Sync,
|
|
||||||
Reason: dep.Dep,
|
|
||||||
Version: "17.0.0-1",
|
|
||||||
SyncDBName: ptrString("core"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, targets, map[string]string{}, []string{}, false)
|
|
||||||
require.NoError(td, errI)
|
|
||||||
|
|
||||||
require.NotEmpty(td, mockRunner.ShowCalls)
|
|
||||||
|
|
||||||
// The first call is the only call being test
|
|
||||||
call := mockRunner.ShowCalls[0]
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
|
|
||||||
if tc.targetMode == parser.ModeAUR {
|
|
||||||
assert.NotContains(td, show, "--upgrades")
|
|
||||||
assert.NotContains(td, show, "-u")
|
|
||||||
} else {
|
|
||||||
assert.Contains(td, show, "--upgrades")
|
|
||||||
assert.Contains(td, show, "-u")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstaller_KeepSrc(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
desc string
|
|
||||||
wantShow []string
|
|
||||||
targets []map[string]*dep.InstallInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir := t.TempDir()
|
|
||||||
|
|
||||||
testCases := []testCase{
|
|
||||||
{
|
|
||||||
desc: "--keepsrc",
|
|
||||||
wantShow: []string{
|
|
||||||
"makepkg --nobuild -f --ignorearch",
|
|
||||||
"makepkg --nobuild --noextract --ignorearch",
|
|
||||||
"pacman -U --config -- /testdir/yay-92.0.0-1-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config -- yay",
|
|
||||||
},
|
|
||||||
targets: []map[string]*dep.InstallInfo{
|
|
||||||
{
|
|
||||||
"yay": {
|
|
||||||
Source: dep.AUR,
|
|
||||||
Reason: dep.Explicit,
|
|
||||||
Version: "92.0.0-1",
|
|
||||||
SrcinfoPath: ptrString(tmpDir + "/.SRCINFO"),
|
|
||||||
AURBase: ptrString("yay"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.desc, func(td *testing.T) {
|
|
||||||
tmpDir := td.TempDir()
|
|
||||||
pkgTar := tmpDir + "/yay-92.0.0-1-x86_64.pkg.tar.zst"
|
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
|
||||||
return pkgTar, "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a mock file
|
|
||||||
f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
|
|
||||||
require.NoError(td, err)
|
|
||||||
require.NoError(td, f.Close())
|
|
||||||
|
|
||||||
mockDB := &mock.DBExecutor{}
|
|
||||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
KeepSrc: true,
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
|
|
||||||
parser.RebuildModeNo, false, newTestLogger())
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddTarget("yay")
|
|
||||||
|
|
||||||
pkgBuildDirs := map[string]string{
|
|
||||||
"yay": tmpDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
errI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)
|
|
||||||
require.NoError(td, errI)
|
|
||||||
|
|
||||||
require.Len(td, mockRunner.ShowCalls, len(tc.wantShow))
|
|
||||||
|
|
||||||
for i, call := range mockRunner.ShowCalls {
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
|
|
||||||
// options are in a different order on different systems and on CI root user is used
|
|
||||||
assert.Subset(td, strings.Split(show, " "), strings.Split(tc.wantShow[i], " "), show)
|
|
||||||
|
|
||||||
// Only assert makepkg commands don't have clean arguments
|
|
||||||
if strings.HasPrefix(show, "makepkg") {
|
|
||||||
assert.NotContains(td, show, "-c")
|
|
||||||
assert.NotContains(td, show, "-C")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package workdir
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -32,11 +32,7 @@ func (e *ErrDownloadSource) Unwrap() error {
|
|||||||
func downloadPKGBUILDSource(ctx context.Context,
|
func downloadPKGBUILDSource(ctx context.Context,
|
||||||
cmdBuilder exe.ICmdBuilder, pkgBuildDir string, installIncompatible bool,
|
cmdBuilder exe.ICmdBuilder, pkgBuildDir string, installIncompatible bool,
|
||||||
) error {
|
) error {
|
||||||
args := []string{"--verifysource", "--skippgpcheck", "-f"}
|
args := []string{"--verifysource", "-Ccf"}
|
||||||
|
|
||||||
if !cmdBuilder.GetKeepSrc() {
|
|
||||||
args = append(args, "-Cc")
|
|
||||||
}
|
|
||||||
|
|
||||||
if installIncompatible {
|
if installIncompatible {
|
||||||
args = append(args, "--ignorearch")
|
args = append(args, "--ignorearch")
|
@ -1,7 +1,4 @@
|
|||||||
//go:build !integration
|
package main
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package workdir
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -33,10 +30,6 @@ func (z *TestMakepkgBuilder) BuildMakepkgCmd(ctx context.Context, dir string, ex
|
|||||||
assert.Contains(z.test, cmd.String(), z.want)
|
assert.Contains(z.test, cmd.String(), z.want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if z.GetKeepSrc() {
|
|
||||||
assert.NotContains(z.test, cmd.String(), "-Cc")
|
|
||||||
}
|
|
||||||
|
|
||||||
if z.wantDir != "" {
|
if z.wantDir != "" {
|
||||||
assert.Equal(z.test, z.wantDir, cmd.Dir)
|
assert.Equal(z.test, z.wantDir, cmd.Dir)
|
||||||
}
|
}
|
||||||
@ -50,54 +43,20 @@ func (z *TestMakepkgBuilder) Show(cmd *exec.Cmd) error {
|
|||||||
return z.showError
|
return z.showError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *TestMakepkgBuilder) GetKeepSrc() bool {
|
|
||||||
return z.parentBuilder.KeepSrc
|
|
||||||
}
|
|
||||||
|
|
||||||
// GIVEN 1 package
|
// GIVEN 1 package
|
||||||
// WHEN downloadPKGBUILDSource is called
|
// WHEN downloadPKGBUILDSource is called
|
||||||
// THEN 1 call should be made to makepkg with the specified parameters and dir
|
// THEN 1 call should be made to makepkg with the specified parameters and dir
|
||||||
func Test_downloadPKGBUILDSource(t *testing.T) {
|
func Test_downloadPKGBUILDSource(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
cmdBuilder := &TestMakepkgBuilder{
|
||||||
type testCase struct {
|
parentBuilder: &exe.CmdBuilder{MakepkgConfPath: "/etc/not.conf", MakepkgFlags: []string{"--nocheck"}, MakepkgBin: "makepkg"},
|
||||||
desc string
|
test: t,
|
||||||
keepSrc bool
|
want: "makepkg --nocheck --config /etc/not.conf --verifysource -Ccf",
|
||||||
want string
|
wantDir: "/tmp/yay-bin",
|
||||||
}
|
|
||||||
|
|
||||||
testCases := []testCase{
|
|
||||||
{
|
|
||||||
desc: "keepsrc",
|
|
||||||
keepSrc: true,
|
|
||||||
want: "makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "nokeepsrc",
|
|
||||||
keepSrc: false,
|
|
||||||
want: "makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f -Cc",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.desc, func(td *testing.T) {
|
|
||||||
cmdBuilder := &TestMakepkgBuilder{
|
|
||||||
parentBuilder: &exe.CmdBuilder{
|
|
||||||
MakepkgConfPath: "/etc/not.conf",
|
|
||||||
MakepkgFlags: []string{"--nocheck"},
|
|
||||||
MakepkgBin: "makepkg",
|
|
||||||
KeepSrc: tc.keepSrc,
|
|
||||||
},
|
|
||||||
test: t,
|
|
||||||
want: tc.want,
|
|
||||||
wantDir: "/tmp/yay-bin",
|
|
||||||
}
|
|
||||||
err := downloadPKGBUILDSource(context.Background(), cmdBuilder, filepath.Join("/tmp", "yay-bin"), false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 1, int(cmdBuilder.passes))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
err := downloadPKGBUILDSource(context.Background(), cmdBuilder, filepath.Join("/tmp", "yay-bin"), false)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 1, int(cmdBuilder.passes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GIVEN 1 package
|
// GIVEN 1 package
|
||||||
@ -108,7 +67,7 @@ func Test_downloadPKGBUILDSourceError(t *testing.T) {
|
|||||||
cmdBuilder := &TestMakepkgBuilder{
|
cmdBuilder := &TestMakepkgBuilder{
|
||||||
parentBuilder: &exe.CmdBuilder{MakepkgConfPath: "/etc/not.conf", MakepkgFlags: []string{"--nocheck"}, MakepkgBin: "makepkg"},
|
parentBuilder: &exe.CmdBuilder{MakepkgConfPath: "/etc/not.conf", MakepkgFlags: []string{"--nocheck"}, MakepkgBin: "makepkg"},
|
||||||
test: t,
|
test: t,
|
||||||
want: "makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f -Cc",
|
want: "makepkg --nocheck --config /etc/not.conf --verifysource -Ccf",
|
||||||
wantDir: "/tmp/yay-bin",
|
wantDir: "/tmp/yay-bin",
|
||||||
showError: &exec.ExitError{},
|
showError: &exec.ExitError{},
|
||||||
}
|
}
|
||||||
@ -140,7 +99,7 @@ func Test_downloadPKGBUILDSourceFanout(t *testing.T) {
|
|||||||
test: t,
|
test: t,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := downloadPKGBUILDSourceFanout(context.Background(), cmdBuilder, pkgBuildDirs, true, maxConcurrentDownloads)
|
err := downloadPKGBUILDSourceFanout(context.Background(), cmdBuilder, pkgBuildDirs, false, maxConcurrentDownloads)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 5, int(cmdBuilder.passes))
|
assert.Equal(t, 5, int(cmdBuilder.passes))
|
||||||
})
|
})
|
@ -1,15 +1,12 @@
|
|||||||
FROM docker.io/ljmf00/archlinux:devel
|
FROM docker.io/jguer/yay-builder:latest
|
||||||
LABEL maintainer="Jguer,docker@jguer.space"
|
|
||||||
|
|
||||||
ENV GO111MODULE=on
|
ENV GO111MODULE=on
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN sed -i '/^\[community\]/,/^\[/ s/^/#/' /etc/pacman.conf
|
|
||||||
|
|
||||||
COPY go.mod .
|
COPY go.mod .
|
||||||
|
|
||||||
RUN pacman-key --init && pacman -Sy && pacman -S --overwrite=* --noconfirm archlinux-keyring && \
|
RUN pacman-key --init && pacman -Sy && pacman -S --overwrite=* --noconfirm archlinux-keyring && \
|
||||||
pacman -Su --overwrite=* --needed --noconfirm pacman doxygen meson asciidoc go git gcc make sudo base-devel && \
|
pacman -Su --overwrite=* --needed --noconfirm doxygen meson asciidoc go git gcc make sudo base-devel && \
|
||||||
rm -rfv /var/cache/pacman/* /var/lib/pacman/sync/* && \
|
rm -rfv /var/cache/pacman/* /var/lib/pacman/sync/* && \
|
||||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v2.1.5 && \
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.52.2 && \
|
||||||
go mod download
|
go mod download
|
||||||
|
106
clean.go
106
clean.go
@ -2,18 +2,19 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/Jguer/aur"
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
"github.com/Jguer/yay/v12/pkg/query"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CleanDependencies removes all dangling dependencies in system.
|
// CleanDependencies removes all dangling dependencies in system.
|
||||||
@ -48,29 +49,28 @@ func cleanRemove(ctx context.Context, cfg *settings.Configuration,
|
|||||||
arguments, cfg.Mode, settings.NoConfirm))
|
arguments, cfg.Mode, settings.NoConfirm))
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncClean(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
func syncClean(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
||||||
keepInstalled := false
|
keepInstalled := false
|
||||||
keepCurrent := false
|
keepCurrent := false
|
||||||
|
|
||||||
_, removeAll, _ := cmdArgs.GetArg("c", "clean")
|
_, removeAll, _ := cmdArgs.GetArg("c", "clean")
|
||||||
|
|
||||||
for _, v := range run.PacmanConf.CleanMethod {
|
for _, v := range cfg.Runtime.PacmanConf.CleanMethod {
|
||||||
switch v {
|
if v == "KeepInstalled" {
|
||||||
case "KeepInstalled":
|
|
||||||
keepInstalled = true
|
keepInstalled = true
|
||||||
case "KeepCurrent":
|
} else if v == "KeepCurrent" {
|
||||||
keepCurrent = true
|
keepCurrent = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Cfg.Mode.AtLeastRepo() {
|
if cfg.Mode.AtLeastRepo() {
|
||||||
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm)); err != nil {
|
cmdArgs, cfg.Mode, settings.NoConfirm)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !run.Cfg.Mode.AtLeastAUR() {
|
if !cfg.Mode.AtLeastAUR() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,10 +81,10 @@ func syncClean(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Argume
|
|||||||
question = gotext.Get("Do you want to remove all other AUR packages from cache?")
|
question = gotext.Get("Do you want to remove all other AUR packages from cache?")
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Println(gotext.Get("\nBuild directory:"), run.Cfg.BuildDir)
|
fmt.Println(gotext.Get("\nBuild directory:"), cfg.BuildDir)
|
||||||
|
|
||||||
if run.Logger.ContinueTask(question, true, settings.NoConfirm) {
|
if text.ContinueTask(os.Stdin, question, true, settings.NoConfirm) {
|
||||||
if err := cleanAUR(ctx, run, keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {
|
if err := cleanAUR(ctx, cfg, keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,24 +93,24 @@ func syncClean(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Argume
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Logger.ContinueTask(gotext.Get("Do you want to remove ALL untracked AUR files?"), true, settings.NoConfirm) {
|
if text.ContinueTask(os.Stdin, gotext.Get("Do you want to remove ALL untracked AUR files?"), true, settings.NoConfirm) {
|
||||||
return cleanUntracked(ctx, run)
|
return cleanUntracked(ctx, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanAUR(ctx context.Context, run *runtime.Runtime,
|
func cleanAUR(ctx context.Context, config *settings.Configuration,
|
||||||
keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor,
|
keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor,
|
||||||
) error {
|
) error {
|
||||||
run.Logger.Println(gotext.Get("removing AUR packages from cache..."))
|
fmt.Println(gotext.Get("removing AUR packages from cache..."))
|
||||||
|
|
||||||
installedBases := mapset.NewThreadUnsafeSet[string]()
|
installedBases := make(stringset.StringSet)
|
||||||
inAURBases := mapset.NewThreadUnsafeSet[string]()
|
inAURBases := make(stringset.StringSet)
|
||||||
|
|
||||||
remotePackages := dbExecutor.InstalledRemotePackages()
|
remotePackages := dbExecutor.InstalledRemotePackages()
|
||||||
|
|
||||||
files, err := os.ReadDir(run.Cfg.BuildDir)
|
files, err := os.ReadDir(config.BuildDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -130,23 +130,21 @@ func cleanAUR(ctx context.Context, run *runtime.Runtime,
|
|||||||
// Querying the AUR is slow and needs internet so don't do it if we
|
// Querying the AUR is slow and needs internet so don't do it if we
|
||||||
// don't need to.
|
// don't need to.
|
||||||
if keepCurrent {
|
if keepCurrent {
|
||||||
info, errInfo := run.AURClient.Get(ctx, &aur.Query{
|
info, errInfo := query.AURInfo(ctx, config.Runtime.AURClient, cachedPackages, &query.AURWarnings{}, config.RequestSplitN)
|
||||||
Needles: cachedPackages,
|
|
||||||
})
|
|
||||||
if errInfo != nil {
|
if errInfo != nil {
|
||||||
return errInfo
|
return errInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range info {
|
for i := range info {
|
||||||
inAURBases.Add(info[i].PackageBase)
|
inAURBases.Set(info[i].PackageBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pkg := range remotePackages {
|
for _, pkg := range remotePackages {
|
||||||
if pkg.Base() != "" {
|
if pkg.Base() != "" {
|
||||||
installedBases.Add(pkg.Base())
|
installedBases.Set(pkg.Base())
|
||||||
} else {
|
} else {
|
||||||
installedBases.Add(pkg.Name())
|
installedBases.Set(pkg.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,29 +154,29 @@ func cleanAUR(ctx context.Context, run *runtime.Runtime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !removeAll {
|
if !removeAll {
|
||||||
if keepInstalled && installedBases.Contains(file.Name()) {
|
if keepInstalled && installedBases.Get(file.Name()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if keepCurrent && inAURBases.Contains(file.Name()) {
|
if keepCurrent && inAURBases.Get(file.Name()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := filepath.Join(run.Cfg.BuildDir, file.Name())
|
dir := filepath.Join(config.BuildDir, file.Name())
|
||||||
run.Logger.Debugln("removing", dir)
|
err = os.RemoveAll(dir)
|
||||||
if err = os.RemoveAll(dir); err != nil {
|
if err != nil {
|
||||||
run.Logger.Warnln(gotext.Get("Unable to remove %s: %s", dir, err))
|
text.Warnln(gotext.Get("Unable to remove %s: %s", dir, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanUntracked(ctx context.Context, run *runtime.Runtime) error {
|
func cleanUntracked(ctx context.Context, cfg *settings.Configuration) error {
|
||||||
run.Logger.Println(gotext.Get("removing untracked AUR files from cache..."))
|
fmt.Println(gotext.Get("removing untracked AUR files from cache..."))
|
||||||
|
|
||||||
files, err := os.ReadDir(run.Cfg.BuildDir)
|
files, err := os.ReadDir(cfg.BuildDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -188,11 +186,11 @@ func cleanUntracked(ctx context.Context, run *runtime.Runtime) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := filepath.Join(run.Cfg.BuildDir, file.Name())
|
dir := filepath.Join(cfg.BuildDir, file.Name())
|
||||||
run.Logger.Debugln("cleaning", dir)
|
|
||||||
if isGitRepository(dir) {
|
if isGitRepository(dir) {
|
||||||
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fx")); err != nil {
|
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fx")); err != nil {
|
||||||
run.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
|
text.Warnln(gotext.Get("Unable to clean:"), dir)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,3 +203,29 @@ func isGitRepository(dir string) bool {
|
|||||||
_, err := os.Stat(filepath.Join(dir, ".git"))
|
_, err := os.Stat(filepath.Join(dir, ".git"))
|
||||||
return !os.IsNotExist(err)
|
return !os.IsNotExist(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cleanAfter(ctx context.Context, config *settings.Configuration,
|
||||||
|
cmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string,
|
||||||
|
) {
|
||||||
|
fmt.Println(gotext.Get("removing untracked AUR files from cache..."))
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, dir := range pkgbuildDirs {
|
||||||
|
text.OperationInfoln(gotext.Get("Cleaning (%d/%d): %s", i+1, len(pkgbuildDirs), text.Cyan(dir)))
|
||||||
|
|
||||||
|
_, stderr, err := cmdBuilder.Capture(
|
||||||
|
cmdBuilder.BuildGitCmd(
|
||||||
|
ctx, dir, "reset", "--hard", "HEAD"))
|
||||||
|
if err != nil {
|
||||||
|
text.Errorln(gotext.Get("error resetting %s: %s", dir, stderr))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := config.Runtime.CmdBuilder.Show(
|
||||||
|
config.Runtime.CmdBuilder.BuildGitCmd(
|
||||||
|
ctx, dir, "clean", "-fx", "--exclude", "*.pkg.*")); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -15,7 +12,6 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db/mock"
|
"github.com/Jguer/yay/v12/pkg/db/mock"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
@ -91,13 +87,15 @@ func TestCleanHanging(t *testing.T) {
|
|||||||
Runner: mockRunner,
|
Runner: mockRunner,
|
||||||
SudoLoopEnabled: false,
|
SudoLoopEnabled: false,
|
||||||
}
|
}
|
||||||
|
cfg := &settings.Configuration{
|
||||||
|
Runtime: &settings.Runtime{CmdBuilder: cmdBuilder},
|
||||||
|
}
|
||||||
|
|
||||||
run := &runtime.Runtime{CmdBuilder: cmdBuilder, Cfg: &settings.Configuration{}}
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
cmdArgs.AddArg(tc.args...)
|
cmdArgs.AddArg(tc.args...)
|
||||||
|
|
||||||
err := handleCmd(context.Background(),
|
err := handleCmd(context.Background(),
|
||||||
run, cmdArgs, dbExc,
|
cfg, cmdArgs, dbExc,
|
||||||
)
|
)
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
226
cmd.go
226
cmd.go
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
alpm "github.com/Jguer/go-alpm/v2"
|
alpm "github.com/Jguer/go-alpm/v2"
|
||||||
@ -17,7 +18,6 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/intrange"
|
"github.com/Jguer/yay/v12/pkg/intrange"
|
||||||
"github.com/Jguer/yay/v12/pkg/news"
|
"github.com/Jguer/yay/v12/pkg/news"
|
||||||
"github.com/Jguer/yay/v12/pkg/query"
|
"github.com/Jguer/yay/v12/pkg/query"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
@ -26,8 +26,8 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/vcs"
|
"github.com/Jguer/yay/v12/pkg/vcs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func usage(logger *text.Logger) {
|
func usage() {
|
||||||
logger.Println(`Usage:
|
fmt.Println(`Usage:
|
||||||
yay
|
yay
|
||||||
yay <operation> [...]
|
yay <operation> [...]
|
||||||
yay <package(s)>
|
yay <package(s)>
|
||||||
@ -44,17 +44,15 @@ operations:
|
|||||||
yay {-U --upgrade} [options] <file(s)>
|
yay {-U --upgrade} [options] <file(s)>
|
||||||
|
|
||||||
New operations:
|
New operations:
|
||||||
yay {-B --build} [options] [dir]
|
|
||||||
yay {-G --getpkgbuild} [options] [package(s)]
|
|
||||||
yay {-P --show} [options]
|
|
||||||
yay {-W --web} [options] [package(s)]
|
|
||||||
yay {-Y --yay} [options] [package(s)]
|
yay {-Y --yay} [options] [package(s)]
|
||||||
|
yay {-P --show} [options]
|
||||||
|
yay {-G --getpkgbuild} [options] [package(s)]
|
||||||
|
|
||||||
If no operation is specified 'yay -Syu' will be performed
|
If no arguments are provided 'yay -Syu' will be performed
|
||||||
If no operation is specified and targets are provided -Y will be assumed
|
If no operation is provided -Y will be assumed
|
||||||
|
|
||||||
New options:
|
New options:
|
||||||
-N --repo Assume targets are from the repositories
|
--repo Assume targets are from the repositories
|
||||||
-a --aur Assume targets are from the AUR
|
-a --aur Assume targets are from the AUR
|
||||||
|
|
||||||
Permanent configuration options:
|
Permanent configuration options:
|
||||||
@ -92,19 +90,24 @@ Permanent configuration options:
|
|||||||
--cleanmenu Give the option to clean build PKGBUILDS
|
--cleanmenu Give the option to clean build PKGBUILDS
|
||||||
--diffmenu Give the option to show diffs for build files
|
--diffmenu Give the option to show diffs for build files
|
||||||
--editmenu Give the option to edit/view PKGBUILDS
|
--editmenu Give the option to edit/view PKGBUILDS
|
||||||
|
--upgrademenu Show a detailed list of updates with the option to skip any
|
||||||
|
--nocleanmenu Don't clean build PKGBUILDS
|
||||||
|
--nodiffmenu Don't show diffs for build files
|
||||||
|
--noeditmenu Don't edit/view PKGBUILDS
|
||||||
|
--noupgrademenu Don't show the upgrade menu
|
||||||
--askremovemake Ask to remove makedepends after install
|
--askremovemake Ask to remove makedepends after install
|
||||||
--askyesremovemake Ask to remove makedepends after install("Y" as default)
|
|
||||||
--removemake Remove makedepends after install
|
--removemake Remove makedepends after install
|
||||||
--noremovemake Don't remove makedepends after install
|
--noremovemake Don't remove makedepends after install
|
||||||
|
|
||||||
--cleanafter Remove package sources after successful install
|
--cleanafter Remove package sources after successful install
|
||||||
--keepsrc Keep pkg/ and src/ after building packages
|
--nocleanafter Do not remove package sources after successful build
|
||||||
--bottomup Shows AUR's packages first and then repository's
|
--bottomup Shows AUR's packages first and then repository's
|
||||||
--topdown Shows repository's packages first and then AUR's
|
--topdown Shows repository's packages first and then AUR's
|
||||||
--singlelineresults List each search result on its own line
|
--singlelineresults List each search result on its own line
|
||||||
--doublelineresults List each search result on two lines, like pacman
|
--doublelineresults List each search result on two lines, like pacman
|
||||||
|
|
||||||
--devel Check development packages during sysupgrade
|
--devel Check development packages during sysupgrade
|
||||||
|
--nodevel Do not check development packages
|
||||||
--rebuild Always build target packages
|
--rebuild Always build target packages
|
||||||
--rebuildall Always build all AUR packages
|
--rebuildall Always build all AUR packages
|
||||||
--norebuild Skip package build if in cache and up to date
|
--norebuild Skip package build if in cache and up to date
|
||||||
@ -113,14 +116,23 @@ Permanent configuration options:
|
|||||||
--noredownload Skip pkgbuild download if in cache and up to date
|
--noredownload Skip pkgbuild download if in cache and up to date
|
||||||
--redownloadall Always download pkgbuilds of all AUR packages
|
--redownloadall Always download pkgbuilds of all AUR packages
|
||||||
--provides Look for matching providers when searching for packages
|
--provides Look for matching providers when searching for packages
|
||||||
|
--noprovides Just look for packages by pkgname
|
||||||
--pgpfetch Prompt to import PGP keys from PKGBUILDs
|
--pgpfetch Prompt to import PGP keys from PKGBUILDs
|
||||||
|
--nopgpfetch Don't prompt to import PGP keys
|
||||||
--useask Automatically resolve conflicts using pacman's ask flag
|
--useask Automatically resolve conflicts using pacman's ask flag
|
||||||
|
--nouseask Confirm conflicts manually during the install
|
||||||
|
--combinedupgrade Refresh then perform the repo and AUR upgrade together
|
||||||
|
--nocombinedupgrade Perform the repo upgrade and AUR upgrade separately
|
||||||
|
--batchinstall Build multiple AUR packages then install them together
|
||||||
|
--nobatchinstall Build and install each AUR package one by one
|
||||||
|
|
||||||
--sudo <file> sudo command to use
|
--sudo <file> sudo command to use
|
||||||
--sudoflags <flags> Pass arguments to sudo
|
--sudoflags <flags> Pass arguments to sudo
|
||||||
--sudoloop Loop sudo calls in the background to avoid timeout
|
--sudoloop Loop sudo calls in the background to avoid timeout
|
||||||
|
--nosudoloop Do not loop sudo calls in the background
|
||||||
|
|
||||||
--timeupdate Check packages' AUR page for changes during sysupgrade
|
--timeupdate Check packages' AUR page for changes during sysupgrade
|
||||||
|
--notimeupdate Do not check packages' AUR page for changes
|
||||||
|
|
||||||
show specific options:
|
show specific options:
|
||||||
-c --complete Used for completions
|
-c --complete Used for completions
|
||||||
@ -130,7 +142,7 @@ show specific options:
|
|||||||
-w --news Print arch news
|
-w --news Print arch news
|
||||||
|
|
||||||
yay specific options:
|
yay specific options:
|
||||||
-c --clean Remove unneeded dependencies (-cc to ignore optdepends)
|
-c --clean Remove unneeded dependencies
|
||||||
--gendb Generates development package DB used for updating
|
--gendb Generates development package DB used for updating
|
||||||
|
|
||||||
getpkgbuild specific options:
|
getpkgbuild specific options:
|
||||||
@ -138,49 +150,50 @@ getpkgbuild specific options:
|
|||||||
-p --print Print pkgbuild of packages`)
|
-p --print Print pkgbuild of packages`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCmd(ctx context.Context, run *runtime.Runtime,
|
func handleCmd(ctx context.Context, cfg *settings.Configuration,
|
||||||
cmdArgs *parser.Arguments, dbExecutor db.Executor,
|
cmdArgs *parser.Arguments, dbExecutor db.Executor,
|
||||||
) error {
|
) error {
|
||||||
if cmdArgs.ExistsArg("h", "help") {
|
if cmdArgs.ExistsArg("h", "help") {
|
||||||
return handleHelp(ctx, run, cmdArgs)
|
return handleHelp(ctx, cfg, cmdArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Cfg.SudoLoop && cmdArgs.NeedRoot(run.Cfg.Mode) {
|
if cfg.SudoLoop && cmdArgs.NeedRoot(cfg.Mode) {
|
||||||
run.CmdBuilder.SudoLoop()
|
cfg.Runtime.CmdBuilder.SudoLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cmdArgs.Op {
|
switch cmdArgs.Op {
|
||||||
case "V", "version":
|
case "V", "version":
|
||||||
handleVersion(run.Logger)
|
handleVersion()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
case "D", "database":
|
case "D", "database":
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
case "F", "files":
|
case "F", "files":
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
case "Q", "query":
|
case "Q", "query":
|
||||||
return handleQuery(ctx, run, cmdArgs, dbExecutor)
|
return handleQuery(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
case "R", "remove":
|
case "R", "remove":
|
||||||
return handleRemove(ctx, run, cmdArgs, run.VCSStore)
|
return handleRemove(ctx, cfg, cmdArgs, cfg.Runtime.VCSStore)
|
||||||
case "S", "sync":
|
case "S", "sync":
|
||||||
return handleSync(ctx, run, cmdArgs, dbExecutor)
|
return handleSync(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
case "T", "deptest":
|
case "T", "deptest":
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
case "U", "upgrade":
|
case "U", "upgrade":
|
||||||
return handleUpgrade(ctx, run, cmdArgs)
|
return handleUpgrade(ctx, cfg, cmdArgs)
|
||||||
case "B", "build":
|
case "B", "build":
|
||||||
return handleBuild(ctx, run, dbExecutor, cmdArgs)
|
return handleBuild(ctx, cfg, dbExecutor, cmdArgs)
|
||||||
case "G", "getpkgbuild":
|
case "G", "getpkgbuild":
|
||||||
return handleGetpkgbuild(ctx, run, cmdArgs, dbExecutor)
|
return handleGetpkgbuild(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
case "P", "show":
|
case "P", "show":
|
||||||
return handlePrint(ctx, run, cmdArgs, dbExecutor)
|
return handlePrint(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
case "Y", "yay":
|
case "Y", "yay":
|
||||||
return handleYay(ctx, run, cmdArgs, run.CmdBuilder,
|
return handleYay(ctx, cfg, cmdArgs, cfg.Runtime.CmdBuilder,
|
||||||
dbExecutor, run.QueryBuilder)
|
dbExecutor, cfg.Runtime.QueryBuilder)
|
||||||
case "W", "web":
|
case "W", "web":
|
||||||
return handleWeb(ctx, run, cmdArgs)
|
return handleWeb(ctx, cfg, cmdArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(gotext.Get("unhandled operation"))
|
return errors.New(gotext.Get("unhandled operation"))
|
||||||
@ -210,19 +223,19 @@ func getFilter(cmdArgs *parser.Arguments) (upgrade.Filter, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleQuery(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
func handleQuery(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
||||||
if cmdArgs.ExistsArg("u", "upgrades") {
|
if cmdArgs.ExistsArg("u", "upgrades") {
|
||||||
filter, err := getFilter(cmdArgs)
|
filter, err := getFilter(cmdArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return printUpdateList(ctx, run, cmdArgs, dbExecutor,
|
return printUpdateList(ctx, cfg, cmdArgs, dbExecutor,
|
||||||
cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
|
cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm)); err != nil {
|
cmdArgs, cfg.Mode, settings.NoConfirm)); err != nil {
|
||||||
if str := err.Error(); strings.Contains(str, "exit status") {
|
if str := err.Error(); strings.Contains(str, "exit status") {
|
||||||
// yay -Qdt should not output anything in case of error
|
// yay -Qdt should not output anything in case of error
|
||||||
return fmt.Errorf("")
|
return fmt.Errorf("")
|
||||||
@ -234,139 +247,141 @@ func handleQuery(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Argu
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleHelp(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments) error {
|
func handleHelp(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments) error {
|
||||||
usage(run.Logger)
|
|
||||||
switch cmdArgs.Op {
|
switch cmdArgs.Op {
|
||||||
case "Y", "yay", "G", "getpkgbuild", "P", "show", "W", "web", "B", "build":
|
case "Y", "yay", "G", "getpkgbuild", "P", "show", "W", "web", "B", "build":
|
||||||
|
usage()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Println("\npacman operation specific options:")
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleVersion(logger *text.Logger) {
|
func handleVersion() {
|
||||||
logger.Printf("yay v%s - libalpm v%s\n", yayVersion, alpm.Version())
|
fmt.Printf("yay v%s - libalpm v%s\n", yayVersion, alpm.Version())
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePrint(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
func handlePrint(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
||||||
switch {
|
switch {
|
||||||
case cmdArgs.ExistsArg("d", "defaultconfig"):
|
case cmdArgs.ExistsArg("d", "defaultconfig"):
|
||||||
tmpConfig := settings.DefaultConfig(yayVersion)
|
tmpConfig := settings.DefaultConfig(yayVersion)
|
||||||
run.Logger.Printf("%v", tmpConfig)
|
fmt.Printf("%v", tmpConfig)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
case cmdArgs.ExistsArg("g", "currentconfig"):
|
case cmdArgs.ExistsArg("g", "currentconfig"):
|
||||||
run.Logger.Printf("%v", run.Cfg)
|
fmt.Printf("%v", cfg)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
case cmdArgs.ExistsArg("w", "news"):
|
case cmdArgs.ExistsArg("w", "news"):
|
||||||
double := cmdArgs.ExistsDouble("w", "news")
|
double := cmdArgs.ExistsDouble("w", "news")
|
||||||
quiet := cmdArgs.ExistsArg("q", "quiet")
|
quiet := cmdArgs.ExistsArg("q", "quiet")
|
||||||
|
|
||||||
return news.PrintNewsFeed(ctx, run.HTTPClient, run.Logger,
|
return news.PrintNewsFeed(ctx, cfg.Runtime.HTTPClient, dbExecutor.LastBuildTime(), cfg.BottomUp, double, quiet)
|
||||||
dbExecutor.LastBuildTime(), run.Cfg.BottomUp, double, quiet)
|
|
||||||
case cmdArgs.ExistsArg("c", "complete"):
|
case cmdArgs.ExistsArg("c", "complete"):
|
||||||
return completion.Show(ctx, run.HTTPClient, dbExecutor,
|
return completion.Show(ctx, cfg.Runtime.HTTPClient, dbExecutor,
|
||||||
run.Cfg.AURURL, run.Cfg.CompletionPath, run.Cfg.CompletionInterval, cmdArgs.ExistsDouble("c", "complete"))
|
cfg.AURURL, cfg.CompletionPath, cfg.CompletionInterval, cmdArgs.ExistsDouble("c", "complete"))
|
||||||
case cmdArgs.ExistsArg("s", "stats"):
|
case cmdArgs.ExistsArg("s", "stats"):
|
||||||
return localStatistics(ctx, run, dbExecutor)
|
return localStatistics(ctx, cfg, dbExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleYay(ctx context.Context, run *runtime.Runtime,
|
func handleYay(ctx context.Context, cfg *settings.Configuration,
|
||||||
cmdArgs *parser.Arguments, cmdBuilder exe.ICmdBuilder,
|
cmdArgs *parser.Arguments, cmdBuilder exe.ICmdBuilder,
|
||||||
dbExecutor db.Executor, queryBuilder query.Builder,
|
dbExecutor db.Executor, queryBuilder query.Builder,
|
||||||
) error {
|
) error {
|
||||||
switch {
|
switch {
|
||||||
case cmdArgs.ExistsArg("gendb"):
|
case cmdArgs.ExistsArg("gendb"):
|
||||||
return createDevelDB(ctx, run, dbExecutor)
|
return createDevelDB(ctx, cfg, dbExecutor)
|
||||||
case cmdArgs.ExistsDouble("c"):
|
case cmdArgs.ExistsDouble("c"):
|
||||||
return cleanDependencies(ctx, run.Cfg, cmdBuilder, cmdArgs, dbExecutor, true)
|
return cleanDependencies(ctx, cfg, cmdBuilder, cmdArgs, dbExecutor, true)
|
||||||
case cmdArgs.ExistsArg("c", "clean"):
|
case cmdArgs.ExistsArg("c", "clean"):
|
||||||
return cleanDependencies(ctx, run.Cfg, cmdBuilder, cmdArgs, dbExecutor, false)
|
return cleanDependencies(ctx, cfg, cmdBuilder, cmdArgs, dbExecutor, false)
|
||||||
case len(cmdArgs.Targets) > 0:
|
case len(cmdArgs.Targets) > 0:
|
||||||
return displayNumberMenu(ctx, run, cmdArgs.Targets, dbExecutor, queryBuilder, cmdArgs)
|
return displayNumberMenu(ctx, cfg, cmdArgs.Targets, dbExecutor, queryBuilder, cmdArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleWeb(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments) error {
|
func handleWeb(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments) error {
|
||||||
switch {
|
switch {
|
||||||
case cmdArgs.ExistsArg("v", "vote"):
|
case cmdArgs.ExistsArg("v", "vote"):
|
||||||
return handlePackageVote(ctx, cmdArgs.Targets, run.AURClient, run.Logger,
|
return handlePackageVote(ctx, cmdArgs.Targets, cfg.Runtime.AURClient,
|
||||||
run.VoteClient, true)
|
cfg.Runtime.VoteClient, cfg.RequestSplitN, true)
|
||||||
case cmdArgs.ExistsArg("u", "unvote"):
|
case cmdArgs.ExistsArg("u", "unvote"):
|
||||||
return handlePackageVote(ctx, cmdArgs.Targets, run.AURClient, run.Logger,
|
return handlePackageVote(ctx, cmdArgs.Targets, cfg.Runtime.AURClient,
|
||||||
run.VoteClient, false)
|
cfg.Runtime.VoteClient, cfg.RequestSplitN, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGetpkgbuild(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {
|
func handleGetpkgbuild(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {
|
||||||
if cmdArgs.ExistsArg("p", "print") {
|
if cmdArgs.ExistsArg("p", "print") {
|
||||||
return printPkgbuilds(dbExecutor, run.AURClient,
|
return printPkgbuilds(dbExecutor, cfg.Runtime.AURCache,
|
||||||
run.HTTPClient, run.Logger, cmdArgs.Targets, run.Cfg.Mode, run.Cfg.AURURL)
|
cfg.Runtime.HTTPClient, cmdArgs.Targets, cfg.Mode, cfg.AURURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
return getPkgbuilds(ctx, dbExecutor, run.AURClient, run,
|
return getPkgbuilds(ctx, dbExecutor, cfg.Runtime.AURCache, cfg,
|
||||||
cmdArgs.Targets, cmdArgs.ExistsArg("f", "force"))
|
cmdArgs.Targets, cmdArgs.ExistsArg("f", "force"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleUpgrade(ctx context.Context,
|
func handleUpgrade(ctx context.Context,
|
||||||
run *runtime.Runtime, cmdArgs *parser.Arguments,
|
config *settings.Configuration, cmdArgs *parser.Arguments,
|
||||||
) error {
|
) error {
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, config.Mode, settings.NoConfirm))
|
||||||
}
|
}
|
||||||
|
|
||||||
// -B* options
|
// -B* options
|
||||||
func handleBuild(ctx context.Context,
|
func handleBuild(ctx context.Context,
|
||||||
run *runtime.Runtime, dbExecutor db.Executor, cmdArgs *parser.Arguments,
|
config *settings.Configuration, dbExecutor db.Executor, cmdArgs *parser.Arguments,
|
||||||
) error {
|
) error {
|
||||||
if cmdArgs.ExistsArg("i", "install") {
|
if cmdArgs.ExistsArg("i", "install") {
|
||||||
return installLocalPKGBUILD(ctx, run, cmdArgs, dbExecutor)
|
return installLocalPKGBUILD(ctx, config, cmdArgs, dbExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSync(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
func handleSync(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
||||||
targets := cmdArgs.Targets
|
targets := cmdArgs.Targets
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cmdArgs.ExistsArg("s", "search"):
|
case cmdArgs.ExistsArg("s", "search"):
|
||||||
return syncSearch(ctx, targets, dbExecutor, run.QueryBuilder, !cmdArgs.ExistsArg("q", "quiet"))
|
return syncSearch(ctx, targets, dbExecutor, cfg.Runtime.QueryBuilder, !cmdArgs.ExistsArg("q", "quiet"))
|
||||||
case cmdArgs.ExistsArg("p", "print", "print-format"):
|
case cmdArgs.ExistsArg("p", "print", "print-format"):
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
case cmdArgs.ExistsArg("c", "clean"):
|
case cmdArgs.ExistsArg("c", "clean"):
|
||||||
return syncClean(ctx, run, cmdArgs, dbExecutor)
|
return syncClean(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
case cmdArgs.ExistsArg("l", "list"):
|
case cmdArgs.ExistsArg("l", "list"):
|
||||||
return syncList(ctx, run, run.HTTPClient, cmdArgs, dbExecutor)
|
return syncList(ctx, cfg, cfg.Runtime.HTTPClient, cmdArgs, dbExecutor)
|
||||||
case cmdArgs.ExistsArg("g", "groups"):
|
case cmdArgs.ExistsArg("g", "groups"):
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
case cmdArgs.ExistsArg("i", "info"):
|
case cmdArgs.ExistsArg("i", "info"):
|
||||||
return syncInfo(ctx, run, cmdArgs, targets, dbExecutor)
|
return syncInfo(ctx, cfg, cmdArgs, targets, dbExecutor)
|
||||||
case cmdArgs.ExistsArg("u", "sysupgrade") || len(cmdArgs.Targets) > 0:
|
case cmdArgs.ExistsArg("u", "sysupgrade") || len(cmdArgs.Targets) > 0:
|
||||||
return syncInstall(ctx, run, cmdArgs, dbExecutor)
|
if cfg.NewInstallEngine {
|
||||||
|
return syncInstall(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return install(ctx, cfg, cmdArgs, dbExecutor, false)
|
||||||
case cmdArgs.ExistsArg("y", "refresh"):
|
case cmdArgs.ExistsArg("y", "refresh"):
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleRemove(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, localCache vcs.Store) error {
|
func handleRemove(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, localCache vcs.Store) error {
|
||||||
err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
localCache.RemovePackages(cmdArgs.Targets)
|
localCache.RemovePackages(cmdArgs.Targets)
|
||||||
}
|
}
|
||||||
@ -375,7 +390,7 @@ func handleRemove(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arg
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NumberMenu presents a CLI for selecting packages to install.
|
// NumberMenu presents a CLI for selecting packages to install.
|
||||||
func displayNumberMenu(ctx context.Context, run *runtime.Runtime, pkgS []string, dbExecutor db.Executor,
|
func displayNumberMenu(ctx context.Context, cfg *settings.Configuration, pkgS []string, dbExecutor db.Executor,
|
||||||
queryBuilder query.Builder, cmdArgs *parser.Arguments,
|
queryBuilder query.Builder, cmdArgs *parser.Arguments,
|
||||||
) error {
|
) error {
|
||||||
queryBuilder.Execute(ctx, dbExecutor, pkgS)
|
queryBuilder.Execute(ctx, dbExecutor, pkgS)
|
||||||
@ -389,9 +404,9 @@ func displayNumberMenu(ctx context.Context, run *runtime.Runtime, pkgS []string,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))
|
text.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))
|
||||||
|
|
||||||
numberBuf, err := run.Logger.GetInput("", false)
|
numberBuf, err := text.GetInput(os.Stdin, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -404,30 +419,35 @@ func displayNumberMenu(ctx context.Context, run *runtime.Runtime, pkgS []string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// modify the arguments to pass for the install
|
// modify the arguments to pass for the install
|
||||||
|
cmdArgs.Op = "S"
|
||||||
cmdArgs.Targets = targets
|
cmdArgs.Targets = targets
|
||||||
|
|
||||||
if len(cmdArgs.Targets) == 0 {
|
if len(cmdArgs.Targets) == 0 {
|
||||||
run.Logger.Println(gotext.Get(" there is nothing to do"))
|
fmt.Println(gotext.Get(" there is nothing to do"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return syncInstall(ctx, run, cmdArgs, dbExecutor)
|
if cfg.NewInstallEngine {
|
||||||
|
return syncInstall(ctx, cfg, cmdArgs, dbExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return install(ctx, cfg, cmdArgs, dbExecutor, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncList(ctx context.Context, run *runtime.Runtime,
|
func syncList(ctx context.Context, cfg *settings.Configuration,
|
||||||
httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.Executor,
|
httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.Executor,
|
||||||
) error {
|
) error {
|
||||||
aur := false
|
aur := false
|
||||||
|
|
||||||
for i := len(cmdArgs.Targets) - 1; i >= 0; i-- {
|
for i := len(cmdArgs.Targets) - 1; i >= 0; i-- {
|
||||||
if cmdArgs.Targets[i] == "aur" && run.Cfg.Mode.AtLeastAUR() {
|
if cmdArgs.Targets[i] == "aur" && cfg.Mode.AtLeastAUR() {
|
||||||
cmdArgs.Targets = append(cmdArgs.Targets[:i], cmdArgs.Targets[i+1:]...)
|
cmdArgs.Targets = append(cmdArgs.Targets[:i], cmdArgs.Targets[i+1:]...)
|
||||||
aur = true
|
aur = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Cfg.Mode.AtLeastAUR() && (len(cmdArgs.Targets) == 0 || aur) {
|
if cfg.Mode.AtLeastAUR() && (len(cmdArgs.Targets) == 0 || aur) {
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, run.Cfg.AURURL+"/packages.gz", http.NoBody)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, cfg.AURURL+"/packages.gz", http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -445,22 +465,22 @@ func syncList(ctx context.Context, run *runtime.Runtime,
|
|||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
name := scanner.Text()
|
name := scanner.Text()
|
||||||
if cmdArgs.ExistsArg("q", "quiet") {
|
if cmdArgs.ExistsArg("q", "quiet") {
|
||||||
run.Logger.Println(name)
|
fmt.Println(name)
|
||||||
} else {
|
} else {
|
||||||
run.Logger.Printf("%s %s %s", text.Magenta("aur"), text.Bold(name), text.Bold(text.Green(gotext.Get("unknown-version"))))
|
fmt.Printf("%s %s %s", text.Magenta("aur"), text.Bold(name), text.Bold(text.Green(gotext.Get("unknown-version"))))
|
||||||
|
|
||||||
if dbExecutor.LocalPackage(name) != nil {
|
if dbExecutor.LocalPackage(name) != nil {
|
||||||
run.Logger.Print(text.Bold(text.Blue(gotext.Get(" [Installed]"))))
|
fmt.Print(text.Bold(text.Blue(gotext.Get(" [Installed]"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Cfg.Mode.AtLeastRepo() && (len(cmdArgs.Targets) != 0 || !aur) {
|
if cfg.Mode.AtLeastRepo() && (len(cmdArgs.Targets) != 0 || !aur) {
|
||||||
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
140
cmd_test.go
140
cmd_test.go
@ -1,140 +0,0 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/Jguer/aur"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db/mock"
|
|
||||||
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/query"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/vcs"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestYogurtMenuAURDB(t *testing.T) {
|
|
||||||
t.Skip("skip until Operation service is an interface")
|
|
||||||
t.Parallel()
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
gitBin := t.TempDir() + "/git"
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
PacmanConfigPath: "/etc/pacman.conf",
|
|
||||||
GitBin: "git",
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddArg("Y")
|
|
||||||
cmdArgs.AddTarget("yay")
|
|
||||||
|
|
||||||
db := &mock.DBExecutor{
|
|
||||||
AlpmArchitecturesFn: func() ([]string, error) {
|
|
||||||
return []string{"x86_64"}, nil
|
|
||||||
},
|
|
||||||
RefreshHandleFn: func() error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
ReposFn: func() []string {
|
|
||||||
return []string{"aur"}
|
|
||||||
},
|
|
||||||
SyncPackagesFn: func(s ...string) []mock.IPackage {
|
|
||||||
return []mock.IPackage{
|
|
||||||
&mock.Package{
|
|
||||||
PName: "yay",
|
|
||||||
PBase: "yay",
|
|
||||||
PVersion: "10.0.0",
|
|
||||||
PDB: mock.NewDB("aur"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(s string) mock.IPackage {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
aurCache := &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{
|
|
||||||
{
|
|
||||||
Name: "yay",
|
|
||||||
PackageBase: "yay",
|
|
||||||
Version: "10.0.0",
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
logger := text.NewLogger(io.Discard, os.Stderr, strings.NewReader("1\n"), true, "test")
|
|
||||||
|
|
||||||
run := &runtime.Runtime{
|
|
||||||
Cfg: &settings.Configuration{
|
|
||||||
RemoveMake: "no",
|
|
||||||
},
|
|
||||||
Logger: logger,
|
|
||||||
CmdBuilder: cmdBuilder,
|
|
||||||
VCSStore: &vcs.Mock{},
|
|
||||||
QueryBuilder: query.NewSourceQueryBuilder(aurCache, logger, "votes", parser.ModeAny, "name",
|
|
||||||
true, false, true),
|
|
||||||
AURClient: aurCache,
|
|
||||||
}
|
|
||||||
err = handleCmd(context.Background(), run, cmdArgs, db)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
wantCapture := []string{}
|
|
||||||
wantShow := []string{
|
|
||||||
"pacman -S -y --config /etc/pacman.conf --",
|
|
||||||
"pacman -S -y -u --config /etc/pacman.conf --",
|
|
||||||
}
|
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
|
||||||
require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
|
|
||||||
|
|
||||||
for i, call := range mockRunner.ShowCalls {
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
show = strings.ReplaceAll(show, gitBin, "pacman")
|
|
||||||
|
|
||||||
// options are in a different order on different systems and on CI root user is used
|
|
||||||
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
|
||||||
}
|
|
||||||
}
|
|
@ -61,22 +61,22 @@ _yay() {
|
|||||||
search unrequired upgrades' 'c e g i k l m n o p s t u')
|
search unrequired upgrades' 'c e g i k l m n o p s t u')
|
||||||
remove=('cascade dbonly nodeps assume-installed nosave print recursive unneeded' 'c n p s u')
|
remove=('cascade dbonly nodeps assume-installed nosave print recursive unneeded' 'c n p s u')
|
||||||
sync=('asdeps asexplicit clean dbonly downloadonly overwrite groups ignore ignoregroup
|
sync=('asdeps asexplicit clean dbonly downloadonly overwrite groups ignore ignoregroup
|
||||||
info list needed nodeps assume-installed print refresh recursive search sysupgrade aur repo'
|
info list needed nodeps assume-installed print refresh recursive search sysupgrade'
|
||||||
'c g i l p s u w y a N')
|
'c g i l p s u w y')
|
||||||
upgrade=('asdeps asexplicit overwrite needed nodeps assume-installed print recursive' 'p')
|
upgrade=('asdeps asexplicit overwrite needed nodeps assume-installed print recursive' 'p')
|
||||||
core=('database files help query remove sync upgrade version' 'D F Q R S U V h')
|
core=('database files help query remove sync upgrade version' 'D F Q R S U V h')
|
||||||
|
|
||||||
##yay stuff
|
##yay stuff
|
||||||
common=('arch cachedir color config confirm dbpath debug gpgdir help hookdir logfile
|
common=('arch cachedir color config confirm dbpath debug gpgdir help hookdir logfile
|
||||||
noconfirm noprogressbar noscriptlet quiet root verbose
|
noconfirm noprogressbar noscriptlet quiet root verbose
|
||||||
makepkg pacman git gpg gpgflags config requestsplitn sudoloop
|
makepkg pacman git gpg gpgflags config requestsplitn sudoloop nosudoloop
|
||||||
redownload noredownload redownloadall rebuild rebuildall rebuildtree norebuild sortby
|
redownload noredownload redownloadall rebuild rebuildall rebuildtree norebuild sortby
|
||||||
singlelineresults doublelineresults answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff
|
singlelineresults doublelineresults answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff
|
||||||
noansweredit noanswerupgrade cleanmenu diffmenu editmenu cleanafter keepsrc
|
noansweredit noanswerupgrade cleanmenu diffmenu editmenu upgrademenu cleanafter nocleanafter
|
||||||
provides pgpfetch
|
nocleanmenu nodiffmenu noupgrademenu provides noprovides pgpfetch nopgpfetch
|
||||||
useask combinedupgrade aur repo makepkgconf
|
useask nouseask combinedupgrade nocombinedupgrade aur repo makepkgconf
|
||||||
nomakepkgconf askremovemake askyesremovemake removemake noremovemake completioninterval aururl aurrpcurl
|
nomakepkgconf askremovemake removemake noremovemake completioninterval aururl aurrpcurl
|
||||||
searchby batchinstall'
|
searchby batchinstall nobatchinstall'
|
||||||
'b d h q r v')
|
'b d h q r v')
|
||||||
yays=('clean gendb' 'c')
|
yays=('clean gendb' 'c')
|
||||||
show=('complete defaultconfig currentconfig stats news' 'c d g s w')
|
show=('complete defaultconfig currentconfig stats news' 'c d g s w')
|
||||||
|
@ -165,8 +165,8 @@ complete -c $progname -n "$webspecific" -s u -l unvote -d 'Unvote for AUR packag
|
|||||||
complete -c $progname -n "$webspecific" -xa "$listall"
|
complete -c $progname -n "$webspecific" -xa "$listall"
|
||||||
|
|
||||||
# New options
|
# New options
|
||||||
complete -c $progname -n "not $noopt" -s a -l aur -d 'Assume targets are from the AUR' -f
|
complete -c $progname -n "not $noopt" -l repo -d 'Assume targets are from the AUR' -f
|
||||||
complete -c $progname -n "not $noopt" -s N -l repo -d 'Assume targets are from the repositories' -f
|
complete -c $progname -n "not $noopt" -s a -l aur -d 'Assume targets are from the repositories' -f
|
||||||
|
|
||||||
# Yay options
|
# Yay options
|
||||||
complete -c $progname -n "$yayspecific" -s c -l clean -d 'Remove unneeded dependencies' -f
|
complete -c $progname -n "$yayspecific" -s c -l clean -d 'Remove unneeded dependencies' -f
|
||||||
@ -216,8 +216,12 @@ complete -c $progname -n "not $noopt" -l noanswerupgrade -d 'Unset the answer fo
|
|||||||
complete -c $progname -n "not $noopt" -l cleanmenu -d 'Give the option to clean build PKGBUILDS' -f
|
complete -c $progname -n "not $noopt" -l cleanmenu -d 'Give the option to clean build PKGBUILDS' -f
|
||||||
complete -c $progname -n "not $noopt" -l diffmenu -d 'Give the option to show diffs for build files' -f
|
complete -c $progname -n "not $noopt" -l diffmenu -d 'Give the option to show diffs for build files' -f
|
||||||
complete -c $progname -n "not $noopt" -l editmenu -d 'Give the option to edit/view PKGBUILDS' -f
|
complete -c $progname -n "not $noopt" -l editmenu -d 'Give the option to edit/view PKGBUILDS' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l upgrademenu -d 'Show a detailed list of updates with the option to skip any' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nocleanmenu -d 'Do not clean build PKGBUILDS' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nodiffmenu -d 'Do not show diffs for build files' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l noeditmenu -d 'Do not edit/view PKGBUILDS' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l noupgrademenu -d 'Do not show the upgrade menu' -f
|
||||||
complete -c $progname -n "not $noopt" -l askremovemake -d 'Ask to remove make deps after install' -f
|
complete -c $progname -n "not $noopt" -l askremovemake -d 'Ask to remove make deps after install' -f
|
||||||
complete -c $progname -n "not $noopt" -l askyesremovemake -d 'Ask to remove make deps after install(with "Y" as default)' -f
|
|
||||||
complete -c $progname -n "not $noopt" -l removemake -d 'Remove make deps after install' -f
|
complete -c $progname -n "not $noopt" -l removemake -d 'Remove make deps after install' -f
|
||||||
complete -c $progname -n "not $noopt" -l noremovemake -d 'Do not remove make deps after install' -f
|
complete -c $progname -n "not $noopt" -l noremovemake -d 'Do not remove make deps after install' -f
|
||||||
complete -c $progname -n "not $noopt" -l topdown -d 'Shows repository packages first and then aur' -f
|
complete -c $progname -n "not $noopt" -l topdown -d 'Shows repository packages first and then aur' -f
|
||||||
@ -225,17 +229,24 @@ complete -c $progname -n "not $noopt" -l bottomup -d 'Shows aur packages first a
|
|||||||
complete -c $progname -n "not $noopt" -l singlelineresults -d 'List each search result on its own line' -f
|
complete -c $progname -n "not $noopt" -l singlelineresults -d 'List each search result on its own line' -f
|
||||||
complete -c $progname -n "not $noopt" -l doublelineresults -d 'List each search result on two lines, like pacman' -f
|
complete -c $progname -n "not $noopt" -l doublelineresults -d 'List each search result on two lines, like pacman' -f
|
||||||
complete -c $progname -n "not $noopt" -l devel -d 'Check -git/-svn/-hg development version' -f
|
complete -c $progname -n "not $noopt" -l devel -d 'Check -git/-svn/-hg development version' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nodevel -d 'Disable development version checking' -f
|
||||||
complete -c $progname -n "not $noopt" -l cleanafter -d 'Clean package sources after successful build' -f
|
complete -c $progname -n "not $noopt" -l cleanafter -d 'Clean package sources after successful build' -f
|
||||||
complete -c $progname -n "not $noopt" -l keepsrc -d 'Keep pkg/ and src/ after building packages' -f
|
complete -c $progname -n "not $noopt" -l nocleanafter -d 'Disable package sources cleaning' -f
|
||||||
complete -c $progname -n "not $noopt" -l timeupdate -d 'Check package modification date and version' -f
|
complete -c $progname -n "not $noopt" -l timeupdate -d 'Check package modification date and version' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l notimeupdate -d 'Check only package version change' -f
|
||||||
complete -c $progname -n "not $noopt" -l redownload -d 'Redownload PKGBUILD of package even if up-to-date' -f
|
complete -c $progname -n "not $noopt" -l redownload -d 'Redownload PKGBUILD of package even if up-to-date' -f
|
||||||
complete -c $progname -n "not $noopt" -l redownloadall -d 'Redownload PKGBUILD of package and deps even if up-to-date' -f
|
complete -c $progname -n "not $noopt" -l redownloadall -d 'Redownload PKGBUILD of package and deps even if up-to-date' -f
|
||||||
complete -c $progname -n "not $noopt" -l noredownload -d 'Do not redownload up-to-date PKGBUILDs' -f
|
complete -c $progname -n "not $noopt" -l noredownload -d 'Do not redownload up-to-date PKGBUILDs' -f
|
||||||
complete -c $progname -n "not $noopt" -l provides -d 'Look for matching providers when searching for packages' -f
|
complete -c $progname -n "not $noopt" -l provides -d 'Look for matching providers when searching for packages' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l noprovides -d 'Just look for packages by pkgname' -f
|
||||||
complete -c $progname -n "not $noopt" -l pgpfetch -d 'Prompt to import PGP keys from PKGBUILDs' -f
|
complete -c $progname -n "not $noopt" -l pgpfetch -d 'Prompt to import PGP keys from PKGBUILDs' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nopgpfetch -d 'Do not prompt to import PGP keys' -f
|
||||||
complete -c $progname -n "not $noopt" -l useask -d 'Automatically resolve conflicts using pacmans ask flag' -f
|
complete -c $progname -n "not $noopt" -l useask -d 'Automatically resolve conflicts using pacmans ask flag' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nouseask -d 'Confirm conflicts manually during the install' -f
|
||||||
complete -c $progname -n "not $noopt" -l combinedupgrade -d 'Refresh then perform the repo and AUR upgrade together' -f
|
complete -c $progname -n "not $noopt" -l combinedupgrade -d 'Refresh then perform the repo and AUR upgrade together' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nocombinedupgrade -d 'Perform the repo upgrade and AUR upgrade separately' -f
|
||||||
complete -c $progname -n "not $noopt" -l batchinstall -d 'Build multiple AUR packages then install them together' -f
|
complete -c $progname -n "not $noopt" -l batchinstall -d 'Build multiple AUR packages then install them together' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nobatchinstall -d 'Build and install each AUR package one by one' -f
|
||||||
complete -c $progname -n "not $noopt" -l rebuild -d 'Always build target packages' -f
|
complete -c $progname -n "not $noopt" -l rebuild -d 'Always build target packages' -f
|
||||||
complete -c $progname -n "not $noopt" -l rebuildall -d 'Always build all AUR packages' -f
|
complete -c $progname -n "not $noopt" -l rebuildall -d 'Always build all AUR packages' -f
|
||||||
complete -c $progname -n "not $noopt" -l rebuildtree -d 'Always build all AUR packages even if installed' -f
|
complete -c $progname -n "not $noopt" -l rebuildtree -d 'Always build all AUR packages even if installed' -f
|
||||||
@ -243,3 +254,4 @@ complete -c $progname -n "not $noopt" -l norebuild -d 'Skip package build if in
|
|||||||
complete -c $progname -n "not $noopt" -l mflags -d 'Pass the following options to makepkg' -f
|
complete -c $progname -n "not $noopt" -l mflags -d 'Pass the following options to makepkg' -f
|
||||||
complete -c $progname -n "not $noopt" -l gpgflags -d 'Pass the following options to gpg' -f
|
complete -c $progname -n "not $noopt" -l gpgflags -d 'Pass the following options to gpg' -f
|
||||||
complete -c $progname -n "not $noopt" -l sudoloop -d 'Loop sudo calls in the background to avoid timeout' -f
|
complete -c $progname -n "not $noopt" -l sudoloop -d 'Loop sudo calls in the background to avoid timeout' -f
|
||||||
|
complete -c $progname -n "not $noopt" -l nosudoloop -d 'Do not loop sudo calls in the background' -f
|
||||||
|
@ -23,7 +23,7 @@ _pacman_opts_commands=(
|
|||||||
|
|
||||||
# options for passing to _arguments: options common to all commands
|
# options for passing to _arguments: options common to all commands
|
||||||
_pacman_opts_common=(
|
_pacman_opts_common=(
|
||||||
{-N,--repo}'[Assume targets are from the repositories]'
|
'--repo[Assume targets are from the repositories]'
|
||||||
{-a,--aur}'[Assume targets are from the AUR]'
|
{-a,--aur}'[Assume targets are from the AUR]'
|
||||||
'--aururl[Set an alternative AUR URL]:url'
|
'--aururl[Set an alternative AUR URL]:url'
|
||||||
'--aurrpcurl[Set an alternative URL for the AUR /rpc endpoint]:url'
|
'--aurrpcurl[Set an alternative URL for the AUR /rpc endpoint]:url'
|
||||||
@ -70,8 +70,12 @@ _pacman_opts_common=(
|
|||||||
'--cleanmenu[Give the option to clean build PKGBUILDS]'
|
'--cleanmenu[Give the option to clean build PKGBUILDS]'
|
||||||
'--diffmenu[Give the option to show diffs for build files]'
|
'--diffmenu[Give the option to show diffs for build files]'
|
||||||
'--editmenu[Give the option to edit/view PKGBUILDS]'
|
'--editmenu[Give the option to edit/view PKGBUILDS]'
|
||||||
|
'--upgrademenu[Show a detailed list of updates with the option to skip any]'
|
||||||
|
"--nocleanmenu[Don't clean build PKGBUILDS]"
|
||||||
|
"--nodiffmenu[Don't show diffs for build files]"
|
||||||
|
"--noeditmenu[Don't edit/view PKGBUILDS]"
|
||||||
|
"--noupgrademenu[Don't show the upgrade menu]"
|
||||||
"--askremovemake[Ask to remove makedepends after install]"
|
"--askremovemake[Ask to remove makedepends after install]"
|
||||||
"--askyesremovemake[Ask to remove makedepends after install(with "Y" as default)]"
|
|
||||||
"--removemake[Remove makedepends after install]"
|
"--removemake[Remove makedepends after install]"
|
||||||
"--noremovemake[Don't remove makedepends after install]"
|
"--noremovemake[Don't remove makedepends after install]"
|
||||||
|
|
||||||
@ -80,26 +84,34 @@ _pacman_opts_common=(
|
|||||||
'--singlelineresults[List each search result on its own line]'
|
'--singlelineresults[List each search result on its own line]'
|
||||||
'--doublelineresults[List each search result on two lines, like pacman]'
|
'--doublelineresults[List each search result on two lines, like pacman]'
|
||||||
'--devel[Check -git/-svn/-hg development version]'
|
'--devel[Check -git/-svn/-hg development version]'
|
||||||
|
'--nodevel[Disable development version checking]'
|
||||||
'--cleanafter[Clean package sources after successful build]'
|
'--cleanafter[Clean package sources after successful build]'
|
||||||
'--keepsrc[Keep pkg/ and src/ after building packages]'
|
'--nocleanafter[Disable package sources cleaning after successful build]'
|
||||||
'--timeupdate[Check packages modification date and version]'
|
'--timeupdate[Check packages modification date and version]'
|
||||||
|
'--notimeupdate[Check only package version change]'
|
||||||
'--redownload[Always download pkgbuilds of targets]'
|
'--redownload[Always download pkgbuilds of targets]'
|
||||||
'--redownloadall[Always download pkgbuilds of all AUR packages]'
|
'--redownloadall[Always download pkgbuilds of all AUR packages]'
|
||||||
'--noredownload[Skip pkgbuild download if in cache and up to date]'
|
'--noredownload[Skip pkgbuild download if in cache and up to date]'
|
||||||
'--rebuild[Always build target packages]'
|
'--rebuild[Always build target packages]'
|
||||||
'--rebuildall[Always build all AUR packages]'
|
'--rebuildall[Always build all AUR packages]'
|
||||||
'--provides[Look for matching providers when searching for packages]'
|
'--provides[Look for matching providers when searching for packages]'
|
||||||
|
'--noprovides[Just look for packages by pkgname]'
|
||||||
'--pgpfetch[Prompt to import PGP keys from PKGBUILDs]'
|
'--pgpfetch[Prompt to import PGP keys from PKGBUILDs]'
|
||||||
|
"--nopgpfetch[Don't prompt to import PGP keys]"
|
||||||
"--useask[Automatically resolve conflicts using pacman's ask flag]"
|
"--useask[Automatically resolve conflicts using pacman's ask flag]"
|
||||||
|
'--nouseask[Confirm conflicts manually during the install]'
|
||||||
'--combinedupgrade[Refresh then perform the repo and AUR upgrade together]'
|
'--combinedupgrade[Refresh then perform the repo and AUR upgrade together]'
|
||||||
|
'--nocombinedupgrade[Perform the repo upgrade and AUR upgrade separately]'
|
||||||
'--rebuildtree[Always build all AUR packages even if installed]'
|
'--rebuildtree[Always build all AUR packages even if installed]'
|
||||||
'--norebuild[Skip package build if in cache and up to date]'
|
'--norebuild[Skip package build if in cache and up to date]'
|
||||||
'--mflags[Pass arguments to makepkg]:mflags'
|
'--mflags[Pass arguments to makepkg]:mflags'
|
||||||
'--gpgflags[Pass arguments to gpg]:gpgflags'
|
'--gpgflags[Pass arguments to gpg]:gpgflags'
|
||||||
'--sudoloop[Loop sudo calls in the background to avoid timeout]'
|
'--sudoloop[Loop sudo calls in the background to avoid timeout]'
|
||||||
|
'--nosudoloop[Do not loop sudo calls in the background]'
|
||||||
'--searchby[Search for packages using a specified field]'
|
'--searchby[Search for packages using a specified field]'
|
||||||
'--sortby[Sort AUR results by a specific field during search]'
|
'--sortby[Sort AUR results by a specific field during search]'
|
||||||
'--batchinstall[Build multiple AUR packages then install them together]'
|
'--batchinstall[Build multiple AUR packages then install them together]'
|
||||||
|
'--nobatchinstall[Build and install each AUR package one by one]'
|
||||||
)
|
)
|
||||||
|
|
||||||
# options for passing to _arguments: options for --upgrade commands
|
# options for passing to _arguments: options for --upgrade commands
|
||||||
|
102
doc/yay.8
102
doc/yay.8
@ -23,7 +23,7 @@ This manpage only covers options unique to Yay. For other options see
|
|||||||
.TP
|
.TP
|
||||||
.B \-Y, \-\-yay
|
.B \-Y, \-\-yay
|
||||||
Perform yay specific operations. This is the default if no other operation is
|
Perform yay specific operations. This is the default if no other operation is
|
||||||
selected and targets are defined.
|
selected.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-B, \-\-build
|
.B \-B, \-\-build
|
||||||
@ -42,9 +42,9 @@ Downloads PKGBUILD from ABS or AUR. The ABS can only be used for Arch Linux repo
|
|||||||
Web related operations such as voting for AUR packages.
|
Web related operations such as voting for AUR packages.
|
||||||
|
|
||||||
.RE
|
.RE
|
||||||
If no operation is specified 'yay \-Syu' will be performed
|
If no arguments are provided 'yay \-Syu' will be performed.
|
||||||
|
|
||||||
If no operation is specified and targets are provided \-Y will be assumed
|
If no operation is selected \-Y will be assumed.
|
||||||
|
|
||||||
.SH EXTENDED PACMAN OPERATIONS
|
.SH EXTENDED PACMAN OPERATIONS
|
||||||
.TP
|
.TP
|
||||||
@ -63,7 +63,7 @@ Yay will also remove cached data about devel packages.
|
|||||||
|
|
||||||
.SH NEW OPTIONS
|
.SH NEW OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-N, \-\-repo
|
.B \-\-repo
|
||||||
Assume all targets are from the repositories. Additionally Actions such as
|
Assume all targets are from the repositories. Additionally Actions such as
|
||||||
sysupgrade will only act on repository packages.
|
sysupgrade will only act on repository packages.
|
||||||
|
|
||||||
@ -82,10 +82,6 @@ packages.
|
|||||||
Displays a list of packages matching the search terms and prompts the user on
|
Displays a list of packages matching the search terms and prompts the user on
|
||||||
which packages to install (yogurt mode).
|
which packages to install (yogurt mode).
|
||||||
|
|
||||||
The first search term is used to query the different sources and
|
|
||||||
the following search terms are used to narrow the search results
|
|
||||||
through exact matching.
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-gendb
|
.B \-\-gendb
|
||||||
Generate development package database. Tracks the latest commit for each
|
Generate development package database. Tracks the latest commit for each
|
||||||
@ -97,10 +93,6 @@ used when migrating to Yay from another AUR helper.
|
|||||||
.B \-c, \-\-clean
|
.B \-c, \-\-clean
|
||||||
Remove unneeded dependencies.
|
Remove unneeded dependencies.
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-cc
|
|
||||||
Remove unneeded dependencies, including packages optionally required by any other package.
|
|
||||||
|
|
||||||
.SH SHOW OPTIONS (APPLY TO \-P AND \-\-show)
|
.SH SHOW OPTIONS (APPLY TO \-P AND \-\-show)
|
||||||
.TP
|
.TP
|
||||||
.B \-c, \-\-complete
|
.B \-c, \-\-complete
|
||||||
@ -182,8 +174,8 @@ the AUR cache when deciding if Yay should skip builds.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-editor <command>
|
.B \-\-editor <command>
|
||||||
Editor to use when editing PKGBUILDs. If this is not set the \fBVISUAL\fR
|
Editor to use when editing PKGBUILDs. If this is not set the \fBEDITOR\fR
|
||||||
environment variable will be checked, followed by \fBEDITOR\fR. If none of
|
environment variable will be checked, followed by \fBVISUAL\fR. If none of
|
||||||
these are set Yay will prompt the user for an editor.
|
these are set Yay will prompt the user for an editor.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
@ -297,9 +289,6 @@ Unset the answer for the upgrade menu.
|
|||||||
Show the clean menu. This menu gives you the chance to fully delete the
|
Show the clean menu. This menu gives you the chance to fully delete the
|
||||||
downloaded build files from Yay's cache before redownloading a fresh copy.
|
downloaded build files from Yay's cache before redownloading a fresh copy.
|
||||||
|
|
||||||
If 'cleanmenu' is enabled in the configuration file, you can temporarily disable it by
|
|
||||||
using '--cleanmenu=false' on the command line
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-diffmenu
|
.B \-\-diffmenu
|
||||||
Show the diff menu. This menu gives you the option to view diffs from
|
Show the diff menu. This menu gives you the option to view diffs from
|
||||||
@ -318,12 +307,35 @@ before building.
|
|||||||
recommended to edit pkgbuild variables unless you know what you are doing.
|
recommended to edit pkgbuild variables unless you know what you are doing.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-askremovemake
|
.B \-\-upgrademenu
|
||||||
Ask to remove makedepends after installing packages.
|
Show a detailed list of updates in a similar format to VerbosePkgLists.
|
||||||
|
Upgrades can also be skipped using numbers, number ranges or repo names.
|
||||||
|
Additionally ^ can be used to invert the selection.
|
||||||
|
|
||||||
|
\fBWarning\fR: It is not recommended to skip updates from the repositories as
|
||||||
|
this can lead to partial upgrades. This feature is intended to easily skip AUR
|
||||||
|
updates on the fly that may be broken or have a long compile time. Ultimately
|
||||||
|
it is up to the user what upgrades they skip.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-askyesremovemake
|
.B \-\-nocleanmenu
|
||||||
Ask to remove makedepends after installing packages(with "Y" as default).
|
Do not show the clean menu.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-nodiffmenu
|
||||||
|
Do not show the diff menu.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-noeditmenu
|
||||||
|
Do not show the edit menu.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-noupgrademenu
|
||||||
|
Do not show the upgrade menu.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-askremovemake
|
||||||
|
Ask to remove makedepends after installing packages.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-removemake
|
.B \-\-removemake
|
||||||
@ -363,8 +375,9 @@ checked almost instantly and not require the original pkgbuild to be downloaded.
|
|||||||
The slower pacaur-like devel checks can be implemented manually by piping
|
The slower pacaur-like devel checks can be implemented manually by piping
|
||||||
a list of packages into yay (see \fBexamples\fR).
|
a list of packages into yay (see \fBexamples\fR).
|
||||||
|
|
||||||
If 'devel' is enabled in the configuration file, you can temporarily disable it by
|
.TP
|
||||||
using '--devel=false' on the command line
|
.B \-\-nodevel
|
||||||
|
Do not check for development packages updates during sysupgrade.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-cleanafter
|
.B \-\-cleanafter
|
||||||
@ -375,18 +388,26 @@ This allows VCS packages to easily pull an update
|
|||||||
instead of having to reclone the entire repo.
|
instead of having to reclone the entire repo.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-keepsrc
|
.B \-\-nocleanafter
|
||||||
Keep pkg/ and src/ after building packages
|
Do not remove package sources after successful Install.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-timeupdate
|
.B \-\-timeupdate
|
||||||
During sysupgrade also compare the build time of installed packages against
|
During sysupgrade also compare the build time of installed packages against
|
||||||
the last modification time of each package's AUR page.
|
the last modification time of each package's AUR page.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-notimeupdate
|
||||||
|
Do not consider build times during sysupgrade.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-separatesources
|
.B \-\-separatesources
|
||||||
Separate query results by source, AUR and sync
|
Separate query results by source, AUR and sync
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-noseparatesources
|
||||||
|
Do not separate query results by source for searching
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-redownload
|
.B \-\-redownload
|
||||||
Always download pkgbuilds of targets even when a copy is available in cache.
|
Always download pkgbuilds of targets even when a copy is available in cache.
|
||||||
@ -407,11 +428,23 @@ Look for matching providers when searching for AUR packages. When multiple
|
|||||||
providers are found a menu will appear prompting you to pick one. This
|
providers are found a menu will appear prompting you to pick one. This
|
||||||
increases dependency resolve time although this should not be noticeable.
|
increases dependency resolve time although this should not be noticeable.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-noprovides
|
||||||
|
Do not look for matching providers when searching for AUR packages.
|
||||||
|
Yay will never show its provider menu but Pacman will still show its
|
||||||
|
provider menu for repo packages.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-pgpfetch
|
.B \-\-pgpfetch
|
||||||
Prompt to import unknown PGP keys from the \fBvalidpgpkeys\fR field of each
|
Prompt to import unknown PGP keys from the \fBvalidpgpkeys\fR field of each
|
||||||
PKGBUILD.
|
PKGBUILD.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-nopgpfetch
|
||||||
|
Do not prompt to import unknown PGP keys. This is likely to cause a build
|
||||||
|
failure unless using options such as \fB\-\-skippgpcheck\fR or a customized
|
||||||
|
gpg config\%.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-useask
|
.B \-\-useask
|
||||||
Use pacman's --ask flag to automatically confirm package conflicts. Yay lists
|
Use pacman's --ask flag to automatically confirm package conflicts. Yay lists
|
||||||
@ -419,6 +452,11 @@ conflicts ahead of time. It is possible that Yay does not detect
|
|||||||
a conflict, causing a package to be removed without the user's confirmation.
|
a conflict, causing a package to be removed without the user's confirmation.
|
||||||
However, this is very unlikely.
|
However, this is very unlikely.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-nouseask
|
||||||
|
Manually resolve package conflicts during the install. Packages which do not
|
||||||
|
conflict will not need to be confined manually.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-combinedupgrade
|
.B \-\-combinedupgrade
|
||||||
During sysupgrade, Yay will first perform a refresh, then show
|
During sysupgrade, Yay will first perform a refresh, then show
|
||||||
@ -430,6 +468,12 @@ If Yay exits for any reason After the refresh without upgrading. It is then
|
|||||||
the user's responsibility to either resolve the reason Yay exited or run
|
the user's responsibility to either resolve the reason Yay exited or run
|
||||||
a sysupgrade through pacman directly.
|
a sysupgrade through pacman directly.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-nocombinedupgrade
|
||||||
|
During sysupgrade, Pacman \-Syu will be called, then the AUR upgrade will
|
||||||
|
start. This means the upgrade menu and pkgbuild review will be performed
|
||||||
|
after the sysupgrade has finished.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-batchinstall
|
.B \-\-batchinstall
|
||||||
When building and installing AUR packages instead of installing each package
|
When building and installing AUR packages instead of installing each package
|
||||||
@ -437,6 +481,10 @@ after building, queue each package for install. Then once either all packages
|
|||||||
are built or a package in the build queue is needed as a dependency to build
|
are built or a package in the build queue is needed as a dependency to build
|
||||||
another package, install all the packages in the install queue.
|
another package, install all the packages in the install queue.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-nobatchinstall
|
||||||
|
Always install AUR packages immediately after building them.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-rebuild
|
.B \-\-rebuild
|
||||||
Always build target packages even when a copy is available in cache.
|
Always build target packages even when a copy is available in cache.
|
||||||
@ -490,6 +538,10 @@ separated list that is quoted by the shell.
|
|||||||
Loop sudo calls in the background to prevent sudo from timing out during long
|
Loop sudo calls in the background to prevent sudo from timing out during long
|
||||||
builds.
|
builds.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-nosudoloop
|
||||||
|
Do not loop sudo calls in the background.
|
||||||
|
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.TP
|
.TP
|
||||||
yay \fIfoo\fR
|
yay \fIfoo\fR
|
||||||
|
53
errors.go
53
errors.go
@ -7,3 +7,56 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var ErrPackagesNotFound = errors.New(gotext.Get("could not find all required packages"))
|
var ErrPackagesNotFound = errors.New(gotext.Get("could not find all required packages"))
|
||||||
|
|
||||||
|
type NoPkgDestsFoundError struct {
|
||||||
|
dir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *NoPkgDestsFoundError) Error() string {
|
||||||
|
return gotext.Get("could not find any package archives listed in %s", e.dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetPkgReasonError struct {
|
||||||
|
exp bool // explicit
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SetPkgReasonError) Error() string {
|
||||||
|
reason := gotext.Get("explicit")
|
||||||
|
if !e.exp {
|
||||||
|
reason = gotext.Get("dependency")
|
||||||
|
}
|
||||||
|
|
||||||
|
return gotext.Get("error updating package install reason to %s", reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindPkgDestError struct {
|
||||||
|
name, pkgDest string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *FindPkgDestError) Error() string {
|
||||||
|
return gotext.Get(
|
||||||
|
"the PKGDEST for %s is listed by makepkg but does not exist: %s",
|
||||||
|
e.name, e.pkgDest)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PkgDestNotInListError struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PkgDestNotInListError) Error() string {
|
||||||
|
return gotext.Get("could not find PKGDEST for: %s", e.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FailedIgnoredPkgError struct {
|
||||||
|
pkgErrors map[string]error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *FailedIgnoredPkgError) Error() string {
|
||||||
|
msg := gotext.Get("Failed to install the following packages. Manual intervention is required:")
|
||||||
|
|
||||||
|
for pkg, err := range e.pkgErrors {
|
||||||
|
msg += "\n" + pkg + " - " + err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
26
get.go
26
get.go
@ -11,23 +11,25 @@ import (
|
|||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/download"
|
"github.com/Jguer/yay/v12/pkg/download"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
// yay -Gp.
|
// yay -Gp.
|
||||||
func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient,
|
func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient, httpClient *http.Client, targets []string,
|
||||||
httpClient *http.Client, logger *text.Logger, targets []string,
|
|
||||||
mode parser.TargetMode, aurURL string,
|
mode parser.TargetMode, aurURL string,
|
||||||
) error {
|
) error {
|
||||||
pkgbuilds, err := download.PKGBUILDs(dbExecutor, aurClient, httpClient, logger, targets, aurURL, mode)
|
pkgbuilds, err := download.PKGBUILDs(dbExecutor, aurClient, httpClient, targets, aurURL, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorln(err)
|
text.Errorln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for target, pkgbuild := range pkgbuilds {
|
if len(pkgbuilds) != 0 {
|
||||||
logger.Printf("\n\n# %s\n\n%s", target, string(pkgbuild))
|
for target, pkgbuild := range pkgbuilds {
|
||||||
|
fmt.Printf("\n\n# %s\n\n", target)
|
||||||
|
fmt.Print(string(pkgbuild))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pkgbuilds) != len(targets) {
|
if len(pkgbuilds) != len(targets) {
|
||||||
@ -39,7 +41,7 @@ func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
|
text.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
|
||||||
|
|
||||||
return fmt.Errorf("")
|
return fmt.Errorf("")
|
||||||
}
|
}
|
||||||
@ -49,7 +51,7 @@ func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient,
|
|||||||
|
|
||||||
// yay -G.
|
// yay -G.
|
||||||
func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient aur.QueryClient,
|
func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient aur.QueryClient,
|
||||||
run *runtime.Runtime, targets []string, force bool,
|
config *settings.Configuration, targets []string, force bool,
|
||||||
) error {
|
) error {
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,9 +59,9 @@ func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
cloned, errD := download.PKGBUILDRepos(ctx, dbExecutor, aurClient,
|
cloned, errD := download.PKGBUILDRepos(ctx, dbExecutor, aurClient,
|
||||||
run.CmdBuilder, run.Logger, targets, run.Cfg.Mode, run.Cfg.AURURL, wd, force)
|
config.Runtime.CmdBuilder, targets, config.Mode, config.AURURL, wd, force)
|
||||||
if errD != nil {
|
if errD != nil {
|
||||||
run.Logger.Errorln(errD)
|
text.Errorln(errD)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(targets) != len(cloned) {
|
if len(targets) != len(cloned) {
|
||||||
@ -71,7 +73,7 @@ func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
|
text.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
|
||||||
|
|
||||||
err = fmt.Errorf("")
|
err = fmt.Errorf("")
|
||||||
}
|
}
|
||||||
|
38
go.mod
38
go.mod
@ -2,34 +2,40 @@ module github.com/Jguer/yay/v12
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Jguer/aur v1.2.3
|
github.com/Jguer/aur v1.2.3
|
||||||
github.com/Jguer/go-alpm/v2 v2.2.2
|
github.com/Jguer/go-alpm/v2 v2.2.0
|
||||||
github.com/Jguer/votar v1.0.0
|
github.com/Jguer/votar v1.0.0
|
||||||
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5
|
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5
|
||||||
github.com/Morganamilo/go-srcinfo v1.0.0
|
github.com/Morganamilo/go-srcinfo v1.0.0
|
||||||
github.com/adrg/strutil v0.3.1
|
|
||||||
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible
|
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible
|
||||||
github.com/deckarep/golang-set/v2 v2.8.0
|
github.com/leonelquinteros/gotext v1.5.2
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/leonelquinteros/gotext v1.7.2
|
golang.org/x/sys v0.6.0
|
||||||
github.com/stretchr/testify v1.10.0
|
golang.org/x/term v0.6.0
|
||||||
golang.org/x/net v0.41.0
|
golang.org/x/text v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.33.0
|
|
||||||
golang.org/x/term v0.32.0
|
|
||||||
gopkg.in/h2non/gock.v1 v1.1.2
|
gopkg.in/h2non/gock.v1 v1.1.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/adrg/strutil v0.3.0
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/itchyny/gojq v0.12.17 // indirect
|
|
||||||
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
|
||||||
github.com/ohler55/ojg v1.26.1 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.23.5
|
require (
|
||||||
|
github.com/deckarep/golang-set/v2 v2.2.0
|
||||||
|
github.com/itchyny/gojq v0.12.12 // indirect
|
||||||
|
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
||||||
|
github.com/ohler55/ojg v1.17.5 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
toolchain go1.24.0
|
require github.com/hashicorp/go-multierror v1.1.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.19
|
||||||
|
74
go.sum
74
go.sum
@ -1,15 +1,15 @@
|
|||||||
github.com/Jguer/aur v1.2.3 h1:D+OGgLxnAnZnw88DsRvnRQsn0Poxsy9ng7pBcsA0krM=
|
github.com/Jguer/aur v1.2.3 h1:D+OGgLxnAnZnw88DsRvnRQsn0Poxsy9ng7pBcsA0krM=
|
||||||
github.com/Jguer/aur v1.2.3/go.mod h1:Dahvb6L1yr0rR7svyYSDwaRJoQMeyvJblwJ3QH/7CUs=
|
github.com/Jguer/aur v1.2.3/go.mod h1:Dahvb6L1yr0rR7svyYSDwaRJoQMeyvJblwJ3QH/7CUs=
|
||||||
github.com/Jguer/go-alpm/v2 v2.2.2 h1:sPwUoZp1X5Tw6K6Ba1lWvVJfcgVNEGVcxARLBttZnC0=
|
github.com/Jguer/go-alpm/v2 v2.2.0 h1:+sh4UEZwTpcAO+vHdySsnLZSnLZIBun8j85BbPExSlg=
|
||||||
github.com/Jguer/go-alpm/v2 v2.2.2/go.mod h1:lfe8gSe83F/KERaQvEfrSqQ4n+8bES+ZIyKWR/gm3MI=
|
github.com/Jguer/go-alpm/v2 v2.2.0/go.mod h1:uLQcTMNM904dRiGU+/JDtDdd7Nd8mVbEVaHjhmziT7w=
|
||||||
github.com/Jguer/votar v1.0.0 h1:drPYpV5Py5BeAQS8xezmT6uCEfLzotNjLf5yfmlHKTg=
|
github.com/Jguer/votar v1.0.0 h1:drPYpV5Py5BeAQS8xezmT6uCEfLzotNjLf5yfmlHKTg=
|
||||||
github.com/Jguer/votar v1.0.0/go.mod h1:rc6vgVlTqNjI4nAnPbDTbdxw/N7kXkbB8BcUDjeFbYQ=
|
github.com/Jguer/votar v1.0.0/go.mod h1:rc6vgVlTqNjI4nAnPbDTbdxw/N7kXkbB8BcUDjeFbYQ=
|
||||||
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 h1:TMscPjkb1ThXN32LuFY5bEYIcXZx3YlwzhS1GxNpn/c=
|
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 h1:TMscPjkb1ThXN32LuFY5bEYIcXZx3YlwzhS1GxNpn/c=
|
||||||
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5/go.mod h1:Hk55m330jNiwxRodIlMCvw5iEyoRUCIY64W1p9D+tHc=
|
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5/go.mod h1:Hk55m330jNiwxRodIlMCvw5iEyoRUCIY64W1p9D+tHc=
|
||||||
github.com/Morganamilo/go-srcinfo v1.0.0 h1:Wh4nEF+HJWo+29hnxM18Q2hi+DUf0GejS13+Wg+dzmI=
|
github.com/Morganamilo/go-srcinfo v1.0.0 h1:Wh4nEF+HJWo+29hnxM18Q2hi+DUf0GejS13+Wg+dzmI=
|
||||||
github.com/Morganamilo/go-srcinfo v1.0.0/go.mod h1:MP6VGY1NNpVUmYIEgoM9acix95KQqIRyqQ0hCLsyYUY=
|
github.com/Morganamilo/go-srcinfo v1.0.0/go.mod h1:MP6VGY1NNpVUmYIEgoM9acix95KQqIRyqQ0hCLsyYUY=
|
||||||
github.com/adrg/strutil v0.3.1 h1:OLvSS7CSJO8lBii4YmBt8jiK9QOtB9CzCzwl4Ic/Fz4=
|
github.com/adrg/strutil v0.3.0 h1:bi/HB2zQbDihC8lxvATDTDzkT4bG7PATtVnDYp5rvq4=
|
||||||
github.com/adrg/strutil v0.3.1/go.mod h1:8h90y18QLrs11IBffcGX3NW/GFBXCMcNg4M7H6MspPA=
|
github.com/adrg/strutil v0.3.0/go.mod h1:Jz0wzBVE6Uiy9wxo62YEqEY1Nwto3QlLl1Il5gkLKWU=
|
||||||
github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA=
|
github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA=
|
||||||
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||||
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible h1:UafIjBvWQmS9i/xRg+CamMrnLTKNzo+bdmT/oH34c2Y=
|
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible h1:UafIjBvWQmS9i/xRg+CamMrnLTKNzo+bdmT/oH34c2Y=
|
||||||
@ -17,8 +17,8 @@ github.com/bradleyjkemp/cupaloy v2.3.0+incompatible/go.mod h1:Au1Xw1sgaJ5iSFktEh
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/deckarep/golang-set/v2 v2.8.0 h1:swm0rlPCmdWn9mESxKOjWk8hXSqoxOp+ZlfuyaAdFlQ=
|
github.com/deckarep/golang-set/v2 v2.2.0 h1:2pMQd3Soi6qfw7E5MMKaEh5W5ES18bW3AbFFnGl6LgQ=
|
||||||
github.com/deckarep/golang-set/v2 v2.8.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
github.com/deckarep/golang-set/v2 v2.2.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
@ -26,39 +26,63 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
|
|||||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg=
|
github.com/itchyny/gojq v0.12.12 h1:x+xGI9BXqKoJQZkr95ibpe3cdrTbY8D9lonrK433rcA=
|
||||||
github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY=
|
github.com/itchyny/gojq v0.12.12/go.mod h1:j+3sVkjxwd7A7Z5jrbKibgOLn0ZfLWkV+Awxr/pyzJE=
|
||||||
github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q=
|
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||||
github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg=
|
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||||
github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=
|
github.com/leonelquinteros/gotext v1.5.2 h1:T2y6ebHli+rMBCjcJlHTXyUrgXqsKBhl/ormgvt7lPo=
|
||||||
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
|
github.com/leonelquinteros/gotext v1.5.2/go.mod h1:AT4NpQrOmyj1L/+hLja6aR0lk81yYYL4ePnj2kp7d6M=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
github.com/ohler55/ojg v1.26.1 h1:J5TaLmVEuvnpVH7JMdT1QdbpJU545Yp6cKiCO4aQILc=
|
github.com/ohler55/ojg v1.17.5 h1:SY6/cdhVzsLinNFIBRNSWhJgihvEWco5Y0TJe46XJ1Y=
|
||||||
github.com/ohler55/ojg v1.26.1/go.mod h1:gQhDVpQLqrmnd2eqGAvJtn+NfKoYJbe/A4Sj3/Vro4o=
|
github.com/ohler55/ojg v1.17.5/go.mod h1:7Ghirupn8NC8hSSDpI0gcjorPxj+vSVIONDWfliHR1k=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||||
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||||
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
|
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
|
||||||
|
907
install.go
Normal file
907
install.go
Normal file
@ -0,0 +1,907 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
alpm "github.com/Jguer/go-alpm/v2"
|
||||||
|
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||||
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/completion"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/dep"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/download"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/menus"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/pgp"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/query"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/srcinfo"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/vcs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setPkgReason(ctx context.Context,
|
||||||
|
cmdBuilder exe.ICmdBuilder,
|
||||||
|
mode parser.TargetMode,
|
||||||
|
cmdArgs *parser.Arguments, pkgs []string, exp bool,
|
||||||
|
) error {
|
||||||
|
if len(pkgs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdArgs = cmdArgs.CopyGlobal()
|
||||||
|
if exp {
|
||||||
|
if err := cmdArgs.AddArg("q", "D", "asexplicit"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cmdArgs.AddArg("q", "D", "asdeps"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, compositePkgName := range pkgs {
|
||||||
|
pkgSplit := strings.Split(compositePkgName, "/")
|
||||||
|
|
||||||
|
pkgName := pkgSplit[0]
|
||||||
|
if len(pkgSplit) > 1 {
|
||||||
|
pkgName = pkgSplit[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdArgs.AddTarget(pkgName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
cmdArgs, mode, settings.NoConfirm)); err != nil {
|
||||||
|
return &SetPkgReasonError{exp: exp}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func asdeps(ctx context.Context,
|
||||||
|
cmdBuilder exe.ICmdBuilder,
|
||||||
|
mode parser.TargetMode, cmdArgs *parser.Arguments, pkgs []string,
|
||||||
|
) error {
|
||||||
|
return setPkgReason(ctx, cmdBuilder, mode, cmdArgs, pkgs, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asexp(ctx context.Context,
|
||||||
|
cmdBuilder exe.ICmdBuilder,
|
||||||
|
mode parser.TargetMode, cmdArgs *parser.Arguments, pkgs []string,
|
||||||
|
) error {
|
||||||
|
return setPkgReason(ctx, cmdBuilder, mode, cmdArgs, pkgs, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install handles package installs.
|
||||||
|
func install(ctx context.Context, cfg *settings.Configuration,
|
||||||
|
cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders bool,
|
||||||
|
) error {
|
||||||
|
var (
|
||||||
|
do *dep.Order
|
||||||
|
srcinfos map[string]*gosrc.Srcinfo
|
||||||
|
noDeps = cmdArgs.ExistsDouble("d", "nodeps")
|
||||||
|
noCheck = strings.Contains(cfg.MFlags, "--nocheck")
|
||||||
|
assumeInstalled = cmdArgs.GetArgs("assume-installed")
|
||||||
|
sysupgradeArg = cmdArgs.ExistsArg("u", "sysupgrade")
|
||||||
|
refreshArg = cmdArgs.ExistsArg("y", "refresh")
|
||||||
|
warnings = query.NewWarnings()
|
||||||
|
)
|
||||||
|
|
||||||
|
if noDeps {
|
||||||
|
cfg.Runtime.CmdBuilder.AddMakepkgFlag("-d")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Mode.AtLeastRepo() {
|
||||||
|
if cfg.CombinedUpgrade {
|
||||||
|
if refreshArg {
|
||||||
|
if errR := earlyRefresh(ctx, cfg, cfg.Runtime.CmdBuilder, cmdArgs); errR != nil {
|
||||||
|
return fmt.Errorf("%s - %w", gotext.Get("error refreshing databases"), errR)
|
||||||
|
}
|
||||||
|
cmdArgs.DelArg("y", "refresh")
|
||||||
|
}
|
||||||
|
} else if refreshArg || sysupgradeArg || len(cmdArgs.Targets) > 0 {
|
||||||
|
if errP := earlyPacmanCall(ctx, cfg, cmdArgs, dbExecutor); errP != nil {
|
||||||
|
return errP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we may have done -Sy, our handle now has an old
|
||||||
|
// database.
|
||||||
|
if errRefresh := dbExecutor.RefreshHandle(); errRefresh != nil {
|
||||||
|
return errRefresh
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteNames := dbExecutor.InstalledRemotePackageNames()
|
||||||
|
localNames := dbExecutor.InstalledSyncPackageNames()
|
||||||
|
|
||||||
|
remoteNamesCache := mapset.NewThreadUnsafeSet(remoteNames...)
|
||||||
|
localNamesCache := stringset.FromSlice(localNames)
|
||||||
|
|
||||||
|
requestTargets := cmdArgs.Copy().Targets
|
||||||
|
|
||||||
|
// create the arguments to pass for the repo install
|
||||||
|
arguments := cmdArgs.Copy()
|
||||||
|
arguments.DelArg("asdeps", "asdep")
|
||||||
|
arguments.DelArg("asexplicit", "asexp")
|
||||||
|
arguments.Op = "S"
|
||||||
|
arguments.ClearTargets()
|
||||||
|
|
||||||
|
if cfg.Mode == parser.ModeAUR {
|
||||||
|
arguments.DelArg("u", "sysupgrade")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we are doing -u also request all packages needing update
|
||||||
|
if sysupgradeArg {
|
||||||
|
var errSysUp error
|
||||||
|
|
||||||
|
requestTargets, errSysUp = addUpgradeTargetsToArgs(ctx, cfg, dbExecutor, cmdArgs, requestTargets, arguments)
|
||||||
|
if errSysUp != nil {
|
||||||
|
return errSysUp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targets := stringset.FromSlice(cmdArgs.Targets)
|
||||||
|
|
||||||
|
dp, err := dep.GetPool(ctx, requestTargets,
|
||||||
|
warnings, dbExecutor, cfg.Runtime.AURClient, cfg.Mode,
|
||||||
|
ignoreProviders, settings.NoConfirm, cfg.Provides, cfg.ReBuild, cfg.RequestSplitN, noDeps, noCheck, assumeInstalled)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if errC := dp.CheckMissing(noDeps, noCheck); errC != nil {
|
||||||
|
return errC
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(dp.Aur) == 0 {
|
||||||
|
if !cfg.CombinedUpgrade {
|
||||||
|
if sysupgradeArg {
|
||||||
|
fmt.Println(gotext.Get(" there is nothing to do"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdArgs.Op = "S"
|
||||||
|
cmdArgs.DelArg("y", "refresh")
|
||||||
|
|
||||||
|
if arguments.ExistsArg("ignore") {
|
||||||
|
cmdArgs.CreateOrAppendOption("ignore", arguments.GetArgs("ignore")...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
cmdArgs, cfg.Mode, settings.NoConfirm))
|
||||||
|
}
|
||||||
|
|
||||||
|
conflicts, errCC := dp.CheckConflicts(cfg.UseAsk, settings.NoConfirm, noDeps)
|
||||||
|
if errCC != nil {
|
||||||
|
return errCC
|
||||||
|
}
|
||||||
|
|
||||||
|
do = dep.GetOrder(dp, noDeps, noCheck)
|
||||||
|
|
||||||
|
for _, pkg := range do.Repo {
|
||||||
|
arguments.AddTarget(pkg.DB().Name() + "/" + pkg.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Groups {
|
||||||
|
arguments.AddTarget(pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(do.Aur) == 0 && len(arguments.Targets) == 0 &&
|
||||||
|
(!cmdArgs.ExistsArg("u", "sysupgrade") || cfg.Mode == parser.ModeAUR) {
|
||||||
|
fmt.Println(gotext.Get(" there is nothing to do"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
do.Print()
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
pkgbuildDirs := make(map[string]string, len(do.Aur))
|
||||||
|
|
||||||
|
for _, base := range do.Aur {
|
||||||
|
dir := filepath.Join(cfg.BuildDir, base.Pkgbase())
|
||||||
|
pkgbuildDirs[base.Pkgbase()] = dir
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.CleanAfter {
|
||||||
|
defer func() {
|
||||||
|
cleanAfter(ctx, cfg, cfg.Runtime.CmdBuilder, pkgbuildDirs)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if do.HasMake() {
|
||||||
|
switch cfg.RemoveMake {
|
||||||
|
case "yes":
|
||||||
|
defer func() {
|
||||||
|
err = removeMake(ctx, cfg, cfg.Runtime.CmdBuilder, do.GetMake(), cmdArgs)
|
||||||
|
}()
|
||||||
|
|
||||||
|
case "no":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
if text.ContinueTask(os.Stdin, gotext.Get("Remove make dependencies after install?"), false, settings.NoConfirm) {
|
||||||
|
defer func() {
|
||||||
|
err = removeMake(ctx, cfg, cfg.Runtime.CmdBuilder, do.GetMake(), cmdArgs)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errCleanMenu := menus.Clean(os.Stdout, cfg.CleanMenu,
|
||||||
|
pkgbuildDirs,
|
||||||
|
remoteNamesCache, settings.NoConfirm, cfg.AnswerClean); errCleanMenu != nil {
|
||||||
|
if errors.As(errCleanMenu, &settings.ErrUserAbort{}) {
|
||||||
|
return errCleanMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Errorln(errCleanMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
toSkip := pkgbuildsToSkip(cfg, do.Aur, targets)
|
||||||
|
toClone := make([]string, 0, len(do.Aur))
|
||||||
|
|
||||||
|
for _, base := range do.Aur {
|
||||||
|
if !toSkip.Get(base.Pkgbase()) {
|
||||||
|
toClone = append(toClone, base.Pkgbase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if toSkipSlice := toSkip.ToSlice(); len(toSkipSlice) != 0 {
|
||||||
|
text.OperationInfoln(
|
||||||
|
gotext.Get("PKGBUILD up to date, Skipping (%d/%d): %s",
|
||||||
|
len(toSkipSlice), len(toClone), text.Cyan(strings.Join(toSkipSlice, ", "))))
|
||||||
|
}
|
||||||
|
|
||||||
|
cloned, errA := download.AURPKGBUILDRepos(ctx,
|
||||||
|
cfg.Runtime.CmdBuilder, toClone, cfg.AURURL, cfg.BuildDir, false)
|
||||||
|
if errA != nil {
|
||||||
|
return errA
|
||||||
|
}
|
||||||
|
|
||||||
|
if errDiffMenu := menus.Diff(ctx, cfg.Runtime.CmdBuilder, os.Stdout, pkgbuildDirs,
|
||||||
|
cfg.DiffMenu, remoteNamesCache,
|
||||||
|
cloned, settings.NoConfirm, cfg.AnswerDiff); errDiffMenu != nil {
|
||||||
|
if errors.As(errDiffMenu, &settings.ErrUserAbort{}) {
|
||||||
|
return errDiffMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Errorln(errDiffMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errM := mergePkgbuilds(ctx, cfg.Runtime.CmdBuilder, pkgbuildDirs); errM != nil {
|
||||||
|
return errM
|
||||||
|
}
|
||||||
|
|
||||||
|
srcinfos, err = srcinfo.ParseSrcinfoFilesByBase(pkgbuildDirs, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if errEditMenu := menus.Edit(os.Stdout, cfg.EditMenu, pkgbuildDirs,
|
||||||
|
cfg.Editor, cfg.EditorFlags, remoteNamesCache, srcinfos,
|
||||||
|
settings.NoConfirm, cfg.AnswerEdit); errEditMenu != nil {
|
||||||
|
if errors.As(errEditMenu, &settings.ErrUserAbort{}) {
|
||||||
|
return errEditMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Errorln(errEditMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errI := confirmIncompatibleInstall(srcinfos, dbExecutor); errI != nil {
|
||||||
|
return errI
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.PGPFetch {
|
||||||
|
if _, errCPK := pgp.CheckPgpKeys(ctx, pkgbuildDirs, srcinfos, cfg.Runtime.CmdBuilder, settings.NoConfirm); errCPK != nil {
|
||||||
|
return errCPK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cfg.CombinedUpgrade {
|
||||||
|
arguments.DelArg("u", "sysupgrade")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(arguments.Targets) > 0 || arguments.ExistsArg("u") {
|
||||||
|
if errShow := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
arguments, cfg.Mode, settings.NoConfirm)); errShow != nil {
|
||||||
|
return errors.New(gotext.Get("error installing repo packages"))
|
||||||
|
}
|
||||||
|
|
||||||
|
deps := make([]string, 0)
|
||||||
|
exp := make([]string, 0)
|
||||||
|
|
||||||
|
for _, pkg := range do.Repo {
|
||||||
|
if !dp.Explicit.Get(pkg.Name()) && !localNamesCache.Get(pkg.Name()) && !remoteNamesCache.Contains(pkg.Name()) {
|
||||||
|
deps = append(deps, pkg.Name())
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdArgs.ExistsArg("asdeps", "asdep") && dp.Explicit.Get(pkg.Name()) {
|
||||||
|
deps = append(deps, pkg.Name())
|
||||||
|
} else if cmdArgs.ExistsArg("asexp", "asexplicit") && dp.Explicit.Get(pkg.Name()) {
|
||||||
|
exp = append(exp, pkg.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errDeps := asdeps(ctx, cfg.Runtime.CmdBuilder, cfg.Mode, cmdArgs, deps); errDeps != nil {
|
||||||
|
return errDeps
|
||||||
|
}
|
||||||
|
|
||||||
|
if errExp := asexp(ctx, cfg.Runtime.CmdBuilder, cfg.Mode, cmdArgs, exp); errExp != nil {
|
||||||
|
return errExp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_ = completion.Update(ctx, cfg.Runtime.HTTPClient, dbExecutor,
|
||||||
|
cfg.AURURL, cfg.CompletionPath, cfg.CompletionInterval, false)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if errP := downloadPKGBUILDSourceFanout(ctx,
|
||||||
|
cfg.Runtime.CmdBuilder,
|
||||||
|
pkgbuildDirs,
|
||||||
|
true, cfg.MaxConcurrentDownloads); errP != nil {
|
||||||
|
text.Errorln(errP)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errB := buildInstallPkgbuilds(ctx, cfg, cmdArgs, dbExecutor, dp, do,
|
||||||
|
srcinfos, true, conflicts, noDeps, noCheck); errB != nil {
|
||||||
|
return errB
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addUpgradeTargetsToArgs(ctx context.Context, cfg *settings.Configuration, dbExecutor db.Executor,
|
||||||
|
cmdArgs *parser.Arguments, requestTargets []string, arguments *parser.Arguments,
|
||||||
|
) ([]string, error) {
|
||||||
|
ignore, targets, errUp := sysupgradeTargets(ctx, cfg, dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"))
|
||||||
|
if errUp != nil {
|
||||||
|
return nil, errUp
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, up := range targets {
|
||||||
|
cmdArgs.AddTarget(up)
|
||||||
|
requestTargets = append(requestTargets, up)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ignore) > 0 {
|
||||||
|
arguments.CreateOrAppendOption("ignore", ignore.ToSlice()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestTargets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeMake(ctx context.Context, config *settings.Configuration,
|
||||||
|
cmdBuilder exe.ICmdBuilder, makeDeps []string, cmdArgs *parser.Arguments,
|
||||||
|
) error {
|
||||||
|
removeArguments := cmdArgs.CopyGlobal()
|
||||||
|
|
||||||
|
err := removeArguments.AddArg("R", "s", "u")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range makeDeps {
|
||||||
|
removeArguments.AddTarget(pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
oldValue := settings.NoConfirm
|
||||||
|
settings.NoConfirm = true
|
||||||
|
err = cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
removeArguments, config.Mode, settings.NoConfirm))
|
||||||
|
settings.NoConfirm = oldValue
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func inRepos(dbExecutor db.Executor, pkg string) bool {
|
||||||
|
target := dep.ToTarget(pkg)
|
||||||
|
|
||||||
|
if target.DB == "aur" {
|
||||||
|
return false
|
||||||
|
} else if target.DB != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
previousHideMenus := settings.HideMenus
|
||||||
|
settings.HideMenus = true
|
||||||
|
exists := dbExecutor.SyncSatisfierExists(target.DepString())
|
||||||
|
settings.HideMenus = previousHideMenus
|
||||||
|
|
||||||
|
return exists || len(dbExecutor.PackagesFromGroup(target.Name)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func earlyPacmanCall(ctx context.Context, cfg *settings.Configuration,
|
||||||
|
cmdArgs *parser.Arguments, dbExecutor db.Executor,
|
||||||
|
) error {
|
||||||
|
arguments := cmdArgs.Copy()
|
||||||
|
arguments.Op = "S"
|
||||||
|
targets := cmdArgs.Targets
|
||||||
|
cmdArgs.ClearTargets()
|
||||||
|
arguments.ClearTargets()
|
||||||
|
|
||||||
|
if cfg.Mode == parser.ModeRepo {
|
||||||
|
arguments.Targets = targets
|
||||||
|
} else {
|
||||||
|
// separate aur and repo targets
|
||||||
|
for _, target := range targets {
|
||||||
|
if inRepos(dbExecutor, target) {
|
||||||
|
arguments.AddTarget(target)
|
||||||
|
} else {
|
||||||
|
cmdArgs.AddTarget(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdArgs.ExistsArg("y", "refresh") || cmdArgs.ExistsArg("u", "sysupgrade") || len(arguments.Targets) > 0 {
|
||||||
|
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
arguments, cfg.Mode, settings.NoConfirm)); err != nil {
|
||||||
|
return errors.New(gotext.Get("error installing repo packages"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func earlyRefresh(ctx context.Context, cfg *settings.Configuration, cmdBuilder exe.ICmdBuilder, cmdArgs *parser.Arguments) error {
|
||||||
|
arguments := cmdArgs.Copy()
|
||||||
|
arguments.DelArg("u", "sysupgrade")
|
||||||
|
arguments.DelArg("s", "search")
|
||||||
|
arguments.DelArg("i", "info")
|
||||||
|
arguments.DelArg("l", "list")
|
||||||
|
arguments.ClearTargets()
|
||||||
|
|
||||||
|
return cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
arguments, cfg.Mode, settings.NoConfirm))
|
||||||
|
}
|
||||||
|
|
||||||
|
func confirmIncompatibleInstall(srcinfos map[string]*gosrc.Srcinfo, dbExecutor db.Executor) error {
|
||||||
|
incompatible := []string{}
|
||||||
|
|
||||||
|
alpmArch, err := dbExecutor.AlpmArchitectures()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nextpkg:
|
||||||
|
for base, srcinfo := range srcinfos {
|
||||||
|
for _, arch := range srcinfo.Arch {
|
||||||
|
if db.ArchIsSupported(alpmArch, arch) {
|
||||||
|
continue nextpkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
incompatible = append(incompatible, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(incompatible) > 0 {
|
||||||
|
text.Warnln(gotext.Get("The following packages are not compatible with your architecture:"))
|
||||||
|
|
||||||
|
for _, pkg := range incompatible {
|
||||||
|
fmt.Print(" " + text.Cyan(pkg))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
if !text.ContinueTask(os.Stdin, gotext.Get("Try to build them anyway?"), true, settings.NoConfirm) {
|
||||||
|
return &settings.ErrUserAbort{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePackageList(ctx context.Context, cmdBuilder exe.ICmdBuilder,
|
||||||
|
dir string,
|
||||||
|
) (pkgdests map[string]string, pkgVersion string, err error) {
|
||||||
|
stdout, stderr, err := cmdBuilder.Capture(
|
||||||
|
cmdBuilder.BuildMakepkgCmd(ctx, dir, "--packagelist"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("%s %w", stderr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(stdout, "\n")
|
||||||
|
pkgdests = make(map[string]string)
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := filepath.Base(line)
|
||||||
|
split := strings.Split(fileName, "-")
|
||||||
|
|
||||||
|
if len(split) < 4 {
|
||||||
|
return nil, "", errors.New(gotext.Get("cannot find package name: %v", split))
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkgname-pkgver-pkgrel-arch.pkgext
|
||||||
|
// This assumes 3 dashes after the pkgname, Will cause an error
|
||||||
|
// if the PKGEXT contains a dash. Please no one do that.
|
||||||
|
pkgName := strings.Join(split[:len(split)-3], "-")
|
||||||
|
pkgVersion = strings.Join(split[len(split)-3:len(split)-1], "-")
|
||||||
|
pkgdests[pkgName] = line
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pkgdests) == 0 {
|
||||||
|
return nil, "", &NoPkgDestsFoundError{dir}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkgdests, pkgVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pkgbuildsToSkip(cfg *settings.Configuration, bases []dep.Base, targets stringset.StringSet) stringset.StringSet {
|
||||||
|
toSkip := make(stringset.StringSet)
|
||||||
|
|
||||||
|
for _, base := range bases {
|
||||||
|
isTarget := false
|
||||||
|
for _, pkg := range base {
|
||||||
|
isTarget = isTarget || targets.Get(pkg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg.ReDownload == "yes" && isTarget) || cfg.ReDownload == "all" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := filepath.Join(cfg.BuildDir, base.Pkgbase(), ".SRCINFO")
|
||||||
|
pkgbuild, err := gosrc.ParseFile(dir)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
if db.VerCmp(pkgbuild.Version(), base.Version()) >= 0 {
|
||||||
|
toSkip.Set(base.Pkgbase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toSkip
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitMerge(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {
|
||||||
|
_, stderr, err := cmdBuilder.Capture(
|
||||||
|
cmdBuilder.BuildGitCmd(ctx,
|
||||||
|
dir, "reset", "--hard", "HEAD"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(gotext.Get("error resetting %s: %s", dir, stderr))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, stderr, err = cmdBuilder.Capture(
|
||||||
|
cmdBuilder.BuildGitCmd(ctx,
|
||||||
|
dir, "merge", "--no-edit", "--ff"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(gotext.Get("error merging %s: %s", dir, stderr))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergePkgbuilds(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string) error {
|
||||||
|
for _, dir := range pkgbuildDirs {
|
||||||
|
err := gitMerge(ctx, cmdBuilder, dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildInstallPkgbuilds(
|
||||||
|
ctx context.Context,
|
||||||
|
cfg *settings.Configuration,
|
||||||
|
cmdArgs *parser.Arguments,
|
||||||
|
dbExecutor db.Executor,
|
||||||
|
dp *dep.Pool,
|
||||||
|
do *dep.Order,
|
||||||
|
srcinfos map[string]*gosrc.Srcinfo,
|
||||||
|
incompatible bool,
|
||||||
|
conflicts stringset.MapStringSet, noDeps, noCheck bool,
|
||||||
|
) error {
|
||||||
|
deps := make([]string, 0)
|
||||||
|
exp := make([]string, 0)
|
||||||
|
pkgArchives := make([]string, 0)
|
||||||
|
oldConfirm := settings.NoConfirm
|
||||||
|
settings.NoConfirm = true
|
||||||
|
|
||||||
|
// remotenames: names of all non repo packages on the system
|
||||||
|
remoteNames := dbExecutor.InstalledRemotePackageNames()
|
||||||
|
localNames := dbExecutor.InstalledSyncPackageNames()
|
||||||
|
|
||||||
|
// cache as a stringset. maybe make it return a string set in the first
|
||||||
|
// place
|
||||||
|
remoteNamesCache := stringset.FromSlice(remoteNames)
|
||||||
|
localNamesCache := stringset.FromSlice(localNames)
|
||||||
|
|
||||||
|
for i, base := range do.Aur {
|
||||||
|
pkg := base.Pkgbase()
|
||||||
|
dir := filepath.Join(cfg.BuildDir, pkg)
|
||||||
|
built := true
|
||||||
|
|
||||||
|
satisfied := true
|
||||||
|
all:
|
||||||
|
for _, pkg := range base {
|
||||||
|
for _, dep := range dep.ComputeCombinedDepList(pkg, noDeps, noCheck) {
|
||||||
|
if !dp.AlpmExecutor.LocalSatisfierExists(dep) {
|
||||||
|
satisfied = false
|
||||||
|
text.Warnln(gotext.Get("%s not satisfied, flushing install queue", dep))
|
||||||
|
|
||||||
|
break all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !satisfied || !cfg.BatchInstall {
|
||||||
|
text.Debugln("non batch installing archives:", pkgArchives)
|
||||||
|
errArchive := installPkgArchive(ctx, cfg.Runtime.CmdBuilder,
|
||||||
|
cfg.Mode, cfg.Runtime.VCSStore, cmdArgs, pkgArchives)
|
||||||
|
errReason := setInstallReason(ctx, cfg.Runtime.CmdBuilder, cfg.Mode, cmdArgs, deps, exp)
|
||||||
|
|
||||||
|
deps = make([]string, 0)
|
||||||
|
exp = make([]string, 0)
|
||||||
|
pkgArchives = make([]string, 0) // reset the pkgarchives
|
||||||
|
|
||||||
|
if errArchive != nil || errReason != nil {
|
||||||
|
if i != 0 {
|
||||||
|
go cfg.Runtime.VCSStore.RemovePackages([]string{do.Aur[i-1].String()})
|
||||||
|
}
|
||||||
|
|
||||||
|
if errArchive != nil {
|
||||||
|
return errArchive
|
||||||
|
}
|
||||||
|
|
||||||
|
return errReason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srcInfo := srcinfos[pkg]
|
||||||
|
|
||||||
|
args := []string{"--nobuild", "-fC"}
|
||||||
|
|
||||||
|
if incompatible {
|
||||||
|
args = append(args, "--ignorearch")
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkgver bump
|
||||||
|
if err := cfg.Runtime.CmdBuilder.Show(
|
||||||
|
cfg.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, dir, args...)); err != nil {
|
||||||
|
return errors.New(gotext.Get("error making: %s", base.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgdests, pkgVersion, errList := parsePackageList(ctx, cfg.Runtime.CmdBuilder, dir)
|
||||||
|
if errList != nil {
|
||||||
|
return errList
|
||||||
|
}
|
||||||
|
|
||||||
|
isExplicit := false
|
||||||
|
for _, b := range base {
|
||||||
|
isExplicit = isExplicit || dp.Explicit.Get(b.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.ReBuild == "no" || (cfg.ReBuild == "yes" && !isExplicit) {
|
||||||
|
for _, split := range base {
|
||||||
|
pkgdest, ok := pkgdests[split.Name]
|
||||||
|
if !ok {
|
||||||
|
return &PkgDestNotInListError{split.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, errStat := os.Stat(pkgdest); os.IsNotExist(errStat) {
|
||||||
|
built = false
|
||||||
|
} else if errStat != nil {
|
||||||
|
return errStat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
built = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdArgs.ExistsArg("needed") {
|
||||||
|
installed := true
|
||||||
|
for _, split := range base {
|
||||||
|
installed = dp.AlpmExecutor.IsCorrectVersionInstalled(split.Name, pkgVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if installed {
|
||||||
|
err := cfg.Runtime.CmdBuilder.Show(
|
||||||
|
cfg.Runtime.CmdBuilder.BuildMakepkgCmd(ctx,
|
||||||
|
dir, "-c", "--nobuild", "--noextract", "--ignorearch"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(gotext.Get("error making: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, gotext.Get("%s is up to date -- skipping", text.Cyan(pkg+"-"+pkgVersion)))
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if built {
|
||||||
|
err := cfg.Runtime.CmdBuilder.Show(
|
||||||
|
cfg.Runtime.CmdBuilder.BuildMakepkgCmd(ctx,
|
||||||
|
dir, "-c", "--nobuild", "--noextract", "--ignorearch"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(gotext.Get("error making: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Warnln(gotext.Get("%s already made -- skipping build", text.Cyan(pkg+"-"+pkgVersion)))
|
||||||
|
} else {
|
||||||
|
args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
|
||||||
|
|
||||||
|
if incompatible {
|
||||||
|
args = append(args, "--ignorearch")
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMake := cfg.Runtime.CmdBuilder.Show(
|
||||||
|
cfg.Runtime.CmdBuilder.BuildMakepkgCmd(ctx,
|
||||||
|
dir, args...)); errMake != nil {
|
||||||
|
return errors.New(gotext.Get("error making: %s", base.String()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// conflicts have been checked so answer y for them
|
||||||
|
if cfg.UseAsk && cmdArgs.ExistsArg("ask") {
|
||||||
|
ask, _ := strconv.Atoi(cmdArgs.Options["ask"].First())
|
||||||
|
uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg
|
||||||
|
cmdArgs.Options["ask"].Set(fmt.Sprint(uask))
|
||||||
|
} else {
|
||||||
|
for _, split := range base {
|
||||||
|
if _, ok := conflicts[split.Name]; ok {
|
||||||
|
settings.NoConfirm = false
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errAdd error
|
||||||
|
|
||||||
|
for _, split := range base {
|
||||||
|
for suffix, optional := range map[string]bool{"": false, "-debug": true} {
|
||||||
|
deps, exp, pkgArchives, errAdd = doAddTarget(dp, localNamesCache, remoteNamesCache,
|
||||||
|
cmdArgs, pkgdests, deps, exp, split.Name+suffix, optional, pkgArchives)
|
||||||
|
if errAdd != nil {
|
||||||
|
return errAdd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text.Debugln("deps:", deps, "exp:", exp, "pkgArchives:", pkgArchives)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for _, pkg := range base {
|
||||||
|
if srcInfo == nil {
|
||||||
|
text.Errorln(gotext.Get("could not find srcinfo for: %s", pkg.Name))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
text.Debugln("checking vcs store for:", pkg.Name)
|
||||||
|
go func(name string) {
|
||||||
|
cfg.Runtime.VCSStore.Update(ctx, name, srcInfo.Source)
|
||||||
|
wg.Done()
|
||||||
|
}(pkg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Debugln("installing archives:", pkgArchives)
|
||||||
|
errArchive := installPkgArchive(ctx, cfg.Runtime.CmdBuilder, cfg.Mode, cfg.Runtime.VCSStore, cmdArgs, pkgArchives)
|
||||||
|
if errArchive != nil {
|
||||||
|
go cfg.Runtime.VCSStore.RemovePackages([]string{do.Aur[len(do.Aur)-1].String()})
|
||||||
|
}
|
||||||
|
|
||||||
|
errReason := setInstallReason(ctx, cfg.Runtime.CmdBuilder, cfg.Mode, cmdArgs, deps, exp)
|
||||||
|
if errReason != nil {
|
||||||
|
go cfg.Runtime.VCSStore.RemovePackages([]string{do.Aur[len(do.Aur)-1].String()})
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.NoConfirm = oldConfirm
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func installPkgArchive(ctx context.Context,
|
||||||
|
cmdBuilder exe.ICmdBuilder,
|
||||||
|
mode parser.TargetMode,
|
||||||
|
vcsStore vcs.Store,
|
||||||
|
cmdArgs *parser.Arguments,
|
||||||
|
pkgArchives []string,
|
||||||
|
) error {
|
||||||
|
if len(pkgArchives) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments := cmdArgs.Copy()
|
||||||
|
arguments.ClearTargets()
|
||||||
|
arguments.Op = "U"
|
||||||
|
arguments.DelArg("confirm")
|
||||||
|
arguments.DelArg("noconfirm")
|
||||||
|
arguments.DelArg("c", "clean")
|
||||||
|
arguments.DelArg("i", "install")
|
||||||
|
arguments.DelArg("q", "quiet")
|
||||||
|
arguments.DelArg("y", "refresh")
|
||||||
|
arguments.DelArg("u", "sysupgrade")
|
||||||
|
arguments.DelArg("w", "downloadonly")
|
||||||
|
arguments.DelArg("asdeps", "asdep")
|
||||||
|
arguments.DelArg("asexplicit", "asexp")
|
||||||
|
|
||||||
|
arguments.AddTarget(pkgArchives...)
|
||||||
|
|
||||||
|
if errShow := cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,
|
||||||
|
arguments, mode, settings.NoConfirm)); errShow != nil {
|
||||||
|
return errShow
|
||||||
|
}
|
||||||
|
|
||||||
|
if errStore := vcsStore.Save(); errStore != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, errStore)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInstallReason(ctx context.Context,
|
||||||
|
cmdBuilder exe.ICmdBuilder, mode parser.TargetMode,
|
||||||
|
cmdArgs *parser.Arguments, deps, exps []string,
|
||||||
|
) error {
|
||||||
|
if len(deps)+len(exps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if errDeps := asdeps(ctx, cmdBuilder, mode, cmdArgs, deps); errDeps != nil {
|
||||||
|
return errDeps
|
||||||
|
}
|
||||||
|
|
||||||
|
return asexp(ctx, cmdBuilder, mode, cmdArgs, exps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doAddTarget(dp *dep.Pool, localNamesCache, remoteNamesCache stringset.StringSet,
|
||||||
|
cmdArgs *parser.Arguments, pkgdests map[string]string,
|
||||||
|
deps, exp []string, name string, optional bool, pkgArchives []string,
|
||||||
|
) (newDeps, newExp, newPkgArchives []string, err error) {
|
||||||
|
pkgdest, ok := pkgdests[name]
|
||||||
|
if !ok {
|
||||||
|
if optional {
|
||||||
|
return deps, exp, pkgArchives, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return deps, exp, pkgArchives, &PkgDestNotInListError{name}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, errStat := os.Stat(pkgdest); os.IsNotExist(errStat) {
|
||||||
|
if optional {
|
||||||
|
return deps, exp, pkgArchives, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return deps, exp, pkgArchives, &FindPkgDestError{pkgDest: pkgdest, name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgArchives = append(pkgArchives, pkgdest)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case cmdArgs.ExistsArg("asdeps", "asdep"):
|
||||||
|
deps = append(deps, name)
|
||||||
|
case cmdArgs.ExistsArg("asexplicit", "asexp"):
|
||||||
|
exp = append(exp, name)
|
||||||
|
case !dp.Explicit.Get(name) && !localNamesCache.Get(name) && !remoteNamesCache.Get(name):
|
||||||
|
deps = append(deps, name)
|
||||||
|
default:
|
||||||
|
exp = append(exp, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return deps, exp, pkgArchives, nil
|
||||||
|
}
|
@ -4,7 +4,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -13,17 +12,20 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
"github.com/Jguer/yay/v12/pkg/dep"
|
"github.com/Jguer/yay/v12/pkg/dep"
|
||||||
"github.com/Jguer/yay/v12/pkg/multierror"
|
"github.com/Jguer/yay/v12/pkg/multierror"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/sync"
|
"github.com/Jguer/yay/v12/pkg/topo"
|
||||||
|
|
||||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNoBuildFiles = errors.New(gotext.Get("cannot find PKGBUILD and .SRCINFO in directory"))
|
var (
|
||||||
|
ErrInstallRepoPkgs = errors.New(gotext.Get("error installing repo packages"))
|
||||||
|
ErrNoBuildFiles = errors.New(gotext.Get("cannot find PKGBUILD and .SRCINFO in directory"))
|
||||||
|
)
|
||||||
|
|
||||||
func srcinfoExists(ctx context.Context,
|
func srcinfoExists(ctx context.Context,
|
||||||
cmdBuilder exe.ICmdBuilder, targetDir string,
|
cmdBuilder exe.ICmdBuilder, targetDir string,
|
||||||
@ -43,10 +45,6 @@ func srcinfoExists(ctx context.Context,
|
|||||||
return fmt.Errorf("unable to generate .SRCINFO: %w - %s", err, stderr)
|
return fmt.Errorf("unable to generate .SRCINFO: %w - %s", err, stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if srcinfo == "" {
|
|
||||||
return fmt.Errorf("generated .SRCINFO is empty, check your PKGBUILD for errors")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.WriteFile(srcInfoDir, []byte(srcinfo), 0o600); err != nil {
|
if err := os.WriteFile(srcInfoDir, []byte(srcinfo), 0o600); err != nil {
|
||||||
return fmt.Errorf("unable to write .SRCINFO: %w", err)
|
return fmt.Errorf("unable to write .SRCINFO: %w", err)
|
||||||
}
|
}
|
||||||
@ -59,40 +57,39 @@ func srcinfoExists(ctx context.Context,
|
|||||||
|
|
||||||
func installLocalPKGBUILD(
|
func installLocalPKGBUILD(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
run *runtime.Runtime,
|
config *settings.Configuration,
|
||||||
cmdArgs *parser.Arguments,
|
cmdArgs *parser.Arguments,
|
||||||
dbExecutor db.Executor,
|
dbExecutor db.Executor,
|
||||||
) error {
|
) error {
|
||||||
aurCache := run.AURClient
|
aurCache := config.Runtime.AURCache
|
||||||
noCheck := strings.Contains(run.Cfg.MFlags, "--nocheck")
|
noCheck := strings.Contains(config.MFlags, "--nocheck")
|
||||||
|
|
||||||
if len(cmdArgs.Targets) < 1 {
|
if len(cmdArgs.Targets) < 1 {
|
||||||
return errors.New(gotext.Get("no target directories specified"))
|
return errors.New(gotext.Get("no target directories specified"))
|
||||||
}
|
}
|
||||||
|
|
||||||
srcInfos := map[string]*gosrc.Srcinfo{}
|
grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm,
|
||||||
|
cmdArgs.ExistsDouble("d", "nodeps"), noCheck, cmdArgs.ExistsArg("needed"),
|
||||||
|
config.Runtime.Logger.Child("grapher"))
|
||||||
|
graph := topo.New[string, *dep.InstallInfo]()
|
||||||
for _, targetDir := range cmdArgs.Targets {
|
for _, targetDir := range cmdArgs.Targets {
|
||||||
if err := srcinfoExists(ctx, run.CmdBuilder, targetDir); err != nil {
|
if err := srcinfoExists(ctx, config.Runtime.CmdBuilder, targetDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgbuild, err := gosrc.ParseFile(filepath.Join(targetDir, ".SRCINFO"))
|
pkgbuild, err := gosrc.ParseFile(filepath.Join(targetDir, ".SRCINFO"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %w", gotext.Get("failed to parse .SRCINFO"), err)
|
return errors.Wrap(err, gotext.Get("failed to parse .SRCINFO"))
|
||||||
}
|
}
|
||||||
|
|
||||||
srcInfos[targetDir] = pkgbuild
|
var errG error
|
||||||
|
graph, errG = grapher.GraphFromSrcInfo(ctx, graph, targetDir, pkgbuild)
|
||||||
|
if errG != nil {
|
||||||
|
return errG
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm,
|
opService := NewOperationService(ctx, config, dbExecutor)
|
||||||
cmdArgs.ExistsDouble("d", "nodeps"), noCheck, cmdArgs.ExistsArg("needed"),
|
|
||||||
run.Logger.Child("grapher"))
|
|
||||||
graph, err := grapher.GraphFromSrcInfos(ctx, nil, srcInfos)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
opService := sync.NewOperationService(ctx, dbExecutor, run)
|
|
||||||
multiErr := &multierror.MultiError{}
|
multiErr := &multierror.MultiError{}
|
||||||
targets := graph.TopoSortedLayerMap(func(name string, ii *dep.InstallInfo) error {
|
targets := graph.TopoSortedLayerMap(func(name string, ii *dep.InstallInfo) error {
|
||||||
if ii.Source == dep.Missing {
|
if ii.Source == dep.Missing {
|
||||||
@ -104,5 +101,5 @@ func installLocalPKGBUILD(
|
|||||||
if err := multiErr.Return(); err != nil {
|
if err := multiErr.Return(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return opService.Run(ctx, run, cmdArgs, targets, []string{})
|
return opService.Run(ctx, cmdArgs, targets, []string{})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -20,7 +17,6 @@ import (
|
|||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db/mock"
|
"github.com/Jguer/yay/v12/pkg/db/mock"
|
||||||
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
@ -28,10 +24,6 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/vcs"
|
"github.com/Jguer/yay/v12/pkg/vcs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestLogger() *text.Logger {
|
|
||||||
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegrationLocalInstall(t *testing.T) {
|
func TestIntegrationLocalInstall(t *testing.T) {
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
makepkgBin := t.TempDir() + "/makepkg"
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
pacmanBin := t.TempDir() + "/pacman"
|
||||||
@ -56,17 +48,17 @@ func TestIntegrationLocalInstall(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wantShow := []string{
|
wantShow := []string{
|
||||||
"makepkg --verifysource --skippgpcheck -f -Cc",
|
"makepkg --verifysource -Ccf",
|
||||||
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
|
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
||||||
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin jellyfin-web",
|
||||||
}
|
}
|
||||||
|
|
||||||
wantCapture := []string{
|
wantCapture := []string{
|
||||||
@ -74,6 +66,7 @@ func TestIntegrationLocalInstall(t *testing.T) {
|
|||||||
"git -C testdata/jfin git reset --hard HEAD",
|
"git -C testdata/jfin git reset --hard HEAD",
|
||||||
"git -C testdata/jfin git merge --no-edit --ff",
|
"git -C testdata/jfin git merge --no-edit --ff",
|
||||||
"makepkg --packagelist",
|
"makepkg --packagelist",
|
||||||
|
"makepkg --packagelist",
|
||||||
}
|
}
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||||
@ -142,25 +135,23 @@ func TestIntegrationLocalInstall(t *testing.T) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
LocalPackageFn: func(s string) mock.IPackage { return nil },
|
|
||||||
InstalledRemotePackageNamesFn: func() []string { return []string{} },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run := &runtime.Runtime{
|
config := &settings.Configuration{
|
||||||
Cfg: &settings.Configuration{
|
RemoveMake: "no",
|
||||||
RemoveMake: "no",
|
Runtime: &settings.Runtime{
|
||||||
},
|
Logger: text.NewLogger(io.Discard, strings.NewReader(""), true, "test"),
|
||||||
Logger: newTestLogger(),
|
CmdBuilder: cmdBuilder,
|
||||||
CmdBuilder: cmdBuilder,
|
VCSStore: &vcs.Mock{},
|
||||||
VCSStore: &vcs.Mock{},
|
AURCache: &mockaur.MockAUR{
|
||||||
AURClient: &mockaur.MockAUR{
|
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
return []aur.Pkg{}, nil
|
||||||
return []aur.Pkg{}, nil
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handleCmd(context.Background(), run, cmdArgs, db)
|
err = handleCmd(context.Background(), config, cmdArgs, db)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
||||||
@ -264,22 +255,22 @@ func TestIntegrationLocalInstallMissingDep(t *testing.T) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
LocalPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run := &runtime.Runtime{
|
config := &settings.Configuration{
|
||||||
Cfg: &settings.Configuration{},
|
Runtime: &settings.Runtime{
|
||||||
Logger: newTestLogger(),
|
Logger: text.NewLogger(io.Discard, strings.NewReader(""), true, "test"),
|
||||||
CmdBuilder: cmdBuilder,
|
CmdBuilder: cmdBuilder,
|
||||||
VCSStore: &vcs.Mock{},
|
VCSStore: &vcs.Mock{},
|
||||||
AURClient: &mockaur.MockAUR{
|
AURCache: &mockaur.MockAUR{
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
||||||
return []aur.Pkg{}, nil
|
return []aur.Pkg{}, nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handleCmd(context.Background(), run, cmdArgs, db)
|
err = handleCmd(context.Background(), config, cmdArgs, db)
|
||||||
require.ErrorContains(t, err, wantErr.Error())
|
require.ErrorContains(t, err, wantErr.Error())
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
||||||
@ -321,12 +312,14 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wantShow := []string{
|
wantShow := []string{
|
||||||
"makepkg --verifysource --skippgpcheck -f -Cc",
|
"makepkg --verifysource -Ccf",
|
||||||
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +328,7 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
|
|||||||
"git -C testdata/jfin git reset --hard HEAD",
|
"git -C testdata/jfin git reset --hard HEAD",
|
||||||
"git -C testdata/jfin git merge --no-edit --ff",
|
"git -C testdata/jfin git merge --no-edit --ff",
|
||||||
"makepkg --packagelist",
|
"makepkg --packagelist",
|
||||||
|
"makepkg --packagelist",
|
||||||
}
|
}
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||||
@ -418,24 +412,23 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
InstalledRemotePackageNamesFn: func() []string { return []string{} },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run := &runtime.Runtime{
|
config := &settings.Configuration{
|
||||||
Cfg: &settings.Configuration{
|
RemoveMake: "no",
|
||||||
RemoveMake: "no",
|
Runtime: &settings.Runtime{
|
||||||
},
|
Logger: text.NewLogger(io.Discard, strings.NewReader(""), true, "test"),
|
||||||
Logger: newTestLogger(),
|
CmdBuilder: cmdBuilder,
|
||||||
CmdBuilder: cmdBuilder,
|
VCSStore: &vcs.Mock{},
|
||||||
VCSStore: &vcs.Mock{},
|
AURCache: &mockaur.MockAUR{
|
||||||
AURClient: &mockaur.MockAUR{
|
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
return []aur.Pkg{}, nil
|
||||||
return []aur.Pkg{}, nil
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handleCmd(context.Background(), run, cmdArgs, db)
|
err = handleCmd(context.Background(), config, cmdArgs, db)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow), "show calls: %v", mockRunner.ShowCalls)
|
require.Len(t, mockRunner.ShowCalls, len(wantShow), "show calls: %v", mockRunner.ShowCalls)
|
||||||
@ -486,17 +479,17 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wantShow := []string{
|
wantShow := []string{
|
||||||
"makepkg --verifysource --skippgpcheck -f -Cc",
|
"makepkg --verifysource -Ccf",
|
||||||
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
||||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
|
"makepkg --nobuild -fC --ignorearch",
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin",
|
"makepkg -c --nobuild --noextract --ignorearch",
|
||||||
|
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
||||||
|
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin jellyfin-web",
|
||||||
}
|
}
|
||||||
|
|
||||||
wantCapture := []string{
|
wantCapture := []string{
|
||||||
@ -505,6 +498,7 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
|
|||||||
"git -C testdata/jfin git reset --hard HEAD",
|
"git -C testdata/jfin git reset --hard HEAD",
|
||||||
"git -C testdata/jfin git merge --no-edit --ff",
|
"git -C testdata/jfin git merge --no-edit --ff",
|
||||||
"makepkg --packagelist",
|
"makepkg --packagelist",
|
||||||
|
"makepkg --packagelist",
|
||||||
}
|
}
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||||
@ -558,7 +552,6 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
LocalPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
SyncSatisfierFn: func(s string) mock.IPackage {
|
||||||
switch s {
|
switch s {
|
||||||
case "dotnet-runtime>=6", "dotnet-runtime<7":
|
case "dotnet-runtime>=6", "dotnet-runtime<7":
|
||||||
@ -579,25 +572,24 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
InstalledRemotePackageNamesFn: func() []string { return []string{} },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run := &runtime.Runtime{
|
config := &settings.Configuration{
|
||||||
Cfg: &settings.Configuration{
|
RemoveMake: "no",
|
||||||
RemoveMake: "no",
|
Debug: false,
|
||||||
Debug: false,
|
Runtime: &settings.Runtime{
|
||||||
},
|
Logger: text.NewLogger(io.Discard, strings.NewReader(""), true, "test"),
|
||||||
Logger: newTestLogger(),
|
CmdBuilder: cmdBuilder,
|
||||||
CmdBuilder: cmdBuilder,
|
VCSStore: &vcs.Mock{},
|
||||||
VCSStore: &vcs.Mock{},
|
AURCache: &mockaur.MockAUR{
|
||||||
AURClient: &mockaur.MockAUR{
|
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
return []aur.Pkg{}, nil
|
||||||
return []aur.Pkg{}, nil
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handleCmd(context.Background(), run, cmdArgs, db)
|
err = handleCmd(context.Background(), config, cmdArgs, db)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
||||||
@ -648,6 +640,7 @@ func TestIntegrationLocalInstallMissingFiles(t *testing.T) {
|
|||||||
wantCapture := []string{}
|
wantCapture := []string{}
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||||
|
fmt.Println(cmd.Args)
|
||||||
if cmd.Args[1] == "--printsrcinfo" {
|
if cmd.Args[1] == "--printsrcinfo" {
|
||||||
return string(srcinfo), "", nil
|
return string(srcinfo), "", nil
|
||||||
}
|
}
|
||||||
@ -718,17 +711,16 @@ func TestIntegrationLocalInstallMissingFiles(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &runtime.Runtime{
|
config := &settings.Configuration{
|
||||||
Cfg: &settings.Configuration{
|
RemoveMake: "no",
|
||||||
RemoveMake: "no",
|
Runtime: &settings.Runtime{
|
||||||
Debug: false,
|
Logger: text.NewLogger(io.Discard, strings.NewReader(""), true, "test"),
|
||||||
},
|
CmdBuilder: cmdBuilder,
|
||||||
Logger: newTestLogger(),
|
VCSStore: &vcs.Mock{},
|
||||||
CmdBuilder: cmdBuilder,
|
AURCache: &mockaur.MockAUR{
|
||||||
VCSStore: &vcs.Mock{},
|
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
||||||
AURClient: &mockaur.MockAUR{
|
return []aur.Pkg{}, nil
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
},
|
||||||
return []aur.Pkg{}, nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -750,270 +742,3 @@ func TestIntegrationLocalInstallMissingFiles(t *testing.T) {
|
|||||||
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntegrationLocalInstallWithDepsProvides(t *testing.T) {
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
gitBin := t.TempDir() + "/git"
|
|
||||||
tmpDir := t.TempDir()
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
tars := []string{
|
|
||||||
tmpDir + "/ceph-bin-17.2.6-2-x86_64.pkg.tar.zst",
|
|
||||||
tmpDir + "/ceph-libs-bin-17.2.6-2-x86_64.pkg.tar.zst",
|
|
||||||
}
|
|
||||||
|
|
||||||
wantShow := []string{
|
|
||||||
"makepkg --verifysource --skippgpcheck -f -Cc",
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/ceph-libs-bin-17.2.6-2-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- ceph-libs-bin",
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir/ceph-bin-17.2.6-2-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- ceph-bin",
|
|
||||||
}
|
|
||||||
|
|
||||||
wantCapture := []string{
|
|
||||||
"git -C testdata/cephbin git reset --hard HEAD",
|
|
||||||
"git -C testdata/cephbin git merge --no-edit --ff",
|
|
||||||
"makepkg --packagelist",
|
|
||||||
"makepkg --packagelist",
|
|
||||||
}
|
|
||||||
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
|
||||||
return strings.Join(tars, "\n"), "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
once := sync.Once{}
|
|
||||||
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
|
||||||
once.Do(func() {
|
|
||||||
for _, tar := range tars {
|
|
||||||
f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
PacmanConfigPath: "/etc/pacman.conf",
|
|
||||||
GitBin: "git",
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddArg("B")
|
|
||||||
cmdArgs.AddArg("i")
|
|
||||||
cmdArgs.AddTarget("testdata/cephbin")
|
|
||||||
settings.NoConfirm = true
|
|
||||||
defer func() { settings.NoConfirm = false }()
|
|
||||||
db := &mock.DBExecutor{
|
|
||||||
AlpmArchitecturesFn: func() ([]string, error) {
|
|
||||||
return []string{"x86_64"}, nil
|
|
||||||
},
|
|
||||||
LocalSatisfierExistsFn: func(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "ceph=17.2.6-2", "ceph-libs=17.2.6-2":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(s string) mock.IPackage { return nil },
|
|
||||||
InstalledRemotePackageNamesFn: func() []string { return []string{} },
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &runtime.Runtime{
|
|
||||||
Cfg: &settings.Configuration{
|
|
||||||
RemoveMake: "no",
|
|
||||||
},
|
|
||||||
Logger: newTestLogger(),
|
|
||||||
CmdBuilder: cmdBuilder,
|
|
||||||
VCSStore: &vcs.Mock{},
|
|
||||||
AURClient: &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = handleCmd(context.Background(), config, cmdArgs, db)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
|
||||||
require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
|
|
||||||
|
|
||||||
for i, call := range mockRunner.ShowCalls {
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
show = strings.ReplaceAll(show, gitBin, "pacman")
|
|
||||||
|
|
||||||
// options are in a different order on different systems and on CI root user is used
|
|
||||||
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegrationLocalInstallTwoSrcInfosWithDeps(t *testing.T) {
|
|
||||||
makepkgBin := t.TempDir() + "/makepkg"
|
|
||||||
pacmanBin := t.TempDir() + "/pacman"
|
|
||||||
gitBin := t.TempDir() + "/git"
|
|
||||||
tmpDir1 := t.TempDir()
|
|
||||||
tmpDir2 := t.TempDir()
|
|
||||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
|
|
||||||
pkgsTars := []string{
|
|
||||||
tmpDir1 + "/libzip-git-1.9.2.r166.gd2c47d0f-1-x86_64.pkg.tar.zst",
|
|
||||||
tmpDir2 + "/gourou-0.8.1-4-x86_64.pkg.tar.zst",
|
|
||||||
}
|
|
||||||
|
|
||||||
wantShow := []string{
|
|
||||||
"makepkg --verifysource --skippgpcheck -f -Cc",
|
|
||||||
"makepkg --verifysource --skippgpcheck -f -Cc",
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir1/libzip-git-1.9.2.r166.gd2c47d0f-1-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- libzip-git",
|
|
||||||
"makepkg --nobuild -f -C --ignorearch",
|
|
||||||
"makepkg -c --nobuild --noextract --ignorearch",
|
|
||||||
"pacman -U --config /etc/pacman.conf -- /testdir2/gourou-0.8.1-4-x86_64.pkg.tar.zst",
|
|
||||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- gourou",
|
|
||||||
}
|
|
||||||
|
|
||||||
wantCapture := []string{
|
|
||||||
"git -C testdata/gourou git reset --hard HEAD",
|
|
||||||
"git -C testdata/gourou git merge --no-edit --ff",
|
|
||||||
"git -C testdata/libzip-git git reset --hard HEAD",
|
|
||||||
"git -C testdata/libzip-git git merge --no-edit --ff",
|
|
||||||
"makepkg --packagelist",
|
|
||||||
"makepkg --packagelist",
|
|
||||||
}
|
|
||||||
|
|
||||||
captureCounter := 0
|
|
||||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
|
||||||
captureCounter++
|
|
||||||
switch captureCounter {
|
|
||||||
case 5:
|
|
||||||
return pkgsTars[0] + "\n", "", nil
|
|
||||||
case 6:
|
|
||||||
return pkgsTars[1] + "\n", "", nil
|
|
||||||
default:
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
once := sync.Once{}
|
|
||||||
|
|
||||||
showOverride := func(cmd *exec.Cmd) error {
|
|
||||||
once.Do(func() {
|
|
||||||
for _, tar := range pkgsTars {
|
|
||||||
f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, f.Close())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
MakepkgBin: makepkgBin,
|
|
||||||
SudoBin: "su",
|
|
||||||
PacmanBin: pacmanBin,
|
|
||||||
PacmanConfigPath: "/etc/pacman.conf",
|
|
||||||
GitBin: "git",
|
|
||||||
Runner: mockRunner,
|
|
||||||
SudoLoopEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
cmdArgs.AddArg("B")
|
|
||||||
cmdArgs.AddArg("i")
|
|
||||||
cmdArgs.AddTarget("testdata/gourou")
|
|
||||||
cmdArgs.AddTarget("testdata/libzip-git")
|
|
||||||
settings.NoConfirm = true
|
|
||||||
defer func() { settings.NoConfirm = false }()
|
|
||||||
db := &mock.DBExecutor{
|
|
||||||
AlpmArchitecturesFn: func() ([]string, error) {
|
|
||||||
return []string{"x86_64"}, nil
|
|
||||||
},
|
|
||||||
LocalSatisfierExistsFn: func(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "gourou", "libzip", "libzip-git":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(s string) mock.IPackage { return nil },
|
|
||||||
InstalledRemotePackageNamesFn: func() []string { return []string{} },
|
|
||||||
}
|
|
||||||
|
|
||||||
run := &runtime.Runtime{
|
|
||||||
Cfg: &settings.Configuration{
|
|
||||||
RemoveMake: "no",
|
|
||||||
},
|
|
||||||
Logger: newTestLogger(),
|
|
||||||
CmdBuilder: cmdBuilder,
|
|
||||||
VCSStore: &vcs.Mock{},
|
|
||||||
AURClient: &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = handleCmd(context.Background(), run, cmdArgs, db)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
|
||||||
require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
|
|
||||||
|
|
||||||
for i, call := range mockRunner.ShowCalls {
|
|
||||||
show := call.Args[0].(*exec.Cmd).String()
|
|
||||||
show = strings.ReplaceAll(show, tmpDir1, "/testdir1") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, tmpDir2, "/testdir2") // replace the temp dir with a static path
|
|
||||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
|
||||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
|
||||||
show = strings.ReplaceAll(show, gitBin, "pacman")
|
|
||||||
|
|
||||||
// options are in a different order on different systems and on CI root user is used
|
|
||||||
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
80
main.go
80
main.go
@ -6,19 +6,19 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
"github.com/Jguer/yay/v12/pkg/db/ialpm"
|
"github.com/Jguer/yay/v12/pkg/db/ialpm"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
"github.com/Jguer/yay/v12/pkg/query"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
yayVersion = "12.0.4" // To be set by compiler.
|
yayVersion = "12.0.0" // To be set by compiler.
|
||||||
localePath = "/usr/share/locale" // To be set by compiler.
|
localePath = "/usr/share/locale" // To be set by compiler.
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,12 +28,7 @@ func initGotext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if lc := os.Getenv("LANGUAGE"); lc != "" {
|
if lc := os.Getenv("LANGUAGE"); lc != "" {
|
||||||
// Split LANGUAGE by ':' and prioritize the first locale
|
gotext.Configure(localePath, lc, "yay")
|
||||||
// Should fix in gotext to support this
|
|
||||||
locales := strings.Split(lc, ":")
|
|
||||||
if len(locales) > 0 && locales[0] != "" {
|
|
||||||
gotext.Configure(localePath, locales[0], "yay")
|
|
||||||
}
|
|
||||||
} else if lc := os.Getenv("LC_ALL"); lc != "" {
|
} else if lc := os.Getenv("LC_ALL"); lc != "" {
|
||||||
gotext.Configure(localePath, lc, "yay")
|
gotext.Configure(localePath, lc, "yay")
|
||||||
} else if lc := os.Getenv("LC_MESSAGES"); lc != "" {
|
} else if lc := os.Getenv("LC_MESSAGES"); lc != "" {
|
||||||
@ -44,7 +39,6 @@ func initGotext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fallbackLog := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, false, "fallback")
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
@ -53,9 +47,8 @@ func main() {
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if rec := recover(); rec != nil {
|
if rec := recover(); rec != nil {
|
||||||
fallbackLog.Errorln("Panic occurred:", rec)
|
text.Errorln(rec)
|
||||||
fallbackLog.Errorln("Stack trace:", string(debug.Stack()))
|
debug.PrintStack()
|
||||||
ret = 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(ret)
|
os.Exit(ret)
|
||||||
@ -64,15 +57,15 @@ func main() {
|
|||||||
initGotext()
|
initGotext()
|
||||||
|
|
||||||
if os.Geteuid() == 0 {
|
if os.Geteuid() == 0 {
|
||||||
fallbackLog.Warnln(gotext.Get("Avoid running yay as root/sudo."))
|
text.Warnln(gotext.Get("Avoid running yay as root/sudo."))
|
||||||
}
|
}
|
||||||
|
|
||||||
configPath := settings.GetConfigPath()
|
configPath := settings.GetConfigPath()
|
||||||
// Parse config
|
// Parse config
|
||||||
cfg, err := settings.NewConfig(fallbackLog, configPath, yayVersion)
|
cfg, err := settings.NewConfig(configPath, yayVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if str := err.Error(); str != "" {
|
if str := err.Error(); str != "" {
|
||||||
fallbackLog.Errorln(str)
|
text.Errorln(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1
|
ret = 1
|
||||||
@ -80,9 +73,13 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if errS := cfg.RunMigrations(fallbackLog,
|
if cfg.Debug {
|
||||||
|
text.GlobalLogger.Debug = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if errS := cfg.RunMigrations(
|
||||||
settings.DefaultMigrations(), configPath, yayVersion); errS != nil {
|
settings.DefaultMigrations(), configPath, yayVersion); errS != nil {
|
||||||
fallbackLog.Errorln(errS)
|
text.Errorln(errS)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
@ -90,7 +87,7 @@ func main() {
|
|||||||
// Parse command line
|
// Parse command line
|
||||||
if err = cfg.ParseCommandLine(cmdArgs); err != nil {
|
if err = cfg.ParseCommandLine(cmdArgs); err != nil {
|
||||||
if str := err.Error(); str != "" {
|
if str := err.Error(); str != "" {
|
||||||
fallbackLog.Errorln(str)
|
text.Errorln(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1
|
ret = 1
|
||||||
@ -100,15 +97,15 @@ func main() {
|
|||||||
|
|
||||||
if cfg.SaveConfig {
|
if cfg.SaveConfig {
|
||||||
if errS := cfg.Save(configPath, yayVersion); errS != nil {
|
if errS := cfg.Save(configPath, yayVersion); errS != nil {
|
||||||
fallbackLog.Errorln(errS)
|
text.Errorln(errS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build run
|
// Build runtime
|
||||||
run, err := runtime.NewRuntime(cfg, cmdArgs, yayVersion)
|
runtime, err := settings.BuildRuntime(cfg, cmdArgs, yayVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if str := err.Error(); str != "" {
|
if str := err.Error(); str != "" {
|
||||||
fallbackLog.Errorln(str)
|
text.Errorln(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1
|
ret = 1
|
||||||
@ -116,10 +113,35 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dbExecutor, err := ialpm.NewExecutor(run.PacmanConf, run.Logger.Child("db"))
|
cfg.Runtime = runtime
|
||||||
|
|
||||||
|
cfg.Runtime.QueryBuilder = query.NewSourceQueryBuilder(
|
||||||
|
cfg.Runtime.AURCache,
|
||||||
|
cfg.Runtime.Logger.Child("mixed.querybuilder"), cfg.SortBy,
|
||||||
|
cfg.Mode, cfg.SearchBy,
|
||||||
|
cfg.BottomUp, cfg.SingleLineResults, cfg.SeparateSources)
|
||||||
|
|
||||||
|
var useColor bool
|
||||||
|
|
||||||
|
cfg.Runtime.PacmanConf, useColor, err = settings.RetrievePacmanConfig(cmdArgs, cfg.PacmanConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if str := err.Error(); str != "" {
|
if str := err.Error(); str != "" {
|
||||||
fallbackLog.Errorln(str)
|
text.Errorln(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Runtime.CmdBuilder.SetPacmanDBPath(cfg.Runtime.PacmanConf.DBPath)
|
||||||
|
|
||||||
|
text.UseColor = useColor
|
||||||
|
|
||||||
|
dbExecutor, err := ialpm.NewExecutor(cfg.Runtime.PacmanConf, runtime.Logger.Child("db"))
|
||||||
|
if err != nil {
|
||||||
|
if str := err.Error(); str != "" {
|
||||||
|
text.Errorln(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1
|
ret = 1
|
||||||
@ -129,16 +151,16 @@ func main() {
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if rec := recover(); rec != nil {
|
if rec := recover(); rec != nil {
|
||||||
fallbackLog.Errorln("Panic occurred in DB operation:", rec)
|
text.Errorln(rec)
|
||||||
fallbackLog.Errorln("Stack trace:", string(debug.Stack()))
|
debug.PrintStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
dbExecutor.Cleanup()
|
dbExecutor.Cleanup()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err = handleCmd(ctx, run, cmdArgs, dbExecutor); err != nil {
|
if err = handleCmd(ctx, cfg, cmdArgs, db.Executor(dbExecutor)); err != nil {
|
||||||
if str := err.Error(); str != "" {
|
if str := err.Error(); str != "" {
|
||||||
fallbackLog.Errorln(str)
|
text.Errorln(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
exitError := &exec.ExitError{}
|
exitError := &exec.ExitError{}
|
||||||
|
@ -2,61 +2,59 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db/ialpm"
|
"github.com/Jguer/yay/v12/pkg/db/ialpm"
|
||||||
"github.com/Jguer/yay/v12/pkg/dep"
|
"github.com/Jguer/yay/v12/pkg/dep"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
|
||||||
"github.com/Jguer/aur/metadata"
|
"github.com/Jguer/aur/metadata"
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleCmd(logger *text.Logger) error {
|
func handleCmd() error {
|
||||||
cfg, err := settings.NewConfig(logger, settings.GetConfigPath(), "")
|
config, err := settings.NewConfig(settings.GetConfigPath(), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs := parser.MakeArguments()
|
cmdArgs := parser.MakeArguments()
|
||||||
if errP := cfg.ParseCommandLine(cmdArgs); errP != nil {
|
if errP := config.ParseCommandLine(cmdArgs); errP != nil {
|
||||||
return errP
|
return errP
|
||||||
}
|
}
|
||||||
|
|
||||||
run, err := runtime.NewRuntime(cfg, cmdArgs, "1.0.0")
|
pacmanConf, _, err := settings.RetrievePacmanConfig(cmdArgs, config.PacmanConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dbExecutor, err := ialpm.NewExecutor(run.PacmanConf, logger)
|
dbExecutor, err := ialpm.NewExecutor(pacmanConf, text.GlobalLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
aurCache, err := metadata.New(
|
aurCache, err := metadata.New(
|
||||||
metadata.WithCacheFilePath(
|
metadata.WithCacheFilePath(
|
||||||
filepath.Join(cfg.BuildDir, "aur.json")))
|
filepath.Join(config.BuildDir, "aur.json")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %w", gotext.Get("failed to retrieve aur Cache"), err)
|
return errors.Wrap(err, gotext.Get("failed to retrieve aur Cache"))
|
||||||
}
|
}
|
||||||
|
|
||||||
grapher := dep.NewGrapher(dbExecutor, aurCache, true, settings.NoConfirm,
|
grapher := dep.NewGrapher(dbExecutor, aurCache, true, settings.NoConfirm,
|
||||||
cmdArgs.ExistsDouble("d", "nodeps"), false, false,
|
cmdArgs.ExistsDouble("d", "nodeps"), false, false,
|
||||||
run.Logger.Child("grapher"))
|
config.Runtime.Logger.Child("grapher"))
|
||||||
|
|
||||||
return graphPackage(context.Background(), grapher, cmdArgs.Targets)
|
return graphPackage(context.Background(), grapher, cmdArgs.Targets)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fallbackLog := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, false, "fallback")
|
if err := handleCmd(); err != nil {
|
||||||
if err := handleCmd(fallbackLog); err != nil {
|
text.Errorln(err)
|
||||||
fallbackLog.Errorln(err)
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ func createAURList(ctx context.Context, client httpRequestDoer, aurURL string, o
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createRepoList appends Repo packages to completion cache.
|
// CreatePackageList appends Repo packages to completion cache.
|
||||||
func createRepoList(dbExecutor PkgSynchronizer, out io.Writer) error {
|
func createRepoList(dbExecutor PkgSynchronizer, out io.Writer) error {
|
||||||
for _, pkg := range dbExecutor.SyncPackages() {
|
for _, pkg := range dbExecutor.SyncPackages() {
|
||||||
_, err := io.WriteString(out, pkg.Name()+"\t"+pkg.DB().Name()+"\n")
|
_, err := io.WriteString(out, pkg.Name()+"\t"+pkg.DB().Name()+"\n")
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package completion
|
package completion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
alpm "github.com/Jguer/go-alpm/v2"
|
alpm "github.com/Jguer/go-alpm/v2"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -26,7 +24,6 @@ type Upgrade struct {
|
|||||||
LocalVersion string
|
LocalVersion string
|
||||||
RemoteVersion string
|
RemoteVersion string
|
||||||
Reason alpm.PkgReason
|
Reason alpm.PkgReason
|
||||||
Extra string // Extra information to be displayed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncUpgrade struct {
|
type SyncUpgrade struct {
|
||||||
@ -47,22 +44,19 @@ type Executor interface {
|
|||||||
LocalPackage(string) IPackage
|
LocalPackage(string) IPackage
|
||||||
LocalPackages() []IPackage
|
LocalPackages() []IPackage
|
||||||
LocalSatisfierExists(string) bool
|
LocalSatisfierExists(string) bool
|
||||||
|
PackageConflicts(IPackage) []Depend
|
||||||
PackageDepends(IPackage) []Depend
|
PackageDepends(IPackage) []Depend
|
||||||
PackageGroups(IPackage) []string
|
PackageGroups(IPackage) []string
|
||||||
PackageOptionalDepends(IPackage) []Depend
|
PackageOptionalDepends(IPackage) []Depend
|
||||||
PackageProvides(IPackage) []Depend
|
PackageProvides(IPackage) []Depend
|
||||||
PackagesFromGroup(string) []IPackage
|
PackagesFromGroup(string) []IPackage
|
||||||
PackagesFromGroupAndDB(string, string) ([]IPackage, error)
|
|
||||||
RefreshHandle() error
|
RefreshHandle() error
|
||||||
SyncUpgrades(enableDowngrade bool) (
|
SyncUpgrades(enableDowngrade bool) (
|
||||||
map[string]SyncUpgrade, error)
|
map[string]SyncUpgrade, error)
|
||||||
Repos() []string
|
Repos() []string
|
||||||
SatisfierFromDB(string, string) (IPackage, error)
|
SatisfierFromDB(string, string) IPackage
|
||||||
SyncPackage(string) IPackage
|
SyncPackage(string) IPackage
|
||||||
SyncPackageFromDB(string, string) IPackage
|
|
||||||
SyncPackages(...string) []IPackage
|
SyncPackages(...string) []IPackage
|
||||||
SyncSatisfier(string) IPackage
|
SyncSatisfier(string) IPackage
|
||||||
SyncSatisfierExists(string) bool
|
SyncSatisfierExists(string) bool
|
||||||
|
|
||||||
SetLogger(logger *text.Logger)
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func NewExecutor(pacmanConf *pacmanconf.Config, logger *text.Logger) (*AlpmExecu
|
|||||||
conf: pacmanConf,
|
conf: pacmanConf,
|
||||||
log: logger,
|
log: logger,
|
||||||
installedRemotePkgNames: nil,
|
installedRemotePkgNames: nil,
|
||||||
installedRemotePkgMap: nil,
|
installedRemotePkgMap: map[string]alpm.IPackage{},
|
||||||
installedSyncPkgNames: nil,
|
installedSyncPkgNames: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ func (ae *AlpmExecutor) questionCallback() func(question alpm.QuestionAny) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
str := text.Bold(gotext.Get("There are %[1]d providers available for %[2]s:", size, qp.Dep()))
|
str := text.Bold(gotext.Get("There are %d providers available for %s:", size, qp.Dep()))
|
||||||
|
|
||||||
size = 1
|
size = 1
|
||||||
|
|
||||||
@ -311,22 +311,6 @@ func (ae *AlpmExecutor) PackagesFromGroup(groupName string) []alpm.IPackage {
|
|||||||
return groupPackages
|
return groupPackages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ae *AlpmExecutor) PackagesFromGroupAndDB(groupName, dbName string) ([]alpm.IPackage, error) {
|
|
||||||
singleDBList, err := ae.handle.SyncDBListByDBName(dbName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
groupPackages := []alpm.IPackage{}
|
|
||||||
_ = singleDBList.FindGroupPkgs(groupName).ForEach(func(pkg alpm.IPackage) error {
|
|
||||||
groupPackages = append(groupPackages, pkg)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return groupPackages, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ae *AlpmExecutor) LocalPackages() []alpm.IPackage {
|
func (ae *AlpmExecutor) LocalPackages() []alpm.IPackage {
|
||||||
localPackages := []alpm.IPackage{}
|
localPackages := []alpm.IPackage{}
|
||||||
_ = ae.localDB.PkgCache().ForEach(func(pkg alpm.IPackage) error {
|
_ = ae.localDB.PkgCache().ForEach(func(pkg alpm.IPackage) error {
|
||||||
@ -385,27 +369,18 @@ func (ae *AlpmExecutor) SyncPackage(pkgName string) alpm.IPackage {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ae *AlpmExecutor) SyncPackageFromDB(pkgName, dbName string) alpm.IPackage {
|
func (ae *AlpmExecutor) SatisfierFromDB(pkgName, dbName string) alpm.IPackage {
|
||||||
singleDB, err := ae.handle.SyncDBByName(dbName)
|
singleDB, err := ae.handle.SyncDBByName(dbName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return singleDB.Pkg(pkgName)
|
foundPkg, err := singleDB.PkgCache().FindSatisfier(pkgName)
|
||||||
}
|
|
||||||
|
|
||||||
func (ae *AlpmExecutor) SatisfierFromDB(pkgName, dbName string) (alpm.IPackage, error) {
|
|
||||||
singleDBList, err := ae.handle.SyncDBListByDBName(dbName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
foundPkg, err := singleDBList.FindSatisfier(pkgName)
|
return foundPkg
|
||||||
if err != nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return foundPkg, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ae *AlpmExecutor) PackageDepends(pkg alpm.IPackage) []alpm.Depend {
|
func (ae *AlpmExecutor) PackageDepends(pkg alpm.IPackage) []alpm.Depend {
|
||||||
@ -423,6 +398,11 @@ func (ae *AlpmExecutor) PackageProvides(pkg alpm.IPackage) []alpm.Depend {
|
|||||||
return alpmPackage.Provides().Slice()
|
return alpmPackage.Provides().Slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ae *AlpmExecutor) PackageConflicts(pkg alpm.IPackage) []alpm.Depend {
|
||||||
|
alpmPackage := pkg.(*alpm.Package)
|
||||||
|
return alpmPackage.Conflicts().Slice()
|
||||||
|
}
|
||||||
|
|
||||||
func (ae *AlpmExecutor) PackageGroups(pkg alpm.IPackage) []string {
|
func (ae *AlpmExecutor) PackageGroups(pkg alpm.IPackage) []string {
|
||||||
alpmPackage := pkg.(*alpm.Package)
|
alpmPackage := pkg.(*alpm.Package)
|
||||||
return alpmPackage.Groups().Slice()
|
return alpmPackage.Groups().Slice()
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package ialpm
|
package ialpm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -48,7 +45,7 @@ func TestAlpmExecutor(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
aExec, err := NewExecutor(pacmanConf, text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), false, "test"))
|
aExec, err := NewExecutor(pacmanConf, text.NewLogger(io.Discard, strings.NewReader(""), false, "test"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.NotNil(t, aExec.conf)
|
assert.NotNil(t, aExec.conf)
|
||||||
|
@ -2,15 +2,10 @@ package ialpm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
alpm "github.com/Jguer/go-alpm/v2"
|
alpm "github.com/Jguer/go-alpm/v2"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPackageNamesBySource returns package names with and without correspondence in SyncDBS respectively.
|
// GetPackageNamesBySource returns package names with and without correspondence in SyncDBS respectively.
|
||||||
func (ae *AlpmExecutor) getPackageNamesBySource() {
|
func (ae *AlpmExecutor) getPackageNamesBySource() {
|
||||||
if ae.installedRemotePkgMap == nil {
|
|
||||||
ae.installedRemotePkgMap = map[string]alpm.IPackage{}
|
|
||||||
}
|
|
||||||
for _, localpkg := range ae.LocalPackages() {
|
for _, localpkg := range ae.LocalPackages() {
|
||||||
pkgName := localpkg.Name()
|
pkgName := localpkg.Name()
|
||||||
if ae.SyncPackage(pkgName) != nil {
|
if ae.SyncPackage(pkgName) != nil {
|
||||||
@ -48,7 +43,3 @@ func (ae *AlpmExecutor) InstalledSyncPackageNames() []string {
|
|||||||
|
|
||||||
return ae.installedSyncPkgNames
|
return ae.installedSyncPkgNames
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ae *AlpmExecutor) SetLogger(logger *text.Logger) {
|
|
||||||
ae.log = logger
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
|
|
||||||
"github.com/Jguer/go-alpm/v2"
|
"github.com/Jguer/go-alpm/v2"
|
||||||
)
|
)
|
||||||
@ -28,15 +27,11 @@ type DBExecutor struct {
|
|||||||
PackageOptionalDependsFn func(alpm.IPackage) []alpm.Depend
|
PackageOptionalDependsFn func(alpm.IPackage) []alpm.Depend
|
||||||
PackageProvidesFn func(IPackage) []Depend
|
PackageProvidesFn func(IPackage) []Depend
|
||||||
PackagesFromGroupFn func(string) []IPackage
|
PackagesFromGroupFn func(string) []IPackage
|
||||||
PackagesFromGroupAndDBFn func(string, string) ([]IPackage, error)
|
|
||||||
RefreshHandleFn func() error
|
RefreshHandleFn func() error
|
||||||
ReposFn func() []string
|
ReposFn func() []string
|
||||||
SyncPackageFn func(string) IPackage
|
SyncPackageFn func(string) IPackage
|
||||||
SyncPackagesFn func(...string) []IPackage
|
|
||||||
SyncSatisfierFn func(string) IPackage
|
SyncSatisfierFn func(string) IPackage
|
||||||
SatisfierFromDBFn func(string, string) (IPackage, error)
|
|
||||||
SyncUpgradesFn func(bool) (map[string]db.SyncUpgrade, error)
|
SyncUpgradesFn func(bool) (map[string]db.SyncUpgrade, error)
|
||||||
SetLoggerFn func(*text.Logger)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBExecutor) InstalledRemotePackageNames() []string {
|
func (t *DBExecutor) InstalledRemotePackageNames() []string {
|
||||||
@ -142,13 +137,6 @@ func (t *DBExecutor) PackagesFromGroup(s string) []IPackage {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBExecutor) PackagesFromGroupAndDB(s, s2 string) ([]IPackage, error) {
|
|
||||||
if t.PackagesFromGroupAndDBFn != nil {
|
|
||||||
return t.PackagesFromGroupAndDBFn(s, s2)
|
|
||||||
}
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *DBExecutor) RefreshHandle() error {
|
func (t *DBExecutor) RefreshHandle() error {
|
||||||
if t.RefreshHandleFn != nil {
|
if t.RefreshHandleFn != nil {
|
||||||
return t.RefreshHandleFn()
|
return t.RefreshHandleFn()
|
||||||
@ -170,10 +158,7 @@ func (t *DBExecutor) Repos() []string {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBExecutor) SatisfierFromDB(s, s2 string) (IPackage, error) {
|
func (t *DBExecutor) SatisfierFromDB(s, s2 string) IPackage {
|
||||||
if t.SatisfierFromDBFn != nil {
|
|
||||||
return t.SatisfierFromDBFn(s, s2)
|
|
||||||
}
|
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,9 +170,6 @@ func (t *DBExecutor) SyncPackage(s string) IPackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBExecutor) SyncPackages(s ...string) []IPackage {
|
func (t *DBExecutor) SyncPackages(s ...string) []IPackage {
|
||||||
if t.SyncPackagesFn != nil {
|
|
||||||
return t.SyncPackagesFn(s...)
|
|
||||||
}
|
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,16 +181,5 @@ func (t *DBExecutor) SyncSatisfier(s string) IPackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBExecutor) SyncSatisfierExists(s string) bool {
|
func (t *DBExecutor) SyncSatisfierExists(s string) bool {
|
||||||
if t.SyncSatisfierFn != nil {
|
|
||||||
return t.SyncSatisfierFn(s) != nil
|
|
||||||
}
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *DBExecutor) SetLogger(logger *text.Logger) {
|
|
||||||
if t.SetLoggerFn != nil {
|
|
||||||
t.SetLoggerFn(logger)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ type Package struct {
|
|||||||
PVersion string
|
PVersion string
|
||||||
PReason alpm.PkgReason
|
PReason alpm.PkgReason
|
||||||
PDepends alpm.IDependList
|
PDepends alpm.IDependList
|
||||||
PProvides alpm.IDependList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Package) Base() string {
|
func (p *Package) Base() string {
|
||||||
@ -173,10 +172,7 @@ func (p *Package) Packager() string {
|
|||||||
|
|
||||||
// Provides returns DependList of packages provides by package.
|
// Provides returns DependList of packages provides by package.
|
||||||
func (p *Package) Provides() alpm.IDependList {
|
func (p *Package) Provides() alpm.IDependList {
|
||||||
if p.PProvides == nil {
|
return alpm.DependList{}
|
||||||
return alpm.DependList{}
|
|
||||||
}
|
|
||||||
return p.PProvides
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Origin returns package origin.
|
// Origin returns package origin.
|
||||||
|
69
pkg/dep/base.go
Normal file
69
pkg/dep/base.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package dep
|
||||||
|
|
||||||
|
import (
|
||||||
|
aur "github.com/Jguer/yay/v12/pkg/query"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Base is an AUR base package.
|
||||||
|
type Base []*aur.Pkg
|
||||||
|
|
||||||
|
// Pkgbase returns the first base package.
|
||||||
|
func (b Base) Pkgbase() string {
|
||||||
|
return b[0].PackageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the first base package version.
|
||||||
|
func (b Base) Version() string {
|
||||||
|
return b[0].Version
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLPath returns the first base package URL.
|
||||||
|
func (b Base) URLPath() string {
|
||||||
|
return b[0].URLPath
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Base) AnyIsInSet(set stringset.StringSet) bool {
|
||||||
|
for _, pkg := range b {
|
||||||
|
if set.Get(pkg.Name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Packages foo and bar from a pkgbase named base would print like so:
|
||||||
|
// base (foo bar).
|
||||||
|
func (b Base) String() string {
|
||||||
|
pkg := b[0]
|
||||||
|
str := pkg.PackageBase
|
||||||
|
|
||||||
|
if len(b) > 1 || pkg.PackageBase != pkg.Name {
|
||||||
|
str2 := " ("
|
||||||
|
for _, split := range b {
|
||||||
|
str2 += split.Name + " "
|
||||||
|
}
|
||||||
|
|
||||||
|
str2 = str2[:len(str2)-1] + ")"
|
||||||
|
|
||||||
|
str += str2
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBases(pkgs []aur.Pkg) []Base {
|
||||||
|
basesMap := make(map[string]Base)
|
||||||
|
for i := range pkgs {
|
||||||
|
pkg := &pkgs[i]
|
||||||
|
basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
bases := make([]Base, 0, len(basesMap))
|
||||||
|
for _, base := range basesMap {
|
||||||
|
bases = append(bases, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bases
|
||||||
|
}
|
@ -5,8 +5,41 @@ import (
|
|||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
aur "github.com/Jguer/yay/v12/pkg/query"
|
aur "github.com/Jguer/yay/v12/pkg/query"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type providers struct {
|
||||||
|
lookfor string
|
||||||
|
Pkgs []*aur.Pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeProviders(name string) providers {
|
||||||
|
return providers{
|
||||||
|
name,
|
||||||
|
make([]*aur.Pkg, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q providers) Len() int {
|
||||||
|
return len(q.Pkgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q providers) Less(i, j int) bool {
|
||||||
|
if q.lookfor == q.Pkgs[i].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.lookfor == q.Pkgs[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.LessRunes([]rune(q.Pkgs[i].Name), []rune(q.Pkgs[j].Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q providers) Swap(i, j int) {
|
||||||
|
q.Pkgs[i], q.Pkgs[j] = q.Pkgs[j], q.Pkgs[i]
|
||||||
|
}
|
||||||
|
|
||||||
func splitDep(dep string) (pkg, mod, ver string) {
|
func splitDep(dep string) (pkg, mod, ver string) {
|
||||||
split := strings.FieldsFunc(dep, func(c rune) bool {
|
split := strings.FieldsFunc(dep, func(c rune) bool {
|
||||||
match := c == '>' || c == '<' || c == '='
|
match := c == '>' || c == '<' || c == '='
|
||||||
@ -85,3 +118,17 @@ func satisfiesAur(dep string, pkg *aur.Pkg) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func satisfiesRepo(dep string, pkg db.IPackage, dbExecutor db.Executor) bool {
|
||||||
|
if pkgSatisfies(pkg.Name(), pkg.Version(), dep) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, provided := range dbExecutor.PackageProvides(pkg) {
|
||||||
|
if provideSatisfies(provided.String(), dep, pkg.Version()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
324
pkg/dep/depCheck.go
Normal file
324
pkg/dep/depCheck.go
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
package dep
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (dp *Pool) checkInnerConflict(name, conflict string, conflicts stringset.MapStringSet) {
|
||||||
|
for _, pkg := range dp.Aur {
|
||||||
|
if pkg.Name == name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if satisfiesAur(conflict, pkg) {
|
||||||
|
conflicts.Add(name, pkg.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Repo {
|
||||||
|
if pkg.Name() == name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
|
||||||
|
conflicts.Add(name, pkg.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) checkForwardConflict(name, conflict string, conflicts stringset.MapStringSet) {
|
||||||
|
for _, pkg := range dp.AlpmExecutor.LocalPackages() {
|
||||||
|
if pkg.Name() == name || dp.hasPackage(pkg.Name()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
|
||||||
|
n := pkg.Name()
|
||||||
|
if n != conflict {
|
||||||
|
n += " (" + conflict + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
conflicts.Add(name, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) checkReverseConflict(name, conflict string, conflicts stringset.MapStringSet) {
|
||||||
|
for _, pkg := range dp.Aur {
|
||||||
|
if pkg.Name == name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if satisfiesAur(conflict, pkg) {
|
||||||
|
if name != conflict {
|
||||||
|
name += " (" + conflict + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
conflicts.Add(pkg.Name, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Repo {
|
||||||
|
if pkg.Name() == name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
|
||||||
|
if name != conflict {
|
||||||
|
name += " (" + conflict + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
conflicts.Add(pkg.Name(), name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) checkInnerConflicts(conflicts stringset.MapStringSet) {
|
||||||
|
for _, pkg := range dp.Aur {
|
||||||
|
for _, conflict := range pkg.Conflicts {
|
||||||
|
dp.checkInnerConflict(pkg.Name, conflict, conflicts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Repo {
|
||||||
|
for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
|
||||||
|
dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) checkForwardConflicts(conflicts stringset.MapStringSet) {
|
||||||
|
for _, pkg := range dp.Aur {
|
||||||
|
for _, conflict := range pkg.Conflicts {
|
||||||
|
dp.checkForwardConflict(pkg.Name, conflict, conflicts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Repo {
|
||||||
|
for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
|
||||||
|
dp.checkForwardConflict(pkg.Name(), conflict.String(), conflicts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) checkReverseConflicts(conflicts stringset.MapStringSet) {
|
||||||
|
for _, pkg := range dp.AlpmExecutor.LocalPackages() {
|
||||||
|
if dp.hasPackage(pkg.Name()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
|
||||||
|
dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) CheckConflicts(useAsk, noConfirm, noDeps bool) (stringset.MapStringSet, error) {
|
||||||
|
conflicts := make(stringset.MapStringSet)
|
||||||
|
if noDeps {
|
||||||
|
return conflicts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
innerConflicts := make(stringset.MapStringSet)
|
||||||
|
|
||||||
|
wg.Add(2)
|
||||||
|
|
||||||
|
text.OperationInfoln(gotext.Get("Checking for conflicts..."))
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
dp.checkForwardConflicts(conflicts)
|
||||||
|
dp.checkReverseConflicts(conflicts)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
text.OperationInfoln(gotext.Get("Checking for inner conflicts..."))
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
dp.checkInnerConflicts(innerConflicts)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if len(innerConflicts) != 0 {
|
||||||
|
text.Errorln(gotext.Get("Inner conflicts found:"))
|
||||||
|
|
||||||
|
for name, pkgs := range innerConflicts {
|
||||||
|
str := text.SprintError(name + ":")
|
||||||
|
for pkg := range pkgs {
|
||||||
|
str += " " + text.Cyan(pkg) + ","
|
||||||
|
}
|
||||||
|
|
||||||
|
str = strings.TrimSuffix(str, ",")
|
||||||
|
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(conflicts) != 0 {
|
||||||
|
text.Errorln(gotext.Get("Package conflicts found:"))
|
||||||
|
|
||||||
|
for name, pkgs := range conflicts {
|
||||||
|
str := text.SprintError(gotext.Get("Installing %s will remove:", text.Cyan(name)))
|
||||||
|
for pkg := range pkgs {
|
||||||
|
str += " " + text.Cyan(pkg) + ","
|
||||||
|
}
|
||||||
|
|
||||||
|
str = strings.TrimSuffix(str, ",")
|
||||||
|
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the inner conflicts to the conflicts
|
||||||
|
// These are used to decide what to pass --ask to (if set) or don't pass --noconfirm to
|
||||||
|
// As we have no idea what the order is yet we add every inner conflict to the slice
|
||||||
|
for name, pkgs := range innerConflicts {
|
||||||
|
conflicts[name] = make(stringset.StringSet)
|
||||||
|
for pkg := range pkgs {
|
||||||
|
conflicts[pkg] = make(stringset.StringSet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(conflicts) > 0 {
|
||||||
|
if !useAsk {
|
||||||
|
if noConfirm {
|
||||||
|
return nil, errors.New(gotext.Get("package conflicts can not be resolved with noconfirm, aborting"))
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Errorln(gotext.Get("Conflicting packages will have to be confirmed manually"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conflicts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type missing struct {
|
||||||
|
Good stringset.StringSet
|
||||||
|
Missing map[string][][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) _checkMissing(dep string, stack []string, missing *missing, noDeps, noCheckDeps bool) {
|
||||||
|
if missing.Good.Get(dep) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if trees, ok := missing.Missing[dep]; ok {
|
||||||
|
for _, tree := range trees {
|
||||||
|
if stringSliceEqual(tree, stack) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
missing.Missing[dep] = append(missing.Missing[dep], stack)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if aurPkg := dp.findSatisfierAur(dep); aurPkg != nil {
|
||||||
|
missing.Good.Set(dep)
|
||||||
|
|
||||||
|
combinedDepList := ComputeCombinedDepList(aurPkg, noDeps, noCheckDeps)
|
||||||
|
for _, aurDep := range combinedDepList {
|
||||||
|
if dp.AlpmExecutor.LocalSatisfierExists(aurDep) {
|
||||||
|
missing.Good.Set(aurDep)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing, noDeps, noCheckDeps)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoPkg := dp.findSatisfierRepo(dep); repoPkg != nil {
|
||||||
|
missing.Good.Set(dep)
|
||||||
|
|
||||||
|
if noDeps {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dep := range dp.AlpmExecutor.PackageDepends(repoPkg) {
|
||||||
|
if dp.AlpmExecutor.LocalSatisfierExists(dep.String()) {
|
||||||
|
missing.Good.Set(dep.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dp._checkMissing(dep.String(), append(stack, repoPkg.Name()), missing, noDeps, noCheckDeps)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
missing.Missing[dep] = [][]string{stack}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringSliceEqual(a, b []string) bool {
|
||||||
|
if a == nil && b == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if a == nil || b == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(a); i++ {
|
||||||
|
if a[i] != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) CheckMissing(noDeps, noCheckDeps bool) error {
|
||||||
|
missing := &missing{
|
||||||
|
make(stringset.StringSet),
|
||||||
|
make(map[string][][]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, target := range dp.Targets {
|
||||||
|
dp._checkMissing(target.DepString(), make([]string, 0), missing, noDeps, noCheckDeps)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missing.Missing) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Errorln(gotext.Get("could not find all required packages:"))
|
||||||
|
|
||||||
|
for dep, trees := range missing.Missing {
|
||||||
|
for _, tree := range trees {
|
||||||
|
fmt.Fprintf(os.Stderr, "\t%s", text.Cyan(dep))
|
||||||
|
|
||||||
|
if len(tree) == 0 {
|
||||||
|
fmt.Fprint(os.Stderr, gotext.Get(" (Target"))
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(os.Stderr, gotext.Get(" (Wanted by: "))
|
||||||
|
for n := 0; n < len(tree)-1; n++ {
|
||||||
|
fmt.Fprint(os.Stderr, text.Cyan(tree[n]), " -> ")
|
||||||
|
}
|
||||||
|
fmt.Fprint(os.Stderr, text.Cyan(tree[len(tree)-1]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stderr, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("")
|
||||||
|
}
|
199
pkg/dep/depOrder.go
Normal file
199
pkg/dep/depOrder.go
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
package dep
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
|
aur "github.com/Jguer/yay/v12/pkg/query"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Order struct {
|
||||||
|
Aur []Base
|
||||||
|
Repo []db.IPackage
|
||||||
|
Runtime stringset.StringSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOrder() *Order {
|
||||||
|
return &Order{
|
||||||
|
make([]Base, 0),
|
||||||
|
make([]db.IPackage, 0),
|
||||||
|
make(stringset.StringSet),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOrder(dp *Pool, noDeps, noCheckDeps bool) *Order {
|
||||||
|
do := newOrder()
|
||||||
|
|
||||||
|
for _, target := range dp.Targets {
|
||||||
|
dep := target.DepString()
|
||||||
|
|
||||||
|
if aurPkg := dp.Aur[dep]; aurPkg != nil && pkgSatisfies(aurPkg.Name, aurPkg.Version, dep) {
|
||||||
|
do.orderPkgAur(aurPkg, dp, true, noDeps, noCheckDeps)
|
||||||
|
} else if aurPkg := dp.findSatisfierAur(dep); aurPkg != nil {
|
||||||
|
do.orderPkgAur(aurPkg, dp, true, noDeps, noCheckDeps)
|
||||||
|
} else if repoPkg := dp.findSatisfierRepo(dep); repoPkg != nil {
|
||||||
|
do.orderPkgRepo(repoPkg, dp, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return do
|
||||||
|
}
|
||||||
|
|
||||||
|
func (do *Order) orderPkgAur(pkg *aur.Pkg, dp *Pool, runtime, noDeps, noCheckDeps bool) {
|
||||||
|
if runtime {
|
||||||
|
do.Runtime.Set(pkg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(dp.Aur, pkg.Name)
|
||||||
|
|
||||||
|
for i, dep := range ComputeCombinedDepList(pkg, noDeps, noCheckDeps) {
|
||||||
|
if aurPkg := dp.findSatisfierAur(dep); aurPkg != nil {
|
||||||
|
do.orderPkgAur(aurPkg, dp, runtime && i == 0, noDeps, noCheckDeps)
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoPkg := dp.findSatisfierRepo(dep); repoPkg != nil {
|
||||||
|
do.orderPkgRepo(repoPkg, dp, runtime && i == 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, base := range do.Aur {
|
||||||
|
if base.Pkgbase() == pkg.PackageBase {
|
||||||
|
do.Aur[i] = append(base, pkg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do.Aur = append(do.Aur, Base{pkg})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (do *Order) orderPkgRepo(pkg db.IPackage, dp *Pool, runtime bool) {
|
||||||
|
if runtime {
|
||||||
|
do.Runtime.Set(pkg.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(dp.Repo, pkg.Name())
|
||||||
|
|
||||||
|
for _, dep := range dp.AlpmExecutor.PackageDepends(pkg) {
|
||||||
|
if repoPkg := dp.findSatisfierRepo(dep.String()); repoPkg != nil {
|
||||||
|
do.orderPkgRepo(repoPkg, dp, runtime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do.Repo = append(do.Repo, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (do *Order) HasMake() bool {
|
||||||
|
lenAur := 0
|
||||||
|
for _, base := range do.Aur {
|
||||||
|
lenAur += len(base)
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(do.Runtime) != lenAur+len(do.Repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (do *Order) GetMake() []string {
|
||||||
|
makeOnly := []string{}
|
||||||
|
|
||||||
|
for _, base := range do.Aur {
|
||||||
|
for _, pkg := range base {
|
||||||
|
if !do.Runtime.Get(pkg.Name) {
|
||||||
|
makeOnly = append(makeOnly, pkg.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range do.Repo {
|
||||||
|
if !do.Runtime.Get(pkg.Name()) {
|
||||||
|
makeOnly = append(makeOnly, pkg.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print prints repository packages to be downloaded.
|
||||||
|
func (do *Order) Print() {
|
||||||
|
repo := ""
|
||||||
|
repoMake := ""
|
||||||
|
aurString := ""
|
||||||
|
aurMake := ""
|
||||||
|
|
||||||
|
repoLen := 0
|
||||||
|
repoMakeLen := 0
|
||||||
|
aurLen := 0
|
||||||
|
aurMakeLen := 0
|
||||||
|
|
||||||
|
for _, pkg := range do.Repo {
|
||||||
|
pkgStr := fmt.Sprintf(" %s-%s", pkg.Name(), pkg.Version())
|
||||||
|
if do.Runtime.Get(pkg.Name()) {
|
||||||
|
repo += pkgStr
|
||||||
|
repoLen++
|
||||||
|
} else {
|
||||||
|
repoMake += pkgStr
|
||||||
|
repoMakeLen++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, base := range do.Aur {
|
||||||
|
pkg := base.Pkgbase()
|
||||||
|
pkgStr := " " + pkg + "-" + base[0].Version
|
||||||
|
pkgStrMake := pkgStr
|
||||||
|
|
||||||
|
push := false
|
||||||
|
pushMake := false
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(base) > 1, pkg != base[0].Name:
|
||||||
|
pkgStr += " ("
|
||||||
|
pkgStrMake += " ("
|
||||||
|
|
||||||
|
for _, split := range base {
|
||||||
|
if do.Runtime.Get(split.Name) {
|
||||||
|
pkgStr += split.Name + " "
|
||||||
|
aurLen++
|
||||||
|
|
||||||
|
push = true
|
||||||
|
} else {
|
||||||
|
pkgStrMake += split.Name + " "
|
||||||
|
aurMakeLen++
|
||||||
|
pushMake = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgStr = pkgStr[:len(pkgStr)-1] + ")"
|
||||||
|
pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")"
|
||||||
|
case do.Runtime.Get(base[0].Name):
|
||||||
|
aurLen++
|
||||||
|
|
||||||
|
push = true
|
||||||
|
default:
|
||||||
|
aurMakeLen++
|
||||||
|
|
||||||
|
pushMake = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if push {
|
||||||
|
aurString += pkgStr
|
||||||
|
}
|
||||||
|
|
||||||
|
if pushMake {
|
||||||
|
aurMake += pkgStrMake
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printDownloads("Repo", repoLen, repo)
|
||||||
|
printDownloads("Repo Make", repoMakeLen, repoMake)
|
||||||
|
printDownloads("Aur", aurLen, aurString)
|
||||||
|
printDownloads("Aur Make", aurMakeLen, aurMake)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printDownloads(repoName string, length int, packages string) {
|
||||||
|
if length < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
repoInfo := fmt.Sprintf(text.Bold(text.Blue("[%s:%d]")), repoName, length)
|
||||||
|
fmt.Println(repoInfo + text.Cyan(packages))
|
||||||
|
}
|
546
pkg/dep/depPool.go
Normal file
546
pkg/dep/depPool.go
Normal file
@ -0,0 +1,546 @@
|
|||||||
|
package dep
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Jguer/aur"
|
||||||
|
"github.com/Jguer/aur/rpc"
|
||||||
|
alpm "github.com/Jguer/go-alpm/v2"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/query"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pool struct {
|
||||||
|
Targets []Target
|
||||||
|
Explicit stringset.StringSet
|
||||||
|
Repo map[string]db.IPackage
|
||||||
|
Aur map[string]*query.Pkg
|
||||||
|
AurCache map[string]*query.Pkg
|
||||||
|
Groups []string
|
||||||
|
AlpmExecutor db.Executor
|
||||||
|
Warnings *query.AURWarnings
|
||||||
|
aurClient rpc.ClientInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPool(dbExecutor db.Executor, aurClient rpc.ClientInterface) *Pool {
|
||||||
|
dp := &Pool{
|
||||||
|
Targets: []Target{},
|
||||||
|
Explicit: map[string]struct{}{},
|
||||||
|
Repo: map[string]alpm.IPackage{},
|
||||||
|
Aur: map[string]*aur.Pkg{},
|
||||||
|
AurCache: map[string]*aur.Pkg{},
|
||||||
|
Groups: []string{},
|
||||||
|
AlpmExecutor: dbExecutor,
|
||||||
|
Warnings: nil,
|
||||||
|
aurClient: aurClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Includes db/ prefixes and group installs.
|
||||||
|
func (dp *Pool) ResolveTargets(ctx context.Context, pkgs []string,
|
||||||
|
mode parser.TargetMode,
|
||||||
|
ignoreProviders, noConfirm, provides bool, rebuild string, splitN int, noDeps, noCheckDeps bool, assumeInstalled []string,
|
||||||
|
) error {
|
||||||
|
// RPC requests are slow
|
||||||
|
// Combine as many AUR package requests as possible into a single RPC call
|
||||||
|
aurTargets := make(stringset.StringSet)
|
||||||
|
|
||||||
|
pkgs = query.RemoveInvalidTargets(pkgs, mode)
|
||||||
|
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
target := ToTarget(pkg)
|
||||||
|
|
||||||
|
// skip targets already satisfied
|
||||||
|
// even if the user enters db/pkg and aur/pkg the latter will
|
||||||
|
// still get skipped even if it's from a different database to
|
||||||
|
// the one specified
|
||||||
|
// this is how pacman behaves
|
||||||
|
if dp.hasPackage(target.DepString()) || isInAssumeInstalled(target.DepString(), assumeInstalled) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var foundPkg db.IPackage
|
||||||
|
|
||||||
|
// aur/ prefix means we only check the aur
|
||||||
|
if target.DB == "aur" || mode == parser.ModeAUR {
|
||||||
|
dp.Targets = append(dp.Targets, target)
|
||||||
|
aurTargets.Set(target.DepString())
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's a different prefix only look in that repo
|
||||||
|
if target.DB != "" {
|
||||||
|
foundPkg = dp.AlpmExecutor.SatisfierFromDB(target.DepString(), target.DB)
|
||||||
|
} else {
|
||||||
|
// otherwise find it in any repo
|
||||||
|
foundPkg = dp.AlpmExecutor.SyncSatisfier(target.DepString())
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundPkg != nil {
|
||||||
|
dp.Targets = append(dp.Targets, target)
|
||||||
|
dp.Explicit.Set(foundPkg.Name())
|
||||||
|
dp.ResolveRepoDependency(foundPkg, noDeps)
|
||||||
|
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
// check for groups
|
||||||
|
// currently we don't resolve the packages in a group
|
||||||
|
// only check if the group exists
|
||||||
|
// would be better to check the groups from singleDB if
|
||||||
|
// the user specified a db but there's no easy way to do
|
||||||
|
// it without making alpm_lists so don't bother for now
|
||||||
|
// db/group is probably a rare use case
|
||||||
|
groupPackages := dp.AlpmExecutor.PackagesFromGroup(target.Name)
|
||||||
|
if len(groupPackages) > 0 {
|
||||||
|
dp.Groups = append(dp.Groups, target.String())
|
||||||
|
for _, pkg := range groupPackages {
|
||||||
|
dp.Explicit.Set(pkg.Name())
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there was no db prefix check the aur
|
||||||
|
if target.DB == "" {
|
||||||
|
aurTargets.Set(target.DepString())
|
||||||
|
}
|
||||||
|
|
||||||
|
dp.Targets = append(dp.Targets, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(aurTargets) > 0 && mode.AtLeastAUR() {
|
||||||
|
return dp.resolveAURPackages(ctx, aurTargets, true, ignoreProviders,
|
||||||
|
noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pseudo provides finder.
|
||||||
|
// Try to find provides by performing a search of the package name
|
||||||
|
// This effectively performs -Ss on each package
|
||||||
|
// then runs -Si on each result to cache the information.
|
||||||
|
//
|
||||||
|
// For example if you were to -S yay then yay -Ss would give:
|
||||||
|
// yay-git yay-bin yay realyog pacui pacui-git ruby-yard
|
||||||
|
// These packages will all be added to the cache in case they are needed later
|
||||||
|
// Ofcouse only the first three packages provide yay, the rest are just false
|
||||||
|
// positives.
|
||||||
|
//
|
||||||
|
// This method increases dependency resolve time.
|
||||||
|
func (dp *Pool) findProvides(ctx context.Context, pkgs stringset.StringSet) error {
|
||||||
|
var (
|
||||||
|
mux sync.Mutex
|
||||||
|
wg sync.WaitGroup
|
||||||
|
)
|
||||||
|
|
||||||
|
doSearch := func(pkg string) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
results []query.Pkg
|
||||||
|
)
|
||||||
|
|
||||||
|
results, err = dp.aurClient.Search(ctx, pkg, aur.Provides)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for iR := range results {
|
||||||
|
mux.Lock()
|
||||||
|
if _, ok := dp.AurCache[results[iR].Name]; !ok {
|
||||||
|
pkgs.Set(results[iR].Name)
|
||||||
|
}
|
||||||
|
mux.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for pkg := range pkgs {
|
||||||
|
if dp.AlpmExecutor.LocalPackage(pkg) != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
text.Debugln("AUR RPC Search:", pkg)
|
||||||
|
|
||||||
|
go doSearch(pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) cacheAURPackages(ctx context.Context, _pkgs stringset.StringSet, provides bool, splitN int) error {
|
||||||
|
pkgs := _pkgs.Copy()
|
||||||
|
toQuery := make([]string, 0)
|
||||||
|
|
||||||
|
for pkg := range pkgs {
|
||||||
|
if _, ok := dp.AurCache[pkg]; ok {
|
||||||
|
pkgs.Remove(pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pkgs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if provides {
|
||||||
|
err := dp.findProvides(ctx, pkgs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for pkg := range pkgs {
|
||||||
|
if _, ok := dp.AurCache[pkg]; !ok {
|
||||||
|
name, _, ver := splitDep(pkg)
|
||||||
|
if ver != "" {
|
||||||
|
toQuery = append(toQuery, name, name+"-"+ver)
|
||||||
|
} else {
|
||||||
|
toQuery = append(toQuery, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := query.AURInfo(ctx, dp.aurClient, toQuery, dp.Warnings, splitN)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range info {
|
||||||
|
// Dump everything in cache just in case we need it later
|
||||||
|
pkg := &info[i]
|
||||||
|
dp.AurCache[pkg.Name] = pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute dependency lists used in Package dep searching and ordering.
|
||||||
|
// Order sensitive TOFIX.
|
||||||
|
func ComputeCombinedDepList(pkg *aur.Pkg, noDeps, noCheckDeps bool) []string {
|
||||||
|
combinedDepList := make([]string, 0, len(pkg.Depends)+len(pkg.MakeDepends)+len(pkg.CheckDepends))
|
||||||
|
|
||||||
|
if !noDeps {
|
||||||
|
combinedDepList = append(combinedDepList, pkg.Depends...)
|
||||||
|
}
|
||||||
|
|
||||||
|
combinedDepList = append(combinedDepList, pkg.MakeDepends...)
|
||||||
|
|
||||||
|
if !noCheckDeps {
|
||||||
|
combinedDepList = append(combinedDepList, pkg.CheckDepends...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinedDepList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) resolveAURPackages(ctx context.Context,
|
||||||
|
pkgs stringset.StringSet,
|
||||||
|
explicit, ignoreProviders, noConfirm, provides bool,
|
||||||
|
rebuild string, splitN int, noDeps, noCheckDeps bool,
|
||||||
|
) error {
|
||||||
|
newPackages := make(stringset.StringSet)
|
||||||
|
newAURPackages := make(stringset.StringSet)
|
||||||
|
|
||||||
|
err := dp.cacheAURPackages(ctx, pkgs, provides, splitN)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pkgs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for name := range pkgs {
|
||||||
|
_, ok := dp.Aur[name]
|
||||||
|
if ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg := dp.findSatisfierAurCache(name, ignoreProviders, noConfirm, provides)
|
||||||
|
if pkg == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if explicit {
|
||||||
|
dp.Explicit.Set(pkg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
dp.Aur[pkg.Name] = pkg
|
||||||
|
|
||||||
|
combinedDepList := ComputeCombinedDepList(pkg, noDeps, noCheckDeps)
|
||||||
|
for _, dep := range combinedDepList {
|
||||||
|
newPackages.Set(dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for dep := range newPackages {
|
||||||
|
if dp.hasSatisfier(dep) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
isInstalled := dp.AlpmExecutor.LocalSatisfierExists(dep)
|
||||||
|
hm := settings.HideMenus
|
||||||
|
settings.HideMenus = isInstalled
|
||||||
|
repoPkg := dp.AlpmExecutor.SyncSatisfier(dep) // has satisfier in repo: fetch it
|
||||||
|
settings.HideMenus = hm
|
||||||
|
|
||||||
|
if isInstalled && (rebuild != "tree" || repoPkg != nil) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoPkg != nil {
|
||||||
|
dp.ResolveRepoDependency(repoPkg, false)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// assume it's in the aur
|
||||||
|
// ditch the versioning because the RPC can't handle it
|
||||||
|
newAURPackages.Set(dep)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dp.resolveAURPackages(ctx, newAURPackages, false, ignoreProviders,
|
||||||
|
noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) ResolveRepoDependency(pkg db.IPackage, noDeps bool) {
|
||||||
|
dp.Repo[pkg.Name()] = pkg
|
||||||
|
|
||||||
|
if noDeps {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dep := range dp.AlpmExecutor.PackageDepends(pkg) {
|
||||||
|
if dp.hasSatisfier(dep.String()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// has satisfier installed: skip
|
||||||
|
if dp.AlpmExecutor.LocalSatisfierExists(dep.String()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// has satisfier in repo: fetch it
|
||||||
|
if repoPkg := dp.AlpmExecutor.SyncSatisfier(dep.String()); repoPkg != nil {
|
||||||
|
dp.ResolveRepoDependency(repoPkg, noDeps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPool(ctx context.Context, pkgs []string,
|
||||||
|
warnings *query.AURWarnings,
|
||||||
|
dbExecutor db.Executor,
|
||||||
|
aurClient rpc.ClientInterface,
|
||||||
|
mode parser.TargetMode,
|
||||||
|
ignoreProviders, noConfirm, provides bool,
|
||||||
|
rebuild string, splitN int, noDeps bool, noCheckDeps bool, assumeInstalled []string,
|
||||||
|
) (*Pool, error) {
|
||||||
|
dp := newPool(dbExecutor, aurClient)
|
||||||
|
|
||||||
|
dp.Warnings = warnings
|
||||||
|
err := dp.ResolveTargets(ctx, pkgs, mode, ignoreProviders, noConfirm, provides,
|
||||||
|
rebuild, splitN, noDeps, noCheckDeps, assumeInstalled)
|
||||||
|
|
||||||
|
return dp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) findSatisfierAur(dep string) *query.Pkg {
|
||||||
|
for _, pkg := range dp.Aur {
|
||||||
|
if satisfiesAur(dep, pkg) {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is mostly used to promote packages from the cache
|
||||||
|
// to the Install list
|
||||||
|
// Provide a pacman style provider menu if there's more than one candidate
|
||||||
|
// This acts slightly differently from Pacman, It will give
|
||||||
|
// a menu even if a package with a matching name exists. I believe this
|
||||||
|
// method is better because most of the time you are choosing between
|
||||||
|
// foo and foo-git.
|
||||||
|
// Using Pacman's ways trying to install foo would never give you
|
||||||
|
// a menu.
|
||||||
|
// TODO: maybe intermix repo providers in the menu.
|
||||||
|
func (dp *Pool) findSatisfierAurCache(dep string, ignoreProviders, noConfirm, provides bool) *query.Pkg {
|
||||||
|
depName, _, _ := splitDep(dep)
|
||||||
|
seen := make(stringset.StringSet)
|
||||||
|
providerSlice := makeProviders(depName)
|
||||||
|
|
||||||
|
if dp.AlpmExecutor.LocalPackage(depName) != nil {
|
||||||
|
if pkg, ok := dp.AurCache[dep]; ok && pkgSatisfies(pkg.Name, pkg.Version, dep) {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ignoreProviders {
|
||||||
|
for _, pkg := range dp.AurCache {
|
||||||
|
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
|
||||||
|
for _, target := range dp.Targets {
|
||||||
|
if target.Name == pkg.Name {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.AurCache {
|
||||||
|
if seen.Get(pkg.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
|
||||||
|
providerSlice.Pkgs = append(providerSlice.Pkgs, pkg)
|
||||||
|
seen.Set(pkg.Name)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, provide := range pkg.Provides {
|
||||||
|
if provideSatisfies(provide, dep, pkg.Version) {
|
||||||
|
providerSlice.Pkgs = append(providerSlice.Pkgs, pkg)
|
||||||
|
seen.Set(pkg.Name)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !provides && providerSlice.Len() >= 1 {
|
||||||
|
return providerSlice.Pkgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if providerSlice.Len() == 1 {
|
||||||
|
return providerSlice.Pkgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if providerSlice.Len() > 1 {
|
||||||
|
sort.Sort(providerSlice)
|
||||||
|
return providerMenu(dep, providerSlice, noConfirm)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) findSatisfierRepo(dep string) db.IPackage {
|
||||||
|
for _, pkg := range dp.Repo {
|
||||||
|
if satisfiesRepo(dep, pkg, dp.AlpmExecutor) {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) hasSatisfier(dep string) bool {
|
||||||
|
return dp.findSatisfierRepo(dep) != nil || dp.findSatisfierAur(dep) != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *Pool) hasPackage(name string) bool {
|
||||||
|
for _, pkg := range dp.Repo {
|
||||||
|
if pkg.Name() == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Aur {
|
||||||
|
if pkg.Name == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range dp.Groups {
|
||||||
|
if pkg == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInAssumeInstalled(name string, assumeInstalled []string) bool {
|
||||||
|
for _, pkgAndVersion := range assumeInstalled {
|
||||||
|
assumeName, _, _ := splitDep(pkgAndVersion)
|
||||||
|
|
||||||
|
depName, _, _ := splitDep(name)
|
||||||
|
if assumeName == depName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func providerMenu(dep string, providers providers, noConfirm bool) *query.Pkg {
|
||||||
|
size := providers.Len()
|
||||||
|
|
||||||
|
str := text.Bold(gotext.Get("There are %d providers available for %s:", size, dep))
|
||||||
|
str += "\n"
|
||||||
|
|
||||||
|
size = 1
|
||||||
|
str += text.SprintOperationInfo(gotext.Get("Repository AUR"), "\n ")
|
||||||
|
|
||||||
|
for _, pkg := range providers.Pkgs {
|
||||||
|
str += fmt.Sprintf("%d) %s ", size, pkg.Name)
|
||||||
|
size++
|
||||||
|
}
|
||||||
|
|
||||||
|
text.OperationInfoln(str)
|
||||||
|
|
||||||
|
for {
|
||||||
|
fmt.Println(gotext.Get("\nEnter a number (default=1): "))
|
||||||
|
|
||||||
|
if noConfirm {
|
||||||
|
fmt.Println("1")
|
||||||
|
return providers.Pkgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
numberBuf, err := text.GetInput(os.Stdin, "", false)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if numberBuf == "" {
|
||||||
|
return providers.Pkgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
num, err := strconv.Atoi(numberBuf)
|
||||||
|
if err != nil {
|
||||||
|
text.Errorln(gotext.Get("invalid number: %s", numberBuf))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if num < 1 || num >= size {
|
||||||
|
text.Errorln(gotext.Get("invalid value: %d is not between %d and %d", num, 1, size-1))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return providers.Pkgs[num-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -12,10 +12,10 @@ import (
|
|||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
"github.com/Jguer/yay/v12/pkg/dep/topo"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/intrange"
|
"github.com/Jguer/yay/v12/pkg/intrange"
|
||||||
aur "github.com/Jguer/yay/v12/pkg/query"
|
aur "github.com/Jguer/yay/v12/pkg/query"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/topo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstallInfo struct {
|
type InstallInfo struct {
|
||||||
@ -27,7 +27,6 @@ type InstallInfo struct {
|
|||||||
AURBase *string
|
AURBase *string
|
||||||
SyncDBName *string
|
SyncDBName *string
|
||||||
|
|
||||||
IsGroup bool
|
|
||||||
Upgrade bool
|
Upgrade bool
|
||||||
Devel bool
|
Devel bool
|
||||||
}
|
}
|
||||||
@ -37,7 +36,7 @@ func (i *InstallInfo) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Reason uint
|
Reason int
|
||||||
Source int
|
Source int
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -123,15 +122,11 @@ func NewGrapher(dbExecutor db.Executor, aurCache aurc.QueryClient,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGraph() *topo.Graph[string, *InstallInfo] {
|
|
||||||
return topo.New[string, *InstallInfo]()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Grapher) GraphFromTargets(ctx context.Context,
|
func (g *Grapher) GraphFromTargets(ctx context.Context,
|
||||||
graph *topo.Graph[string, *InstallInfo], targets []string,
|
graph *topo.Graph[string, *InstallInfo], targets []string,
|
||||||
) (*topo.Graph[string, *InstallInfo], error) {
|
) (*topo.Graph[string, *InstallInfo], error) {
|
||||||
if graph == nil {
|
if graph == nil {
|
||||||
graph = NewGraph()
|
graph = topo.New[string, *InstallInfo]()
|
||||||
}
|
}
|
||||||
|
|
||||||
aurTargets := make([]string, 0, len(targets))
|
aurTargets := make([]string, 0, len(targets))
|
||||||
@ -142,7 +137,25 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
|
|||||||
switch target.DB {
|
switch target.DB {
|
||||||
case "": // unspecified db
|
case "": // unspecified db
|
||||||
if pkg := g.dbExecutor.SyncSatisfier(target.Name); pkg != nil {
|
if pkg := g.dbExecutor.SyncSatisfier(target.Name); pkg != nil {
|
||||||
g.GraphSyncPkg(ctx, graph, pkg, nil)
|
dbName := pkg.DB().Name()
|
||||||
|
graph.AddNode(pkg.Name())
|
||||||
|
g.ValidateAndSetNodeInfo(graph, pkg.Name(), &topo.NodeInfo[*InstallInfo]{
|
||||||
|
Color: colorMap[Explicit],
|
||||||
|
Background: bgColorMap[Sync],
|
||||||
|
Value: &InstallInfo{
|
||||||
|
Source: Sync,
|
||||||
|
Reason: Explicit,
|
||||||
|
Version: pkg.Version(),
|
||||||
|
SyncDBName: &dbName,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
g.GraphSyncPkg(ctx, graph, pkg, &InstallInfo{
|
||||||
|
Source: Sync,
|
||||||
|
Reason: Explicit,
|
||||||
|
Version: pkg.Version(),
|
||||||
|
SyncDBName: &dbName,
|
||||||
|
})
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -150,7 +163,17 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
|
|||||||
groupPackages := g.dbExecutor.PackagesFromGroup(target.Name)
|
groupPackages := g.dbExecutor.PackagesFromGroup(target.Name)
|
||||||
if len(groupPackages) > 0 {
|
if len(groupPackages) > 0 {
|
||||||
dbName := groupPackages[0].DB().Name()
|
dbName := groupPackages[0].DB().Name()
|
||||||
g.GraphSyncGroup(ctx, graph, target.Name, dbName)
|
graph.AddNode(target.Name)
|
||||||
|
g.ValidateAndSetNodeInfo(graph, target.Name, &topo.NodeInfo[*InstallInfo]{
|
||||||
|
Color: colorMap[Explicit],
|
||||||
|
Background: bgColorMap[Sync],
|
||||||
|
Value: &InstallInfo{
|
||||||
|
Source: Sync,
|
||||||
|
Reason: Explicit,
|
||||||
|
Version: "",
|
||||||
|
SyncDBName: &dbName,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -159,26 +182,17 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
|
|||||||
case "aur":
|
case "aur":
|
||||||
aurTargets = append(aurTargets, target.Name)
|
aurTargets = append(aurTargets, target.Name)
|
||||||
default:
|
default:
|
||||||
pkg, err := g.dbExecutor.SatisfierFromDB(target.Name, target.DB)
|
graph.AddNode(target.Name)
|
||||||
if err != nil {
|
g.ValidateAndSetNodeInfo(graph, target.Name, &topo.NodeInfo[*InstallInfo]{
|
||||||
return nil, err
|
Color: colorMap[Explicit],
|
||||||
}
|
Background: bgColorMap[Sync],
|
||||||
if pkg != nil {
|
Value: &InstallInfo{
|
||||||
g.GraphSyncPkg(ctx, graph, pkg, nil)
|
Source: Sync,
|
||||||
continue
|
Reason: Explicit,
|
||||||
}
|
Version: target.Version,
|
||||||
|
SyncDBName: &target.DB,
|
||||||
groupPackages, err := g.dbExecutor.PackagesFromGroupAndDB(target.Name, target.DB)
|
},
|
||||||
if err != nil {
|
})
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(groupPackages) > 0 {
|
|
||||||
g.GraphSyncGroup(ctx, graph, target.Name, target.DB)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
g.logger.Errorln(gotext.Get("No package found for"), " ", target)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +205,8 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
|
|||||||
return graph, nil
|
return graph, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Grapher) pickSrcInfoPkgs(pkgs []*aurc.Pkg) ([]*aurc.Pkg, error) {
|
func (g *Grapher) pickSrcInfoPkgs(pkgs []aurc.Pkg) ([]aurc.Pkg, error) {
|
||||||
final := make([]*aurc.Pkg, 0, len(pkgs))
|
final := make([]aurc.Pkg, 0, len(pkgs))
|
||||||
for i := range pkgs {
|
for i := range pkgs {
|
||||||
g.logger.Println(text.Magenta(strconv.Itoa(i+1)+" ") + text.Bold(pkgs[i].Name) +
|
g.logger.Println(text.Magenta(strconv.Itoa(i+1)+" ") + text.Bold(pkgs[i].Name) +
|
||||||
" " + text.Cyan(pkgs[i].Version))
|
" " + text.Cyan(pkgs[i].Version))
|
||||||
@ -206,7 +220,7 @@ func (g *Grapher) pickSrcInfoPkgs(pkgs []*aurc.Pkg) ([]*aurc.Pkg, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
include, exclude, _, otherExclude := intrange.ParseNumberMenu(numberBuf)
|
include, exclude, _, otherExclude := intrange.ParseNumberMenu(numberBuf)
|
||||||
isInclude := len(exclude) == 0 && otherExclude.Cardinality() == 0
|
isInclude := len(exclude) == 0 && len(otherExclude) == 0
|
||||||
|
|
||||||
for i := 1; i <= len(pkgs); i++ {
|
for i := 1; i <= len(pkgs); i++ {
|
||||||
target := i - 1
|
target := i - 1
|
||||||
@ -223,79 +237,46 @@ func (g *Grapher) pickSrcInfoPkgs(pkgs []*aurc.Pkg) ([]*aurc.Pkg, error) {
|
|||||||
return final, nil
|
return final, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Grapher) addAurPkgProvides(pkg *aurc.Pkg, graph *topo.Graph[string, *InstallInfo]) {
|
func (g *Grapher) GraphFromSrcInfo(ctx context.Context, graph *topo.Graph[string, *InstallInfo], pkgBuildDir string,
|
||||||
for i := range pkg.Provides {
|
pkgbuild *gosrc.Srcinfo,
|
||||||
depName, mod, version := splitDep(pkg.Provides[i])
|
|
||||||
g.logger.Debugln(pkg.String() + " provides: " + depName)
|
|
||||||
graph.Provides(depName, &alpm.Depend{
|
|
||||||
Name: depName,
|
|
||||||
Version: version,
|
|
||||||
Mod: aurDepModToAlpmDep(mod),
|
|
||||||
}, pkg.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Grapher) GraphFromSrcInfos(ctx context.Context, graph *topo.Graph[string, *InstallInfo],
|
|
||||||
srcInfos map[string]*gosrc.Srcinfo,
|
|
||||||
) (*topo.Graph[string, *InstallInfo], error) {
|
) (*topo.Graph[string, *InstallInfo], error) {
|
||||||
if graph == nil {
|
if graph == nil {
|
||||||
graph = NewGraph()
|
graph = topo.New[string, *InstallInfo]()
|
||||||
}
|
}
|
||||||
|
|
||||||
aurPkgsAdded := []*aurc.Pkg{}
|
aurPkgs, err := makeAURPKGFromSrcinfo(g.dbExecutor, pkgbuild)
|
||||||
for pkgBuildDir, pkgbuild := range srcInfos {
|
if err != nil {
|
||||||
pkgBuildDir := pkgBuildDir
|
return nil, err
|
||||||
|
|
||||||
aurPkgs, err := makeAURPKGFromSrcinfo(g.dbExecutor, pkgbuild)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aurPkgs) > 1 {
|
|
||||||
var errPick error
|
|
||||||
aurPkgs, errPick = g.pickSrcInfoPkgs(aurPkgs)
|
|
||||||
if errPick != nil {
|
|
||||||
return nil, errPick
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pkg := range aurPkgs {
|
|
||||||
pkg := pkg
|
|
||||||
|
|
||||||
reason := Explicit
|
|
||||||
if pkg := g.dbExecutor.LocalPackage(pkg.Name); pkg != nil {
|
|
||||||
reason = Reason(pkg.Reason())
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.AddNode(pkg.Name)
|
|
||||||
|
|
||||||
g.addAurPkgProvides(pkg, graph)
|
|
||||||
|
|
||||||
g.ValidateAndSetNodeInfo(graph, pkg.Name, &topo.NodeInfo[*InstallInfo]{
|
|
||||||
Color: colorMap[reason],
|
|
||||||
Background: bgColorMap[AUR],
|
|
||||||
Value: &InstallInfo{
|
|
||||||
Source: SrcInfo,
|
|
||||||
Reason: reason,
|
|
||||||
SrcinfoPath: &pkgBuildDir,
|
|
||||||
AURBase: &pkg.PackageBase,
|
|
||||||
Version: pkg.Version,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
aurPkgsAdded = append(aurPkgsAdded, aurPkgs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.AddDepsForPkgs(ctx, aurPkgsAdded, graph)
|
if len(aurPkgs) > 1 {
|
||||||
|
var errPick error
|
||||||
|
aurPkgs, errPick = g.pickSrcInfoPkgs(aurPkgs)
|
||||||
|
if errPick != nil {
|
||||||
|
return nil, errPick
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return graph, nil
|
for i := range aurPkgs {
|
||||||
}
|
pkg := &aurPkgs[i]
|
||||||
|
|
||||||
|
graph.AddNode(pkg.Name)
|
||||||
|
g.ValidateAndSetNodeInfo(graph, pkg.Name, &topo.NodeInfo[*InstallInfo]{
|
||||||
|
Color: colorMap[Explicit],
|
||||||
|
Background: bgColorMap[AUR],
|
||||||
|
Value: &InstallInfo{
|
||||||
|
Source: SrcInfo,
|
||||||
|
Reason: Explicit,
|
||||||
|
SrcinfoPath: &pkgBuildDir,
|
||||||
|
AURBase: &pkg.PackageBase,
|
||||||
|
Version: pkg.Version,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
func (g *Grapher) AddDepsForPkgs(ctx context.Context, pkgs []*aur.Pkg, graph *topo.Graph[string, *InstallInfo]) {
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
g.addDepNodes(ctx, pkg, graph)
|
g.addDepNodes(ctx, pkg, graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return graph, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Grapher) addDepNodes(ctx context.Context, pkg *aur.Pkg, graph *topo.Graph[string, *InstallInfo]) {
|
func (g *Grapher) addDepNodes(ctx context.Context, pkg *aur.Pkg, graph *topo.Graph[string, *InstallInfo]) {
|
||||||
@ -314,66 +295,17 @@ func (g *Grapher) addDepNodes(ctx context.Context, pkg *aur.Pkg, graph *topo.Gra
|
|||||||
|
|
||||||
func (g *Grapher) GraphSyncPkg(ctx context.Context,
|
func (g *Grapher) GraphSyncPkg(ctx context.Context,
|
||||||
graph *topo.Graph[string, *InstallInfo],
|
graph *topo.Graph[string, *InstallInfo],
|
||||||
pkg alpm.IPackage, upgradeInfo *db.SyncUpgrade,
|
pkg alpm.IPackage, instalInfo *InstallInfo,
|
||||||
) *topo.Graph[string, *InstallInfo] {
|
) *topo.Graph[string, *InstallInfo] {
|
||||||
if graph == nil {
|
if graph == nil {
|
||||||
graph = NewGraph()
|
graph = topo.New[string, *InstallInfo]()
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.AddNode(pkg.Name())
|
graph.AddNode(pkg.Name())
|
||||||
_ = pkg.Provides().ForEach(func(p *alpm.Depend) error {
|
|
||||||
g.logger.Debugln(pkg.Name() + " provides: " + p.String())
|
|
||||||
graph.Provides(p.Name, p, pkg.Name())
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
dbName := pkg.DB().Name()
|
|
||||||
info := &InstallInfo{
|
|
||||||
Source: Sync,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: pkg.Version(),
|
|
||||||
SyncDBName: &dbName,
|
|
||||||
}
|
|
||||||
|
|
||||||
if upgradeInfo == nil {
|
|
||||||
if localPkg := g.dbExecutor.LocalPackage(pkg.Name()); localPkg != nil {
|
|
||||||
info.Reason = Reason(localPkg.Reason())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info.Upgrade = true
|
|
||||||
info.Reason = Reason(upgradeInfo.Reason)
|
|
||||||
info.LocalVersion = upgradeInfo.LocalVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
g.ValidateAndSetNodeInfo(graph, pkg.Name(), &topo.NodeInfo[*InstallInfo]{
|
g.ValidateAndSetNodeInfo(graph, pkg.Name(), &topo.NodeInfo[*InstallInfo]{
|
||||||
Color: colorMap[info.Reason],
|
|
||||||
Background: bgColorMap[info.Source],
|
|
||||||
Value: info,
|
|
||||||
})
|
|
||||||
|
|
||||||
return graph
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Grapher) GraphSyncGroup(ctx context.Context,
|
|
||||||
graph *topo.Graph[string, *InstallInfo],
|
|
||||||
groupName, dbName string,
|
|
||||||
) *topo.Graph[string, *InstallInfo] {
|
|
||||||
if graph == nil {
|
|
||||||
graph = NewGraph()
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.AddNode(groupName)
|
|
||||||
|
|
||||||
g.ValidateAndSetNodeInfo(graph, groupName, &topo.NodeInfo[*InstallInfo]{
|
|
||||||
Color: colorMap[Explicit],
|
Color: colorMap[Explicit],
|
||||||
Background: bgColorMap[Sync],
|
Background: bgColorMap[Sync],
|
||||||
Value: &InstallInfo{
|
Value: instalInfo,
|
||||||
Source: Sync,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "",
|
|
||||||
SyncDBName: &dbName,
|
|
||||||
IsGroup: true,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return graph
|
return graph
|
||||||
@ -384,19 +316,18 @@ func (g *Grapher) GraphAURTarget(ctx context.Context,
|
|||||||
pkg *aurc.Pkg, instalInfo *InstallInfo,
|
pkg *aurc.Pkg, instalInfo *InstallInfo,
|
||||||
) *topo.Graph[string, *InstallInfo] {
|
) *topo.Graph[string, *InstallInfo] {
|
||||||
if graph == nil {
|
if graph == nil {
|
||||||
graph = NewGraph()
|
graph = topo.New[string, *InstallInfo]()
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.AddNode(pkg.Name)
|
graph.AddNode(pkg.Name)
|
||||||
|
|
||||||
g.addAurPkgProvides(pkg, graph)
|
|
||||||
|
|
||||||
g.ValidateAndSetNodeInfo(graph, pkg.Name, &topo.NodeInfo[*InstallInfo]{
|
g.ValidateAndSetNodeInfo(graph, pkg.Name, &topo.NodeInfo[*InstallInfo]{
|
||||||
Color: colorMap[instalInfo.Reason],
|
Color: colorMap[Explicit],
|
||||||
Background: bgColorMap[AUR],
|
Background: bgColorMap[AUR],
|
||||||
Value: instalInfo,
|
Value: instalInfo,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
g.addDepNodes(ctx, pkg, graph)
|
||||||
|
|
||||||
return graph
|
return graph
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +336,7 @@ func (g *Grapher) GraphFromAUR(ctx context.Context,
|
|||||||
targets []string,
|
targets []string,
|
||||||
) (*topo.Graph[string, *InstallInfo], error) {
|
) (*topo.Graph[string, *InstallInfo], error) {
|
||||||
if graph == nil {
|
if graph == nil {
|
||||||
graph = NewGraph()
|
graph = topo.New[string, *InstallInfo]()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(targets) == 0 {
|
if len(targets) == 0 {
|
||||||
@ -424,8 +355,6 @@ func (g *Grapher) GraphFromAUR(ctx context.Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aurPkgsAdded := []*aurc.Pkg{}
|
|
||||||
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
if cachedProvidePkg, ok := g.providerCache[target]; ok {
|
if cachedProvidePkg, ok := g.providerCache[target]; ok {
|
||||||
aurPkgs = cachedProvidePkg
|
aurPkgs = cachedProvidePkg
|
||||||
@ -433,7 +362,7 @@ func (g *Grapher) GraphFromAUR(ctx context.Context,
|
|||||||
var errA error
|
var errA error
|
||||||
aurPkgs, errA = g.aurClient.Get(ctx, &aurc.Query{By: aurc.Provides, Needles: []string{target}, Contains: true})
|
aurPkgs, errA = g.aurClient.Get(ctx, &aurc.Query{By: aurc.Provides, Needles: []string{target}, Contains: true})
|
||||||
if errA != nil {
|
if errA != nil {
|
||||||
g.logger.Errorln(gotext.Get("Failed to find AUR package for"), " ", target, ":", errA)
|
g.logger.Errorln(gotext.Get("Failed to find AUR package for"), target, ":", errA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,11 +379,8 @@ func (g *Grapher) GraphFromAUR(ctx context.Context,
|
|||||||
g.providerCache[target] = []aurc.Pkg{*aurPkg}
|
g.providerCache[target] = []aurc.Pkg{*aurPkg}
|
||||||
}
|
}
|
||||||
|
|
||||||
reason := Explicit
|
if g.needed {
|
||||||
if pkg := g.dbExecutor.LocalPackage(aurPkg.Name); pkg != nil {
|
if pkg := g.dbExecutor.LocalPackage(aurPkg.Name); pkg != nil {
|
||||||
reason = Reason(pkg.Reason())
|
|
||||||
|
|
||||||
if g.needed {
|
|
||||||
if db.VerCmp(pkg.Version(), aurPkg.Version) >= 0 {
|
if db.VerCmp(pkg.Version(), aurPkg.Version) >= 0 {
|
||||||
g.logger.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(pkg.Name()+"-"+pkg.Version())))
|
g.logger.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(pkg.Name()+"-"+pkg.Version())))
|
||||||
continue
|
continue
|
||||||
@ -464,15 +390,12 @@ func (g *Grapher) GraphFromAUR(ctx context.Context,
|
|||||||
|
|
||||||
graph = g.GraphAURTarget(ctx, graph, aurPkg, &InstallInfo{
|
graph = g.GraphAURTarget(ctx, graph, aurPkg, &InstallInfo{
|
||||||
AURBase: &aurPkg.PackageBase,
|
AURBase: &aurPkg.PackageBase,
|
||||||
Reason: reason,
|
Reason: Explicit,
|
||||||
Source: AUR,
|
Source: AUR,
|
||||||
Version: aurPkg.Version,
|
Version: aurPkg.Version,
|
||||||
})
|
})
|
||||||
aurPkgsAdded = append(aurPkgsAdded, aurPkg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.AddDepsForPkgs(ctx, aurPkgsAdded, graph)
|
|
||||||
|
|
||||||
return graph, nil
|
return graph, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,18 +429,15 @@ func (g *Grapher) findDepsFromAUR(ctx context.Context,
|
|||||||
|
|
||||||
for i := range aurPkgs {
|
for i := range aurPkgs {
|
||||||
pkg := &aurPkgs[i]
|
pkg := &aurPkgs[i]
|
||||||
if deps.Contains(pkg.Name) {
|
|
||||||
g.providerCache[pkg.Name] = append(g.providerCache[pkg.Name], *pkg)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, val := range pkg.Provides {
|
for _, val := range pkg.Provides {
|
||||||
if val == pkg.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if deps.Contains(val) {
|
if deps.Contains(val) {
|
||||||
g.providerCache[val] = append(g.providerCache[val], *pkg)
|
g.providerCache[val] = append(g.providerCache[val], *pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if deps.Contains(pkg.Name) {
|
||||||
|
g.providerCache[pkg.Name] = append(g.providerCache[pkg.Name], *pkg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,13 +456,12 @@ func (g *Grapher) findDepsFromAUR(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove packages that don't satisfy the dependency
|
// remove packages that don't satisfy the dependency
|
||||||
satisfyingPkgs := make([]aurc.Pkg, 0, len(aurPkgs))
|
for i := 0; i < len(aurPkgs); i++ {
|
||||||
for i := range aurPkgs {
|
if !satisfiesAur(depString, &aurPkgs[i]) {
|
||||||
if satisfiesAur(depString, &aurPkgs[i]) {
|
aurPkgs = append(aurPkgs[:i], aurPkgs[i+1:]...)
|
||||||
satisfyingPkgs = append(satisfyingPkgs, aurPkgs[i])
|
i--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aurPkgs = satisfyingPkgs
|
|
||||||
|
|
||||||
if len(aurPkgs) == 0 {
|
if len(aurPkgs) == 0 {
|
||||||
g.logger.Errorln(gotext.Get("No AUR package found for"), " ", depString)
|
g.logger.Errorln(gotext.Get("No AUR package found for"), " ", depString)
|
||||||
@ -569,13 +488,9 @@ func (g *Grapher) ValidateAndSetNodeInfo(graph *topo.Graph[string, *InstallInfo]
|
|||||||
) {
|
) {
|
||||||
info := graph.GetNodeInfo(node)
|
info := graph.GetNodeInfo(node)
|
||||||
if info != nil && info.Value != nil {
|
if info != nil && info.Value != nil {
|
||||||
if info.Value.Reason < nodeInfo.Value.Reason {
|
if info.Value.Reason <= nodeInfo.Value.Reason {
|
||||||
return // refuse to downgrade reason
|
return // refuse to downgrade reason
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.Value.Upgrade {
|
|
||||||
return // refuse to overwrite an upgrade
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.SetNodeInfo(node, nodeInfo)
|
graph.SetNodeInfo(node, nodeInfo)
|
||||||
@ -592,27 +507,15 @@ func (g *Grapher) addNodes(
|
|||||||
// Check if in graph already
|
// Check if in graph already
|
||||||
for _, depString := range targetsToFind.ToSlice() {
|
for _, depString := range targetsToFind.ToSlice() {
|
||||||
depName, _, _ := splitDep(depString)
|
depName, _, _ := splitDep(depString)
|
||||||
if !graph.Exists(depName) && !graph.ProvidesExists(depName) {
|
if !graph.Exists(depName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if graph.Exists(depName) {
|
if err := graph.DependOn(depName, parentPkgName); err != nil {
|
||||||
if err := graph.DependOn(depName, parentPkgName); err != nil {
|
g.logger.Warnln(depString, parentPkgName, err)
|
||||||
g.logger.Warnln(depString, parentPkgName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
targetsToFind.Remove(depString)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p := graph.GetProviderNode(depName); p != nil {
|
targetsToFind.Remove(depString)
|
||||||
if provideSatisfies(p.String(), depString, p.Version) {
|
|
||||||
if err := graph.DependOn(p.Provider, parentPkgName); err != nil {
|
|
||||||
g.logger.Warnln(p.Provider, parentPkgName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
targetsToFind.Remove(depString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check installed
|
// Check installed
|
||||||
@ -702,9 +605,7 @@ func (g *Grapher) addNodes(
|
|||||||
for _, depString := range targetsToFind.ToSlice() {
|
for _, depString := range targetsToFind.ToSlice() {
|
||||||
depName, mod, ver := splitDep(depString)
|
depName, mod, ver := splitDep(depString)
|
||||||
// no dep found. add as missing
|
// no dep found. add as missing
|
||||||
if err := graph.DependOn(depName, parentPkgName); err != nil {
|
graph.AddNode(depName)
|
||||||
g.logger.Warnln("missing dep warn:", depString, parentPkgName, err)
|
|
||||||
}
|
|
||||||
graph.SetNodeInfo(depName, &topo.NodeInfo[*InstallInfo]{
|
graph.SetNodeInfo(depName, &topo.NodeInfo[*InstallInfo]{
|
||||||
Color: colorMap[depType],
|
Color: colorMap[depType],
|
||||||
Background: bgColorMap[Missing],
|
Background: bgColorMap[Missing],
|
||||||
@ -723,7 +624,7 @@ func (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {
|
|||||||
return &options[0]
|
return &options[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
str := text.Bold(gotext.Get("There are %[1]d providers available for %[2]s:", size, dep))
|
str := text.Bold(gotext.Get("There are %d providers available for %s:", size, dep))
|
||||||
str += "\n"
|
str += "\n"
|
||||||
|
|
||||||
size = 1
|
size = 1
|
||||||
@ -749,7 +650,7 @@ func (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Errorln(err)
|
g.logger.Errorln(err)
|
||||||
|
|
||||||
return &options[0]
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if numberBuf == "" {
|
if numberBuf == "" {
|
||||||
@ -772,10 +673,12 @@ func (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {
|
|||||||
|
|
||||||
return &options[num-1]
|
return &options[num-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]*aur.Pkg, error) {
|
func makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]aur.Pkg, error) {
|
||||||
pkgs := make([]*aur.Pkg, 0, 1)
|
pkgs := make([]aur.Pkg, 0, 1)
|
||||||
|
|
||||||
alpmArch, err := dbExecutor.AlpmArchitectures()
|
alpmArch, err := dbExecutor.AlpmArchitectures()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -795,7 +698,7 @@ func makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]*a
|
|||||||
for i := range srcInfo.Packages {
|
for i := range srcInfo.Packages {
|
||||||
pkg := &srcInfo.Packages[i]
|
pkg := &srcInfo.Packages[i]
|
||||||
|
|
||||||
pkgs = append(pkgs, &aur.Pkg{
|
pkgs = append(pkgs, aur.Pkg{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Name: pkg.Pkgname,
|
Name: pkg.Pkgname,
|
||||||
PackageBaseID: 0,
|
PackageBaseID: 0,
|
||||||
@ -804,20 +707,19 @@ func makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]*a
|
|||||||
Description: getDesc(pkg),
|
Description: getDesc(pkg),
|
||||||
URL: pkg.URL,
|
URL: pkg.URL,
|
||||||
Depends: append(archStringToString(alpmArch, pkg.Depends),
|
Depends: append(archStringToString(alpmArch, pkg.Depends),
|
||||||
archStringToString(alpmArch, srcInfo.Depends)...),
|
archStringToString(alpmArch, srcInfo.Package.Depends)...),
|
||||||
MakeDepends: archStringToString(alpmArch, srcInfo.MakeDepends),
|
MakeDepends: archStringToString(alpmArch, srcInfo.PackageBase.MakeDepends),
|
||||||
CheckDepends: archStringToString(alpmArch, srcInfo.CheckDepends),
|
CheckDepends: archStringToString(alpmArch, srcInfo.PackageBase.CheckDepends),
|
||||||
Conflicts: append(archStringToString(alpmArch, pkg.Conflicts),
|
Conflicts: append(archStringToString(alpmArch, pkg.Conflicts),
|
||||||
archStringToString(alpmArch, srcInfo.Conflicts)...),
|
archStringToString(alpmArch, srcInfo.Package.Conflicts)...),
|
||||||
Provides: append(archStringToString(alpmArch, pkg.Provides),
|
Provides: append(archStringToString(alpmArch, pkg.Provides),
|
||||||
archStringToString(alpmArch, srcInfo.Provides)...),
|
archStringToString(alpmArch, srcInfo.Package.Provides)...),
|
||||||
Replaces: append(archStringToString(alpmArch, pkg.Replaces),
|
Replaces: append(archStringToString(alpmArch, pkg.Replaces),
|
||||||
archStringToString(alpmArch, srcInfo.Replaces)...),
|
archStringToString(alpmArch, srcInfo.Package.Replaces)...),
|
||||||
OptDepends: append(archStringToString(alpmArch, pkg.OptDepends),
|
OptDepends: []string{},
|
||||||
archStringToString(alpmArch, srcInfo.OptDepends)...),
|
Groups: pkg.Groups,
|
||||||
Groups: pkg.Groups,
|
License: pkg.License,
|
||||||
License: pkg.License,
|
Keywords: []string{},
|
||||||
Keywords: []string{},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,19 +737,3 @@ func archStringToString(alpmArches []string, archString []gosrc.ArchString) []st
|
|||||||
|
|
||||||
return pkgs
|
return pkgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func aurDepModToAlpmDep(mod string) alpm.DepMod {
|
|
||||||
switch mod {
|
|
||||||
case "=":
|
|
||||||
return alpm.DepModEq
|
|
||||||
case ">=":
|
|
||||||
return alpm.DepModGE
|
|
||||||
case "<=":
|
|
||||||
return alpm.DepModLE
|
|
||||||
case ">":
|
|
||||||
return alpm.DepModGT
|
|
||||||
case "<":
|
|
||||||
return alpm.DepModLT
|
|
||||||
}
|
|
||||||
return alpm.DepModAny
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package dep
|
package dep
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -12,7 +9,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
aurc "github.com/Jguer/aur"
|
aurc "github.com/Jguer/aur"
|
||||||
alpm "github.com/Jguer/go-alpm/v2"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
@ -76,7 +72,6 @@ func TestGrapher_GraphFromTargets_jellyfin(t *testing.T) {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
LocalPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {
|
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {
|
||||||
@ -202,7 +197,7 @@ func TestGrapher_GraphFromTargets_jellyfin(t *testing.T) {
|
|||||||
g := NewGrapher(tt.fields.dbExecutor,
|
g := NewGrapher(tt.fields.dbExecutor,
|
||||||
tt.fields.aurCache, false, true,
|
tt.fields.aurCache, false, true,
|
||||||
tt.fields.noDeps, tt.fields.noCheckDeps, false,
|
tt.fields.noDeps, tt.fields.noCheckDeps, false,
|
||||||
text.NewLogger(io.Discard, io.Discard, &os.File{}, true, "test"))
|
text.NewLogger(io.Discard, &os.File{}, true, "test"))
|
||||||
got, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets)
|
got, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
layers := got.TopoSortedLayerMap(nil)
|
layers := got.TopoSortedLayerMap(nil)
|
||||||
@ -210,602 +205,3 @@ func TestGrapher_GraphFromTargets_jellyfin(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGrapher_GraphProvides_androidsdk(t *testing.T) {
|
|
||||||
mockDB := &mock.DBExecutor{
|
|
||||||
SyncPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
|
||||||
switch s {
|
|
||||||
case "android-sdk":
|
|
||||||
return nil
|
|
||||||
case "jdk11-openjdk":
|
|
||||||
return &mock.Package{
|
|
||||||
PName: "jdk11-openjdk",
|
|
||||||
PVersion: "11.0.12.u7-1",
|
|
||||||
PDB: mock.NewDB("community"),
|
|
||||||
PProvides: mock.DependList{
|
|
||||||
Depends: []alpm.Depend{
|
|
||||||
{Name: "java-environment", Version: "11", Mod: alpm.DepModEq},
|
|
||||||
{Name: "java-environment-openjdk", Version: "11", Mod: alpm.DepModEq},
|
|
||||||
{Name: "jdk11-openjdk", Version: "11.0.19.u7-1", Mod: alpm.DepModEq},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "java-environment":
|
|
||||||
panic("not supposed to be called")
|
|
||||||
}
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
PackagesFromGroupFn: func(string) []mock.IPackage { return nil },
|
|
||||||
LocalSatisfierExistsFn: func(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "java-environment":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case "libxtst", "fontconfig", "freetype2", "lib32-gcc-libs", "lib32-glibc", "libx11", "libxext", "libxrender", "zlib", "gcc-libs":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
}
|
|
||||||
|
|
||||||
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {
|
|
||||||
if query.Needles[0] == "android-sdk" {
|
|
||||||
jfinFn := getFromFile(t, "testdata/android-sdk.json")
|
|
||||||
return jfinFn(ctx, query)
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(fmt.Sprintf("implement me %v", query.Needles))
|
|
||||||
}}
|
|
||||||
|
|
||||||
type fields struct {
|
|
||||||
dbExecutor db.Executor
|
|
||||||
aurCache aurc.QueryClient
|
|
||||||
noDeps bool
|
|
||||||
noCheckDeps bool
|
|
||||||
}
|
|
||||||
type args struct {
|
|
||||||
targets []string
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fields fields
|
|
||||||
args args
|
|
||||||
want []map[string]*InstallInfo
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "explicit dep",
|
|
||||||
fields: fields{
|
|
||||||
dbExecutor: mockDB,
|
|
||||||
aurCache: mockAUR,
|
|
||||||
noDeps: false,
|
|
||||||
noCheckDeps: false,
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
targets: []string{"android-sdk", "jdk11-openjdk"},
|
|
||||||
},
|
|
||||||
want: []map[string]*InstallInfo{
|
|
||||||
{
|
|
||||||
"android-sdk": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "26.1.1-2",
|
|
||||||
AURBase: ptrString("android-sdk"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jdk11-openjdk": {
|
|
||||||
Source: Sync,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "11.0.12.u7-1",
|
|
||||||
SyncDBName: ptrString("community"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
g := NewGrapher(tt.fields.dbExecutor,
|
|
||||||
tt.fields.aurCache, false, true,
|
|
||||||
tt.fields.noDeps, tt.fields.noCheckDeps, false,
|
|
||||||
text.NewLogger(io.Discard, io.Discard, &os.File{}, true, "test"))
|
|
||||||
got, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets)
|
|
||||||
require.NoError(t, err)
|
|
||||||
layers := got.TopoSortedLayerMap(nil)
|
|
||||||
require.EqualValues(t, tt.want, layers, layers)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGrapher_GraphFromAUR_Deps_ceph_bin(t *testing.T) {
|
|
||||||
mockDB := &mock.DBExecutor{
|
|
||||||
SyncPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
PackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
|
||||||
switch s {
|
|
||||||
case "ceph-bin", "ceph-libs-bin":
|
|
||||||
return nil
|
|
||||||
case "ceph", "ceph-libs", "ceph-libs=17.2.6-2":
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
|
|
||||||
LocalSatisfierExistsFn: func(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "ceph-libs", "ceph-libs=17.2.6-2":
|
|
||||||
return false
|
|
||||||
case "dep1", "dep2", "dep3", "makedep1", "makedep2", "checkdep1":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
}
|
|
||||||
|
|
||||||
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {
|
|
||||||
mockPkgs := map[string]aur.Pkg{
|
|
||||||
"ceph-bin": {
|
|
||||||
Name: "ceph-bin",
|
|
||||||
PackageBase: "ceph-bin",
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
Depends: []string{"ceph-libs=17.2.6-2", "dep1"},
|
|
||||||
Provides: []string{"ceph=17.2.6-2"},
|
|
||||||
},
|
|
||||||
"ceph-libs-bin": {
|
|
||||||
Name: "ceph-libs-bin",
|
|
||||||
PackageBase: "ceph-bin",
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
Depends: []string{"dep1", "dep2"},
|
|
||||||
Provides: []string{"ceph-libs=17.2.6-2"},
|
|
||||||
},
|
|
||||||
"ceph": {
|
|
||||||
Name: "ceph",
|
|
||||||
PackageBase: "ceph",
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
Depends: []string{"ceph-libs=17.2.6-2", "dep1"},
|
|
||||||
MakeDepends: []string{"makedep1"},
|
|
||||||
CheckDepends: []string{"checkdep1"},
|
|
||||||
Provides: []string{"ceph=17.2.6-2"},
|
|
||||||
},
|
|
||||||
"ceph-libs": {
|
|
||||||
Name: "ceph-libs",
|
|
||||||
PackageBase: "ceph",
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
Depends: []string{"dep1", "dep2", "dep3"},
|
|
||||||
MakeDepends: []string{"makedep1", "makedep2"},
|
|
||||||
CheckDepends: []string{"checkdep1"},
|
|
||||||
Provides: []string{"ceph-libs=17.2.6-2"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgs := []aur.Pkg{}
|
|
||||||
for _, needle := range query.Needles {
|
|
||||||
if pkg, ok := mockPkgs[needle]; ok {
|
|
||||||
pkgs = append(pkgs, pkg)
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("implement me %v", needle))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgs, nil
|
|
||||||
}}
|
|
||||||
|
|
||||||
installInfos := map[string]*InstallInfo{
|
|
||||||
"ceph-bin exp": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
AURBase: ptrString("ceph-bin"),
|
|
||||||
},
|
|
||||||
"ceph-libs-bin exp": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
AURBase: ptrString("ceph-bin"),
|
|
||||||
},
|
|
||||||
"ceph exp": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
AURBase: ptrString("ceph"),
|
|
||||||
},
|
|
||||||
"ceph-libs exp": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
AURBase: ptrString("ceph"),
|
|
||||||
},
|
|
||||||
"ceph-libs dep": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Dep,
|
|
||||||
Version: "17.2.6-2",
|
|
||||||
AURBase: ptrString("ceph"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
targets []string
|
|
||||||
wantLayers []map[string]*InstallInfo
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "ceph-bin ceph-libs-bin",
|
|
||||||
targets: []string{"ceph-bin", "ceph-libs-bin"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph-bin": installInfos["ceph-bin exp"]},
|
|
||||||
{"ceph-libs-bin": installInfos["ceph-libs-bin exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph-libs-bin ceph-bin (reversed order)",
|
|
||||||
targets: []string{"ceph-libs-bin", "ceph-bin"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph-bin": installInfos["ceph-bin exp"]},
|
|
||||||
{"ceph-libs-bin": installInfos["ceph-libs-bin exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph",
|
|
||||||
targets: []string{"ceph"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph": installInfos["ceph exp"]},
|
|
||||||
{"ceph-libs": installInfos["ceph-libs dep"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph-bin",
|
|
||||||
targets: []string{"ceph-bin"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph-bin": installInfos["ceph-bin exp"]},
|
|
||||||
{"ceph-libs": installInfos["ceph-libs dep"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph-bin ceph-libs",
|
|
||||||
targets: []string{"ceph-bin", "ceph-libs"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph-bin": installInfos["ceph-bin exp"]},
|
|
||||||
{"ceph-libs": installInfos["ceph-libs exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph-libs ceph-bin (reversed order)",
|
|
||||||
targets: []string{"ceph-libs", "ceph-bin"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph-bin": installInfos["ceph-bin exp"]},
|
|
||||||
{"ceph-libs": installInfos["ceph-libs exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph ceph-libs-bin",
|
|
||||||
targets: []string{"ceph", "ceph-libs-bin"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph": installInfos["ceph exp"]},
|
|
||||||
{"ceph-libs-bin": installInfos["ceph-libs-bin exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ceph-libs-bin ceph (reversed order)",
|
|
||||||
targets: []string{"ceph-libs-bin", "ceph"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"ceph": installInfos["ceph exp"]},
|
|
||||||
{"ceph-libs-bin": installInfos["ceph-libs-bin exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
g := NewGrapher(mockDB, mockAUR,
|
|
||||||
false, true, false, false, false,
|
|
||||||
text.NewLogger(io.Discard, io.Discard, &os.File{}, true, "test"))
|
|
||||||
got, err := g.GraphFromTargets(context.Background(), nil, tt.targets)
|
|
||||||
require.NoError(t, err)
|
|
||||||
layers := got.TopoSortedLayerMap(nil)
|
|
||||||
require.EqualValues(t, tt.wantLayers, layers, layers)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGrapher_GraphFromAUR_Deps_gourou(t *testing.T) {
|
|
||||||
mockDB := &mock.DBExecutor{
|
|
||||||
SyncPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
PackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
|
||||||
switch s {
|
|
||||||
case "gourou", "libzip-git":
|
|
||||||
return nil
|
|
||||||
case "libzip":
|
|
||||||
return &mock.Package{
|
|
||||||
PName: "libzip",
|
|
||||||
PVersion: "1.9.2-1",
|
|
||||||
PDB: mock.NewDB("extra"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
|
|
||||||
LocalSatisfierExistsFn: func(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "gourou", "libzip", "libzip-git":
|
|
||||||
return false
|
|
||||||
case "dep1", "dep2":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
}
|
|
||||||
|
|
||||||
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {
|
|
||||||
mockPkgs := map[string]aur.Pkg{
|
|
||||||
"gourou": {
|
|
||||||
Name: "gourou",
|
|
||||||
PackageBase: "gourou",
|
|
||||||
Version: "0.8.1",
|
|
||||||
Depends: []string{"libzip"},
|
|
||||||
},
|
|
||||||
"libzip-git": {
|
|
||||||
Name: "libzip-git",
|
|
||||||
PackageBase: "libzip-git",
|
|
||||||
Version: "1.9.2.r159.gb3ac716c-1",
|
|
||||||
Depends: []string{"dep1", "dep2"},
|
|
||||||
Provides: []string{"libzip=1.9.2.r159.gb3ac716c"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgs := []aur.Pkg{}
|
|
||||||
for _, needle := range query.Needles {
|
|
||||||
if pkg, ok := mockPkgs[needle]; ok {
|
|
||||||
pkgs = append(pkgs, pkg)
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("implement me %v", needle))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgs, nil
|
|
||||||
}}
|
|
||||||
|
|
||||||
installInfos := map[string]*InstallInfo{
|
|
||||||
"gourou exp": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "0.8.1",
|
|
||||||
AURBase: ptrString("gourou"),
|
|
||||||
},
|
|
||||||
"libzip dep": {
|
|
||||||
Source: Sync,
|
|
||||||
Reason: Dep,
|
|
||||||
Version: "1.9.2-1",
|
|
||||||
SyncDBName: ptrString("extra"),
|
|
||||||
},
|
|
||||||
"libzip exp": {
|
|
||||||
Source: Sync,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "1.9.2-1",
|
|
||||||
SyncDBName: ptrString("extra"),
|
|
||||||
},
|
|
||||||
"libzip-git exp": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Explicit,
|
|
||||||
Version: "1.9.2.r159.gb3ac716c-1",
|
|
||||||
AURBase: ptrString("libzip-git"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
targets []string
|
|
||||||
wantLayers []map[string]*InstallInfo
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "gourou",
|
|
||||||
targets: []string{"gourou"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"gourou": installInfos["gourou exp"]},
|
|
||||||
{"libzip": installInfos["libzip dep"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gourou libzip",
|
|
||||||
targets: []string{"gourou", "libzip"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"gourou": installInfos["gourou exp"]},
|
|
||||||
{"libzip": installInfos["libzip exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gourou libzip-git",
|
|
||||||
targets: []string{"gourou", "libzip-git"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"gourou": installInfos["gourou exp"]},
|
|
||||||
{"libzip-git": installInfos["libzip-git exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "libzip-git gourou (reversed order)",
|
|
||||||
targets: []string{"libzip-git", "gourou"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"gourou": installInfos["gourou exp"]},
|
|
||||||
{"libzip-git": installInfos["libzip-git exp"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
g := NewGrapher(mockDB, mockAUR,
|
|
||||||
false, true, false, false, false,
|
|
||||||
text.NewLogger(io.Discard, io.Discard, &os.File{}, true, "test"))
|
|
||||||
got, err := g.GraphFromTargets(context.Background(), nil, tt.targets)
|
|
||||||
require.NoError(t, err)
|
|
||||||
layers := got.TopoSortedLayerMap(nil)
|
|
||||||
require.EqualValues(t, tt.wantLayers, layers, layers)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGrapher_GraphFromTargets_ReinstalledDeps(t *testing.T) {
|
|
||||||
mockDB := &mock.DBExecutor{
|
|
||||||
SyncPackageFn: func(string) mock.IPackage { return nil },
|
|
||||||
PackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },
|
|
||||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
|
||||||
switch s {
|
|
||||||
case "gourou":
|
|
||||||
return nil
|
|
||||||
case "libzip":
|
|
||||||
return &mock.Package{
|
|
||||||
PName: "libzip",
|
|
||||||
PVersion: "1.9.2-1",
|
|
||||||
PDB: mock.NewDB("extra"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
SatisfierFromDBFn: func(s, s2 string) (mock.IPackage, error) {
|
|
||||||
if s2 == "extra" {
|
|
||||||
switch s {
|
|
||||||
case "libzip":
|
|
||||||
return &mock.Package{
|
|
||||||
PName: "libzip",
|
|
||||||
PVersion: "1.9.2-1",
|
|
||||||
PDB: mock.NewDB("extra"),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s2 + "/" + s)
|
|
||||||
},
|
|
||||||
|
|
||||||
LocalSatisfierExistsFn: func(s string) bool {
|
|
||||||
switch s {
|
|
||||||
case "gourou", "libzip":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("implement me " + s)
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(s string) mock.IPackage {
|
|
||||||
switch s {
|
|
||||||
case "libzip":
|
|
||||||
return &mock.Package{
|
|
||||||
PName: "libzip",
|
|
||||||
PVersion: "1.9.2-1",
|
|
||||||
PDB: mock.NewDB("extra"),
|
|
||||||
PReason: alpm.PkgReasonDepend,
|
|
||||||
}
|
|
||||||
case "gourou":
|
|
||||||
return &mock.Package{
|
|
||||||
PName: "gourou",
|
|
||||||
PVersion: "0.8.1",
|
|
||||||
PDB: mock.NewDB("aur"),
|
|
||||||
PReason: alpm.PkgReasonDepend,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {
|
|
||||||
mockPkgs := map[string]aur.Pkg{
|
|
||||||
"gourou": {
|
|
||||||
Name: "gourou",
|
|
||||||
PackageBase: "gourou",
|
|
||||||
Version: "0.8.1",
|
|
||||||
Depends: []string{"libzip"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgs := []aur.Pkg{}
|
|
||||||
for _, needle := range query.Needles {
|
|
||||||
if pkg, ok := mockPkgs[needle]; ok {
|
|
||||||
pkgs = append(pkgs, pkg)
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("implement me %v", needle))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgs, nil
|
|
||||||
}}
|
|
||||||
|
|
||||||
installInfos := map[string]*InstallInfo{
|
|
||||||
"gourou dep": {
|
|
||||||
Source: AUR,
|
|
||||||
Reason: Dep,
|
|
||||||
Version: "0.8.1",
|
|
||||||
AURBase: ptrString("gourou"),
|
|
||||||
},
|
|
||||||
"libzip dep": {
|
|
||||||
Source: Sync,
|
|
||||||
Reason: Dep,
|
|
||||||
Version: "1.9.2-1",
|
|
||||||
SyncDBName: ptrString("extra"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
targets []string
|
|
||||||
wantLayers []map[string]*InstallInfo
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "gourou libzip",
|
|
||||||
targets: []string{"gourou", "libzip"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"gourou": installInfos["gourou dep"]},
|
|
||||||
{"libzip": installInfos["libzip dep"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "aur/gourou extra/libzip",
|
|
||||||
targets: []string{"aur/gourou", "extra/libzip"},
|
|
||||||
wantLayers: []map[string]*InstallInfo{
|
|
||||||
{"gourou": installInfos["gourou dep"]},
|
|
||||||
{"libzip": installInfos["libzip dep"]},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
g := NewGrapher(mockDB, mockAUR,
|
|
||||||
false, true, false, false, false,
|
|
||||||
text.NewLogger(io.Discard, io.Discard, &os.File{}, true, "test"))
|
|
||||||
got, err := g.GraphFromTargets(context.Background(), nil, tt.targets)
|
|
||||||
require.NoError(t, err)
|
|
||||||
layers := got.TopoSortedLayerMap(nil)
|
|
||||||
require.EqualValues(t, tt.wantLayers, layers, layers)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
3
pkg/dep/testdata/android-sdk.json
vendored
3
pkg/dep/testdata/android-sdk.json
vendored
@ -1,3 +0,0 @@
|
|||||||
[
|
|
||||||
{"ID":1055234,"Name":"android-sdk","PackageBaseID":13751,"PackageBase":"android-sdk","Version":"26.1.1-2","Description":"Google Android SDK","URL":"https://developer.android.com/studio/releases/sdk-tools.html","NumVotes":1487,"Popularity":0.802316,"OutOfDate":null,"Maintainer":"dreamingincode","Submitter":null,"FirstSubmitted":1194895596,"LastModified":1647982720,"URLPath":"/cgit/aur.git/snapshot/android-sdk.tar.gz","Depends":["java-environment","libxtst","fontconfig","freetype2","lib32-gcc-libs","lib32-glibc","libx11","libxext","libxrender","zlib","gcc-libs"],"OptDepends":["android-emulator","android-sdk-platform-tools","android-udev"],"License":["custom"],"Keywords":["android","development"]}
|
|
||||||
]
|
|
@ -1,9 +0,0 @@
|
|||||||
package topo
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrSelfReferential = errors.New(" self-referential dependencies not allowed")
|
|
||||||
ErrConflictingAlias = errors.New(" alias already defined")
|
|
||||||
ErrCircular = errors.New(" circular dependencies not allowed")
|
|
||||||
)
|
|
@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
@ -15,52 +14,55 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
MaxConcurrentFetch = 20
|
MaxConcurrentFetch = 20
|
||||||
absPackageURL = "https://gitlab.archlinux.org/archlinux/packaging/packages"
|
_urlPackagePath = "%s/raw/packages/%s/trunk/PKGBUILD"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidRepository = errors.New(gotext.Get("invalid repository"))
|
ErrInvalidRepository = errors.New(gotext.Get("invalid repository"))
|
||||||
ErrABSPackageNotFound = errors.New(gotext.Get("package not found in repos"))
|
ErrABSPackageNotFound = errors.New(gotext.Get("package not found in repos"))
|
||||||
|
ABSPackageURL = "https://github.com/archlinux/svntogit-packages"
|
||||||
|
ABSCommunityURL = "https://github.com/archlinux/svntogit-community"
|
||||||
)
|
)
|
||||||
|
|
||||||
type regexReplace struct {
|
func getRepoURL(db string) (string, error) {
|
||||||
repl string
|
switch db {
|
||||||
match *regexp.Regexp
|
case "core", "extra", "testing":
|
||||||
}
|
return ABSPackageURL, nil
|
||||||
|
case "community", "multilib", "community-testing", "multilib-testing":
|
||||||
|
return ABSCommunityURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
// regex replacements for Gitlab URLs
|
return "", ErrInvalidRepository
|
||||||
// info: https://gitlab.archlinux.org/archlinux/devtools/-/blob/6ce666a1669235749c17d5c44d8a24dea4a135da/src/lib/api/gitlab.sh#L84
|
|
||||||
var gitlabRepl = []regexReplace{
|
|
||||||
{repl: `$1-$2`, match: regexp.MustCompile(`([a-zA-Z0-9]+)\+([a-zA-Z]+)`)},
|
|
||||||
{repl: `plus`, match: regexp.MustCompile(`\+`)},
|
|
||||||
{repl: `-`, match: regexp.MustCompile(`[^a-zA-Z0-9_\-.]`)},
|
|
||||||
{repl: `-`, match: regexp.MustCompile(`[_\-]{2,}`)},
|
|
||||||
{repl: `unix-tree`, match: regexp.MustCompile(`^tree$`)},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return format for pkgbuild
|
// Return format for pkgbuild
|
||||||
// https://gitlab.archlinux.org/archlinux/packaging/packages/0ad/-/raw/main/PKGBUILD
|
// https://github.com/archlinux/svntogit-community/raw/packages/neovim/trunk/PKGBUILD
|
||||||
func getPackagePKGBUILDURL(pkgName string) string {
|
func getPackageURL(db, pkgName string) (string, error) {
|
||||||
return fmt.Sprintf("%s/%s/-/raw/main/PKGBUILD", absPackageURL, convertPkgNameForURL(pkgName))
|
repoURL, err := getRepoURL(db)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(_urlPackagePath, repoURL, pkgName), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return format for pkgbuild repo
|
// Return format for pkgbuild repo
|
||||||
// https://gitlab.archlinux.org/archlinux/packaging/packages/0ad.git
|
// https://github.com/archlinux/svntogit-community.git
|
||||||
func getPackageRepoURL(pkgName string) string {
|
func getPackageRepoURL(db string) (string, error) {
|
||||||
return fmt.Sprintf("%s/%s.git", absPackageURL, convertPkgNameForURL(pkgName))
|
repoURL, err := getRepoURL(db)
|
||||||
}
|
if err != nil {
|
||||||
|
return "", err
|
||||||
// convert pkgName for Gitlab URL path (repo name)
|
|
||||||
func convertPkgNameForURL(pkgName string) string {
|
|
||||||
for _, regex := range gitlabRepl {
|
|
||||||
pkgName = regex.match.ReplaceAllString(pkgName, regex.repl)
|
|
||||||
}
|
}
|
||||||
return pkgName
|
|
||||||
|
return repoURL + ".git", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ABSPKGBUILD retrieves the PKGBUILD file to a dest directory.
|
// ABSPKGBUILD retrieves the PKGBUILD file to a dest directory.
|
||||||
func ABSPKGBUILD(httpClient httpRequestDoer, dbName, pkgName string) ([]byte, error) {
|
func ABSPKGBUILD(httpClient httpRequestDoer, dbName, pkgName string) ([]byte, error) {
|
||||||
packageURL := getPackagePKGBUILDURL(pkgName)
|
packageURL, err := getPackageURL(dbName, pkgName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := httpClient.Get(packageURL)
|
resp, err := httpClient.Get(packageURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -85,8 +87,11 @@ func ABSPKGBUILD(httpClient httpRequestDoer, dbName, pkgName string) ([]byte, er
|
|||||||
func ABSPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
|
func ABSPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
|
||||||
dbName, pkgName, dest string, force bool,
|
dbName, pkgName, dest string, force bool,
|
||||||
) (bool, error) {
|
) (bool, error) {
|
||||||
pkgURL := getPackageRepoURL(pkgName)
|
pkgURL, err := getPackageRepoURL(dbName)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
return downloadGitRepo(ctx, cmdBuilder, pkgURL,
|
return downloadGitRepo(ctx, cmdBuilder, pkgURL,
|
||||||
pkgName, dest, force, "--single-branch")
|
pkgName, dest, force, "--single-branch", "-b", "packages/"+pkgName)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package download
|
package download
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -50,12 +47,12 @@ func Test_getPackageURL(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "extra package",
|
name: "community package",
|
||||||
args: args{
|
args: args{
|
||||||
db: "extra",
|
db: "community",
|
||||||
pkgName: "kitty",
|
pkgName: "kitty",
|
||||||
},
|
},
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/kitty/-/raw/main/PKGBUILD",
|
want: "https://github.com/archlinux/svntogit-community/raw/packages/kitty/trunk/PKGBUILD",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -64,69 +61,27 @@ func Test_getPackageURL(t *testing.T) {
|
|||||||
db: "core",
|
db: "core",
|
||||||
pkgName: "linux",
|
pkgName: "linux",
|
||||||
},
|
},
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/linux/-/raw/main/PKGBUILD",
|
want: "https://github.com/archlinux/svntogit-packages/raw/packages/linux/trunk/PKGBUILD",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "personal repo package",
|
name: "personal repo package",
|
||||||
args: args{
|
args: args{
|
||||||
db: "sweswe",
|
db: "sweswe",
|
||||||
pkgName: "zabix",
|
pkgName: "linux",
|
||||||
},
|
},
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/zabix/-/raw/main/PKGBUILD",
|
want: "",
|
||||||
wantErr: false,
|
wantErr: true,
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name +",
|
|
||||||
args: args{
|
|
||||||
db: "core",
|
|
||||||
pkgName: "my+package",
|
|
||||||
},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/my-package/-/raw/main/PKGBUILD",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name %",
|
|
||||||
args: args{
|
|
||||||
db: "core",
|
|
||||||
pkgName: "my%package",
|
|
||||||
},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/my-package/-/raw/main/PKGBUILD",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name _-",
|
|
||||||
args: args{
|
|
||||||
db: "core",
|
|
||||||
pkgName: "my_-package",
|
|
||||||
},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/my-package/-/raw/main/PKGBUILD",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name ++",
|
|
||||||
args: args{
|
|
||||||
db: "core",
|
|
||||||
pkgName: "my++package",
|
|
||||||
},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/mypluspluspackage/-/raw/main/PKGBUILD",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name tree",
|
|
||||||
args: args{
|
|
||||||
db: "sweswe",
|
|
||||||
pkgName: "tree",
|
|
||||||
},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/unix-tree/-/raw/main/PKGBUILD",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got := getPackagePKGBUILDURL(tt.args.pkgName)
|
got, err := getPackageURL(tt.args.db, tt.args.pkgName)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.ErrorIs(t, err, ErrInvalidRepository)
|
||||||
|
}
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -155,7 +110,7 @@ func TestGetABSPkgbuild(t *testing.T) {
|
|||||||
body: gitExtrasPKGBUILD,
|
body: gitExtrasPKGBUILD,
|
||||||
status: 200,
|
status: 200,
|
||||||
pkgName: "git-extras",
|
pkgName: "git-extras",
|
||||||
wantURL: "https://gitlab.archlinux.org/archlinux/packaging/packages/git-extras/-/raw/main/PKGBUILD",
|
wantURL: "https://github.com/archlinux/svntogit-packages/raw/packages/git-extras/trunk/PKGBUILD",
|
||||||
},
|
},
|
||||||
want: gitExtrasPKGBUILD,
|
want: gitExtrasPKGBUILD,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
@ -167,7 +122,7 @@ func TestGetABSPkgbuild(t *testing.T) {
|
|||||||
body: "",
|
body: "",
|
||||||
status: 404,
|
status: 404,
|
||||||
pkgName: "git-git",
|
pkgName: "git-git",
|
||||||
wantURL: "https://gitlab.archlinux.org/archlinux/packaging/packages/git-git/-/raw/main/PKGBUILD",
|
wantURL: "https://github.com/archlinux/svntogit-packages/raw/packages/git-git/trunk/PKGBUILD",
|
||||||
},
|
},
|
||||||
want: "",
|
want: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
@ -199,7 +154,7 @@ func Test_getPackageRepoURL(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
pkgName string
|
db string
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -208,59 +163,32 @@ func Test_getPackageRepoURL(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "extra package",
|
name: "community package",
|
||||||
args: args{pkgName: "zoxide"},
|
args: args{db: "community"},
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/zoxide.git",
|
want: "https://github.com/archlinux/svntogit-community.git",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "core package",
|
name: "core package",
|
||||||
args: args{pkgName: "linux"},
|
args: args{db: "core"},
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/linux.git",
|
want: "https://github.com/archlinux/svntogit-packages.git",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "personal repo package",
|
name: "personal repo package",
|
||||||
args: args{pkgName: "sweswe"},
|
args: args{db: "sweswe"},
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/sweswe.git",
|
want: "",
|
||||||
wantErr: false,
|
wantErr: true,
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name +",
|
|
||||||
args: args{pkgName: "my+package"},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/my-package.git",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name %",
|
|
||||||
args: args{pkgName: "my%package"},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/my-package.git",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name _-",
|
|
||||||
args: args{pkgName: "my_-package"},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/my-package.git",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name ++",
|
|
||||||
args: args{pkgName: "my++package"},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/mypluspluspackage.git",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special name tree",
|
|
||||||
args: args{pkgName: "tree"},
|
|
||||||
want: "https://gitlab.archlinux.org/archlinux/packaging/packages/unix-tree.git",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got := getPackageRepoURL(tt.args.pkgName)
|
got, err := getPackageRepoURL(tt.args.db)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.ErrorIs(t, err, ErrInvalidRepository)
|
||||||
|
}
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -272,13 +200,13 @@ func Test_getPackageRepoURL(t *testing.T) {
|
|||||||
func TestABSPKGBUILDRepo(t *testing.T) {
|
func TestABSPKGBUILDRepo(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
cmdRunner := &testRunner{}
|
cmdRunner := &testRunner{}
|
||||||
want := "/usr/local/bin/git --no-replace-objects -C /tmp/doesnt-exist clone --no-progress --single-branch https://gitlab.archlinux.org/archlinux/packaging/packages/linux.git linux"
|
want := "/usr/local/bin/git --no-replace-objects -C /tmp/doesnt-exist clone --no-progress --single-branch -b packages/linux https://github.com/archlinux/svntogit-packages.git linux"
|
||||||
if os.Getuid() == 0 {
|
if os.Getuid() == 0 {
|
||||||
ld := "systemd-run"
|
ld := "systemd-run"
|
||||||
if path, _ := exec.LookPath(ld); path != "" {
|
if path, _ := exec.LookPath(ld); path != "" {
|
||||||
ld = path
|
ld = path
|
||||||
}
|
}
|
||||||
want = fmt.Sprintf("%s --service-type=oneshot --pipe --wait --pty --quiet -p DynamicUser=yes -p CacheDirectory=yay -E HOME=/tmp --no-replace-objects -C /tmp/doesnt-exist clone --no-progress --single-branch https://gitlab.archlinux.org/archlinux/packaging/packages/linux.git linux", ld)
|
want = fmt.Sprintf("%s --service-type=oneshot --pipe --wait --pty --quiet -p DynamicUser=yes -p CacheDirectory=yay -E HOME=/tmp --no-replace-objects -C /tmp/doesnt-exist clone --no-progress --single-branch -b packages/linux https://github.com/archlinux/svntogit-packages.git linux", ld)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdBuilder := &testGitBuilder{
|
cmdBuilder := &testGitBuilder{
|
||||||
|
@ -48,7 +48,7 @@ func AURPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder, aurURL,
|
|||||||
|
|
||||||
func AURPKGBUILDRepos(
|
func AURPKGBUILDRepos(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
cmdBuilder exe.GitCmdBuilder, logger *text.Logger,
|
cmdBuilder exe.GitCmdBuilder,
|
||||||
targets []string, aurURL, dest string, force bool,
|
targets []string, aurURL, dest string, force bool,
|
||||||
) (map[string]bool, error) {
|
) (map[string]bool, error) {
|
||||||
cloned := make(map[string]bool, len(targets))
|
cloned := make(map[string]bool, len(targets))
|
||||||
@ -63,34 +63,30 @@ func AURPKGBUILDRepos(
|
|||||||
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
sem <- 1
|
sem <- 1
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
go func(target string) {
|
go func(target string) {
|
||||||
defer func() {
|
|
||||||
<-sem
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
newClone, err := AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, target, dest, force)
|
newClone, err := AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, target, dest, force)
|
||||||
|
|
||||||
mux.Lock()
|
progress := 0
|
||||||
progress := len(cloned)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs.Add(err)
|
errs.Add(err)
|
||||||
|
} else {
|
||||||
|
mux.Lock()
|
||||||
|
cloned[target] = newClone
|
||||||
|
progress = len(cloned)
|
||||||
mux.Unlock()
|
mux.Unlock()
|
||||||
logger.OperationInfoln(
|
|
||||||
gotext.Get("(%d/%d) Failed to download PKGBUILD: %s",
|
|
||||||
progress, len(targets), text.Cyan(target)))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cloned[target] = newClone
|
text.OperationInfoln(
|
||||||
progress = len(cloned)
|
|
||||||
mux.Unlock()
|
|
||||||
|
|
||||||
logger.OperationInfoln(
|
|
||||||
gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
|
gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
|
||||||
progress, len(targets), text.Cyan(target)))
|
progress, len(targets), text.Cyan(target)))
|
||||||
|
|
||||||
|
<-sem
|
||||||
|
|
||||||
|
wg.Done()
|
||||||
}(target)
|
}(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package download
|
package download
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -158,7 +155,7 @@ func TestAURPKGBUILDRepos(t *testing.T) {
|
|||||||
GitFlags: []string{},
|
GitFlags: []string{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cloned, err := AURPKGBUILDRepos(context.Background(), cmdBuilder, newTestLogger(), targets, "https://aur.archlinux.org", dir, false)
|
cloned, err := AURPKGBUILDRepos(context.Background(), cmdBuilder, targets, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, map[string]bool{"yay": true, "yay-bin": false, "yay-git": true}, cloned)
|
assert.EqualValues(t, map[string]bool{"yay": true, "yay-bin": false, "yay-git": true}, cloned)
|
||||||
|
@ -24,7 +24,7 @@ type httpRequestDoer interface {
|
|||||||
|
|
||||||
type DBSearcher interface {
|
type DBSearcher interface {
|
||||||
SyncPackage(string) db.IPackage
|
SyncPackage(string) db.IPackage
|
||||||
SyncPackageFromDB(string, string) db.IPackage
|
SatisfierFromDB(string, string) db.IPackage
|
||||||
}
|
}
|
||||||
|
|
||||||
func downloadGitRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
|
func downloadGitRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
|
||||||
@ -81,8 +81,8 @@ func getURLName(pkg db.IPackage) string {
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *http.Client,
|
func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *http.Client, targets []string,
|
||||||
logger *text.Logger, targets []string, aurURL string, mode parser.TargetMode,
|
aurURL string, mode parser.TargetMode,
|
||||||
) (map[string][]byte, error) {
|
) (map[string][]byte, error) {
|
||||||
pkgbuilds := make(map[string][]byte, len(targets))
|
pkgbuilds := make(map[string][]byte, len(targets))
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *htt
|
|||||||
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
// Probably replaceable by something in query.
|
// Probably replaceable by something in query.
|
||||||
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, logger, target, mode)
|
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, target, mode)
|
||||||
if toSkip {
|
if toSkip {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.QueryClient,
|
func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.QueryClient,
|
||||||
cmdBuilder exe.GitCmdBuilder, logger *text.Logger,
|
cmdBuilder exe.GitCmdBuilder,
|
||||||
targets []string, mode parser.TargetMode, aurURL, dest string, force bool,
|
targets []string, mode parser.TargetMode, aurURL, dest string, force bool,
|
||||||
) (map[string]bool, error) {
|
) (map[string]bool, error) {
|
||||||
cloned := make(map[string]bool, len(targets))
|
cloned := make(map[string]bool, len(targets))
|
||||||
@ -151,7 +151,7 @@ func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.Que
|
|||||||
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
// Probably replaceable by something in query.
|
// Probably replaceable by something in query.
|
||||||
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, logger, target, mode)
|
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, target, mode)
|
||||||
if toSkip {
|
if toSkip {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -184,11 +184,11 @@ func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.Que
|
|||||||
}
|
}
|
||||||
|
|
||||||
if aur {
|
if aur {
|
||||||
logger.OperationInfoln(
|
text.OperationInfoln(
|
||||||
gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
|
gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
|
||||||
progress, len(targets), text.Cyan(pkgName)))
|
progress, len(targets), text.Cyan(pkgName)))
|
||||||
} else {
|
} else {
|
||||||
logger.OperationInfoln(
|
text.OperationInfoln(
|
||||||
gotext.Get("(%d/%d) Downloaded PKGBUILD from ABS: %s",
|
gotext.Get("(%d/%d) Downloaded PKGBUILD from ABS: %s",
|
||||||
progress, len(targets), text.Cyan(pkgName)))
|
progress, len(targets), text.Cyan(pkgName)))
|
||||||
}
|
}
|
||||||
@ -206,13 +206,13 @@ func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.Que
|
|||||||
|
|
||||||
// TODO: replace with dep.ResolveTargets.
|
// TODO: replace with dep.ResolveTargets.
|
||||||
func getPackageUsableName(dbExecutor DBSearcher, aurClient aur.QueryClient,
|
func getPackageUsableName(dbExecutor DBSearcher, aurClient aur.QueryClient,
|
||||||
logger *text.Logger, target string, mode parser.TargetMode,
|
target string, mode parser.TargetMode,
|
||||||
) (dbname, pkgname string, isAUR, toSkip bool) {
|
) (dbname, pkgname string, isAUR, toSkip bool) {
|
||||||
dbName, name := text.SplitDBFromName(target)
|
dbName, name := text.SplitDBFromName(target)
|
||||||
if dbName != "aur" && mode.AtLeastRepo() {
|
if dbName != "aur" && mode.AtLeastRepo() {
|
||||||
var pkg db.IPackage
|
var pkg db.IPackage
|
||||||
if dbName != "" {
|
if dbName != "" {
|
||||||
pkg = dbExecutor.SyncPackageFromDB(name, dbName)
|
pkg = dbExecutor.SatisfierFromDB(name, dbName)
|
||||||
} else {
|
} else {
|
||||||
pkg = dbExecutor.SyncPackage(name)
|
pkg = dbExecutor.SyncPackage(name)
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ func getPackageUsableName(dbExecutor DBSearcher, aurClient aur.QueryClient,
|
|||||||
Needles: []string{name},
|
Needles: []string{name},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnln(err)
|
text.Warnln(err)
|
||||||
return dbName, name, true, true
|
return dbName, name, true, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
//go:build integration
|
|
||||||
// +build integration
|
|
||||||
|
|
||||||
package download
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/Jguer/aur"
|
|
||||||
|
|
||||||
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIntegrationPKGBUILDReposDefinedDBClone(t *testing.T) {
|
|
||||||
dir := t.TempDir()
|
|
||||||
|
|
||||||
mockClient := &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{{}}, nil // fakes a package found for all
|
|
||||||
},
|
|
||||||
}
|
|
||||||
targets := []string{"core/linux", "yay-bin", "yay-git"}
|
|
||||||
|
|
||||||
testLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(""), true, "test")
|
|
||||||
cmdRunner := &exe.OSRunner{Log: testLogger}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
Runner: cmdRunner,
|
|
||||||
GitBin: "git",
|
|
||||||
GitFlags: []string{},
|
|
||||||
Log: testLogger,
|
|
||||||
}
|
|
||||||
searcher := &testDBSearcher{
|
|
||||||
absPackagesDB: map[string]string{"linux": "core"},
|
|
||||||
}
|
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
|
||||||
cmdBuilder, testLogger.Child("test"),
|
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, map[string]bool{"core/linux": true, "yay-bin": true, "yay-git": true}, cloned)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegrationPKGBUILDReposNotExist(t *testing.T) {
|
|
||||||
dir := t.TempDir()
|
|
||||||
|
|
||||||
mockClient := &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{{}}, nil // fakes a package found for all
|
|
||||||
},
|
|
||||||
}
|
|
||||||
targets := []string{"core/yay", "yay-bin", "yay-git"}
|
|
||||||
testLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(""), true, "test")
|
|
||||||
cmdRunner := &exe.OSRunner{Log: testLogger}
|
|
||||||
cmdBuilder := &exe.CmdBuilder{
|
|
||||||
Runner: cmdRunner,
|
|
||||||
GitBin: "git",
|
|
||||||
GitFlags: []string{},
|
|
||||||
Log: testLogger,
|
|
||||||
}
|
|
||||||
|
|
||||||
searcher := &testDBSearcher{
|
|
||||||
absPackagesDB: map[string]string{"yay": "core"},
|
|
||||||
}
|
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
|
||||||
cmdBuilder, testLogger.Child("test"),
|
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
|
||||||
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.EqualValues(t, map[string]bool{"yay-bin": true, "yay-git": true}, cloned)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GIVEN 2 aur packages and 1 in repo
|
|
||||||
// WHEN defining as specified targets
|
|
||||||
// THEN all aur be found and cloned
|
|
||||||
func TestIntegrationPKGBUILDFull(t *testing.T) {
|
|
||||||
mockClient := &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{{}}, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
testLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(""), true, "test")
|
|
||||||
targets := []string{"core/linux", "aur/yay-bin", "yay-git"}
|
|
||||||
searcher := &testDBSearcher{
|
|
||||||
absPackagesDB: map[string]string{"linux": "core"},
|
|
||||||
}
|
|
||||||
|
|
||||||
fetched, err := PKGBUILDs(searcher, mockClient, &http.Client{}, testLogger.Child("test"),
|
|
||||||
targets, "https://aur.archlinux.org", parser.ModeAny)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
for _, target := range targets {
|
|
||||||
assert.Contains(t, fetched, target)
|
|
||||||
assert.NotEmpty(t, fetched[target])
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,10 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package download
|
package download
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -20,13 +15,8 @@ import (
|
|||||||
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestLogger() *text.Logger {
|
|
||||||
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GIVEN 2 aur packages and 1 in repo
|
// GIVEN 2 aur packages and 1 in repo
|
||||||
// GIVEN package in repo is already present
|
// GIVEN package in repo is already present
|
||||||
// WHEN defining package db as a target
|
// WHEN defining package db as a target
|
||||||
@ -41,8 +31,6 @@ func TestPKGBUILDReposDefinedDBPull(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
testLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(""), true, "test")
|
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(dir, "yay", ".git"), 0o777)
|
os.MkdirAll(filepath.Join(dir, "yay", ".git"), 0o777)
|
||||||
|
|
||||||
targets := []string{"core/yay", "yay-bin", "yay-git"}
|
targets := []string{"core/yay", "yay-bin", "yay-git"}
|
||||||
@ -54,14 +42,13 @@ func TestPKGBUILDReposDefinedDBPull(t *testing.T) {
|
|||||||
Runner: cmdRunner,
|
Runner: cmdRunner,
|
||||||
GitBin: "/usr/local/bin/git",
|
GitBin: "/usr/local/bin/git",
|
||||||
GitFlags: []string{},
|
GitFlags: []string{},
|
||||||
Log: testLogger,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
searcher := &testDBSearcher{
|
searcher := &testDBSearcher{
|
||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
||||||
cmdBuilder, newTestLogger(),
|
cmdBuilder,
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -95,7 +82,7 @@ func TestPKGBUILDReposDefinedDBClone(t *testing.T) {
|
|||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
||||||
cmdBuilder, newTestLogger(),
|
cmdBuilder,
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -129,7 +116,7 @@ func TestPKGBUILDReposClone(t *testing.T) {
|
|||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
||||||
cmdBuilder, newTestLogger(),
|
cmdBuilder,
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -163,7 +150,7 @@ func TestPKGBUILDReposNotFound(t *testing.T) {
|
|||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
||||||
cmdBuilder, newTestLogger(),
|
cmdBuilder,
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -197,7 +184,7 @@ func TestPKGBUILDReposRepoMode(t *testing.T) {
|
|||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
||||||
cmdBuilder, newTestLogger(),
|
cmdBuilder,
|
||||||
targets, parser.ModeRepo, "https://aur.archlinux.org", dir, false)
|
targets, parser.ModeRepo, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -224,8 +211,8 @@ func TestPKGBUILDFull(t *testing.T) {
|
|||||||
Reply(200).
|
Reply(200).
|
||||||
BodyString("example_yay-bin")
|
BodyString("example_yay-bin")
|
||||||
|
|
||||||
gock.New("https://gitlab.archlinux.org/").
|
gock.New("https://github.com/").
|
||||||
Get("archlinux/packaging/packages/yay/-/raw/main/PKGBUILD").
|
Get("/archlinux/svntogit-packages/raw/packages/yay/trunk/PKGBUILD").
|
||||||
Reply(200).
|
Reply(200).
|
||||||
BodyString("example_yay")
|
BodyString("example_yay")
|
||||||
|
|
||||||
@ -235,7 +222,7 @@ func TestPKGBUILDFull(t *testing.T) {
|
|||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
|
|
||||||
fetched, err := PKGBUILDs(searcher, mockClient, &http.Client{}, newTestLogger(),
|
fetched, err := PKGBUILDs(searcher, mockClient, &http.Client{},
|
||||||
targets, "https://aur.archlinux.org", parser.ModeAny)
|
targets, "https://aur.archlinux.org", parser.ModeAny)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -273,7 +260,7 @@ func TestPKGBUILDReposMissingAUR(t *testing.T) {
|
|||||||
absPackagesDB: map[string]string{"yay": "core"},
|
absPackagesDB: map[string]string{"yay": "core"},
|
||||||
}
|
}
|
||||||
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
|
||||||
cmdBuilder, newTestLogger(),
|
cmdBuilder,
|
||||||
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -102,7 +102,7 @@ func (d *testDBSearcher) SyncPackage(name string) db.IPackage {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *testDBSearcher) SyncPackageFromDB(name string, db string) db.IPackage {
|
func (d *testDBSearcher) SatisfierFromDB(name string, db string) db.IPackage {
|
||||||
if v, ok := d.absPackagesDB[name]; ok && v == db {
|
if v, ok := d.absPackagesDB[name]; ok && v == db {
|
||||||
return &testPackage{
|
return &testPackage{
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IntRange stores a max and min amount for range.
|
// IntRange stores a max and min amount for range.
|
||||||
@ -17,10 +17,10 @@ type IntRange struct {
|
|||||||
// IntRanges is a slice of IntRange.
|
// IntRanges is a slice of IntRange.
|
||||||
type IntRanges []IntRange
|
type IntRanges []IntRange
|
||||||
|
|
||||||
func makeIntRange(minVal, maxVal int) IntRange {
|
func makeIntRange(min, max int) IntRange {
|
||||||
return IntRange{
|
return IntRange{
|
||||||
min: minVal,
|
min,
|
||||||
max: maxVal,
|
max,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +42,24 @@ func (rs IntRanges) Get(n int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Min returns min value between a and b.
|
||||||
|
func Min(a, b int) int {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max returns max value between a and b.
|
||||||
|
func Max(a, b int) int {
|
||||||
|
if a < b {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
// ParseNumberMenu parses input for number menus split by spaces or commas
|
// ParseNumberMenu parses input for number menus split by spaces or commas
|
||||||
// supports individual selection: 1 2 3 4
|
// supports individual selection: 1 2 3 4
|
||||||
// supports range selections: 1-4 10-20
|
// supports range selections: 1-4 10-20
|
||||||
@ -53,12 +71,12 @@ func (rs IntRanges) Get(n int) bool {
|
|||||||
// of course the implementation is up to the caller, this function mearley parses
|
// of course the implementation is up to the caller, this function mearley parses
|
||||||
// the input and organizes it.
|
// the input and organizes it.
|
||||||
func ParseNumberMenu(input string) (include, exclude IntRanges,
|
func ParseNumberMenu(input string) (include, exclude IntRanges,
|
||||||
otherInclude, otherExclude mapset.Set[string],
|
otherInclude, otherExclude stringset.StringSet,
|
||||||
) {
|
) {
|
||||||
include = make(IntRanges, 0)
|
include = make(IntRanges, 0)
|
||||||
exclude = make(IntRanges, 0)
|
exclude = make(IntRanges, 0)
|
||||||
otherInclude = mapset.NewThreadUnsafeSet[string]()
|
otherInclude = make(stringset.StringSet)
|
||||||
otherExclude = mapset.NewThreadUnsafeSet[string]()
|
otherExclude = make(stringset.StringSet)
|
||||||
|
|
||||||
words := strings.FieldsFunc(input, func(c rune) bool {
|
words := strings.FieldsFunc(input, func(c rune) bool {
|
||||||
return unicode.IsSpace(c) || c == ','
|
return unicode.IsSpace(c) || c == ','
|
||||||
@ -84,22 +102,22 @@ func ParseNumberMenu(input string) (include, exclude IntRanges,
|
|||||||
|
|
||||||
num1, err = strconv.Atoi(ranges[0])
|
num1, err = strconv.Atoi(ranges[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
other.Add(strings.ToLower(word))
|
other.Set(strings.ToLower(word))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ranges) == 2 {
|
if len(ranges) == 2 {
|
||||||
num2, err = strconv.Atoi(ranges[1])
|
num2, err = strconv.Atoi(ranges[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
other.Add(strings.ToLower(word))
|
other.Set(strings.ToLower(word))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
num2 = num1
|
num2 = num1
|
||||||
}
|
}
|
||||||
|
|
||||||
mi := min(num1, num2)
|
mi := Min(num1, num2)
|
||||||
ma := max(num1, num2)
|
ma := Max(num1, num2)
|
||||||
|
|
||||||
if !invert {
|
if !invert {
|
||||||
include = append(include, makeIntRange(mi, ma))
|
include = append(include, makeIntRange(mi, ma))
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package intrange
|
package intrange
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseNumberMenu(t *testing.T) {
|
func TestParseNumberMenu(t *testing.T) {
|
||||||
@ -15,8 +11,8 @@ func TestParseNumberMenu(t *testing.T) {
|
|||||||
type result struct {
|
type result struct {
|
||||||
Include IntRanges
|
Include IntRanges
|
||||||
Exclude IntRanges
|
Exclude IntRanges
|
||||||
OtherInclude mapset.Set[string]
|
OtherInclude stringset.StringSet
|
||||||
OtherExclude mapset.Set[string]
|
OtherExclude stringset.StringSet
|
||||||
}
|
}
|
||||||
|
|
||||||
inputs := []string{
|
inputs := []string{
|
||||||
@ -41,15 +37,15 @@ func TestParseNumberMenu(t *testing.T) {
|
|||||||
makeIntRange(3, 3),
|
makeIntRange(3, 3),
|
||||||
makeIntRange(4, 4),
|
makeIntRange(4, 4),
|
||||||
makeIntRange(5, 5),
|
makeIntRange(5, 5),
|
||||||
}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{IntRanges{
|
{IntRanges{
|
||||||
makeIntRange(1, 10),
|
makeIntRange(1, 10),
|
||||||
makeIntRange(5, 15),
|
makeIntRange(5, 15),
|
||||||
}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{IntRanges{
|
{IntRanges{
|
||||||
makeIntRange(5, 10),
|
makeIntRange(5, 10),
|
||||||
makeIntRange(85, 90),
|
makeIntRange(85, 90),
|
||||||
}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{
|
{
|
||||||
IntRanges{
|
IntRanges{
|
||||||
makeIntRange(1, 1),
|
makeIntRange(1, 1),
|
||||||
@ -62,18 +58,18 @@ func TestParseNumberMenu(t *testing.T) {
|
|||||||
makeIntRange(38, 40),
|
makeIntRange(38, 40),
|
||||||
makeIntRange(123, 123),
|
makeIntRange(123, 123),
|
||||||
},
|
},
|
||||||
mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string](),
|
make(stringset.StringSet), make(stringset.StringSet),
|
||||||
},
|
},
|
||||||
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("abort", "all", "none"), mapset.NewThreadUnsafeSet[string]()},
|
{IntRanges{}, IntRanges{}, stringset.Make("abort", "all", "none"), make(stringset.StringSet)},
|
||||||
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("a-b"), mapset.NewThreadUnsafeSet("abort", "a-b")},
|
{IntRanges{}, IntRanges{}, stringset.Make("a-b"), stringset.Make("abort", "a-b")},
|
||||||
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("-9223372036854775809-9223372036854775809"), mapset.NewThreadUnsafeSet[string]()},
|
{IntRanges{}, IntRanges{}, stringset.Make("-9223372036854775809-9223372036854775809"), make(stringset.StringSet)},
|
||||||
{IntRanges{
|
{IntRanges{
|
||||||
makeIntRange(1, 1),
|
makeIntRange(1, 1),
|
||||||
makeIntRange(2, 2),
|
makeIntRange(2, 2),
|
||||||
makeIntRange(3, 3),
|
makeIntRange(3, 3),
|
||||||
makeIntRange(4, 4),
|
makeIntRange(4, 4),
|
||||||
makeIntRange(5, 5),
|
makeIntRange(5, 5),
|
||||||
}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{IntRanges{
|
{IntRanges{
|
||||||
makeIntRange(1, 1),
|
makeIntRange(1, 1),
|
||||||
makeIntRange(2, 2),
|
makeIntRange(2, 2),
|
||||||
@ -83,20 +79,23 @@ func TestParseNumberMenu(t *testing.T) {
|
|||||||
makeIntRange(6, 6),
|
makeIntRange(6, 6),
|
||||||
makeIntRange(7, 7),
|
makeIntRange(7, 7),
|
||||||
makeIntRange(8, 8),
|
makeIntRange(8, 8),
|
||||||
}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
{IntRanges{}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
|
{IntRanges{}, IntRanges{}, make(stringset.StringSet), make(stringset.StringSet)},
|
||||||
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("a", "b", "c", "d", "e"), mapset.NewThreadUnsafeSet[string]()},
|
{IntRanges{}, IntRanges{}, stringset.Make("a", "b", "c", "d", "e"), make(stringset.StringSet)},
|
||||||
}
|
}
|
||||||
|
|
||||||
for n, in := range inputs {
|
for n, in := range inputs {
|
||||||
res := expected[n]
|
res := expected[n]
|
||||||
include, exclude, otherInclude, otherExclude := ParseNumberMenu(in)
|
include, exclude, otherInclude, otherExclude := ParseNumberMenu(in)
|
||||||
|
|
||||||
assert.True(t, intRangesEqual(include, res.Include), "Test %d Failed: Expected: include=%+v got include=%+v", n+1, res.Include, include)
|
if !intRangesEqual(include, res.Include) ||
|
||||||
assert.True(t, intRangesEqual(exclude, res.Exclude), "Test %d Failed: Expected: exclude=%+v got exclude=%+v", n+1, res.Exclude, exclude)
|
!intRangesEqual(exclude, res.Exclude) ||
|
||||||
assert.True(t, otherInclude.Equal(res.OtherInclude), "Test %d Failed: Expected: otherInclude=%+v got otherInclude=%+v", n+1, res.OtherInclude, otherInclude)
|
!stringset.Equal(otherInclude, res.OtherInclude) ||
|
||||||
assert.True(t, otherExclude.Equal(res.OtherExclude), "Test %d Failed: Expected: otherExclude=%+v got otherExclude=%+v", n+1, res.OtherExclude, otherExclude)
|
!stringset.Equal(otherExclude, res.OtherExclude) {
|
||||||
|
t.Fatalf("Test %d Failed: Expected: include=%+v exclude=%+v otherInclude=%+v otherExclude=%+v got include=%+v excluive=%+v otherInclude=%+v otherExclude=%+v",
|
||||||
|
n+1, res.Include, res.Exclude, res.OtherInclude, res.OtherExclude, include, exclude, otherInclude, otherExclude)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,13 +3,13 @@ package menus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
@ -24,9 +24,7 @@ func anyExistInCache(pkgbuildDirs map[string]string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
func CleanFn(ctx context.Context, config *settings.Configuration, w io.Writer, pkgbuildDirsByBase map[string]string) error {
|
||||||
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
|
|
||||||
) error {
|
|
||||||
if len(pkgbuildDirsByBase) == 0 {
|
if len(pkgbuildDirsByBase) == 0 {
|
||||||
return nil // no work to do
|
return nil // no work to do
|
||||||
}
|
}
|
||||||
@ -37,7 +35,6 @@ func CleanFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
|||||||
|
|
||||||
skipFunc := func(pkg string) bool {
|
skipFunc := func(pkg string) bool {
|
||||||
dir := pkgbuildDirsByBase[pkg]
|
dir := pkgbuildDirsByBase[pkg]
|
||||||
// TOFIX: new install engine dir will always exist, check if unclean instead
|
|
||||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -50,25 +47,26 @@ func CleanFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
|||||||
bases = append(bases, pkg)
|
bases = append(bases, pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
toClean, errClean := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed,
|
// TOFIX: empty installed slice means installed filter is disabled
|
||||||
|
toClean, errClean := selectionMenu(w, pkgbuildDirsByBase, bases, mapset.NewSet[string](),
|
||||||
gotext.Get("Packages to cleanBuild?"),
|
gotext.Get("Packages to cleanBuild?"),
|
||||||
settings.NoConfirm, run.Cfg.AnswerClean, skipFunc)
|
settings.NoConfirm, config.AnswerClean, skipFunc)
|
||||||
if errClean != nil {
|
if errClean != nil {
|
||||||
return errClean
|
return errClean
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, base := range toClean {
|
for i, base := range toClean {
|
||||||
dir := pkgbuildDirsByBase[base]
|
dir := pkgbuildDirsByBase[base]
|
||||||
run.Logger.OperationInfoln(gotext.Get("Deleting (%d/%d): %s", i+1, len(toClean), text.Cyan(dir)))
|
text.OperationInfoln(gotext.Get("Deleting (%d/%d): %s", i+1, len(toClean), text.Cyan(dir)))
|
||||||
|
|
||||||
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, "reset", "--hard", "origin/HEAD")); err != nil {
|
if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "reset", "--hard", "HEAD")); err != nil {
|
||||||
run.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
|
text.Warnln(gotext.Get("Unable to clean:"), dir)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fdx")); err != nil {
|
if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fdx")); err != nil {
|
||||||
run.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
|
text.Warnln(gotext.Get("Unable to clean:"), dir)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -76,3 +74,42 @@ func CleanFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Clean(w io.Writer, cleanMenuOption bool, pkgbuildDirs map[string]string,
|
||||||
|
installed mapset.Set[string], noConfirm bool, answerClean string,
|
||||||
|
) error {
|
||||||
|
if !(cleanMenuOption && anyExistInCache(pkgbuildDirs)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
skipFunc := func(pkg string) bool {
|
||||||
|
dir := pkgbuildDirs[pkg]
|
||||||
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
bases := make([]string, 0, len(pkgbuildDirs))
|
||||||
|
for pkg := range pkgbuildDirs {
|
||||||
|
bases = append(bases, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
toClean, errClean := selectionMenu(w, pkgbuildDirs, bases, installed, gotext.Get("Packages to cleanBuild?"),
|
||||||
|
noConfirm, answerClean, skipFunc)
|
||||||
|
if errClean != nil {
|
||||||
|
return errClean
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, base := range toClean {
|
||||||
|
dir := pkgbuildDirs[base]
|
||||||
|
text.OperationInfoln(gotext.Get("Deleting (%d/%d): %s", i+1, len(toClean), text.Cyan(dir)))
|
||||||
|
|
||||||
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -5,13 +5,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/multierror"
|
"github.com/Jguer/yay/v12/pkg/multierror"
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
@ -22,7 +22,7 @@ const (
|
|||||||
gitDiffRefName = "AUR_SEEN"
|
gitDiffRefName = "AUR_SEEN"
|
||||||
)
|
)
|
||||||
|
|
||||||
func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder, logger *text.Logger,
|
func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder,
|
||||||
pkgbuildDirs map[string]string, bases []string,
|
pkgbuildDirs map[string]string, bases []string,
|
||||||
) error {
|
) error {
|
||||||
var errMulti multierror.MultiError
|
var errMulti multierror.MultiError
|
||||||
@ -46,7 +46,7 @@ func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder, logger *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !hasDiff {
|
if !hasDiff {
|
||||||
logger.Warnln(gotext.Get("%s: No changes -- skipping", text.Cyan(pkg)))
|
text.Warnln(gotext.Get("%s: No changes -- skipping", text.Cyan(pkg)))
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -85,13 +85,13 @@ func gitHasDiff(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) (bo
|
|||||||
|
|
||||||
return lastseen != upstream, nil
|
return lastseen != upstream, nil
|
||||||
}
|
}
|
||||||
// If AUR_SEEN does not exists, we have never reviewed a diff for this package
|
// If YAY_DIFF_REVIEW does not exists, we have never reviewed a diff for this package
|
||||||
// and should display it.
|
// and should display it.
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether or not we have reviewed a diff yet. It checks for the existence of
|
// Return wether or not we have reviewed a diff yet. It checks for the existence of
|
||||||
// AUR_SEEN in the git ref-list.
|
// YAY_DIFF_REVIEW in the git ref-list.
|
||||||
func gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) bool {
|
func gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) bool {
|
||||||
_, _, err := cmdBuilder.Capture(
|
_, _, err := cmdBuilder.Capture(
|
||||||
cmdBuilder.BuildGitCmd(ctx,
|
cmdBuilder.BuildGitCmd(ctx,
|
||||||
@ -100,7 +100,7 @@ func gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir stri
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the last reviewed hash. If AUR_SEEN exists it will return this hash.
|
// Returns the last reviewed hash. If YAY_DIFF_REVIEW exists it will return this hash.
|
||||||
// If it does not it will return empty tree as no diff have been reviewed yet.
|
// If it does not it will return empty tree as no diff have been reviewed yet.
|
||||||
func getLastSeenHash(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) (string, error) {
|
func getLastSeenHash(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) (string, error) {
|
||||||
if gitHasLastSeenRef(ctx, cmdBuilder, dir) {
|
if gitHasLastSeenRef(ctx, cmdBuilder, dir) {
|
||||||
@ -119,7 +119,7 @@ func getLastSeenHash(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string
|
|||||||
return gitEmptyTree, nil
|
return gitEmptyTree, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the AUR_SEEN ref to HEAD. We use this ref to determine which diff were
|
// Update the YAY_DIFF_REVIEW ref to HEAD. We use this ref to determine which diff were
|
||||||
// reviewed by the user.
|
// reviewed by the user.
|
||||||
func gitUpdateSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {
|
func gitUpdateSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {
|
||||||
_, stderr, err := cmdBuilder.Capture(
|
_, stderr, err := cmdBuilder.Capture(
|
||||||
@ -145,9 +145,43 @@ func updatePkgbuildSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgb
|
|||||||
return errMulti.Return()
|
return errMulti.Return()
|
||||||
}
|
}
|
||||||
|
|
||||||
func DiffFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
func Diff(ctx context.Context, cmdBuilder exe.ICmdBuilder, w io.Writer,
|
||||||
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
|
pkgbuildDirs map[string]string, diffMenuOption bool,
|
||||||
|
installed mapset.Set[string], cloned map[string]bool, noConfirm bool, diffDefaultAnswer string,
|
||||||
) error {
|
) error {
|
||||||
|
if !diffMenuOption {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bases := make([]string, 0, len(pkgbuildDirs))
|
||||||
|
for base := range pkgbuildDirs {
|
||||||
|
bases = append(bases, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
toDiff, errMenu := selectionMenu(w, pkgbuildDirs, bases, installed, gotext.Get("Diffs to show?"),
|
||||||
|
noConfirm, diffDefaultAnswer, nil)
|
||||||
|
if errMenu != nil || len(toDiff) == 0 {
|
||||||
|
return errMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
if errD := showPkgbuildDiffs(ctx, cmdBuilder, pkgbuildDirs, toDiff); errD != nil {
|
||||||
|
return errD
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
|
||||||
|
return settings.ErrUserAbort{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errUpd := updatePkgbuildSeenRef(ctx, cmdBuilder, pkgbuildDirs, toDiff); errUpd != nil {
|
||||||
|
return errUpd
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiffFn(ctx context.Context, config *settings.Configuration, w io.Writer, pkgbuildDirsByBase map[string]string) error {
|
||||||
if len(pkgbuildDirsByBase) == 0 {
|
if len(pkgbuildDirsByBase) == 0 {
|
||||||
return nil // no work to do
|
return nil // no work to do
|
||||||
}
|
}
|
||||||
@ -157,23 +191,23 @@ func DiffFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
|||||||
bases = append(bases, base)
|
bases = append(bases, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
toDiff, errMenu := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed, gotext.Get("Diffs to show?"),
|
toDiff, errMenu := selectionMenu(w, pkgbuildDirsByBase, bases, mapset.NewThreadUnsafeSet[string](), gotext.Get("Diffs to show?"),
|
||||||
settings.NoConfirm, run.Cfg.AnswerDiff, nil)
|
settings.NoConfirm, config.AnswerDiff, nil)
|
||||||
if errMenu != nil || len(toDiff) == 0 {
|
if errMenu != nil || len(toDiff) == 0 {
|
||||||
return errMenu
|
return errMenu
|
||||||
}
|
}
|
||||||
|
|
||||||
if errD := showPkgbuildDiffs(ctx, run.CmdBuilder, run.Logger, pkgbuildDirsByBase, toDiff); errD != nil {
|
if errD := showPkgbuildDiffs(ctx, config.Runtime.CmdBuilder, pkgbuildDirsByBase, toDiff); errD != nil {
|
||||||
return errD
|
return errD
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Println()
|
fmt.Println()
|
||||||
|
|
||||||
if !run.Logger.ContinueTask(gotext.Get("Proceed with install?"), true, false) {
|
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
|
||||||
return settings.ErrUserAbort{}
|
return settings.ErrUserAbort{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if errUpd := updatePkgbuildSeenRef(ctx, run.CmdBuilder, pkgbuildDirsByBase, toDiff); errUpd != nil {
|
if errUpd := updatePkgbuildSeenRef(ctx, config.Runtime.CmdBuilder, pkgbuildDirsByBase, toDiff); errUpd != nil {
|
||||||
return errUpd
|
return errUpd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ package menus
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -14,18 +15,17 @@ import (
|
|||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
"github.com/Jguer/yay/v12/pkg/settings"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Editor returns the preferred system editor.
|
// Editor returns the preferred system editor.
|
||||||
func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool) (editor string, args []string) {
|
func editor(editorConfig, editorFlags string, noConfirm bool) (editor string, args []string) {
|
||||||
switch {
|
switch {
|
||||||
case editorConfig != "":
|
case editorConfig != "":
|
||||||
editor, err := exec.LookPath(editorConfig)
|
editor, err := exec.LookPath(editorConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
} else {
|
} else {
|
||||||
return editor, strings.Fields(editorFlags)
|
return editor, strings.Fields(editorFlags)
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool)
|
|||||||
if editorArgs := strings.Fields(os.Getenv("VISUAL")); len(editorArgs) != 0 {
|
if editorArgs := strings.Fields(os.Getenv("VISUAL")); len(editorArgs) != 0 {
|
||||||
editor, err := exec.LookPath(editorArgs[0])
|
editor, err := exec.LookPath(editorArgs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
} else {
|
} else {
|
||||||
return editor, editorArgs[1:]
|
return editor, editorArgs[1:]
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool)
|
|||||||
if editorArgs := strings.Fields(os.Getenv("EDITOR")); len(editorArgs) != 0 {
|
if editorArgs := strings.Fields(os.Getenv("EDITOR")); len(editorArgs) != 0 {
|
||||||
editor, err := exec.LookPath(editorArgs[0])
|
editor, err := exec.LookPath(editorArgs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
} else {
|
} else {
|
||||||
return editor, editorArgs[1:]
|
return editor, editorArgs[1:]
|
||||||
}
|
}
|
||||||
@ -54,15 +54,16 @@ func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool)
|
|||||||
|
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
log.Errorln("\n", gotext.Get("%s is not set", text.Bold(text.Cyan("$EDITOR"))))
|
fmt.Fprintln(os.Stderr)
|
||||||
log.Warnln(gotext.Get("Add %s or %s to your environment variables", text.Bold(text.Cyan("$EDITOR")), text.Bold(text.Cyan("$VISUAL"))))
|
text.Errorln(gotext.Get("%s is not set", text.Bold(text.Cyan("$EDITOR"))))
|
||||||
|
text.Warnln(gotext.Get("Add %s or %s to your environment variables", text.Bold(text.Cyan("$EDITOR")), text.Bold(text.Cyan("$VISUAL"))))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
log.Infoln(gotext.Get("Edit PKGBUILD with?"))
|
text.Infoln(gotext.Get("Edit PKGBUILD with?"))
|
||||||
|
|
||||||
editorInput, err := log.GetInput("", noConfirm)
|
editorInput, err := text.GetInput(os.Stdin, "", noConfirm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool)
|
|||||||
|
|
||||||
editor, err := exec.LookPath(editorArgs[0])
|
editor, err := exec.LookPath(editorArgs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func editPkgbuilds(log *text.Logger, pkgbuildDirs map[string]string, bases []string, editorConfig,
|
func editPkgbuilds(pkgbuildDirs map[string]string, bases []string, editorConfig,
|
||||||
editorFlags string, srcinfos map[string]*gosrc.Srcinfo, noConfirm bool,
|
editorFlags string, srcinfos map[string]*gosrc.Srcinfo, noConfirm bool,
|
||||||
) error {
|
) error {
|
||||||
pkgbuilds := make([]string, 0, len(bases))
|
pkgbuilds := make([]string, 0, len(bases))
|
||||||
@ -101,7 +102,7 @@ func editPkgbuilds(log *text.Logger, pkgbuildDirs map[string]string, bases []str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(pkgbuilds) > 0 {
|
if len(pkgbuilds) > 0 {
|
||||||
editor, editorArgs := editor(log, editorConfig, editorFlags, noConfirm)
|
editor, editorArgs := editor(editorConfig, editorFlags, noConfirm)
|
||||||
editorArgs = append(editorArgs, pkgbuilds...)
|
editorArgs = append(editorArgs, pkgbuilds...)
|
||||||
editcmd := exec.Command(editor, editorArgs...)
|
editcmd := exec.Command(editor, editorArgs...)
|
||||||
editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
@ -114,8 +115,40 @@ func editPkgbuilds(log *text.Logger, pkgbuildDirs map[string]string, bases []str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EditFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
func Edit(w io.Writer, editMenuOption bool, pkgbuildDirs map[string]string, editorConfig,
|
||||||
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
|
editorFlags string, installed mapset.Set[string], srcinfos map[string]*gosrc.Srcinfo,
|
||||||
|
noConfirm bool, editDefaultAnswer string,
|
||||||
|
) error {
|
||||||
|
if !editMenuOption {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bases := make([]string, 0, len(pkgbuildDirs))
|
||||||
|
for pkg := range pkgbuildDirs {
|
||||||
|
bases = append(bases, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
toEdit, errMenu := selectionMenu(w, pkgbuildDirs, bases,
|
||||||
|
installed, gotext.Get("PKGBUILDs to edit?"), noConfirm, editDefaultAnswer, nil)
|
||||||
|
if errMenu != nil || len(toEdit) == 0 {
|
||||||
|
return errMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
if errEdit := editPkgbuilds(pkgbuildDirs, toEdit, editorConfig, editorFlags, srcinfos, noConfirm); errEdit != nil {
|
||||||
|
return errEdit
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
|
||||||
|
return settings.ErrUserAbort{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EditFn(ctx context.Context, config *settings.Configuration, w io.Writer,
|
||||||
|
pkgbuildDirsByBase map[string]string,
|
||||||
) error {
|
) error {
|
||||||
if len(pkgbuildDirsByBase) == 0 {
|
if len(pkgbuildDirsByBase) == 0 {
|
||||||
return nil // no work to do
|
return nil // no work to do
|
||||||
@ -126,21 +159,22 @@ func EditFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
|
|||||||
bases = append(bases, pkg)
|
bases = append(bases, pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
toEdit, errMenu := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed,
|
toEdit, errMenu := selectionMenu(w, pkgbuildDirsByBase, bases,
|
||||||
gotext.Get("PKGBUILDs to edit?"), settings.NoConfirm, run.Cfg.AnswerEdit, nil)
|
mapset.NewThreadUnsafeSet[string](),
|
||||||
|
gotext.Get("PKGBUILDs to edit?"), settings.NoConfirm, config.AnswerEdit, nil)
|
||||||
if errMenu != nil || len(toEdit) == 0 {
|
if errMenu != nil || len(toEdit) == 0 {
|
||||||
return errMenu
|
return errMenu
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOFIX: remove or use srcinfo data
|
// TOFIX: remove or use srcinfo data
|
||||||
if errEdit := editPkgbuilds(run.Logger, pkgbuildDirsByBase,
|
if errEdit := editPkgbuilds(pkgbuildDirsByBase,
|
||||||
toEdit, run.Cfg.Editor, run.Cfg.EditorFlags, nil, settings.NoConfirm); errEdit != nil {
|
toEdit, config.Editor, config.EditorFlags, nil, settings.NoConfirm); errEdit != nil {
|
||||||
return errEdit
|
return errEdit
|
||||||
}
|
}
|
||||||
|
|
||||||
run.Logger.Println()
|
fmt.Println()
|
||||||
|
|
||||||
if !run.Logger.ContinueTask(gotext.Get("Proceed with install?"), true, false) {
|
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
|
||||||
return settings.ErrUserAbort{}
|
return settings.ErrUserAbort{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package menus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
@ -13,9 +14,7 @@ import (
|
|||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pkgbuildNumberMenu(logger *text.Logger, pkgbuildDirs map[string]string,
|
func pkgbuildNumberMenu(w io.Writer, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string]) {
|
||||||
bases []string, installed mapset.Set[string],
|
|
||||||
) {
|
|
||||||
toPrint := ""
|
toPrint := ""
|
||||||
|
|
||||||
for n, pkgBase := range bases {
|
for n, pkgBase := range bases {
|
||||||
@ -27,7 +26,6 @@ func pkgbuildNumberMenu(logger *text.Logger, pkgbuildDirs map[string]string,
|
|||||||
toPrint += text.Bold(text.Green(gotext.Get(" (Installed)")))
|
toPrint += text.Bold(text.Green(gotext.Get(" (Installed)")))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove or refactor to check if git dir is unclean
|
|
||||||
if _, err := os.Stat(dir); !os.IsNotExist(err) {
|
if _, err := os.Stat(dir); !os.IsNotExist(err) {
|
||||||
toPrint += text.Bold(text.Green(gotext.Get(" (Build Files Exist)")))
|
toPrint += text.Bold(text.Green(gotext.Get(" (Build Files Exist)")))
|
||||||
}
|
}
|
||||||
@ -35,32 +33,32 @@ func pkgbuildNumberMenu(logger *text.Logger, pkgbuildDirs map[string]string,
|
|||||||
toPrint += "\n"
|
toPrint += "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Print(toPrint)
|
fmt.Fprint(w, toPrint)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectionMenu(logger *text.Logger, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string],
|
func selectionMenu(w io.Writer, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string],
|
||||||
message string, noConfirm bool, defaultAnswer string, skipFunc func(string) bool,
|
message string, noConfirm bool, defaultAnswer string, skipFunc func(string) bool,
|
||||||
) ([]string, error) {
|
) ([]string, error) {
|
||||||
selected := make([]string, 0)
|
selected := make([]string, 0)
|
||||||
|
|
||||||
pkgbuildNumberMenu(logger, pkgbuildDirs, bases, installed)
|
pkgbuildNumberMenu(w, pkgbuildDirs, bases, installed)
|
||||||
|
|
||||||
logger.Infoln(message)
|
text.Infoln(message)
|
||||||
logger.Infoln(gotext.Get("%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)", text.Cyan(gotext.Get("[N]one"))))
|
text.Infoln(gotext.Get("%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)", text.Cyan(gotext.Get("[N]one"))))
|
||||||
|
|
||||||
selectInput, err := logger.GetInput(defaultAnswer, noConfirm)
|
selectInput, err := text.GetInput(os.Stdin, defaultAnswer, noConfirm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
eInclude, eExclude, eOtherInclude, eOtherExclude := intrange.ParseNumberMenu(selectInput)
|
eInclude, eExclude, eOtherInclude, eOtherExclude := intrange.ParseNumberMenu(selectInput)
|
||||||
eIsInclude := len(eExclude) == 0 && eOtherExclude.Cardinality() == 0
|
eIsInclude := len(eExclude) == 0 && len(eOtherExclude) == 0
|
||||||
|
|
||||||
if eOtherInclude.Contains("abort") || eOtherInclude.Contains("ab") {
|
if eOtherInclude.Get("abort") || eOtherInclude.Get("ab") {
|
||||||
return nil, settings.ErrUserAbort{}
|
return nil, settings.ErrUserAbort{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if eOtherInclude.Contains("n") || eOtherInclude.Contains("none") {
|
if eOtherInclude.Get("n") || eOtherInclude.Get("none") {
|
||||||
return selected, nil
|
return selected, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,26 +73,26 @@ func selectionMenu(logger *text.Logger, pkgbuildDirs map[string]string, bases []
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if anyInstalled && (eOtherInclude.Contains("i") || eOtherInclude.Contains("installed")) {
|
if anyInstalled && (eOtherInclude.Get("i") || eOtherInclude.Get("installed")) {
|
||||||
selected = append(selected, pkgBase)
|
selected = append(selected, pkgBase)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !anyInstalled && (eOtherInclude.Contains("no") || eOtherInclude.Contains("notinstalled")) {
|
if !anyInstalled && (eOtherInclude.Get("no") || eOtherInclude.Get("notinstalled")) {
|
||||||
selected = append(selected, pkgBase)
|
selected = append(selected, pkgBase)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if eOtherInclude.Contains("a") || eOtherInclude.Contains("all") {
|
if eOtherInclude.Get("a") || eOtherInclude.Get("all") {
|
||||||
selected = append(selected, pkgBase)
|
selected = append(selected, pkgBase)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if eIsInclude && (eInclude.Get(len(bases)-i) || eOtherInclude.Contains(pkgBase)) {
|
if eIsInclude && (eInclude.Get(len(bases)-i) || eOtherInclude.Get(pkgBase)) {
|
||||||
selected = append(selected, pkgBase)
|
selected = append(selected, pkgBase)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !eIsInclude && (!eExclude.Get(len(bases)-i) && !eOtherExclude.Contains(pkgBase)) {
|
if !eIsInclude && (!eExclude.Get(len(bases)-i) && !eOtherExclude.Get(pkgBase)) {
|
||||||
selected = append(selected, pkgBase)
|
selected = append(selected, pkgBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -21,13 +23,13 @@ type item struct {
|
|||||||
Creator string `xml:"dc:creator"`
|
Creator string `xml:"dc:creator"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (item *item) printNews(logger *text.Logger, buildTime time.Time, all, quiet bool) {
|
func (item *item) print(buildTime time.Time, all, quiet bool) {
|
||||||
var fd string
|
var fd string
|
||||||
|
|
||||||
date, err := time.Parse(time.RFC1123Z, item.PubDate)
|
date, err := time.Parse(time.RFC1123Z, item.PubDate)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorln(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
} else {
|
} else {
|
||||||
fd = text.FormatTime(int(date.Unix()))
|
fd = text.FormatTime(int(date.Unix()))
|
||||||
if !all && !buildTime.IsZero() {
|
if !all && !buildTime.IsZero() {
|
||||||
@ -37,11 +39,11 @@ func (item *item) printNews(logger *text.Logger, buildTime time.Time, all, quiet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println(text.Bold(text.Magenta(fd)), text.Bold(strings.TrimSpace(item.Title)))
|
fmt.Println(text.Bold(text.Magenta(fd)), text.Bold(strings.TrimSpace(item.Title)))
|
||||||
|
|
||||||
if !quiet {
|
if !quiet {
|
||||||
desc := strings.TrimSpace(parseNews(item.Description))
|
desc := strings.TrimSpace(parseNews(item.Description))
|
||||||
logger.Println(desc)
|
fmt.Println(desc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,9 +60,7 @@ type rss struct {
|
|||||||
Channel channel `xml:"channel"`
|
Channel channel `xml:"channel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrintNewsFeed(ctx context.Context, client *http.Client, logger *text.Logger,
|
func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Time, bottomUp, all, quiet bool) error {
|
||||||
cutOffDate time.Time, bottomUp, all, quiet bool,
|
|
||||||
) error {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://archlinux.org/feeds/news", http.NoBody)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://archlinux.org/feeds/news", http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -87,11 +87,11 @@ func PrintNewsFeed(ctx context.Context, client *http.Client, logger *text.Logger
|
|||||||
|
|
||||||
if bottomUp {
|
if bottomUp {
|
||||||
for i := len(rssGot.Channel.Items) - 1; i >= 0; i-- {
|
for i := len(rssGot.Channel.Items) - 1; i >= 0; i-- {
|
||||||
rssGot.Channel.Items[i].printNews(logger, cutOffDate, all, quiet)
|
rssGot.Channel.Items[i].print(cutOffDate, all, quiet)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < len(rssGot.Channel.Items); i++ {
|
for i := 0; i < len(rssGot.Channel.Items); i++ {
|
||||||
rssGot.Channel.Items[i].printNews(logger, cutOffDate, all, quiet)
|
rssGot.Channel.Items[i].print(cutOffDate, all, quiet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package news
|
package news
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -8,15 +5,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bradleyjkemp/cupaloy"
|
"github.com/bradleyjkemp/cupaloy"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/h2non/gock.v1"
|
"gopkg.in/h2non/gock.v1"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const lastNews = `
|
const lastNews = `
|
||||||
@ -127,7 +121,6 @@ func TestPrintNewsFeed(t *testing.T) {
|
|||||||
{name: "latest-quiet", args: args{bottomUp: true, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
|
{name: "latest-quiet", args: args{bottomUp: true, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
|
||||||
{name: "latest-quiet-topdown", args: args{bottomUp: false, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
|
{name: "latest-quiet-topdown", args: args{bottomUp: false, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
|
||||||
}
|
}
|
||||||
t.Setenv("TZ", "UTC")
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
@ -138,16 +131,17 @@ func TestPrintNewsFeed(t *testing.T) {
|
|||||||
|
|
||||||
defer gock.Off()
|
defer gock.Off()
|
||||||
|
|
||||||
|
rescueStdout := os.Stdout
|
||||||
r, w, _ := os.Pipe()
|
r, w, _ := os.Pipe()
|
||||||
logger := text.NewLogger(w, w, strings.NewReader(""), false, "logger")
|
os.Stdout = w
|
||||||
|
|
||||||
err := PrintNewsFeed(context.Background(), &http.Client{}, logger,
|
err := PrintNewsFeed(context.Background(), &http.Client{}, tt.args.cutOffDate, tt.args.bottomUp, tt.args.all, tt.args.quiet)
|
||||||
tt.args.cutOffDate, tt.args.bottomUp, tt.args.all, tt.args.quiet)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
w.Close()
|
w.Close()
|
||||||
out, _ := io.ReadAll(r)
|
out, _ := io.ReadAll(r)
|
||||||
cupaloy.SnapshotT(t, out)
|
cupaloy.SnapshotT(t, out)
|
||||||
|
os.Stdout = rescueStdout
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,14 +160,15 @@ func TestPrintNewsFeedSameDay(t *testing.T) {
|
|||||||
|
|
||||||
defer gock.Off()
|
defer gock.Off()
|
||||||
|
|
||||||
|
rescueStdout := os.Stdout
|
||||||
r, w, _ := os.Pipe()
|
r, w, _ := os.Pipe()
|
||||||
logger := text.NewLogger(w, w, strings.NewReader(""), false, "logger")
|
os.Stdout = w
|
||||||
|
|
||||||
err := PrintNewsFeed(context.Background(), &http.Client{}, logger,
|
err := PrintNewsFeed(context.Background(), &http.Client{}, lastNewsTime, true, false, false)
|
||||||
lastNewsTime, true, false, false)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
w.Close()
|
w.Close()
|
||||||
out, _ := io.ReadAll(r)
|
out, _ := io.ReadAll(r)
|
||||||
cupaloy.SnapshotT(t, out)
|
cupaloy.SnapshotT(t, out)
|
||||||
|
os.Stdout = rescueStdout
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ type GPGCmdBuilder interface {
|
|||||||
|
|
||||||
// CheckPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,
|
// CheckPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,
|
||||||
// asks the user whether yay should try to import them.
|
// asks the user whether yay should try to import them.
|
||||||
func CheckPgpKeys(ctx context.Context, logger *text.Logger, pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
|
func CheckPgpKeys(ctx context.Context, pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
|
||||||
cmdBuilder GPGCmdBuilder, noConfirm bool,
|
cmdBuilder GPGCmdBuilder, noConfirm bool,
|
||||||
) ([]string, error) {
|
) ([]string, error) {
|
||||||
// Let's check the keys individually, and then we can offer to import
|
// Let's check the keys individually, and then we can offer to import
|
||||||
@ -78,23 +80,24 @@ func CheckPgpKeys(ctx context.Context, logger *text.Logger, pkgbuildDirsByBase m
|
|||||||
return []string{}, nil
|
return []string{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
str, err := formatKeysToImport(logger, problematic)
|
str, err := formatKeysToImport(problematic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println("\n", str)
|
fmt.Println()
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
if logger.ContinueTask(gotext.Get("Import?"), true, noConfirm) {
|
if text.ContinueTask(os.Stdin, gotext.Get("Import?"), true, noConfirm) {
|
||||||
return problematic.toSlice(), importKeys(ctx, logger, cmdBuilder, problematic.toSlice())
|
return problematic.toSlice(), importKeys(ctx, cmdBuilder, problematic.toSlice())
|
||||||
}
|
}
|
||||||
|
|
||||||
return problematic.toSlice(), nil
|
return problematic.toSlice(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// importKeys tries to import the list of keys specified in its argument.
|
// importKeys tries to import the list of keys specified in its argument.
|
||||||
func importKeys(ctx context.Context, logger *text.Logger, cmdBuilder GPGCmdBuilder, keys []string) error {
|
func importKeys(ctx context.Context, cmdBuilder GPGCmdBuilder, keys []string) error {
|
||||||
logger.OperationInfoln(gotext.Get("Importing keys with gpg..."))
|
text.OperationInfoln(gotext.Get("Importing keys with gpg..."))
|
||||||
|
|
||||||
if err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, append([]string{"--recv-keys"}, keys...)...)); err != nil {
|
if err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, append([]string{"--recv-keys"}, keys...)...)); err != nil {
|
||||||
return errors.New(gotext.Get("problem importing keys"))
|
return errors.New(gotext.Get("problem importing keys"))
|
||||||
@ -105,14 +108,14 @@ func importKeys(ctx context.Context, logger *text.Logger, cmdBuilder GPGCmdBuild
|
|||||||
|
|
||||||
// formatKeysToImport receives a set of keys and returns a string containing the
|
// formatKeysToImport receives a set of keys and returns a string containing the
|
||||||
// question asking the user wants to import the problematic keys.
|
// question asking the user wants to import the problematic keys.
|
||||||
func formatKeysToImport(logger *text.Logger, keys pgpKeySet) (string, error) {
|
func formatKeysToImport(keys pgpKeySet) (string, error) {
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
return "", errors.New(gotext.Get("no keys to import"))
|
return "", errors.New(gotext.Get("no keys to import"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
|
|
||||||
buffer.WriteString(logger.SprintOperationInfo(gotext.Get("PGP keys need importing:")))
|
buffer.WriteString(text.SprintOperationInfo(gotext.Get("PGP keys need importing:")))
|
||||||
|
|
||||||
for key, bases := range keys {
|
for key, bases := range keys {
|
||||||
pkglist := ""
|
pkglist := ""
|
||||||
@ -121,7 +124,7 @@ func formatKeysToImport(logger *text.Logger, keys pgpKeySet) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkglist = strings.TrimRight(pkglist, " ")
|
pkglist = strings.TrimRight(pkglist, " ")
|
||||||
buffer.WriteString("\n" + logger.SprintWarn(gotext.Get("%s, required by: %s", text.Cyan(key), text.Cyan(pkglist))))
|
buffer.WriteString("\n" + text.SprintWarn(gotext.Get("%s, required by: %s", text.Cyan(key), text.Cyan(pkglist))))
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.String(), nil
|
return buffer.String(), nil
|
@ -1,12 +1,8 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package pgp
|
package pgp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sort"
|
"sort"
|
||||||
@ -18,13 +14,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestLogger() *text.Logger {
|
|
||||||
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeSrcinfo(pkgbase string, pgpkeys ...string) *gosrc.Srcinfo {
|
func makeSrcinfo(pkgbase string, pgpkeys ...string) *gosrc.Srcinfo {
|
||||||
srcinfo := gosrc.Srcinfo{}
|
srcinfo := gosrc.Srcinfo{}
|
||||||
srcinfo.Pkgbase = pkgbase
|
srcinfo.Pkgbase = pkgbase
|
||||||
@ -234,7 +225,7 @@ func TestCheckPgpKeys(t *testing.T) {
|
|||||||
GPGFlags: []string{"--homedir /tmp"},
|
GPGFlags: []string{"--homedir /tmp"},
|
||||||
Runner: mockRunner,
|
Runner: mockRunner,
|
||||||
}
|
}
|
||||||
problematic, err := CheckPgpKeys(context.Background(), newTestLogger(), tt.pkgs, tt.srcinfos, &cmdBuilder, true)
|
problematic, err := CheckPgpKeys(context.Background(), tt.pkgs, tt.srcinfos, &cmdBuilder, true)
|
||||||
|
|
||||||
require.Len(t, mockRunner.ShowCalls, len(tt.wantShow))
|
require.Len(t, mockRunner.ShowCalls, len(tt.wantShow))
|
||||||
require.Len(t, mockRunner.CaptureCalls, len(tt.wantCapture))
|
require.Len(t, mockRunner.CaptureCalls, len(tt.wantCapture))
|
101
pkg/query/aur_info.go
Normal file
101
pkg/query/aur_info.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Jguer/aur"
|
||||||
|
"github.com/Jguer/aur/rpc"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/intrange"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/multierror"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pkg = aur.Pkg
|
||||||
|
|
||||||
|
// Queries the aur for information about specified packages.
|
||||||
|
// All packages should be queried in a single aur request except when the number
|
||||||
|
// of packages exceeds the number set in config.RequestSplitN.
|
||||||
|
// If the number does exceed config.RequestSplitN multiple aur requests will be
|
||||||
|
// performed concurrently.
|
||||||
|
func AURInfo(ctx context.Context, aurClient rpc.ClientInterface, names []string, warnings *AURWarnings, splitN int) ([]Pkg, error) {
|
||||||
|
info := make([]Pkg, 0, len(names))
|
||||||
|
seen := make(map[string]int)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mux sync.Mutex
|
||||||
|
wg sync.WaitGroup
|
||||||
|
errs multierror.MultiError
|
||||||
|
)
|
||||||
|
|
||||||
|
makeRequest := func(n, max int) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
text.Debugln("AUR RPC:", names[n:max])
|
||||||
|
|
||||||
|
tempInfo, requestErr := aurClient.Info(ctx, names[n:max])
|
||||||
|
if requestErr != nil {
|
||||||
|
errs.Add(requestErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mux.Lock()
|
||||||
|
info = append(info, tempInfo...)
|
||||||
|
mux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for n := 0; n < len(names); n += splitN {
|
||||||
|
max := intrange.Min(len(names), n+splitN)
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go makeRequest(n, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if err := errs.Return(); err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for k := range info {
|
||||||
|
seen[info[k].Name] = k
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
i, ok := seen[name]
|
||||||
|
if !ok && !warnings.Ignore.Get(name) {
|
||||||
|
warnings.Missing = append(warnings.Missing, name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg := info[i]
|
||||||
|
|
||||||
|
if pkg.Maintainer == "" && !warnings.Ignore.Get(name) {
|
||||||
|
warnings.Orphans = append(warnings.Orphans, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkg.OutOfDate != 0 && !warnings.Ignore.Get(name) {
|
||||||
|
warnings.OutOfDate = append(warnings.OutOfDate, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AURInfoPrint(ctx context.Context, aurClient rpc.ClientInterface, names []string, splitN int) ([]Pkg, error) {
|
||||||
|
text.OperationInfoln(gotext.Get("Querying AUR..."))
|
||||||
|
|
||||||
|
warnings := &AURWarnings{}
|
||||||
|
|
||||||
|
info, err := AURInfo(ctx, aurClient, names, warnings, splitN)
|
||||||
|
if err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings.Print()
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
@ -1,92 +1,47 @@
|
|||||||
package query
|
package query
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/aur"
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
"github.com/Jguer/go-alpm/v2"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AURWarnings struct {
|
type AURWarnings struct {
|
||||||
Orphans []string
|
Orphans []string
|
||||||
OutOfDate []string
|
OutOfDate []string
|
||||||
Missing []string
|
Missing []string
|
||||||
LocalNewer []string
|
Ignore stringset.StringSet
|
||||||
|
|
||||||
log *text.Logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWarnings(logger *text.Logger) *AURWarnings {
|
func NewWarnings() *AURWarnings {
|
||||||
return &AURWarnings{log: logger}
|
return &AURWarnings{Ignore: make(stringset.StringSet)}
|
||||||
}
|
|
||||||
|
|
||||||
func (warnings *AURWarnings) AddToWarnings(remote map[string]alpm.IPackage, aurPkg *aur.Pkg) {
|
|
||||||
name := aurPkg.Name
|
|
||||||
pkg, ok := remote[name]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if aurPkg.Maintainer == "" && !pkg.ShouldIgnore() {
|
|
||||||
warnings.Orphans = append(warnings.Orphans, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if aurPkg.OutOfDate != 0 && !pkg.ShouldIgnore() {
|
|
||||||
warnings.OutOfDate = append(warnings.OutOfDate, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !pkg.ShouldIgnore() && !isDevelPackage(pkg) && db.VerCmp(pkg.Version(), aurPkg.Version) > 0 {
|
|
||||||
left, right := GetVersionDiff(pkg.Version(), aurPkg.Version)
|
|
||||||
|
|
||||||
newerMsg := gotext.Get("%s: local (%s) is newer than AUR (%s)",
|
|
||||||
text.Cyan(name),
|
|
||||||
left, right,
|
|
||||||
)
|
|
||||||
|
|
||||||
warnings.LocalNewer = append(warnings.LocalNewer, newerMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (warnings *AURWarnings) CalculateMissing(remoteNames []string,
|
|
||||||
remote map[string]alpm.IPackage, aurData map[string]*aur.Pkg,
|
|
||||||
) {
|
|
||||||
for _, name := range remoteNames {
|
|
||||||
if _, ok := aurData[name]; !ok && !remote[name].ShouldIgnore() {
|
|
||||||
if _, ok := aurData[strings.TrimSuffix(name, "-debug")]; !ok {
|
|
||||||
warnings.Missing = append(warnings.Missing, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (warnings *AURWarnings) Print() {
|
func (warnings *AURWarnings) Print() {
|
||||||
normalMissing, debugMissing := filterDebugPkgs(warnings.Missing)
|
normalMissing, debugMissing := filterDebugPkgs(warnings.Missing)
|
||||||
|
|
||||||
if len(normalMissing) > 0 {
|
if len(normalMissing) > 0 {
|
||||||
warnings.log.Warnln(gotext.Get("Packages not in AUR:"), formatNames(normalMissing))
|
text.Warn(gotext.Get("Packages not in AUR:"))
|
||||||
|
printRange(normalMissing)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(debugMissing) > 0 {
|
if len(debugMissing) > 0 {
|
||||||
warnings.log.Warnln(gotext.Get("Missing AUR Debug Packages:"), formatNames(debugMissing))
|
text.Warn(gotext.Get("Missing AUR Debug Packages:"))
|
||||||
|
printRange(debugMissing)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(warnings.Orphans) > 0 {
|
if len(warnings.Orphans) > 0 {
|
||||||
warnings.log.Warnln(gotext.Get("Orphan (unmaintained) AUR Packages:"), formatNames(warnings.Orphans))
|
text.Warn(gotext.Get("Orphan (unmaintained) AUR Packages:"))
|
||||||
|
printRange(warnings.Orphans)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(warnings.OutOfDate) > 0 {
|
if len(warnings.OutOfDate) > 0 {
|
||||||
warnings.log.Warnln(gotext.Get("Flagged Out Of Date AUR Packages:"), formatNames(warnings.OutOfDate))
|
text.Warn(gotext.Get("Flagged Out Of Date AUR Packages:"))
|
||||||
}
|
printRange(warnings.OutOfDate)
|
||||||
|
|
||||||
if len(warnings.LocalNewer) > 0 {
|
|
||||||
for _, newer := range warnings.LocalNewer {
|
|
||||||
warnings.log.Warnln(newer)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +60,10 @@ func filterDebugPkgs(names []string) (normal, debug []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatNames(names []string) string {
|
func printRange(names []string) {
|
||||||
return " " + text.Cyan(strings.Join(names, " "))
|
for _, name := range names {
|
||||||
|
fmt.Print(" " + text.Cyan(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,19 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RemoveInvalidTargets(logger *text.Logger, targets []string, mode parser.TargetMode) []string {
|
func RemoveInvalidTargets(targets []string, mode parser.TargetMode) []string {
|
||||||
filteredTargets := make([]string, 0)
|
filteredTargets := make([]string, 0)
|
||||||
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
dbName, _ := text.SplitDBFromName(target)
|
dbName, _ := text.SplitDBFromName(target)
|
||||||
|
|
||||||
if dbName == "aur" && !mode.AtLeastAUR() {
|
if dbName == "aur" && !mode.AtLeastAUR() {
|
||||||
logger.Warnln(gotext.Get("%s: can't use target with option --repo -- skipping", text.Cyan(target)))
|
text.Warnln(gotext.Get("%s: can't use target with option --repo -- skipping", text.Cyan(target)))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbName != "aur" && dbName != "" && !mode.AtLeastRepo() {
|
if dbName != "aur" && dbName != "" && !mode.AtLeastRepo() {
|
||||||
logger.Warnln(gotext.Get("%s: can't use target with option --aur -- skipping", text.Cyan(target)))
|
text.Warnln(gotext.Get("%s: can't use target with option --aur -- skipping", text.Cyan(target)))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,31 +11,22 @@ import (
|
|||||||
"github.com/Jguer/go-alpm/v2"
|
"github.com/Jguer/go-alpm/v2"
|
||||||
"github.com/adrg/strutil"
|
"github.com/adrg/strutil"
|
||||||
"github.com/adrg/strutil/metrics"
|
"github.com/adrg/strutil/metrics"
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db"
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
"github.com/Jguer/yay/v12/pkg/intrange"
|
"github.com/Jguer/yay/v12/pkg/intrange"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/stringset"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sourceAUR = "aur"
|
const sourceAUR = "aur"
|
||||||
|
|
||||||
type SearchVerbosity int
|
|
||||||
|
|
||||||
// Verbosity settings for search.
|
|
||||||
const (
|
|
||||||
NumberMenu SearchVerbosity = iota
|
|
||||||
Detailed
|
|
||||||
Minimal
|
|
||||||
)
|
|
||||||
|
|
||||||
type Builder interface {
|
type Builder interface {
|
||||||
Len() int
|
Len() int
|
||||||
Execute(ctx context.Context, dbExecutor db.Executor, pkgS []string)
|
Execute(ctx context.Context, dbExecutor db.Executor, pkgS []string)
|
||||||
Results(dbExecutor db.Executor, verboseSearch SearchVerbosity) error
|
Results(dbExecutor db.Executor, verboseSearch SearchVerbosity) error
|
||||||
GetTargets(include, exclude intrange.IntRanges, otherExclude mapset.Set[string]) ([]string, error)
|
GetTargets(include, exclude intrange.IntRanges, otherExclude stringset.StringSet) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SourceQueryBuilder struct {
|
type SourceQueryBuilder struct {
|
||||||
@ -103,34 +94,20 @@ func (a *abstractResults) Less(i, j int) bool {
|
|||||||
pkgA := a.results[i]
|
pkgA := a.results[i]
|
||||||
pkgB := a.results[j]
|
pkgB := a.results[j]
|
||||||
|
|
||||||
var cmpResult bool
|
simA := a.calculateMetric(&pkgA)
|
||||||
|
simB := a.calculateMetric(&pkgB)
|
||||||
switch a.sortBy {
|
|
||||||
case "name":
|
|
||||||
cmpResult = !text.LessRunes([]rune(pkgA.name), []rune(pkgB.name))
|
|
||||||
if a.separateSources {
|
|
||||||
cmpSources := strings.Compare(pkgA.source, pkgB.source)
|
|
||||||
if cmpSources != 0 {
|
|
||||||
cmpResult = cmpSources > 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
simA := a.calculateMetric(&pkgA)
|
|
||||||
simB := a.calculateMetric(&pkgB)
|
|
||||||
cmpResult = simA > simB
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.bottomUp {
|
if a.bottomUp {
|
||||||
cmpResult = !cmpResult
|
return simA < simB
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmpResult
|
return simA > simB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor, pkgS []string) {
|
func (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor, pkgS []string) {
|
||||||
var aurErr error
|
var aurErr error
|
||||||
|
|
||||||
pkgS = RemoveInvalidTargets(s.logger, pkgS, s.targetMode)
|
pkgS = RemoveInvalidTargets(pkgS, s.targetMode)
|
||||||
|
|
||||||
metric := &metrics.Hamming{
|
metric := &metrics.Hamming{
|
||||||
CaseSensitive: false,
|
CaseSensitive: false,
|
||||||
@ -234,12 +211,12 @@ func (s *SourceQueryBuilder) Results(dbExecutor db.Executor, verboseSearch Searc
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkg := s.queryMap[s.results[i].source][s.results[i].name]
|
pkg := s.queryMap[s.results[i].source][s.results[i].name]
|
||||||
|
if s.results[i].source == sourceAUR {
|
||||||
switch pPkg := pkg.(type) {
|
aurPkg := pkg.(aur.Pkg)
|
||||||
case aur.Pkg:
|
toPrint += aurPkgSearchString(&aurPkg, dbExecutor, s.singleLineResults)
|
||||||
toPrint += aurPkgSearchString(&pPkg, dbExecutor, s.singleLineResults)
|
} else {
|
||||||
case alpm.IPackage:
|
syncPkg := pkg.(alpm.IPackage)
|
||||||
toPrint += syncPkgSearchString(pPkg, dbExecutor, s.singleLineResults)
|
toPrint += syncPkgSearchString(syncPkg, dbExecutor, s.singleLineResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.logger.Println(toPrint)
|
s.logger.Println(toPrint)
|
||||||
@ -253,15 +230,15 @@ func (s *SourceQueryBuilder) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
|
func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
|
||||||
otherExclude mapset.Set[string],
|
otherExclude stringset.StringSet,
|
||||||
) ([]string, error) {
|
) ([]string, error) {
|
||||||
var (
|
var (
|
||||||
isInclude = len(exclude) == 0 && otherExclude.Cardinality() == 0
|
isInclude = len(exclude) == 0 && len(otherExclude) == 0
|
||||||
targets []string
|
targets []string
|
||||||
lenRes = len(s.results)
|
lenRes = len(s.results)
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := 1; i <= s.Len(); i++ {
|
for i := 0; i <= s.Len(); i++ {
|
||||||
target := i - 1
|
target := i - 1
|
||||||
if s.bottomUp {
|
if s.bottomUp {
|
||||||
target = lenRes - i
|
target = lenRes - i
|
||||||
@ -289,7 +266,7 @@ func matchesSearch(pkg *aur.Pkg, terms []string) bool {
|
|||||||
desc := strings.ToLower(pkg.Description)
|
desc := strings.ToLower(pkg.Description)
|
||||||
targ := strings.ToLower(pkgN)
|
targ := strings.ToLower(pkgN)
|
||||||
|
|
||||||
if !strings.Contains(name, targ) && !strings.Contains(desc, targ) {
|
if !(strings.Contains(name, targ) || strings.Contains(desc, targ)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,362 +1,69 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package query
|
package query
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Jguer/aur"
|
"github.com/Jguer/aur/rpc"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/db/mock"
|
|
||||||
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSourceQueryBuilder(t *testing.T) {
|
func TestMixedSourceQueryBuilder(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
desc string
|
desc string
|
||||||
search []string
|
bottomUp bool
|
||||||
bottomUp bool
|
want string
|
||||||
separateSources bool
|
|
||||||
sortBy string
|
|
||||||
verbosity SearchVerbosity
|
|
||||||
targetMode parser.TargetMode
|
|
||||||
singleLineResults bool
|
|
||||||
searchBy string
|
|
||||||
wantResults []string
|
|
||||||
wantOutput []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{
|
{
|
||||||
desc: "sort-by-votes bottomup separatesources",
|
desc: "bottomup", bottomUp: true,
|
||||||
search: []string{"linux"},
|
want: "\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "votes",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux-ck", "linux-zen", "linux"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "sort-by-votes topdown separatesources",
|
desc: "topdown", bottomUp: false,
|
||||||
search: []string{"linux"},
|
want: "\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
||||||
bottomUp: false,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "votes",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux", "linux-zen", "linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-votes bottomup noseparatesources",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: false,
|
|
||||||
sortBy: "votes",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux-zen", "linux-ck", "linux"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-votes topdown noseparatesources",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: false,
|
|
||||||
separateSources: false,
|
|
||||||
sortBy: "votes",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux", "linux-ck", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name bottomup separatesources",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux-ck", "linux", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name topdown separatesources",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: false,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux-zen", "linux", "linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name bottomup noseparatesources",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: false,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux", "linux-ck", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name topdown noseparatesources",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: false,
|
|
||||||
separateSources: false,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Detailed,
|
|
||||||
wantResults: []string{"linux-zen", "linux-ck", "linux"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-votes bottomup separatesources number-menu",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "votes",
|
|
||||||
verbosity: NumberMenu,
|
|
||||||
wantResults: []string{"linux-ck", "linux-zen", "linux"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[35m3\x1b[0m \x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[35m2\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[35m1\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-votes topdown separatesources number-menu",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: false,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "votes",
|
|
||||||
verbosity: NumberMenu,
|
|
||||||
wantResults: []string{"linux", "linux-zen", "linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[35m1\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[35m2\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[35m3\x1b[0m \x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name bottomup separatesources number-menu",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: NumberMenu,
|
|
||||||
wantResults: []string{"linux-ck", "linux", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[35m3\x1b[0m \x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[35m2\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[35m1\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name topdown separatesources number-menu",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: false,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: NumberMenu,
|
|
||||||
wantResults: []string{"linux-zen", "linux", "linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[35m1\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n",
|
|
||||||
"\x1b[35m2\x1b[0m \x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n",
|
|
||||||
"\x1b[35m3\x1b[0m \x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name bottomup noseparatesources minimal",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: false,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Minimal,
|
|
||||||
wantResults: []string{"linux", "linux-ck", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"linux\n",
|
|
||||||
"linux-ck\n",
|
|
||||||
"linux-zen\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "only-aur minimal",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Minimal,
|
|
||||||
targetMode: parser.ModeAUR,
|
|
||||||
wantResults: []string{"linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"linux-ck\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "only-repo minimal",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Minimal,
|
|
||||||
targetMode: parser.ModeRepo,
|
|
||||||
wantResults: []string{"linux", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"linux\n",
|
|
||||||
"linux-zen\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name singleline",
|
|
||||||
search: []string{"linux"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Detailed,
|
|
||||||
singleLineResults: true,
|
|
||||||
wantResults: []string{"linux-ck", "linux", "linux-zen"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\tThe Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\tThe Linux kernel and modules\n",
|
|
||||||
"\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\tThe Linux ZEN kernel and modules\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sort-by-name search-by-name",
|
|
||||||
search: []string{"linux-ck"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
sortBy: "name",
|
|
||||||
verbosity: Detailed,
|
|
||||||
searchBy: "name",
|
|
||||||
targetMode: parser.ModeAUR,
|
|
||||||
wantResults: []string{"linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "only-aur search-by-several-terms",
|
|
||||||
search: []string{"linux-ck", "hrtimer"},
|
|
||||||
bottomUp: true,
|
|
||||||
separateSources: true,
|
|
||||||
verbosity: Detailed,
|
|
||||||
targetMode: parser.ModeAUR,
|
|
||||||
wantResults: []string{"linux-ck"},
|
|
||||||
wantOutput: []string{
|
|
||||||
"\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mockDB := &mock.DBExecutor{
|
|
||||||
SyncPackagesFn: func(pkgs ...string) []mock.IPackage {
|
|
||||||
mockDB := mock.NewDB("core")
|
|
||||||
return []mock.IPackage{
|
|
||||||
&mock.Package{
|
|
||||||
PName: "linux",
|
|
||||||
PVersion: "5.16.0",
|
|
||||||
PDescription: "The Linux kernel and modules",
|
|
||||||
PSize: 1,
|
|
||||||
PISize: 1,
|
|
||||||
PDB: mockDB,
|
|
||||||
},
|
|
||||||
&mock.Package{
|
|
||||||
PName: "linux-zen",
|
|
||||||
PVersion: "5.16.0",
|
|
||||||
PDescription: "The Linux ZEN kernel and modules",
|
|
||||||
PSize: 1,
|
|
||||||
PISize: 1,
|
|
||||||
PDB: mockDB,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LocalPackageFn: func(string) mock.IPackage {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mockAUR := &mockaur.MockAUR{
|
|
||||||
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
|
|
||||||
return []aur.Pkg{
|
|
||||||
{
|
|
||||||
Description: "The Linux-ck kernel and modules with ck's hrtimer patches",
|
|
||||||
FirstSubmitted: 1311346274,
|
|
||||||
ID: 1045311,
|
|
||||||
LastModified: 1646250901,
|
|
||||||
Maintainer: "graysky",
|
|
||||||
Name: "linux-ck",
|
|
||||||
NumVotes: 450,
|
|
||||||
OutOfDate: 0,
|
|
||||||
PackageBase: "linux-ck",
|
|
||||||
PackageBaseID: 50911,
|
|
||||||
Popularity: 1.511141,
|
|
||||||
URL: "https://wiki.archlinux.org/index.php/Linux-ck",
|
|
||||||
URLPath: "/cgit/aur.git/snapshot/linux-ck.tar.gz",
|
|
||||||
Version: "5.16.12-1",
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.desc, func(t *testing.T) {
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
client, err := rpc.NewClient(rpc.WithHTTPClient(&mockDoer{}))
|
||||||
|
|
||||||
w := &strings.Builder{}
|
w := &strings.Builder{}
|
||||||
queryBuilder := NewSourceQueryBuilder(mockAUR,
|
queryBuilder := NewSourceQueryBuilder(client,
|
||||||
text.NewLogger(w, io.Discard, strings.NewReader(""), false, "test"),
|
text.NewLogger(w, strings.NewReader(""), false, "test"),
|
||||||
tc.sortBy, tc.targetMode, tc.searchBy, tc.bottomUp,
|
"votes", parser.ModeAny, "", tc.bottomUp, false, false)
|
||||||
tc.singleLineResults, tc.separateSources)
|
search := []string{"linux"}
|
||||||
|
mockStore := &mockDB{}
|
||||||
|
|
||||||
queryBuilder.Execute(context.Background(), mockDB, tc.search)
|
require.NoError(t, err)
|
||||||
|
queryBuilder.Execute(context.Background(), mockStore, search)
|
||||||
|
assert.Len(t, queryBuilder.results, 3)
|
||||||
|
assert.Equal(t, 3, queryBuilder.Len())
|
||||||
|
|
||||||
assert.Len(t, queryBuilder.results, len(tc.wantResults))
|
if tc.bottomUp {
|
||||||
assert.Equal(t, len(tc.wantResults), queryBuilder.Len())
|
assert.Equal(t, "linux-zen", queryBuilder.results[0].name)
|
||||||
for i, name := range tc.wantResults {
|
assert.Equal(t, "linux-ck", queryBuilder.results[1].name)
|
||||||
assert.Equal(t, name, queryBuilder.results[i].name)
|
assert.Equal(t, "linux", queryBuilder.results[2].name)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, "linux-zen", queryBuilder.results[2].name)
|
||||||
|
assert.Equal(t, "linux-ck", queryBuilder.results[1].name)
|
||||||
|
assert.Equal(t, "linux", queryBuilder.results[0].name)
|
||||||
}
|
}
|
||||||
|
|
||||||
queryBuilder.Results(mockDB, tc.verbosity)
|
queryBuilder.Results(mockStore, Detailed)
|
||||||
|
|
||||||
assert.Equal(t, strings.Join(tc.wantOutput, ""), w.String())
|
wString := w.String()
|
||||||
|
require.GreaterOrEqual(t, len(wString), 1, wString)
|
||||||
|
assert.Equal(t, tc.want, wString)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,15 @@ import (
|
|||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SearchVerbosity int
|
||||||
|
|
||||||
|
// Verbosity settings for search.
|
||||||
|
const (
|
||||||
|
NumberMenu SearchVerbosity = iota
|
||||||
|
Detailed
|
||||||
|
Minimal
|
||||||
|
)
|
||||||
|
|
||||||
// queryAUR searches AUR and narrows based on subarguments.
|
// queryAUR searches AUR and narrows based on subarguments.
|
||||||
func queryAUR(ctx context.Context,
|
func queryAUR(ctx context.Context,
|
||||||
aurClient aur.QueryClient,
|
aurClient aur.QueryClient,
|
||||||
|
134
pkg/query/source_test.go
Normal file
134
pkg/query/source_test.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Jguer/aur/rpc"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/db"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/db/mock"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
|
||||||
|
"github.com/Jguer/go-alpm/v2"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
const validPayload = `{
|
||||||
|
"resultcount": 1,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"Description": "The Linux-ck kernel and modules with ck's hrtimer patches",
|
||||||
|
"FirstSubmitted": 1311346274,
|
||||||
|
"ID": 1045311,
|
||||||
|
"LastModified": 1646250901,
|
||||||
|
"Maintainer": "graysky",
|
||||||
|
"Name": "linux-ck",
|
||||||
|
"NumVotes": 450,
|
||||||
|
"OutOfDate": null,
|
||||||
|
"PackageBase": "linux-ck",
|
||||||
|
"PackageBaseID": 50911,
|
||||||
|
"Popularity": 1.511141,
|
||||||
|
"URL": "https://wiki.archlinux.org/index.php/Linux-ck",
|
||||||
|
"URLPath": "/cgit/aur.git/snapshot/linux-ck.tar.gz",
|
||||||
|
"Version": "5.16.12-1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "search",
|
||||||
|
"version": 5
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
type mockDB struct {
|
||||||
|
db.Executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockDB) LocalPackage(string) alpm.IPackage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockDB) PackageGroups(pkg alpm.IPackage) []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockDB) SyncPackages(...string) []alpm.IPackage {
|
||||||
|
mockDB := mock.NewDB("core")
|
||||||
|
linuxRepo := &mock.Package{
|
||||||
|
PName: "linux",
|
||||||
|
PVersion: "5.16.0",
|
||||||
|
PDescription: "The Linux kernel and modules",
|
||||||
|
PSize: 1,
|
||||||
|
PISize: 1,
|
||||||
|
PDB: mockDB,
|
||||||
|
}
|
||||||
|
|
||||||
|
linuxZen := &mock.Package{
|
||||||
|
PName: "linux-zen",
|
||||||
|
PVersion: "5.16.0",
|
||||||
|
PDescription: "The Linux ZEN kernel and modules",
|
||||||
|
PSize: 1,
|
||||||
|
PISize: 1,
|
||||||
|
PDB: mockDB,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []alpm.IPackage{linuxRepo, linuxZen}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockDoer struct{}
|
||||||
|
|
||||||
|
func (m *mockDoer) Do(req *http.Request) (*http.Response, error) {
|
||||||
|
return &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: io.NopCloser(bytes.NewBufferString(validPayload)),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSourceQueryBuilder(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
type testCase struct {
|
||||||
|
desc string
|
||||||
|
bottomUp bool
|
||||||
|
want string
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []testCase{
|
||||||
|
{desc: "bottomup", bottomUp: true, want: "\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n"},
|
||||||
|
{
|
||||||
|
desc: "topdown", bottomUp: false,
|
||||||
|
want: "\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux kernel and modules\n\x1b[1m\x1b[33mcore\x1b[0m\x1b[0m/\x1b[1mlinux-zen\x1b[0m \x1b[36m5.16.0\x1b[0m\x1b[1m (1.0 B 1.0 B) \x1b[0m\n The Linux ZEN kernel and modules\n\x1b[1m\x1b[34maur\x1b[0m\x1b[0m/\x1b[1mlinux-ck\x1b[0m \x1b[36m5.16.12-1\x1b[0m\x1b[1m (+450\x1b[0m \x1b[1m1.51) \x1b[0m\n The Linux-ck kernel and modules with ck's hrtimer patches\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
client, err := rpc.NewClient(rpc.WithHTTPClient(&mockDoer{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
queryBuilder := NewSourceQueryBuilder(client,
|
||||||
|
text.NewLogger(io.Discard, bytes.NewBufferString(""), false, "test"),
|
||||||
|
"votes", parser.ModeAny, "", tc.bottomUp, false, true)
|
||||||
|
search := []string{"linux"}
|
||||||
|
mockStore := &mockDB{}
|
||||||
|
|
||||||
|
queryBuilder.Execute(context.Background(), mockStore, search)
|
||||||
|
assert.Equal(t, 3, queryBuilder.Len())
|
||||||
|
|
||||||
|
if tc.bottomUp {
|
||||||
|
assert.Equal(t, "linux-ck", queryBuilder.results[0].name)
|
||||||
|
assert.Equal(t, "linux-zen", queryBuilder.results[1].name)
|
||||||
|
assert.Equal(t, "linux", queryBuilder.results[2].name)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, "linux-ck", queryBuilder.results[2].name)
|
||||||
|
assert.Equal(t, "linux-zen", queryBuilder.results[1].name)
|
||||||
|
assert.Equal(t, "linux", queryBuilder.results[0].name)
|
||||||
|
}
|
||||||
|
|
||||||
|
queryBuilder.Results(mockStore, Detailed)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,6 @@ import (
|
|||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pkg = aur.Pkg
|
|
||||||
|
|
||||||
func getSearchBy(value string) aur.By {
|
func getSearchBy(value string) aur.By {
|
||||||
switch value {
|
switch value {
|
||||||
case "name":
|
case "name":
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
package query
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
|
|
||||||
"github.com/Jguer/go-alpm/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetVersionDiff(oldVersion, newVersion string) (left, right string) {
|
|
||||||
if oldVersion == newVersion {
|
|
||||||
return oldVersion + text.Red(""), newVersion + text.Green("")
|
|
||||||
}
|
|
||||||
|
|
||||||
diffPosition := 0
|
|
||||||
|
|
||||||
checkWords := func(str string, index int, words ...string) bool {
|
|
||||||
// Make sure the word is not part of a longer word
|
|
||||||
ongoingWord := unicode.IsLetter(rune(str[index]))
|
|
||||||
if ongoingWord {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, word := range words {
|
|
||||||
wordLength := len(word)
|
|
||||||
|
|
||||||
nextIndex := index + 1
|
|
||||||
if (index < len(str)-wordLength) &&
|
|
||||||
(str[nextIndex:(nextIndex+wordLength)] == word) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, char := range oldVersion {
|
|
||||||
charIsSpecial := !unicode.IsLetter(char) && !unicode.IsNumber(char)
|
|
||||||
|
|
||||||
if (index >= len(newVersion)) || (char != rune(newVersion[index])) {
|
|
||||||
if charIsSpecial {
|
|
||||||
diffPosition = index
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if charIsSpecial ||
|
|
||||||
(((index == len(oldVersion)-1) || (index == len(newVersion)-1)) &&
|
|
||||||
((len(oldVersion) != len(newVersion)) ||
|
|
||||||
(oldVersion[index] == newVersion[index]))) ||
|
|
||||||
checkWords(oldVersion, index, "rc", "pre", "alpha", "beta") {
|
|
||||||
diffPosition = index + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
samePart := oldVersion[0:diffPosition]
|
|
||||||
|
|
||||||
left = samePart + text.Red(oldVersion[diffPosition:])
|
|
||||||
right = samePart + text.Green(newVersion[diffPosition:])
|
|
||||||
|
|
||||||
return left, right
|
|
||||||
}
|
|
||||||
|
|
||||||
func isDevelName(name string) bool {
|
|
||||||
for _, suffix := range []string{"git", "svn", "hg", "bzr", "nightly", "insiders-bin"} {
|
|
||||||
if strings.HasSuffix(name, "-"+suffix) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Contains(name, "-always-")
|
|
||||||
}
|
|
||||||
|
|
||||||
func isDevelPackage(pkg alpm.IPackage) bool {
|
|
||||||
return isDevelName(pkg.Name()) || isDevelName(pkg.Base())
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package query
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestVersionDiff(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
a string
|
|
||||||
b string
|
|
||||||
wantDiff string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "1.0.0-1 -> 1.0.0-2",
|
|
||||||
a: "1.0.0-1",
|
|
||||||
b: "1.0.0-2",
|
|
||||||
wantDiff: "1.0.0-" + text.Red("1") + " " + "1.0.0-" + text.Green("2"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "1.0.0-1 -> 1.0.1-1",
|
|
||||||
a: "1.0.0-1",
|
|
||||||
b: "1.0.1-1",
|
|
||||||
wantDiff: "1.0." + text.Red("0-1") + " " + "1.0." + text.Green("1-1"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "3.0.0~alpha7-3 -> 3.0.0~alpha7-4",
|
|
||||||
a: "3.0.0~alpha7-3",
|
|
||||||
b: "3.0.0~alpha7-4",
|
|
||||||
wantDiff: "3.0.0~alpha7-" + text.Red("3") + " " + "3.0.0~alpha7-" + text.Green("4"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "3.0.0~beta7-3 -> 3.0.0~beta8-3",
|
|
||||||
a: "3.0.0~beta7-3",
|
|
||||||
b: "3.0.0~beta8-3",
|
|
||||||
wantDiff: "3.0.0~" + text.Red("beta7-3") + " " + "3.0.0~" + text.Green("beta8-3"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "23.04.r131.b1bfe05-1 -> 23.04.r131.b1bfe07-1",
|
|
||||||
a: "23.04.r131.b1bfe05-1",
|
|
||||||
b: "23.04.r131.b1bfe07-1",
|
|
||||||
wantDiff: "23.04.r131." + text.Red("b1bfe05-1") + " " + "23.04.r131." + text.Green("b1bfe07-1"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "1.0.arch0-1 -> 1.0.arch1-2",
|
|
||||||
a: "1.0.arch0-1",
|
|
||||||
b: "1.0.arch1-2",
|
|
||||||
wantDiff: "1.0." + text.Red("arch0-1") + " " + "1.0." + text.Green("arch1-2"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
originalUseColor := text.UseColor
|
|
||||||
text.UseColor = true
|
|
||||||
left, right := GetVersionDiff(tc.a, tc.b)
|
|
||||||
gotDiff := left + " " + right
|
|
||||||
if gotDiff != tc.wantDiff {
|
|
||||||
t.Errorf("VersionDiff(%s, %s) = %s, want %s", tc.a, tc.b, gotDiff, tc.wantDiff)
|
|
||||||
}
|
|
||||||
text.UseColor = originalUseColor
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/Morganamilo/go-pacmanconf"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPacmanConf(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
path := "../../testdata/pacman.conf"
|
|
||||||
|
|
||||||
absPath, err := filepath.Abs(path)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// detect the architecture of the system
|
|
||||||
expectedArch := []string{"x86_64"}
|
|
||||||
if runtime.GOARCH == "arm64" {
|
|
||||||
expectedArch = []string{"aarch64"}
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedPacmanConf := &pacmanconf.Config{
|
|
||||||
RootDir: "/", DBPath: "/var/lib/pacman/",
|
|
||||||
CacheDir: []string{"/var/cache/pacman/pkg/"},
|
|
||||||
HookDir: []string{"/etc/pacman.d/hooks/"},
|
|
||||||
GPGDir: "/etc/pacman.d/gnupg/", LogFile: "/var/log/pacman.log",
|
|
||||||
HoldPkg: []string{"pacman", "glibc"}, IgnorePkg: []string{"xorm"},
|
|
||||||
IgnoreGroup: []string{"yorm"}, Architecture: expectedArch,
|
|
||||||
XferCommand: "/usr/bin/wget --passive-ftp -c -O %o %u",
|
|
||||||
NoUpgrade: []string(nil), NoExtract: []string(nil), CleanMethod: []string{"KeepInstalled"},
|
|
||||||
SigLevel: []string{"PackageRequired", "PackageTrustedOnly", "DatabaseOptional", "DatabaseTrustedOnly"},
|
|
||||||
LocalFileSigLevel: []string{"PackageOptional", "PackageTrustedOnly"},
|
|
||||||
RemoteFileSigLevel: []string{"PackageRequired", "PackageTrustedOnly"}, UseSyslog: true,
|
|
||||||
Color: true, UseDelta: 0, TotalDownload: false, CheckSpace: true,
|
|
||||||
VerbosePkgLists: true, DisableDownloadTimeout: false,
|
|
||||||
Repos: []pacmanconf.Repository{
|
|
||||||
{
|
|
||||||
Name: "core", Servers: []string{"Core"},
|
|
||||||
SigLevel: []string(nil), Usage: []string{"All"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "extra", Servers: []string{"Extra"}, SigLevel: []string(nil),
|
|
||||||
Usage: []string{"All"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "multilib", Servers: []string{"repo3", "multilib"},
|
|
||||||
SigLevel: []string(nil), Usage: []string{"All"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pacmanConf, color, err := retrievePacmanConfig(parser.MakeArguments(), absPath)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.NotNil(t, pacmanConf)
|
|
||||||
assert.Equal(t, color, false)
|
|
||||||
assert.EqualValues(t, expectedPacmanConf, pacmanConf)
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package runtime_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/runtime"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBuildRuntime(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
path := "../../testdata/pacman.conf"
|
|
||||||
|
|
||||||
absPath, err := filepath.Abs(path)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Prepare test inputs
|
|
||||||
cfg := &settings.Configuration{
|
|
||||||
Debug: true,
|
|
||||||
UseRPC: false,
|
|
||||||
AURURL: "https://aur.archlinux.org",
|
|
||||||
AURRPCURL: "https://aur.archlinux.org/rpc",
|
|
||||||
BuildDir: "/tmp",
|
|
||||||
VCSFilePath: "",
|
|
||||||
PacmanConf: absPath,
|
|
||||||
}
|
|
||||||
cmdArgs := parser.MakeArguments()
|
|
||||||
version := "1.0.0"
|
|
||||||
|
|
||||||
// Call the function being tested
|
|
||||||
run, err := runtime.NewRuntime(cfg, cmdArgs, version)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Assert the function's output
|
|
||||||
assert.NotNil(t, run)
|
|
||||||
assert.NotNil(t, run.QueryBuilder)
|
|
||||||
assert.NotNil(t, run.PacmanConf)
|
|
||||||
assert.NotNil(t, run.VCSStore)
|
|
||||||
assert.NotNil(t, run.CmdBuilder)
|
|
||||||
assert.NotNil(t, run.HTTPClient)
|
|
||||||
assert.NotNil(t, run.VoteClient)
|
|
||||||
assert.NotNil(t, run.AURClient)
|
|
||||||
assert.NotNil(t, run.Logger)
|
|
||||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Configuration) ParseCommandLine(a *parser.Arguments) error {
|
func (c *Configuration) ParseCommandLine(a *parser.Arguments) error {
|
||||||
@ -14,6 +15,9 @@ func (c *Configuration) ParseCommandLine(a *parser.Arguments) error {
|
|||||||
|
|
||||||
c.extractYayOptions(a)
|
c.extractYayOptions(a)
|
||||||
|
|
||||||
|
// Reload CmdBuilder
|
||||||
|
c.Runtime.CmdBuilder = c.CmdBuilder(nil)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,29 +46,29 @@ func (c *Configuration) extractYayOptions(a *parser.Arguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Configuration) handleOption(option, value string) bool {
|
func (c *Configuration) handleOption(option, value string) bool {
|
||||||
boolValue, err := strconv.ParseBool(value)
|
|
||||||
if err != nil {
|
|
||||||
boolValue = true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch option {
|
switch option {
|
||||||
case "aururl":
|
case "aururl":
|
||||||
c.AURURL = value
|
c.AURURL = value
|
||||||
case "aurrpcurl":
|
case "aurrpcurl":
|
||||||
c.AURRPCURL = value
|
c.AURRPCURL = value
|
||||||
case "save":
|
case "save":
|
||||||
c.SaveConfig = boolValue
|
c.SaveConfig = true
|
||||||
case "afterclean", "cleanafter":
|
case "afterclean", "cleanafter":
|
||||||
c.CleanAfter = boolValue
|
c.CleanAfter = true
|
||||||
case "keepsrc":
|
case "noafterclean", "nocleanafter":
|
||||||
c.KeepSrc = boolValue
|
c.CleanAfter = false
|
||||||
case "debug":
|
case "debug":
|
||||||
c.Debug = boolValue
|
c.Debug = true
|
||||||
return !boolValue
|
text.GlobalLogger.Debug = true
|
||||||
|
return false
|
||||||
case "devel":
|
case "devel":
|
||||||
c.Devel = boolValue
|
c.Devel = true
|
||||||
|
case "nodevel":
|
||||||
|
c.Devel = false
|
||||||
case "timeupdate":
|
case "timeupdate":
|
||||||
c.TimeUpdate = boolValue
|
c.TimeUpdate = true
|
||||||
|
case "notimeupdate":
|
||||||
|
c.TimeUpdate = false
|
||||||
case "topdown":
|
case "topdown":
|
||||||
c.BottomUp = false
|
c.BottomUp = false
|
||||||
case "bottomup":
|
case "bottomup":
|
||||||
@ -83,7 +87,7 @@ func (c *Configuration) handleOption(option, value string) bool {
|
|||||||
case "searchby":
|
case "searchby":
|
||||||
c.SearchBy = value
|
c.SearchBy = value
|
||||||
case "noconfirm":
|
case "noconfirm":
|
||||||
NoConfirm = boolValue
|
NoConfirm = true
|
||||||
case "config":
|
case "config":
|
||||||
c.PacmanConf = value
|
c.PacmanConf = value
|
||||||
case "redownload":
|
case "redownload":
|
||||||
@ -93,15 +97,17 @@ func (c *Configuration) handleOption(option, value string) bool {
|
|||||||
case "noredownload":
|
case "noredownload":
|
||||||
c.ReDownload = "no"
|
c.ReDownload = "no"
|
||||||
case "rebuild":
|
case "rebuild":
|
||||||
c.ReBuild = parser.RebuildModeYes
|
c.ReBuild = "yes"
|
||||||
case "rebuildall":
|
case "rebuildall":
|
||||||
c.ReBuild = parser.RebuildModeAll
|
c.ReBuild = "all"
|
||||||
case "rebuildtree":
|
case "rebuildtree":
|
||||||
c.ReBuild = parser.RebuildModeTree
|
c.ReBuild = "tree"
|
||||||
case "norebuild":
|
case "norebuild":
|
||||||
c.ReBuild = parser.RebuildModeNo
|
c.ReBuild = "no"
|
||||||
case "batchinstall":
|
case "batchinstall":
|
||||||
c.BatchInstall = boolValue
|
c.BatchInstall = true
|
||||||
|
case "nobatchinstall":
|
||||||
|
c.BatchInstall = false
|
||||||
case "answerclean":
|
case "answerclean":
|
||||||
c.AnswerClean = value
|
c.AnswerClean = value
|
||||||
case "noanswerclean":
|
case "noanswerclean":
|
||||||
@ -152,24 +158,44 @@ func (c *Configuration) handleOption(option, value string) bool {
|
|||||||
c.RequestSplitN = n
|
c.RequestSplitN = n
|
||||||
}
|
}
|
||||||
case "sudoloop":
|
case "sudoloop":
|
||||||
c.SudoLoop = boolValue
|
c.SudoLoop = true
|
||||||
|
case "nosudoloop":
|
||||||
|
c.SudoLoop = false
|
||||||
case "provides":
|
case "provides":
|
||||||
c.Provides = boolValue
|
c.Provides = true
|
||||||
|
case "noprovides":
|
||||||
|
c.Provides = false
|
||||||
case "pgpfetch":
|
case "pgpfetch":
|
||||||
c.PGPFetch = boolValue
|
c.PGPFetch = true
|
||||||
|
case "nopgpfetch":
|
||||||
|
c.PGPFetch = false
|
||||||
|
case "upgrademenu":
|
||||||
|
c.UpgradeMenu = true
|
||||||
|
case "noupgrademenu":
|
||||||
|
c.UpgradeMenu = false
|
||||||
case "cleanmenu":
|
case "cleanmenu":
|
||||||
c.CleanMenu = boolValue
|
c.CleanMenu = true
|
||||||
|
case "nocleanmenu":
|
||||||
|
c.CleanMenu = false
|
||||||
case "diffmenu":
|
case "diffmenu":
|
||||||
c.DiffMenu = boolValue
|
c.DiffMenu = true
|
||||||
|
case "nodiffmenu":
|
||||||
|
c.DiffMenu = false
|
||||||
case "editmenu":
|
case "editmenu":
|
||||||
c.EditMenu = boolValue
|
c.EditMenu = true
|
||||||
|
case "noeditmenu":
|
||||||
|
c.EditMenu = false
|
||||||
case "useask":
|
case "useask":
|
||||||
c.UseAsk = boolValue
|
c.UseAsk = true
|
||||||
|
case "nouseask":
|
||||||
|
c.UseAsk = false
|
||||||
case "combinedupgrade":
|
case "combinedupgrade":
|
||||||
c.CombinedUpgrade = boolValue
|
c.CombinedUpgrade = true
|
||||||
|
case "nocombinedupgrade":
|
||||||
|
c.CombinedUpgrade = false
|
||||||
case "a", "aur":
|
case "a", "aur":
|
||||||
c.Mode = parser.ModeAUR
|
c.Mode = parser.ModeAUR
|
||||||
case "N", "repo":
|
case "repo":
|
||||||
c.Mode = parser.ModeRepo
|
c.Mode = parser.ModeRepo
|
||||||
case "removemake":
|
case "removemake":
|
||||||
c.RemoveMake = "yes"
|
c.RemoveMake = "yes"
|
||||||
@ -177,10 +203,10 @@ func (c *Configuration) handleOption(option, value string) bool {
|
|||||||
c.RemoveMake = "no"
|
c.RemoveMake = "no"
|
||||||
case "askremovemake":
|
case "askremovemake":
|
||||||
c.RemoveMake = "ask"
|
c.RemoveMake = "ask"
|
||||||
case "askyesremovemake":
|
|
||||||
c.RemoveMake = "askyes"
|
|
||||||
case "separatesources":
|
case "separatesources":
|
||||||
c.SeparateSources = boolValue
|
c.SeparateSources = true
|
||||||
|
case "noseparatesources":
|
||||||
|
c.SeparateSources = false
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Jguer/yay/v12/pkg/settings/exe"
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
|
|
||||||
@ -23,60 +24,61 @@ var NoConfirm = false
|
|||||||
|
|
||||||
// Configuration stores yay's config.
|
// Configuration stores yay's config.
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
AURURL string `json:"aururl"`
|
Runtime *Runtime `json:"-"`
|
||||||
AURRPCURL string `json:"aurrpcurl"`
|
AURURL string `json:"aururl"`
|
||||||
BuildDir string `json:"buildDir"`
|
AURRPCURL string `json:"aurrpcurl"`
|
||||||
Editor string `json:"editor"`
|
BuildDir string `json:"buildDir"`
|
||||||
EditorFlags string `json:"editorflags"`
|
Editor string `json:"editor"`
|
||||||
MakepkgBin string `json:"makepkgbin"`
|
EditorFlags string `json:"editorflags"`
|
||||||
MakepkgConf string `json:"makepkgconf"`
|
MakepkgBin string `json:"makepkgbin"`
|
||||||
PacmanBin string `json:"pacmanbin"`
|
MakepkgConf string `json:"makepkgconf"`
|
||||||
PacmanConf string `json:"pacmanconf"`
|
PacmanBin string `json:"pacmanbin"`
|
||||||
ReDownload string `json:"redownload"`
|
PacmanConf string `json:"pacmanconf"`
|
||||||
AnswerClean string `json:"answerclean"`
|
ReDownload string `json:"redownload"`
|
||||||
AnswerDiff string `json:"answerdiff"`
|
ReBuild string `json:"rebuild"`
|
||||||
AnswerEdit string `json:"answeredit"`
|
AnswerClean string `json:"answerclean"`
|
||||||
AnswerUpgrade string `json:"answerupgrade"`
|
AnswerDiff string `json:"answerdiff"`
|
||||||
GitBin string `json:"gitbin"`
|
AnswerEdit string `json:"answeredit"`
|
||||||
GpgBin string `json:"gpgbin"`
|
AnswerUpgrade string `json:"answerupgrade"`
|
||||||
GpgFlags string `json:"gpgflags"`
|
GitBin string `json:"gitbin"`
|
||||||
MFlags string `json:"mflags"`
|
GpgBin string `json:"gpgbin"`
|
||||||
SortBy string `json:"sortby"`
|
GpgFlags string `json:"gpgflags"`
|
||||||
SearchBy string `json:"searchby"`
|
MFlags string `json:"mflags"`
|
||||||
GitFlags string `json:"gitflags"`
|
SortBy string `json:"sortby"`
|
||||||
RemoveMake string `json:"removemake"`
|
SearchBy string `json:"searchby"`
|
||||||
SudoBin string `json:"sudobin"`
|
GitFlags string `json:"gitflags"`
|
||||||
SudoFlags string `json:"sudoflags"`
|
RemoveMake string `json:"removemake"`
|
||||||
Version string `json:"version"`
|
SudoBin string `json:"sudobin"`
|
||||||
RequestSplitN int `json:"requestsplitn"`
|
SudoFlags string `json:"sudoflags"`
|
||||||
CompletionInterval int `json:"completionrefreshtime"`
|
Version string `json:"version"`
|
||||||
MaxConcurrentDownloads int `json:"maxconcurrentdownloads"`
|
RequestSplitN int `json:"requestsplitn"`
|
||||||
BottomUp bool `json:"bottomup"`
|
CompletionInterval int `json:"completionrefreshtime"`
|
||||||
SudoLoop bool `json:"sudoloop"`
|
MaxConcurrentDownloads int `json:"maxconcurrentdownloads"`
|
||||||
TimeUpdate bool `json:"timeupdate"`
|
BottomUp bool `json:"bottomup"`
|
||||||
Devel bool `json:"devel"`
|
SudoLoop bool `json:"sudoloop"`
|
||||||
CleanAfter bool `json:"cleanAfter"`
|
TimeUpdate bool `json:"timeupdate"`
|
||||||
KeepSrc bool `json:"keepSrc"`
|
Devel bool `json:"devel"`
|
||||||
Provides bool `json:"provides"`
|
CleanAfter bool `json:"cleanAfter"`
|
||||||
PGPFetch bool `json:"pgpfetch"`
|
Provides bool `json:"provides"`
|
||||||
CleanMenu bool `json:"cleanmenu"`
|
PGPFetch bool `json:"pgpfetch"`
|
||||||
DiffMenu bool `json:"diffmenu"`
|
UpgradeMenu bool `json:"upgrademenu"`
|
||||||
EditMenu bool `json:"editmenu"`
|
CleanMenu bool `json:"cleanmenu"`
|
||||||
CombinedUpgrade bool `json:"combinedupgrade"`
|
DiffMenu bool `json:"diffmenu"`
|
||||||
UseAsk bool `json:"useask"`
|
EditMenu bool `json:"editmenu"`
|
||||||
BatchInstall bool `json:"batchinstall"`
|
CombinedUpgrade bool `json:"combinedupgrade"`
|
||||||
SingleLineResults bool `json:"singlelineresults"`
|
UseAsk bool `json:"useask"`
|
||||||
SeparateSources bool `json:"separatesources"`
|
BatchInstall bool `json:"batchinstall"`
|
||||||
Debug bool `json:"debug"`
|
SingleLineResults bool `json:"singlelineresults"`
|
||||||
UseRPC bool `json:"rpc"`
|
SeparateSources bool `json:"separatesources"`
|
||||||
DoubleConfirm bool `json:"doubleconfirm"` // confirm install before and after build
|
NewInstallEngine bool `json:"newinstallengine"`
|
||||||
|
Debug bool `json:"debug"`
|
||||||
|
UseRPC bool `json:"rpc"`
|
||||||
|
|
||||||
CompletionPath string `json:"-"`
|
CompletionPath string `json:"-"`
|
||||||
VCSFilePath string `json:"-"`
|
VCSFilePath string `json:"-"`
|
||||||
// ConfigPath string `json:"-"`
|
// ConfigPath string `json:"-"`
|
||||||
SaveConfig bool `json:"-"`
|
SaveConfig bool `json:"-"`
|
||||||
Mode parser.TargetMode `json:"-"`
|
Mode parser.TargetMode `json:"-"`
|
||||||
ReBuild parser.RebuildMode `json:"rebuild"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveConfig writes yay config to file.
|
// SaveConfig writes yay config to file.
|
||||||
@ -130,7 +132,7 @@ func (c *Configuration) expandEnv() {
|
|||||||
c.SudoBin = expandEnvOrHome(c.SudoBin)
|
c.SudoBin = expandEnvOrHome(c.SudoBin)
|
||||||
c.SudoFlags = os.ExpandEnv(c.SudoFlags)
|
c.SudoFlags = os.ExpandEnv(c.SudoFlags)
|
||||||
c.ReDownload = os.ExpandEnv(c.ReDownload)
|
c.ReDownload = os.ExpandEnv(c.ReDownload)
|
||||||
c.ReBuild = parser.RebuildMode(os.ExpandEnv(string(c.ReBuild)))
|
c.ReBuild = os.ExpandEnv(c.ReBuild)
|
||||||
c.AnswerClean = os.ExpandEnv(c.AnswerClean)
|
c.AnswerClean = os.ExpandEnv(c.AnswerClean)
|
||||||
c.AnswerDiff = os.ExpandEnv(c.AnswerDiff)
|
c.AnswerDiff = os.ExpandEnv(c.AnswerDiff)
|
||||||
c.AnswerEdit = os.ExpandEnv(c.AnswerEdit)
|
c.AnswerEdit = os.ExpandEnv(c.AnswerEdit)
|
||||||
@ -194,7 +196,6 @@ func DefaultConfig(version string) *Configuration {
|
|||||||
AURURL: "https://aur.archlinux.org",
|
AURURL: "https://aur.archlinux.org",
|
||||||
BuildDir: os.ExpandEnv("$HOME/.cache/yay"),
|
BuildDir: os.ExpandEnv("$HOME/.cache/yay"),
|
||||||
CleanAfter: false,
|
CleanAfter: false,
|
||||||
KeepSrc: false,
|
|
||||||
Editor: "",
|
Editor: "",
|
||||||
EditorFlags: "",
|
EditorFlags: "",
|
||||||
Devel: false,
|
Devel: false,
|
||||||
@ -208,7 +209,7 @@ func DefaultConfig(version string) *Configuration {
|
|||||||
GitFlags: "",
|
GitFlags: "",
|
||||||
BottomUp: true,
|
BottomUp: true,
|
||||||
CompletionInterval: 7,
|
CompletionInterval: 7,
|
||||||
MaxConcurrentDownloads: 1,
|
MaxConcurrentDownloads: 0,
|
||||||
SortBy: "votes",
|
SortBy: "votes",
|
||||||
SearchBy: "name-desc",
|
SearchBy: "name-desc",
|
||||||
SudoLoop: false,
|
SudoLoop: false,
|
||||||
@ -227,26 +228,30 @@ func DefaultConfig(version string) *Configuration {
|
|||||||
AnswerUpgrade: "",
|
AnswerUpgrade: "",
|
||||||
RemoveMake: "ask",
|
RemoveMake: "ask",
|
||||||
Provides: true,
|
Provides: true,
|
||||||
|
UpgradeMenu: true,
|
||||||
CleanMenu: true,
|
CleanMenu: true,
|
||||||
DiffMenu: true,
|
DiffMenu: true,
|
||||||
EditMenu: false,
|
EditMenu: false,
|
||||||
UseAsk: false,
|
UseAsk: false,
|
||||||
CombinedUpgrade: true,
|
CombinedUpgrade: false,
|
||||||
SeparateSources: true,
|
SeparateSources: true,
|
||||||
|
NewInstallEngine: true,
|
||||||
Version: version,
|
Version: version,
|
||||||
Debug: false,
|
Debug: false,
|
||||||
UseRPC: true,
|
UseRPC: true,
|
||||||
DoubleConfirm: true,
|
Runtime: &Runtime{
|
||||||
Mode: parser.ModeAny,
|
Logger: text.GlobalLogger,
|
||||||
|
},
|
||||||
|
Mode: parser.ModeAny,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig(logger *text.Logger, configPath, version string) (*Configuration, error) {
|
func NewConfig(configPath, version string) (*Configuration, error) {
|
||||||
newConfig := DefaultConfig(version)
|
newConfig := DefaultConfig(version)
|
||||||
|
|
||||||
cacheHome, errCache := getCacheHome()
|
cacheHome, errCache := getCacheHome()
|
||||||
if errCache != nil && logger != nil {
|
if errCache != nil {
|
||||||
logger.Errorln(errCache)
|
text.Errorln(errCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
newConfig.BuildDir = cacheHome
|
newConfig.BuildDir = cacheHome
|
||||||
@ -292,3 +297,27 @@ func (c *Configuration) load(configPath string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) CmdBuilder(runner exe.Runner) exe.ICmdBuilder {
|
||||||
|
if runner == nil {
|
||||||
|
runner = &exe.OSRunner{Log: c.Runtime.Logger.Child("runner")}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &exe.CmdBuilder{
|
||||||
|
GitBin: c.GitBin,
|
||||||
|
GitFlags: strings.Fields(c.GitFlags),
|
||||||
|
GPGBin: c.GpgBin,
|
||||||
|
GPGFlags: strings.Fields(c.GpgFlags),
|
||||||
|
MakepkgFlags: strings.Fields(c.MFlags),
|
||||||
|
MakepkgConfPath: c.MakepkgConf,
|
||||||
|
MakepkgBin: c.MakepkgBin,
|
||||||
|
SudoBin: c.SudoBin,
|
||||||
|
SudoFlags: strings.Fields(c.SudoFlags),
|
||||||
|
SudoLoopEnabled: c.SudoLoop,
|
||||||
|
PacmanBin: c.PacmanBin,
|
||||||
|
PacmanConfigPath: c.PacmanConf,
|
||||||
|
PacmanDBPath: "",
|
||||||
|
Runner: runner,
|
||||||
|
Log: c.Runtime.Logger.Child("cmd_builder"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -36,7 +33,7 @@ func TestNewConfig(t *testing.T) {
|
|||||||
_, err = f.WriteString(string(configJSON))
|
_, err = f.WriteString(string(configJSON))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
newConfig, err := NewConfig(nil, GetConfigPath(), "v1.0.0")
|
newConfig, err := NewConfig(GetConfigPath(), "v1.0.0")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, filepath.Join(cacheDir, "test-build-dir"), newConfig.BuildDir)
|
assert.Equal(t, filepath.Join(cacheDir, "test-build-dir"), newConfig.BuildDir)
|
||||||
@ -69,7 +66,7 @@ func TestNewConfigAURDEST(t *testing.T) {
|
|||||||
_, err = f.WriteString(string(configJSON))
|
_, err = f.WriteString(string(configJSON))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
newConfig, err := NewConfig(nil, GetConfigPath(), "v1.0.0")
|
newConfig, err := NewConfig(GetConfigPath(), "v1.0.0")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, filepath.Join(cacheDir, "test-build-dir"), newConfig.BuildDir)
|
assert.Equal(t, filepath.Join(cacheDir, "test-build-dir"), newConfig.BuildDir)
|
||||||
@ -102,7 +99,7 @@ func TestNewConfigAURDESTTildeExpansion(t *testing.T) {
|
|||||||
_, err = f.WriteString(string(configJSON))
|
_, err = f.WriteString(string(configJSON))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
newConfig, err := NewConfig(nil, GetConfigPath(), "v1.0.0")
|
newConfig, err := NewConfig(GetConfigPath(), "v1.0.0")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, filepath.Join(homeDir, "test-build-dir"), newConfig.BuildDir)
|
assert.Equal(t, filepath.Join(homeDir, "test-build-dir"), newConfig.BuildDir)
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build !integration
|
|
||||||
// +build !integration
|
|
||||||
|
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings"
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
"github.com/Jguer/yay/v12/pkg/text"
|
"github.com/Jguer/yay/v12/pkg/text"
|
||||||
)
|
)
|
||||||
@ -39,7 +38,7 @@ type ICmdBuilder interface {
|
|||||||
BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
|
BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
|
||||||
BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
|
BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
|
||||||
AddMakepkgFlag(string)
|
AddMakepkgFlag(string)
|
||||||
GetKeepSrc() bool
|
SetPacmanDBPath(string)
|
||||||
SudoLoop()
|
SudoLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,32 +56,10 @@ type CmdBuilder struct {
|
|||||||
PacmanBin string
|
PacmanBin string
|
||||||
PacmanConfigPath string
|
PacmanConfigPath string
|
||||||
PacmanDBPath string
|
PacmanDBPath string
|
||||||
KeepSrc bool
|
|
||||||
Runner Runner
|
Runner Runner
|
||||||
Log *text.Logger
|
Log *text.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmdBuilder(cfg *settings.Configuration, runner Runner, logger *text.Logger, dbPath string) *CmdBuilder {
|
|
||||||
return &CmdBuilder{
|
|
||||||
GitBin: cfg.GitBin,
|
|
||||||
GitFlags: strings.Fields(cfg.GitFlags),
|
|
||||||
GPGBin: cfg.GpgBin,
|
|
||||||
GPGFlags: strings.Fields(cfg.GpgFlags),
|
|
||||||
MakepkgFlags: strings.Fields(cfg.MFlags),
|
|
||||||
MakepkgConfPath: cfg.MakepkgConf,
|
|
||||||
MakepkgBin: cfg.MakepkgBin,
|
|
||||||
SudoBin: cfg.SudoBin,
|
|
||||||
SudoFlags: strings.Fields(cfg.SudoFlags),
|
|
||||||
SudoLoopEnabled: cfg.SudoLoop,
|
|
||||||
PacmanBin: cfg.PacmanBin,
|
|
||||||
PacmanConfigPath: cfg.PacmanConf,
|
|
||||||
PacmanDBPath: dbPath,
|
|
||||||
KeepSrc: cfg.KeepSrc,
|
|
||||||
Runner: runner,
|
|
||||||
Log: logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CmdBuilder) BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd {
|
func (c *CmdBuilder) BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd {
|
||||||
args := make([]string, len(c.GPGFlags), len(c.GPGFlags)+len(extraArgs))
|
args := make([]string, len(c.GPGFlags), len(c.GPGFlags)+len(extraArgs))
|
||||||
copy(args, c.GPGFlags)
|
copy(args, c.GPGFlags)
|
||||||
@ -158,6 +135,10 @@ func (c *CmdBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CmdBuilder) SetPacmanDBPath(dbPath string) {
|
||||||
|
c.PacmanDBPath = dbPath
|
||||||
|
}
|
||||||
|
|
||||||
// deElevateCommand, `systemd-run` code based on pikaur.
|
// deElevateCommand, `systemd-run` code based on pikaur.
|
||||||
func (c *CmdBuilder) deElevateCommand(ctx context.Context, cmd *exec.Cmd) *exec.Cmd {
|
func (c *CmdBuilder) deElevateCommand(ctx context.Context, cmd *exec.Cmd) *exec.Cmd {
|
||||||
if os.Geteuid() != 0 {
|
if os.Geteuid() != 0 {
|
||||||
@ -173,12 +154,11 @@ func (c *CmdBuilder) deElevateCommand(ctx context.Context, cmd *exec.Cmd) *exec.
|
|||||||
|
|
||||||
if userFound, err := user.Lookup(ogCaller); err == nil {
|
if userFound, err := user.Lookup(ogCaller); err == nil {
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
uid64, errUid := strconv.ParseUint(userFound.Uid, 10, 32)
|
uid, _ := strconv.Atoi(userFound.Uid)
|
||||||
gid64, errGid := strconv.ParseUint(userFound.Gid, 10, 32)
|
gid, _ := strconv.Atoi(userFound.Gid)
|
||||||
if errUid == nil && errGid == nil {
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid64), Gid: uint32(gid64)}
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs := []string{
|
cmdArgs := []string{
|
||||||
@ -262,7 +242,7 @@ func (c *CmdBuilder) waitLock(dbPath string) {
|
|||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
if _, err := os.Stat(lockDBPath); err != nil {
|
if _, err := os.Stat(lockDBPath); err != nil {
|
||||||
c.Log.Println()
|
fmt.Println()
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -300,7 +280,3 @@ func (c *CmdBuilder) Show(cmd *exec.Cmd) error {
|
|||||||
func (c *CmdBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
|
func (c *CmdBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
|
||||||
return c.Runner.Capture(cmd)
|
return c.Runner.Capture(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CmdBuilder) GetKeepSrc() bool {
|
|
||||||
return c.KeepSrc
|
|
||||||
}
|
|
||||||
|
@ -19,10 +19,6 @@ type OSRunner struct {
|
|||||||
Log *text.Logger
|
Log *text.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOSRunner(log *text.Logger) *OSRunner {
|
|
||||||
return &OSRunner{log}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *OSRunner) Show(cmd *exec.Cmd) error {
|
func (r *OSRunner) Show(cmd *exec.Cmd) error {
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
||||||
)
|
)
|
||||||
@ -20,25 +19,17 @@ func (c *Call) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MockBuilder struct {
|
type MockBuilder struct {
|
||||||
Runner Runner
|
Runner Runner
|
||||||
BuildMakepkgCmdCallsMu sync.Mutex
|
BuildMakepkgCmdCalls []Call
|
||||||
BuildMakepkgCmdCalls []Call
|
BuildMakepkgCmdFn func(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
|
||||||
BuildMakepkgCmdFn func(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
|
BuildPacmanCmdFn func(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
|
||||||
BuildPacmanCmdFn func(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
|
|
||||||
GetKeepSrcFn func() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MockRunner struct {
|
type MockRunner struct {
|
||||||
ShowCallsMu sync.Mutex
|
ShowCalls []Call
|
||||||
ShowCalls []Call
|
CaptureCalls []Call
|
||||||
CaptureCallsMu sync.Mutex
|
ShowFn func(cmd *exec.Cmd) error
|
||||||
CaptureCalls []Call
|
CaptureFn func(cmd *exec.Cmd) (stdout string, stderr string, err error)
|
||||||
ShowFn func(cmd *exec.Cmd) error
|
|
||||||
CaptureFn func(cmd *exec.Cmd) (stdout string, stderr string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockBuilder) BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd {
|
|
||||||
return exec.CommandContext(ctx, "gpg", extraArgs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {
|
func (m *MockBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {
|
||||||
@ -49,7 +40,6 @@ func (m *MockBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs
|
|||||||
res = exec.CommandContext(ctx, "makepkg", extraArgs...)
|
res = exec.CommandContext(ctx, "makepkg", extraArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.BuildMakepkgCmdCallsMu.Lock()
|
|
||||||
m.BuildMakepkgCmdCalls = append(m.BuildMakepkgCmdCalls, Call{
|
m.BuildMakepkgCmdCalls = append(m.BuildMakepkgCmdCalls, Call{
|
||||||
Res: []interface{}{res},
|
Res: []interface{}{res},
|
||||||
Args: []interface{}{
|
Args: []interface{}{
|
||||||
@ -58,7 +48,6 @@ func (m *MockBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs
|
|||||||
extraArgs,
|
extraArgs,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
m.BuildMakepkgCmdCallsMu.Unlock()
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -96,19 +85,13 @@ func (m *MockBuilder) Show(cmd *exec.Cmd) error {
|
|||||||
return m.Runner.Show(cmd)
|
return m.Runner.Show(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockBuilder) GetKeepSrc() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
|
func (m *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
|
||||||
m.CaptureCallsMu.Lock()
|
|
||||||
m.CaptureCalls = append(m.CaptureCalls, Call{
|
m.CaptureCalls = append(m.CaptureCalls, Call{
|
||||||
Args: []interface{}{
|
Args: []interface{}{
|
||||||
cmd,
|
cmd,
|
||||||
},
|
},
|
||||||
Dir: cmd.Dir,
|
Dir: cmd.Dir,
|
||||||
})
|
})
|
||||||
m.CaptureCallsMu.Unlock()
|
|
||||||
|
|
||||||
if m.CaptureFn != nil {
|
if m.CaptureFn != nil {
|
||||||
return m.CaptureFn(cmd)
|
return m.CaptureFn(cmd)
|
||||||
@ -123,14 +106,12 @@ func (m *MockRunner) Show(cmd *exec.Cmd) error {
|
|||||||
err = m.ShowFn(cmd)
|
err = m.ShowFn(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.ShowCallsMu.Lock()
|
|
||||||
m.ShowCalls = append(m.ShowCalls, Call{
|
m.ShowCalls = append(m.ShowCalls, Call{
|
||||||
Args: []interface{}{
|
Args: []interface{}{
|
||||||
cmd,
|
cmd,
|
||||||
},
|
},
|
||||||
Dir: cmd.Dir,
|
Dir: cmd.Dir,
|
||||||
})
|
})
|
||||||
m.ShowCallsMu.Unlock()
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func DefaultMigrations() []configMigration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Configuration) RunMigrations(logger *text.Logger, migrations []configMigration,
|
func (c *Configuration) RunMigrations(migrations []configMigration,
|
||||||
configPath, newVersion string,
|
configPath, newVersion string,
|
||||||
) error {
|
) error {
|
||||||
saveConfig := false
|
saveConfig := false
|
||||||
@ -53,7 +53,7 @@ func (c *Configuration) RunMigrations(logger *text.Logger, migrations []configMi
|
|||||||
for _, migration := range migrations {
|
for _, migration := range migrations {
|
||||||
if db.VerCmp(migration.TargetVersion(), c.Version) > 0 {
|
if db.VerCmp(migration.TargetVersion(), c.Version) > 0 {
|
||||||
if migration.Do(c) {
|
if migration.Do(c) {
|
||||||
logger.Infoln("Config migration executed (",
|
text.Infoln("Config migration executed (",
|
||||||
migration.TargetVersion(), "):", migration)
|
migration.TargetVersion(), "):", migration)
|
||||||
|
|
||||||
saveConfig = true
|
saveConfig = true
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user