Compare commits

...

155 Commits

Author SHA1 Message Date
dependabot[bot]
6f3bc5cc4c
chore(deps): bump golang.org/x/net from 0.40.0 to 0.41.0 in the go-all group (#2632)
chore(deps): bump golang.org/x/net in the go-all group

Bumps the go-all group with 1 update: [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/net` from 0.40.0 to 0.41.0
- [Commits](https://github.com/golang/net/compare/v0.40.0...v0.41.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 15:38:14 +02:00
dependabot[bot]
c2caf9c7d7
chore(deps): bump github.com/leonelquinteros/gotext from 1.7.1 to 1.7.2 in the go-all group (#2629)
chore(deps): bump github.com/leonelquinteros/gotext in the go-all group

Bumps the go-all group with 1 update: [github.com/leonelquinteros/gotext](https://github.com/leonelquinteros/gotext).


Updates `github.com/leonelquinteros/gotext` from 1.7.1 to 1.7.2
- [Release notes](https://github.com/leonelquinteros/gotext/releases)
- [Commits](https://github.com/leonelquinteros/gotext/compare/v1.7.1...v1.7.2)

---
updated-dependencies:
- dependency-name: github.com/leonelquinteros/gotext
  dependency-version: 1.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-04 23:45:08 +02:00
transifex-integration[bot]
8615239329
Updates for file po/en.po in zh_CN (#2628)
Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 14:07:22 +02:00
transifex-integration[bot]
c9a8507654
Updates for file po/en.po in ko (#2626)
* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-27 14:59:55 +02:00
dependabot[bot]
75e90c3a6d
chore(deps): bump the go-all group with 2 updates (#2622)
Bumps the go-all group with 2 updates: [golang.org/x/net](https://github.com/golang/net) and [golang.org/x/term](https://github.com/golang/term).


Updates `golang.org/x/net` from 0.39.0 to 0.40.0
- [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0)

Updates `golang.org/x/term` from 0.31.0 to 0.32.0
- [Commits](https://github.com/golang/term/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-all
- dependency-name: golang.org/x/term
  dependency-version: 0.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 12:15:33 +02:00
Jo
8ab3652846
Fix locale initialization logic (#2619)
* Fix locale initialization logic

* add comment

* Update main.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update GitHub Actions workflow for testing

* Update GitHub Actions workflow to allow artifact overwrite

* Update GitHub Actions workflow to allow artifact overwrite

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-06 18:16:47 +02:00
dependabot[bot]
98be3fec97
chore(deps): bump golang.org/x/sys from 0.32.0 to 0.33.0 in the go-all group (#2620)
chore(deps): bump golang.org/x/sys in the go-all group

Bumps the go-all group with 1 update: [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sys` from 0.32.0 to 0.33.0
- [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 18:08:17 +02:00
Jo
c6a2226ce1
add locale tooling (#2618) 2025-05-01 22:07:39 +00:00
transifex-integration[bot]
3e82496057
Updates for file po/en.po in hu (#2617)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-01 23:08:02 +02:00
Jo
a26ac1ba95
Add SECURITY.md with contact and supported version policy (#2616)
* docs: add SECURITY.md with contact and supported version policy

* fix image render
2025-05-01 08:18:31 +00:00
Jo
b745f87210
chore(ci): update golangci lint v2.1.5 (#2615)
* chore(ci): update golangci-lint to v2.1.5 in ci.Dockerfile

* add golangci

* fix lint

* fix lint pkg/upgrade

* reenable lint
2025-05-01 10:00:10 +02:00
dependabot[bot]
b4a41700ee
chore(deps): bump golang.org/x/net from 0.38.0 to 0.39.0 (#2609)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.38.0 to 0.39.0.
- [Commits](https://github.com/golang/net/compare/v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 09:58:03 +02:00
dependabot[bot]
0aa80e521e
chore(deps): bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#2612)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-version: 1.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 09:55:03 +02:00
Jo
bce9f2fc72
Update dependabot.yml (#2614) 2025-05-01 09:54:47 +02:00
dependabot[bot]
5a71db2526
chore(deps): bump github.com/deckarep/golang-set/v2 from 2.7.0 to 2.8.0 (#2611)
Bumps [github.com/deckarep/golang-set/v2](https://github.com/deckarep/golang-set) from 2.7.0 to 2.8.0.
- [Release notes](https://github.com/deckarep/golang-set/releases)
- [Commits](https://github.com/deckarep/golang-set/compare/v2.7.0...v2.8.0)

---
updated-dependencies:
- dependency-name: github.com/deckarep/golang-set/v2
  dependency-version: 2.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 08:40:49 +02:00
dependabot[bot]
535370bca0
chore(deps): bump golang.org/x/term from 0.30.0 to 0.31.0 (#2613)
Bumps [golang.org/x/term](https://github.com/golang/term) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/term/compare/v0.30.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/term
  dependency-version: 0.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 08:37:38 +02:00
Jo
9a3be07887
Create dependabot.yml (#2608)
* Create dependabot.yml

* Update dependabot.yml

* Update dependabot.yml
2025-04-30 21:49:38 +00:00
Jo
2f205ee96c
chore(ci): update golangci-lint to v2.1.5 in ci.Dockerfile (#2607) 2025-04-30 21:45:29 +00:00
Jo
1982ce0366
chore(devcontainer): add devcontainer for clean builds (#2606)
chore(devcontainer): set up passwordless sudo for docker user for clean development and testing
2025-04-30 23:08:02 +02:00
Jo
2dcf94544c
refactor(build): optimize allocations and add tests (#2601)
* perf(build): optimize map/slice allocations and use strings.Builder

* test(build): add tests for parsePackageList
2025-04-29 22:45:24 +02:00
Ferdinand Bachmann
95fc0938fd
fix(installer): Fix the same pkgbase being built multiple times on error (#2561)
fix(installer): Fixes the same pkgbase being built multiple times on error

The previous fix commit ec837c8 failed to address the case where the
build fails, as packages are only added to builtPkgDests on a successful
build. This commit addresses this by adding the package to the map earlier.

Fixes #2560.
2025-04-29 22:45:10 +02:00
transifex-integration[bot]
ff176c0dd2
Updates for file po/en.po in hu (#2605)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-04-28 10:17:56 +02:00
Jo
bf315041b1
refactor(upgrade): optimize code and improve maintainability (#2600)
* refactor(upgrade): reduce code duplication in Print methods and fix typo in Filter documentation

* refactor(upgrade): optimize UserExcludeUpgrades with early return and simplify GraphUpgrades function
2025-04-24 12:06:27 +02:00
dependabot[bot]
559bc06b31
chore(deps): bump golang.org/x/net from 0.37.0 to 0.38.0 (#2598)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/net/compare/v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.38.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 11:41:44 +02:00
transifex-integration[bot]
35019f95b6
Updates for file po/en.po in nl (#2592)
* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-03-20 15:11:04 +01:00
transifex-integration[bot]
50cbf70bf4
Updates for file po/en.po in zh_TW (#2591)
* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-03-20 15:10:57 +01:00
Jo
0b5f5f0ccd
fix(main): return 1 exit code on panic (#2590) 2025-03-09 22:59:50 +01:00
Jo
a300330b94
fix(ci): prefer ghcr image (#2589)
prefer ghcr image
2025-03-09 22:50:58 +01:00
Jo
670598912e
fix: correct Docker manifest creation in builder image workflow (#2588)
* fix: correct Docker manifest creation in builder image workflow

- Fix "invalid reference format" error by properly separating Docker Hub and
  GitHub Container Registry tags
- Use short SHA format instead of long format for more manageable tags
- Improve manifest list creation process to handle multiple registries correctly
- Ensure proper handling of ghcr.io prefix for GitHub Container Registry

* update golangci and comment out community
2025-03-09 22:20:50 +01:00
Jo
257b230e39
chore(yay): update deps (#2587)
update deps
2025-03-09 20:45:10 +01:00
Jo
d2c67ae0a4
fix(yay): fix minor performance and safety issue (#2581) 2025-02-25 17:15:34 +01:00
Jo
4432c60246 fix(ci): fix issue with builder image CI 2025-02-20 17:16:35 +00:00
Jo
33ba07fe0d
fix(yay): update go mod (#2580)
update go mod
2025-02-17 15:54:21 +01:00
Dominik Link
d37e365ac3
fixed issue #2471 where it wouldn't show info when packages are in a group (#2576)
fixed issue #2471 where it wouldn't show info when packages are in a group and modified test
2025-02-17 15:28:35 +01:00
transifex-integration[bot]
6807ecc081
Updates for file po/en.po in zh_TW (#2571)
* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

* Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-02-14 14:36:32 +01:00
transifex-integration[bot]
b07d8c1447
Updates for file po/en.po in de (#2572)
Translate po/en.po in de

100% translated source file: 'po/en.po'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-02-14 14:36:13 +01:00
transifex-integration[bot]
3da808847f
Updates for file po/en.po in ru_RU (#2574)
Translate po/en.po in ru_RU

100% translated source file: 'po/en.po'
on 'ru_RU'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-02-05 12:01:03 +01:00
transifex-integration[bot]
590a3d3a8c
Updates for file po/en.po in ru (#2575)
Translate po/en.po in ru

100% translated source file: 'po/en.po'
on 'ru'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-02-05 12:00:33 +01:00
Ikko Eltociear Ashimine
69685d0fb5
docs: update README.md (#2564)
minor fix
2025-01-23 14:42:52 +01:00
transifex-integration[bot]
5572d1817e
Updates for file po/en.po in zh_TW (#2569)
Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-15 11:11:08 +01:00
transifex-integration[bot]
2f403a4f28
Updates for file po/en.po in zh_CN (#2568)
* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-15 11:09:49 +01:00
transifex-integration[bot]
9322197d0c
Updates for file po/en.po in ca_ES (#2556)
Translate po/en.po in ca_ES

100% translated source file: 'po/en.po'
on 'ca_ES'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-03 16:06:02 +01:00
transifex-integration[bot]
46f3842e6f
Updates for file po/en.po in ca (#2555)
Translate po/en.po in ca

100% translated source file: 'po/en.po'
on 'ca'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-03 14:55:04 +01:00
transifex-integration[bot]
76000ae987
Updates for file po/en.po in fr (#2557)
* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-03 14:54:45 +01:00
transifex-integration[bot]
e27979d21d
Updates for file po/en.po in fr_FR (#2558)
* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-03 14:54:16 +01:00
transifex-integration[bot]
c0baacd633
Updates for file po/en.po in sv (#2559)
Translate po/en.po in sv

100% translated source file: 'po/en.po'
on 'sv'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-30 10:57:45 +00:00
transifex-integration[bot]
43567b5d85
Updates for file po/en.po in it_IT (#2548)
Translate po/en.po in it_IT

100% translated source file: 'po/en.po'
on 'it_IT'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-23 14:22:27 +00:00
transifex-integration[bot]
e18cc87307
Updates for file po/en.po in hu (#2549)
Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-23 14:22:06 +00:00
transifex-integration[bot]
81a2a19101
Updates for file po/en.po in id (#2550)
Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 15:28:42 +00:00
transifex-integration[bot]
669d7af6d1
Updates for file po/en.po in nl (#2551)
Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 15:27:33 +00:00
transifex-integration[bot]
65ce4b9f6f
Updates for file po/en.po in pt (#2553)
Translate po/en.po in pt

100% translated source file: 'po/en.po'
on 'pt'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 15:27:04 +00:00
transifex-integration[bot]
5f2b94ce7c
Updates for file po/en.po in pt_BR (#2552)
* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 15:26:31 +00:00
dmitrodem
3f2f6eae31
socks5 support (#2543)
* socks5 support

socks5 support via environment variable, e.g. SOCKS5_PROXY=localhost:1080 yay ...

* use default transport and update tests to work on arm
2024-12-20 16:49:05 +00:00
scarf
da53d3855f
fix: use positional argument for "providers available" translation (#2537) 2024-12-20 16:43:28 +00:00
Matthias Kurz
f23fe98a66
Fix comments: AUR_SEEN is the correct name (#2535)
Fix comments: AUR_SEEN is the correct name
2024-11-21 12:00:11 +01:00
Ferdinand Bachmann
ec837c831d
fix(installer): Fixes the same pkgbase being built multiple times (#2534)
* fix(installer): Fixes the same pkgbase being built multiple times

When building a PKGBUILD pkgbase with multiple pkgnames,
installAURPackages() invokes buildPkg() multiple times for the same
pkgbase. This causes prepare() to be run multiple times for the same
pkgbase, since detection of already built packages happens after
prepare().

Additionally, detection of already built packages can fail if the split
debug packages are enabled and the package does not contain any
binaries, causing no -debug package to be created by makepkg even though
it is listed by makepkg --packagelist.

This commit fixes this by keeping track of the pkgdests built by
buildPkg() and avoiding rebuilds of the same pkgbase in the same yay
invocation.

Fixes #2340.

Signed-off-by: Ferdinand Bachmann <ferdinand.bachmann@yrlf.at>

* fix(installer): Fixes buildPkg() isTarget param being order-dependent

Previously, the buildPkg invocation for a pkgbase only considered
whether the current pkgname is part of installer.origTargets. This made
the decision whether to rebuild the package order-dependent.

This commit fixes this by keeping track of which pkgbases are part of
installer.origTargets and rebuilding the pkgbase if any of its pkgnames
is part of origTargets.

* fix(tests): Test that installing split packages avoids rebuilds

The previous two commits changed how split packages (packages with the same
pkgbase) are built, ensuring that those packages aren't built multiple
times.

This commit updates the lists of commands that the tests expect to be
run so that `makepkg` isn't run multiple times per pkgbase.

---------

Signed-off-by: Ferdinand Bachmann <ferdinand.bachmann@yrlf.at>
2024-11-19 11:08:28 +01:00
transifex-integration[bot]
f100c1d54b
Updates for file po/en.po in uk (#2533)
Translate po/en.po in uk

100% translated source file: 'po/en.po'
on 'uk'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-15 14:52:12 +01:00
April Hall
3f5d26c4f9
Replace "⚠️ {warning}" with Github Warning Blocks (#2531)
Update README.md
2024-11-12 20:03:03 +00:00
Alice Jacka
3003f1667c
Add missing sudo to binary install instructions (#2525) 2024-10-25 11:12:49 +02:00
Anmol W
fb168fb176
fix swapped fish completion descriptions for --repo and --aur (#2523)
fix swapped fish completions for --repo and --aur
2024-10-25 10:35:07 +02:00
transifex-integration[bot]
842067256b
Updates for file po/en.po in id (#2522)
* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

* Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-25 10:30:32 +02:00
transifex-integration[bot]
a6a6dc0acb
Updates for file po/en.po in hu (#2521)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-25 10:30:21 +02:00
transifex-integration[bot]
2e06552211
Updates for file po/en.po in zh_CN (#2524)
* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

* Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-25 10:30:11 +02:00
transifex-integration[bot]
138c2dd6cd
Updates for file po/en.po in sk (#2516)
Translate po/en.po in sk

100% translated source file: 'po/en.po'
on 'sk'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-30 09:32:30 +02:00
transifex-integration[bot]
4872b8b829
Updates for file po/en.po in pl_PL (#2513)
Translate po/en.po in pl_PL

100% translated source file: 'po/en.po'
on 'pl_PL'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-27 10:33:58 +02:00
transifex-integration[bot]
1b6ad7b305
Updates for file po/en.po in hu (#2512)
Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-27 10:33:51 +02:00
transifex-integration[bot]
d6e961af70
Updates for file po/en.po in pl (#2514)
Translate po/en.po in pl

100% translated source file: 'po/en.po'
on 'pl'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-27 10:33:41 +02:00
Jo
89b32ee9ce
fix(parser): allow disable-sandbox option. fixes #2509 (#2511) 2024-09-24 08:12:41 +00:00
transifex-integration[bot]
f68a57129f
Updates for file po/en.po in hu (#2510)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-24 09:57:49 +02:00
Absobel
bea53a4a09
fix: added missing spaces (#2386) 2024-09-19 14:15:44 +02:00
Rodrigo Barrios
13df7e79eb
Document -Ycc in manpage (#2482)
Signed-off-by: r.b4rr10s <rodrigoedu11@gmail.com>
2024-09-19 14:14:16 +02:00
Tim Konick
0f496c9af9
Fixes syntax error #2506 (#2507)
* Fixes syntax error

* Use escape-chars instead
2024-09-18 07:46:51 +00:00
Jo
84d8f1b7b3
chore: update default po (#2505)
update default po
2024-09-17 16:50:02 +00:00
Jo
3a118b7690
chore: fix failing build actions (#2503) 2024-09-17 17:14:26 +02:00
transifex-integration[bot]
a32f5e7e2c
Updates for file po/en.po in nl (#2504)
* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-17 14:01:14 +02:00
Oliver Tzeng
3c881d577f
fix(zh_TW.po): fixed a lot of simplified chinese (#2498)
- Changelog
 * Added myself as the initial translator, got removed for some
   reason(#1776)
 * Converted simplified to traditional Chinese
 * Formatting
2024-09-14 17:52:30 +02:00
transifex-integration[bot]
86f5c08ec4
Updates for file po/en.po in he (#2491)
* Translate po/en.po in he

100% translated source file: 'po/en.po'
on 'he'.

* Translate po/en.po in he

100% translated source file: 'po/en.po'
on 'he'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-14 17:20:59 +02:00
Stephan Burns
675f0ba3f3
Add sudo to install instructions so it can be run without user switching (#2483)
* Add sudo to install instructions so it can be run without user switching

* Add sudo to one liner and a note for people using different root tools
2024-09-02 15:21:57 +02:00
transifex-integration[bot]
d7d67e3fd3
Updates for file po/en.po in hu (#2490)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-02 15:21:04 +02:00
transifex-integration[bot]
c28be1d8b0
Updates for file po/en.po in ru_RU (#2481)
* Translate po/en.po in ru_RU

100% translated source file: 'po/en.po'
on 'ru_RU'.

* Translate po/en.po in ru_RU

100% translated source file: 'po/en.po'
on 'ru_RU'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-08-07 09:56:31 +02:00
iTrooz
1b8f823f7c
Refactor part of UserExcludeUpgrades() (#2450) 2024-07-29 09:15:20 +02:00
Daniel Oh
836fc5922a
add short option for --repo (#2380)
* add short option for --repo

* run pre-commit

* update man page

* add fish completion

* add a N options

* add long options

---------

Co-authored-by: jguer <me@jguer.space>
2024-06-28 16:40:35 +02:00
Joey Holtzman
0165486bf4
Respect provided targets when using -Si flag (#2460) 2024-06-28 16:39:49 +02:00
Jo
5149e3714d
fix(query): match empty pacman -Si with AUR info (#2459) 2024-06-21 10:06:02 +02:00
Marcus B Spencer
9ed9b0b4e1
Update README.md (#2458)
Update the README to prevent partial upgrades.

Partial upgrades are dangerous on Arch Linux.
Partial upgrades may occur when a `-y` operation is given without a corresponding `-u` operation.

Quote from the ArchWiki:
> Do not use:
> `pacman -Sy package`
> `pacman -Sy` followed by `pacman -S` package (Note the absence of `-S**u**` in the installation of the package.)
> `pacman -Syuw` (Note that `pacman -Syuw` does imply the same risks like pacman -Sy`, as it will update the pacman sync database without installing the newer packages.)

https://wiki.archlinux.org/title/System_maintenance#Partial_upgrades_are_unsupported
2024-06-20 14:15:14 +02:00
transifex-integration[bot]
e19700234f
Updates for file po/en.po in he (#2447)
* Translate po/en.po in he

100% translated source file: 'po/en.po'
on 'he'.

* Translate po/en.po in he

100% translated source file: 'po/en.po'
on 'he'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-06-03 09:56:18 +02:00
transifex-integration[bot]
965f8956e9
Updates for file po/en.po in he_IL (#2448)
Translate po/en.po in he_IL

100% translated source file: 'po/en.po'
on 'he_IL'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-06-03 09:38:39 +02:00
transifex-integration[bot]
53c9d0ef34
Updates for file po/en.po in es (#2441)
* Translate po/en.po in es

100% translated source file: 'po/en.po'
on 'es'.

* Translate po/en.po in es

100% translated source file: 'po/en.po'
on 'es'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-05-13 09:23:23 +02:00
Adivardhan Maheshwari
9b41f136d6
Add a package update command (#2205)
* Add a package update command

when running these commands on archlinux-base proxmox lxc, found out that these commands return 404 error unless the pacman -Sy command is run.

This although seeming simplistic might be something unknown when someone uses yay and archlinux for the first time.

* Update README.md
2024-05-02 11:00:29 +00:00
Tom
d956dd7888
Fix incorrect formatting of some msgstr of the spanish translation (#2437)
fix: Fix incorrect formatting for "%s to upgrade/install." and "%s will also be installed for this operation." in Spanish translation
2024-05-02 12:58:59 +02:00
eveneast
61dd708a4a
chore: fix function name in comment (#2430)
Signed-off-by: eveneast <qcqs@foxmail.com>
2024-05-02 10:54:16 +00:00
transifex-integration[bot]
ff3ad18fa8
Updates for file po/en.po in fr (#2425)
* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

* Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-05-02 12:53:37 +02:00
transifex-integration[bot]
803f708106
Updates for file po/en.po in fr_FR (#2424)
* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-05-02 12:53:29 +02:00
transifex-integration[bot]
9b6d40d7f9
Updates for file po/en.po in hu (#2431)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-05-02 12:53:20 +02:00
transifex-integration[bot]
779a9f16bd
Updates for file po/en.po in fr_FR (#2423)
* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-04-03 14:32:00 +02:00
transifex-integration[bot]
02d3e2e1c0
Updates for file po/en.po in ru_RU (#2422)
Translate po/en.po in ru_RU

100% translated source file: 'po/en.po'
on 'ru_RU'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-04-03 14:31:51 +02:00
transifex-integration[bot]
8de397ed11
Updates for file po/en.po in fr (#2419)
Translate po/en.po in fr

100% translated source file: 'po/en.po'
on 'fr'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-04-03 10:37:48 +02:00
transifex-integration[bot]
de7ad4070f
Updates for file po/en.po in zh_TW (#2420)
Translate po/en.po in zh_TW

100% translated source file: 'po/en.po'
on 'zh_TW'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-04-03 10:37:41 +02:00
transifex-integration[bot]
3b18e2197c
Updates for file po/en.po in ca_ES (#2421)
Translate po/en.po in ca_ES

100% translated source file: 'po/en.po'
on 'ca_ES'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-04-03 10:37:33 +02:00
transifex-integration[bot]
127b3a5b1a
Updates for file po/en.po in fr_FR (#2414)
* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

* Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-03-31 16:53:36 +02:00
Jo
2ff794da32
chore: update go-alpm (#2409)
* update go alpm

* update golangci

* add missing ldflag
2024-03-23 23:46:02 +01:00
James Raspass
6c2330528f
Use Go 1.21's min/max built-ins (#2405)
This simplifies the code compared to either rolling our own or awkwardly
using math's float functions with integers.
2024-03-23 23:27:30 +01:00
transifex-integration[bot]
a1d530cbf4
Updates for file po/en.po in hu (#2401)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-03-17 14:14:46 +01:00
James Raspass
5d887cbd41
Replace github.com/pkg/errors with stdlib errors/fmt (#2400) 2024-03-16 09:10:49 +01:00
Jo
05b76852bd
chore(yay): fix missing command (#2399)
fix missing command
2024-03-16 01:22:48 +01:00
Jo
9524cbbaed
chore: ensure pacman update in builder (#2398)
* ensure pacman up

* lint step fix
2024-03-16 01:13:30 +01:00
Jo
48d1d3d2d5
chore(yay): update dependencies and builder (#2396)
* fix libalpm14 build

* update deps

* try alternative arch
2024-03-16 00:55:05 +01:00
transifex-integration[bot]
741d83c1f0
Updates for file po/en.po in fr_FR (#2388)
Translate po/en.po in fr_FR

100% translated source file: 'po/en.po'
on 'fr_FR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-03-15 23:30:13 +01:00
transifex-integration[bot]
9c02af429a
Updates for file po/en.po in ru (#2389)
* Translate po/en.po in ru

100% translated source file: 'po/en.po'
on 'ru'.

* Translate po/en.po in ru

100% translated source file: 'po/en.po'
on 'ru'.

* Translate po/en.po in ru

100% translated source file: 'po/en.po'
on 'ru'.

* Translate po/en.po in ru

100% translated source file: 'po/en.po'
on 'ru'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-03-11 15:27:27 +01:00
Jo
03e89d660f
chore: fix min go version (#2383)
fix min go version
2024-03-02 16:40:21 +01:00
transifex-integration[bot]
f7f2169992
Updates for file po/en.po in nl (#2377)
* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

* Translate po/en.po in nl

100% translated source file: 'po/en.po'
on 'nl'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-02-23 08:28:24 +01:00
Jo
e8080f87c2
chore(yay): fix breaking -git ci test (#2373)
* chore(yay): fix breaking test

* chore(yay): fix breaking test

* chore(yay): fix breaking test

* update gomod

* remove debug commands
2024-02-19 17:04:06 +01:00
Jo
26aa171b2b
fix(query): remove -debug packages from missing list if base package is installed (#2372)
* chore(yay): fix pre-commit

* chore(yay): fix git ignore
2024-02-19 10:29:47 +00:00
transifex-integration[bot]
92d7cb0faa
Updates for file po/en.po in id (#2366)
Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-02-02 09:41:56 +01:00
transifex-integration[bot]
f3a4fc8987
Updates for file po/en.po in cs (#2367)
Translate po/en.po in cs

100% translated source file: 'po/en.po'
on 'cs'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-02-02 09:41:48 +01:00
transifex-integration[bot]
aa6cad75a3
Updates for file po/en.po in ca (#2353)
Translate po/en.po in ca

100% translated source file: 'po/en.po'
on 'ca'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:44:40 +01:00
transifex-integration[bot]
2078bc936f
Updates for file po/en.po in es (#2354)
Translate po/en.po in es

100% translated source file: 'po/en.po'
on 'es'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:44:23 +01:00
transifex-integration[bot]
d778be4f9f
Updates for file po/en.po in de (#2352)
Translate po/en.po in de

100% translated source file: 'po/en.po'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:44:06 +01:00
transifex-integration[bot]
aeafe23027
Updates for file po/en.po in hu (#2355)
Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:43:51 +01:00
transifex-integration[bot]
6c31477ccd
Updates for file po/en.po in pt_BR (#2357)
Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:43:39 +01:00
transifex-integration[bot]
0a930c9ffc
Updates for file po/en.po in id (#2358)
Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:43:15 +01:00
transifex-integration[bot]
d411524481
Updates for file po/en.po in pt (#2356)
Translate po/en.po in pt

100% translated source file: 'po/en.po'
on 'pt'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:42:51 +01:00
transifex-integration[bot]
15ef062bb5
Updates for file po/en.po in zh_CN (#2359)
Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:42:28 +01:00
transifex-integration[bot]
c2d7d99e43
Updates for file po/en.po in it_IT (#2360)
Translate po/en.po in it_IT

100% translated source file: 'po/en.po'
on 'it_IT'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:42:20 +01:00
transifex-integration[bot]
86207fce64
Updates for file po/en.po in sv (#2361)
Translate po/en.po in sv

100% translated source file: 'po/en.po'
on 'sv'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-25 16:42:00 +01:00
Jo
dc68b1a8fa
chore: update locale files (#2351)
update po
2024-01-25 15:16:21 +00:00
Joey Holtzman
d02c45e5b6
Remove deprecated flags in favor of boolean flags (#2350) 2024-01-25 16:03:47 +01:00
Joey Holtzman
8d773aa6a3
Remove deprecated warning when using -yc together (#2347) 2024-01-24 16:11:51 +01:00
transifex-integration[bot]
b81d34d5cc
Updates for file po/en.po in zh_CN (#2341)
Translate po/en.po in zh_CN

100% translated source file: 'po/en.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-18 15:10:57 +01:00
transifex-integration[bot]
d77dd77141
Updates for file po/en.po in hu (#2338)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-01-04 17:51:26 +01:00
transifex-integration[bot]
e34bce003d
Updates for file po/en.po in hu (#2337)
* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

* Translate po/en.po in hu

100% translated source file: 'po/en.po'
on 'hu'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-12-27 16:59:38 +01:00
Eng Zer Jun
d23e8925fa
fix(dep_graph): fix panic on selecting AUR providers (#2333)
This commit fixes https://github.com/Jguer/yay/issues/2289 by making
`provideMenu` returns the first option when it receives an error input
from the user (e.g. user sends EOF).

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2023-12-11 17:45:54 +01:00
Jo
643830fccd
chore: Use custom image (#2328)
* self-host image

* update deps
2023-11-30 09:39:56 +01:00
transifex-integration[bot]
cb4cd7b451
Updates for file po/en.po in sv (#2321)
Translate po/en.po in sv

100% translated source file: 'po/en.po'
on 'sv'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-29 11:17:30 +01:00
transifex-integration[bot]
350ff1c70a
Updates for file po/en.po in id (#2323)
Translate po/en.po in id

100% translated source file: 'po/en.po'
on 'id'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-29 11:17:16 +01:00
transifex-integration[bot]
26dc74ed67
Updates for file po/en.po in ca (#2320)
Translate po/en.po in ca

100% translated source file: 'po/en.po'
on 'ca'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-29 11:16:57 +01:00
transifex-integration[bot]
a00ff6b3cc
Updates for file po/en.po in de (#2324)
Translate po/en.po in de

100% translated source file: 'po/en.po'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-29 11:16:43 +01:00
transifex-integration[bot]
9e665a98b9
Updates for file po/en.po in pt_BR (#2325)
* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

* Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-29 11:16:30 +01:00
transifex-integration[bot]
4169f0ee42
Updates for file po/en.po in es (#2326)
* Translate po/en.po in es

100% translated source file: 'po/en.po'
on 'es'.

* Translate po/en.po in es

100% translated source file: 'po/en.po'
on 'es'.

* Translate po/en.po in es

100% translated source file: 'po/en.po'
on 'es'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-29 11:16:15 +01:00
transifex-integration[bot]
5a6b18fe23
Updates for file po/en.po in pt (#2322)
* Translate po/en.po in pt

100% translated source file: 'po/en.po'
on 'pt'.

* Translate po/en.po in pt

100% translated source file: 'po/en.po'
on 'pt'.

* Translate po/en.po in pt

100% translated source file: 'po/en.po'
on 'pt'.

* Translate po/en.po in pt

100% translated source file: 'po/en.po'
on 'pt'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-23 16:34:20 +01:00
transifex-integration[bot]
c8577bb613
Updates for file po/en.po in pt_BR (#2317)
Translate po/en.po in pt_BR

100% translated source file: 'po/en.po'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-21 14:10:18 +01:00
transifex-integration[bot]
965f41b938
Updates for file po/en.po in it_IT (#2316)
Translate po/en.po in it_IT

100% translated source file: 'po/en.po'
on 'it_IT'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-21 14:10:06 +01:00
Kirill Motkov
0771ded99b
Refactor AURPKGBUILDRepos and Fix Localization Command in Makefile (#2313)
* optimize mutex usage and logging in AURPKGBUILDRepos function

* fix localization script

Fix localization script Makefile by adding missing semicolon and --no-translator flag
2023-11-20 16:58:20 +01:00
transifex-integration[bot]
8f98ab3d4b
Updates for file po/en.po in de (#2312)
Translate po/en.po in de

100% translated source file: 'po/en.po'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-15 16:43:40 +01:00
Joey Holtzman
d368f99be0
feat(yay): add boolean flags (#2285)
* feat(yay): add boolean flags

This feature now allows users to specify --<option>=<bool value> instead
of using --<option> and --no<option>. Specifying nothing results in the
boolean value being true. The flags prefixed with `no` are deprecated.

* chore(args): Print warning when using deprecated flags

* chore(yay): Update man page for deprecated options and add examples of
boolean flags being used
2023-09-27 12:36:57 +02:00
Eng Zer Jun
a1121556be
refactor: remove redundant len check (#2291)
`len` returns 0 if the slice or map is nil. From the Go specification
[1]:

  "1. For a nil slice, the number of iterations is 0."
  "3. If the map is nil, the number of iterations is 0."

Therefore, an additional `len(v) != 0` check for before the loop is
unnecessary.

[1]: https://go.dev/ref/spec#For_range

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2023-09-27 12:36:08 +02:00
Jo
299aa1e123
fix(download): do not garble download output by default (#2283)
limit default concurrent downloads to 1
2023-09-18 09:51:32 +02:00
Joey Holtzman
04c76a404e
feat(install): add --keepsrc to keep pkg/ and src/ directories (#2272)
* feat(install): add --nocleanbuild to keep pkg/ and src/ directories for
AUR packages

Providing this flag during installation of AUR packages allows for keeping
the src/ and pkg/ directories produced my makepkg. If the user wants to
delete the directories, they can either select to cleanBuild in the
cleanmenu or run the installation without the --nocleanbuild flag (yay
will only remove the directories if the package is rebuilt)

* fix(completion): simplify description for --nocleanbuild in fish

This makes the description consistent with the descriptions in the
man page, --help, and zsh completion.

* refactor(install): Rename --nocleanbuild to --keepsrc

This naming scheme is more familiar to users since it is the name of the
flag in Paru.

---------

Co-authored-by: jguer <me@jguer.space>
2023-09-18 09:21:42 +02:00
Jo
e60ccdf8b7
Fix image recursive build (#2280)
* fix image recursive build

* add test fixes

* disable buildvcs

* fix integration
2023-09-15 11:17:18 +02:00
transifex-integration[bot]
b6c72ce7a2
Updates for file po/en.po in he on branch next (#2274)
Translate po/en.po in he

100% translated source file: 'po/en.po'
on 'he'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-08 18:21:41 +02:00
Esteban Blanc
87d1fd1c06
Add oneliner install for binray source (#2268) 2023-09-07 10:58:30 +02:00
transifex-integration[bot]
92d50910de
Updates for file po/en.po in ko on branch next (#2266)
* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

* Translate po/en.po in ko

100% translated source file: 'po/en.po'
on 'ko'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-07 10:44:11 +02:00
Joey Holtzman
a0e6838a5f
fix(yay): fix missing placeholders in translations (#2271) 2023-09-07 10:43:45 +02:00
Jo
8916cd174b
refactor(yay): move cfg inside of runtime (#2259)
* rework relationship between runtime and cfg

* separate runtime from cfg

* simplify instantiation logic

* move installer to appropriate package

* move operator to sync package

* add tests for srcinfo service

* consolidate srcinfo service in sync

* add logger to srcinfo

* add logger to preparer

* remove unused text functions

* remove remaining text.* from srcinfo

* remove global logger parts

* remove global org method exports

* remove global logger

* move text->input

* add rule to prevent fmt.Print

* update golangci go version

* remove outdated FAQs

* remove outdated FAQs
2023-08-06 21:39:41 +02:00
Jo
7483393377
fix(sync): add missing Replaces to -Si (#2257) 2023-08-02 07:45:14 +00:00
137 changed files with 13694 additions and 7793 deletions

26
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,26 @@
# 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"]

View File

@ -0,0 +1,14 @@
{
"name": "Existing Dockerfile",
"build": {
"context": "..",
"dockerfile": "../.devcontainer/Dockerfile"
},
"customizations": {
"vscode": {
"extensions": [
"golang.go"
]
}
}
}

15
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,15 @@
# 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:
- '*'

View File

@ -1,12 +1,12 @@
name: Builder image
name: Builder Image
on:
schedule:
- cron: "0 3 * * 1"
- cron: "0 3 * * 1" # Every Monday at 3 AM
push:
paths:
- "ci.Dockerfile"
- "**/builder-image.yml"
- ".github/workflows/builder-image.yml"
env:
REGISTRY_IMAGE: jguer/yay-builder
@ -15,95 +15,129 @@ jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: true
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=raw,value=latest
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-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@v4
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
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 }}"
touch "/tmp/digests/${digest#sha256:}"
echo -n "$digest" > "/tmp/digests/$(echo "${{ matrix.platform }}" | tr '/' '_')"
- name: Upload digest
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: digests
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
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: digests
pattern: digest-*
merge-multiple: true
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=raw,value=latest
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
- 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:
DOCKER_CLI_EXPERIMENTAL: enabled
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
# Extract Docker Hub tags
DH_TAGS=$(echo '${{ steps.meta.outputs.tags }}' | grep -v "^ghcr.io" | xargs -I {} echo "-t {}")
# Extract GitHub Container Registry tags
GHCR_TAGS=$(echo '${{ steps.meta.outputs.tags }}' | grep "^ghcr.io" | xargs -I {} echo "-t {}")
# Create a manifest list using the image digests from /tmp/digests/*
DIGESTS=$(for file in /tmp/digests/*; do
echo -n "${{ env.REGISTRY_IMAGE }}@$(cat $file) "
done)
# 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 }}:${{ steps.meta.outputs.version }}
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:latest

View File

@ -1,4 +1,5 @@
name: Build Release
on:
push:
tags:
@ -8,31 +9,36 @@ jobs:
build-releases:
strategy:
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 }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Read info
id: tags
shell: bash
run: |
echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/v/}
echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
arch="${{ matrix.arch }}"
echo ::set-output name=PLATFORM::${arch%% *}
echo ::set-output name=ARCH::${arch##* }
echo "PLATFORM=${arch%% *}" >> $GITHUB_OUTPUT
echo "ARCH=${arch##* }" >> $GITHUB_OUTPUT
- name: Build ${{ matrix.arch }} release
run: |
mkdir artifacts
@ -43,74 +49,44 @@ jobs:
-t yay:${{ steps.tags.outputs.arch }} . --load
make docker-release ARCH=${{ steps.tags.outputs.arch }} VERSION=${{ steps.tags.outputs.version }} PREFIX="/usr"
mv *.tar.gz artifacts
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: yay_${{ steps.tags.outputs.arch }}
path: artifacts
create_release:
name: Create release from this build
needs: [build-releases]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read info
id: tags
shell: bash
run: |
echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/v/}
echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
- uses: actions/download-artifact@v2
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- uses: actions/download-artifact@v4
with:
name: yay_x86_64
- uses: actions/download-artifact@v2
with:
name: yay_armv7h
- uses: actions/download-artifact@v2
with:
name: yay_aarch64
pattern: yay_*
merge-multiple: true
- name: Create Release
id: create_release
uses: actions/create-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.tags.outputs.tag }}
release_name: ${{ steps.tags.outputs.tag }}
draft: false
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
run: |
gh release create ${{ steps.tags.outputs.tag }} \
--title "${{ steps.tags.outputs.tag }}" \
--generate-notes \
./yay_${{ steps.tags.outputs.version }}_*.tar.gz
- name: Release Notary Action
uses: docker://aevea/release-notary:latest
env:

View File

@ -12,9 +12,9 @@ jobs:
name: Lint and test yay (-git)
runs-on: ubuntu-latest
container:
image: jguer/yay-builder:latest
image: ghcr.io/jguer/yay-builder:latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
@ -35,4 +35,5 @@ jobs:
chmod -R 777 pacman-git
su github -c 'cd pacman-git; yes | makepkg -i --nocheck'
- name: Run Build and Tests with pacman-git
run: make test
run: |
make test

View File

@ -7,9 +7,9 @@ jobs:
name: Lint and test yay
runs-on: ubuntu-latest
container:
image: jguer/yay-builder:latest
image: ghcr.io/jguer/yay-builder:latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
@ -17,9 +17,12 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Lint
run: /app/bin/golangci-lint run ./...
env:
GOFLAGS: -buildvcs=false -tags=next
run: /app/bin/golangci-lint run -v ./...
- name: Run Build and Tests
run: make test
- name: Run Integration Tests
continue-on-error: true
run: |
@ -28,3 +31,14 @@ jobs:
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
View File

@ -28,3 +28,7 @@ qemu-*
*.pot
*.po~
*.pprof
node_modules/
xgotext
.devcontainer/

View File

@ -1,4 +1,31 @@
linters-settings:
version: "2"
run:
go: "1.20"
linters:
default: none
enable:
- bodyclose
- dogsled
- dupl
- errcheck
- errorlint
- gochecknoinits
- gocritic
- goprintffuncname
- gosec
- govet
- ineffassign
- lll
- misspell
- nakedret
- noctx
- nolintlint
- staticcheck
- unconvert
- unparam
- unused
- whitespace
settings:
dupl:
threshold: 100
funlen:
@ -16,88 +43,52 @@ linters-settings:
- 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:
# 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:
- bodyclose
- dogsled
require-explanation: false
require-specific: false
allow-unused: false
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- dupl
- errorlint
- errcheck
- exportloopref
# - funlen # TOFIX
- errorlint
- gochecknoinits
# - goconst # TOFIX
- gocritic
# - gocyclo # TOFIX
- gofmt
- goimports
# - gomnd # TOFIX
- goprintffuncname
- gosec
- gosimple
- godot
- govet
- ineffassign
- lll
- misspell
- nakedret
- noctx
- nolintlint
- staticcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- whitespace
run:
go: "1.18"
timeout: "10m"
issues:
exclude-rules:
- path: (.+)_test.go
linters:
- lll
- revive
- staticcheck
- wsl
- govet
- godot
- errcheck
- stylecheck
- dupl
- gocritic
- gochecknoinits
- errorlint
exclude:
- G204
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$

View File

@ -5,19 +5,17 @@ repos:
rev: v0.5.1
hooks:
- id: go-fmt
- id: go-imports
args: [-local=github.com/Jguer/yay/v12/]
- id: golangci-lint
- id: go-unit-tests
- id: go-build
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.0-alpha.4 # Use the sha or tag you want to point at
rev: v4.0.0-alpha.8 # Use the sha or tag you want to point at
hooks:
- id: prettier
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0 # Use the ref you want to point at
rev: v4.5.0 # Use the ref you want to point at
hooks:
- id: trailing-whitespace
- id: check-json
@ -25,7 +23,7 @@ repos:
- id: check-added-large-files
- repo: https://github.com/commitizen-tools/commitizen
rev: v2.38.0
rev: v3.15.0
hooks:
- id: commitizen
stages: [commit-msg]

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"go.lintTool": "golangci-lint",
"gopls": {
"formatting.gofumpt": true,
"formatting.local": "github.com/Jguer/yay/v12"
}
}

View File

@ -1,4 +1,4 @@
FROM docker.io/jguer/yay-builder:latest
FROM ghcr.io/jguer/yay-builder:latest
LABEL maintainer="Jguer,docker@jguer.space"
ARG VERSION

View File

@ -26,8 +26,7 @@ MOFILES := $(POFILES:.po=.mo)
FLAGS ?= -trimpath -mod=readonly -modcacherw
EXTRA_FLAGS ?= -buildmode=pie
LDFLAGS := -X "main.yayVersion=${VERSION}" -X "main.localePath=${SYSTEMLOCALEPATH}" -linkmode=external
FLAGS += $(shell pacman -T 'pacman-git' >/dev/null 2>&1 && echo "-tags next")
LDFLAGS := -X "main.yayVersion=${VERSION}" -X "main.localePath=${SYSTEMLOCALEPATH}" -linkmode=external -compressdwarf=false
RELEASE_DIR := ${PKGNAME}_${VERSION}_${ARCH}
PACKAGE := $(RELEASE_DIR).tar.gz
@ -70,7 +69,7 @@ docker-release-all:
make docker-release-aarch64 ARCH=aarch64
docker-release:
docker create --name yay-$(ARCH) yay:${ARCH}
docker create --name yay-$(ARCH) yay:${ARCH} /bin/sh
docker cp yay-$(ARCH):/app/${PACKAGE} $(PACKAGE)
docker container rm yay-$(ARCH)
@ -83,9 +82,7 @@ docker-build:
.PHONY: lint
lint:
$(GO) vet $(FLAGS) ./...
@test -z "$$(gofmt -l $(SOURCES))" || (echo "Files need to be linted. Use make fmt" && false)
golangci-lint run ./...
GOFLAGS="$(FLAGS)" golangci-lint run ./...
.PHONY: fmt
fmt:
@ -126,8 +123,9 @@ $(PACKAGE): $(BIN) $(RELEASE_DIR) ${MOFILES}
locale:
xgotext -in . -out po
mv po/default.pot po/en.po
for lang in ${LANGS}; do \
test -f po/$$lang.po || msginit -l po/$$lang.po -i po/${POTFILE} -o po/$$lang.po \
test -f po/$$lang.po || msginit --no-translator -l po/$$lang.po -i po/${POTFILE} -o po/$$lang.po; \
msgmerge -U po/$$lang.po po/${POTFILE}; \
touch po/$$lang.po; \
done

View File

@ -30,15 +30,18 @@ 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.
> [!WARNING]
> We are using `sudo` in these examples, you can switch that out for a different privilege escalation tool.
### Source
The initial installation of Yay can be done by cloning the PKGBUILD and
building with makepkg:
Before you begin, make sure you have the `base-devel` package group installed.
We make sure we have the `base-devel` package group installed.
```sh
pacman -S --needed git base-devel
sudo pacman -S --needed git base-devel
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
@ -47,7 +50,7 @@ makepkg -si
If you want to do all of this at once, we can chain the commands like so:
```sh
pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si
sudo pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si
```
### Binary
@ -56,12 +59,18 @@ If you do not want to compile yay yourself you can use the builds generated by
GitHub Actions.
```sh
pacman -S --needed git base-devel
sudo pacman -S --needed git base-devel
git clone https://aur.archlinux.org/yay-bin.git
cd yay-bin
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
If you're using Manjaro or [another distribution that packages `yay`](https://repology.org/project/yay/versions)
@ -70,8 +79,8 @@ you can simply install yay using pacman (as root):
```sh
pacman -S --needed git base-devel yay
```
⚠️ distributions sometimes lag updating yay on their repositories.
> [!WARNING]
> distributions sometimes lag updating yay on their repositories.
## First Use
@ -111,17 +120,6 @@ pacman -S --needed git base-devel yay
Make sure you have the `Color` option in your `/etc/pacman.conf`
(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?**
Yay uses `git diff` to display diffs, which by default tells less not to
@ -130,14 +128,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 --editmenu --nodiffmenu --save`
`yay --editmenu --diffmenu=false --save`
- **How can I tell Yay to act only on AUR packages, or only on repo packages?**
`yay -{OPERATION} --aur`
`yay -{OPERATION} --repo`
- **An `Out Of Date AUR Packages` message is displayed. Why doesn't Yay update them?**
- **A `Flagged 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
the packages have been flagged out of date on the AUR, but
@ -152,28 +150,13 @@ pacman -S --needed git base-devel yay
- **I know my `-git` package has updates but yay doesn't offer to update it**
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`.
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`.
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!**
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
All support related to Yay should be requested via GitHub issues. Since Yay is not
@ -189,14 +172,14 @@ tools.
## Images
<p float="left">
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay.png" width="42%"/>
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay-s.png" width="42%"/>
<p align="center">
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay.png" width="42%">
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-s.png" width="42%">
</p>
<p float="left">
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay-y.png" width="42%"/>
<img src="https://rawcdn.githack.com/Jguer/jguer.github.io/77647f396cb7156fd32e30970dbeaf6d6dc7f983/yay/yay-ps.png" width="42%"/>
<p align="center">
<img src="https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/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%">
</p>
### Other AUR helpers/tools

13
SECURITY.md Normal file
View File

@ -0,0 +1,13 @@
# 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.

View File

@ -1,13 +1,15 @@
FROM docker.io/jguer/yay-builder:latest
FROM docker.io/ljmf00/archlinux:devel
LABEL maintainer="Jguer,docker@jguer.space"
ENV GO111MODULE=on
WORKDIR /app
RUN sed -i '/^\[community\]/,/^\[/ s/^/#/' /etc/pacman.conf
COPY go.mod .
RUN pacman-key --init && pacman -Sy && pacman -S --overwrite=* --noconfirm archlinux-keyring && \
pacman -Su --overwrite=* --needed --noconfirm doxygen meson asciidoc go git gcc make sudo base-devel && \
pacman -Su --overwrite=* --needed --noconfirm pacman doxygen meson asciidoc go git gcc make sudo base-devel && \
rm -rfv /var/cache/pacman/* /var/lib/pacman/sync/* && \
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.53.3 && \
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v2.1.5 && \
go mod download

View File

@ -2,7 +2,6 @@ package main
import (
"context"
"fmt"
"os"
"path/filepath"
@ -11,10 +10,10 @@ import (
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v12/pkg/db"
"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"
)
// CleanDependencies removes all dangling dependencies in system.
@ -49,28 +48,29 @@ func cleanRemove(ctx context.Context, cfg *settings.Configuration,
arguments, cfg.Mode, settings.NoConfirm))
}
func syncClean(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
func syncClean(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
keepInstalled := false
keepCurrent := false
_, removeAll, _ := cmdArgs.GetArg("c", "clean")
for _, v := range cfg.Runtime.PacmanConf.CleanMethod {
if v == "KeepInstalled" {
for _, v := range run.PacmanConf.CleanMethod {
switch v {
case "KeepInstalled":
keepInstalled = true
} else if v == "KeepCurrent" {
case "KeepCurrent":
keepCurrent = true
}
}
if cfg.Mode.AtLeastRepo() {
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm)); err != nil {
if run.Cfg.Mode.AtLeastRepo() {
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm)); err != nil {
return err
}
}
if !cfg.Mode.AtLeastAUR() {
if !run.Cfg.Mode.AtLeastAUR() {
return nil
}
@ -81,10 +81,10 @@ func syncClean(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser
question = gotext.Get("Do you want to remove all other AUR packages from cache?")
}
fmt.Println(gotext.Get("\nBuild directory:"), cfg.BuildDir)
run.Logger.Println(gotext.Get("\nBuild directory:"), run.Cfg.BuildDir)
if text.ContinueTask(os.Stdin, question, true, settings.NoConfirm) {
if err := cleanAUR(ctx, cfg, keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {
if run.Logger.ContinueTask(question, true, settings.NoConfirm) {
if err := cleanAUR(ctx, run, keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {
return err
}
}
@ -93,24 +93,24 @@ func syncClean(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser
return nil
}
if text.ContinueTask(os.Stdin, gotext.Get("Do you want to remove ALL untracked AUR files?"), true, settings.NoConfirm) {
return cleanUntracked(ctx, cfg)
if run.Logger.ContinueTask(gotext.Get("Do you want to remove ALL untracked AUR files?"), true, settings.NoConfirm) {
return cleanUntracked(ctx, run)
}
return nil
}
func cleanAUR(ctx context.Context, cfg *settings.Configuration,
func cleanAUR(ctx context.Context, run *runtime.Runtime,
keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor,
) error {
cfg.Runtime.Logger.Println(gotext.Get("removing AUR packages from cache..."))
run.Logger.Println(gotext.Get("removing AUR packages from cache..."))
installedBases := mapset.NewThreadUnsafeSet[string]()
inAURBases := mapset.NewThreadUnsafeSet[string]()
remotePackages := dbExecutor.InstalledRemotePackages()
files, err := os.ReadDir(cfg.BuildDir)
files, err := os.ReadDir(run.Cfg.BuildDir)
if err != nil {
return err
}
@ -130,7 +130,7 @@ func cleanAUR(ctx context.Context, cfg *settings.Configuration,
// Querying the AUR is slow and needs internet so don't do it if we
// don't need to.
if keepCurrent {
info, errInfo := cfg.Runtime.AURClient.Get(ctx, &aur.Query{
info, errInfo := run.AURClient.Get(ctx, &aur.Query{
Needles: cachedPackages,
})
if errInfo != nil {
@ -165,20 +165,20 @@ func cleanAUR(ctx context.Context, cfg *settings.Configuration,
}
}
dir := filepath.Join(cfg.BuildDir, file.Name())
cfg.Runtime.Logger.Debugln("removing", dir)
dir := filepath.Join(run.Cfg.BuildDir, file.Name())
run.Logger.Debugln("removing", dir)
if err = os.RemoveAll(dir); err != nil {
cfg.Runtime.Logger.Warnln(gotext.Get("Unable to remove %s: %s", dir, err))
run.Logger.Warnln(gotext.Get("Unable to remove %s: %s", dir, err))
}
}
return nil
}
func cleanUntracked(ctx context.Context, cfg *settings.Configuration) error {
cfg.Runtime.Logger.Println(gotext.Get("removing untracked AUR files from cache..."))
func cleanUntracked(ctx context.Context, run *runtime.Runtime) error {
run.Logger.Println(gotext.Get("removing untracked AUR files from cache..."))
files, err := os.ReadDir(cfg.BuildDir)
files, err := os.ReadDir(run.Cfg.BuildDir)
if err != nil {
return err
}
@ -188,12 +188,11 @@ func cleanUntracked(ctx context.Context, cfg *settings.Configuration) error {
continue
}
dir := filepath.Join(cfg.BuildDir, file.Name())
cfg.Runtime.Logger.Debugln("cleaning", dir)
dir := filepath.Join(run.Cfg.BuildDir, file.Name())
run.Logger.Debugln("cleaning", dir)
if isGitRepository(dir) {
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fx")); err != nil {
cfg.Runtime.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fx")); err != nil {
run.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
return err
}
}
@ -206,29 +205,3 @@ func isGitRepository(dir string) bool {
_, err := os.Stat(filepath.Join(dir, ".git"))
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++
}
}

View File

@ -15,6 +15,7 @@ import (
"github.com/stretchr/testify/require"
"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/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
@ -90,15 +91,13 @@ func TestCleanHanging(t *testing.T) {
Runner: mockRunner,
SudoLoopEnabled: false,
}
cfg := &settings.Configuration{
Runtime: &settings.Runtime{CmdBuilder: cmdBuilder},
}
run := &runtime.Runtime{CmdBuilder: cmdBuilder, Cfg: &settings.Configuration{}}
cmdArgs := parser.MakeArguments()
cmdArgs.AddArg(tc.args...)
err := handleCmd(context.Background(),
cfg, cmdArgs, dbExc,
run, cmdArgs, dbExc,
)
require.NoError(t, err)

200
cmd.go
View File

@ -17,6 +17,7 @@ import (
"github.com/Jguer/yay/v12/pkg/intrange"
"github.com/Jguer/yay/v12/pkg/news"
"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"
@ -25,8 +26,8 @@ import (
"github.com/Jguer/yay/v12/pkg/vcs"
)
func usage() {
fmt.Println(`Usage:
func usage(logger *text.Logger) {
logger.Println(`Usage:
yay
yay <operation> [...]
yay <package(s)>
@ -53,7 +54,7 @@ If no operation is specified 'yay -Syu' will be performed
If no operation is specified and targets are provided -Y will be assumed
New options:
--repo Assume targets are from the repositories
-N --repo Assume targets are from the repositories
-a --aur Assume targets are from the AUR
Permanent configuration options:
@ -91,23 +92,19 @@ Permanent configuration options:
--cleanmenu Give the option to clean build PKGBUILDS
--diffmenu Give the option to show diffs for build files
--editmenu Give the option to edit/view PKGBUILDS
--nocleanmenu Don't clean build PKGBUILDS
--nodiffmenu Don't show diffs for build files
--noeditmenu Don't edit/view PKGBUILDS
--askremovemake Ask to remove makedepends after install
--askyesremovemake Ask to remove makedepends after install("Y" as default)
--removemake Remove makedepends after install
--noremovemake Don't remove makedepends after install
--cleanafter Remove package sources after successful install
--nocleanafter Do not remove package sources after successful build
--keepsrc Keep pkg/ and src/ after building packages
--bottomup Shows AUR's packages first and then repository's
--topdown Shows repository's packages first and then AUR's
--singlelineresults List each search result on its own line
--doublelineresults List each search result on two lines, like pacman
--devel Check development packages during sysupgrade
--nodevel Do not check development packages
--rebuild Always build target packages
--rebuildall Always build all AUR packages
--norebuild Skip package build if in cache and up to date
@ -116,19 +113,14 @@ Permanent configuration options:
--noredownload Skip pkgbuild download if in cache and up to date
--redownloadall Always download pkgbuilds of all AUR 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
--nopgpfetch Don't prompt to import PGP keys
--useask Automatically resolve conflicts using pacman's ask flag
--nouseask Confirm conflicts manually during the install
--sudo <file> sudo command to use
--sudoflags <flags> Pass arguments to sudo
--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
--notimeupdate Do not check packages' AUR page for changes
show specific options:
-c --complete Used for completions
@ -138,7 +130,7 @@ show specific options:
-w --news Print arch news
yay specific options:
-c --clean Remove unneeded dependencies
-c --clean Remove unneeded dependencies (-cc to ignore optdepends)
--gendb Generates development package DB used for updating
getpkgbuild specific options:
@ -146,50 +138,49 @@ getpkgbuild specific options:
-p --print Print pkgbuild of packages`)
}
func handleCmd(ctx context.Context, cfg *settings.Configuration,
func handleCmd(ctx context.Context, run *runtime.Runtime,
cmdArgs *parser.Arguments, dbExecutor db.Executor,
) error {
if cmdArgs.ExistsArg("h", "help") {
return handleHelp(ctx, cfg, cmdArgs)
return handleHelp(ctx, run, cmdArgs)
}
if cfg.SudoLoop && cmdArgs.NeedRoot(cfg.Mode) {
cfg.Runtime.CmdBuilder.SudoLoop()
if run.Cfg.SudoLoop && cmdArgs.NeedRoot(run.Cfg.Mode) {
run.CmdBuilder.SudoLoop()
}
switch cmdArgs.Op {
case "V", "version":
handleVersion()
handleVersion(run.Logger)
return nil
case "D", "database":
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
case "F", "files":
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
case "Q", "query":
return handleQuery(ctx, cfg, cmdArgs, dbExecutor)
return handleQuery(ctx, run, cmdArgs, dbExecutor)
case "R", "remove":
return handleRemove(ctx, cfg, cmdArgs, cfg.Runtime.VCSStore)
return handleRemove(ctx, run, cmdArgs, run.VCSStore)
case "S", "sync":
return handleSync(ctx, cfg, cmdArgs, dbExecutor)
return handleSync(ctx, run, cmdArgs, dbExecutor)
case "T", "deptest":
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
case "U", "upgrade":
return handleUpgrade(ctx, cfg, cmdArgs)
return handleUpgrade(ctx, run, cmdArgs)
case "B", "build":
return handleBuild(ctx, cfg, dbExecutor, cmdArgs)
return handleBuild(ctx, run, dbExecutor, cmdArgs)
case "G", "getpkgbuild":
return handleGetpkgbuild(ctx, cfg, cmdArgs, dbExecutor)
return handleGetpkgbuild(ctx, run, cmdArgs, dbExecutor)
case "P", "show":
return handlePrint(ctx, cfg, cmdArgs, dbExecutor)
return handlePrint(ctx, run, cmdArgs, dbExecutor)
case "Y", "yay":
return handleYay(ctx, cfg, cmdArgs, cfg.Runtime.CmdBuilder,
dbExecutor, cfg.Runtime.QueryBuilder)
return handleYay(ctx, run, cmdArgs, run.CmdBuilder,
dbExecutor, run.QueryBuilder)
case "W", "web":
return handleWeb(ctx, cfg, cmdArgs)
return handleWeb(ctx, run, cmdArgs)
}
return errors.New(gotext.Get("unhandled operation"))
@ -219,19 +210,19 @@ func getFilter(cmdArgs *parser.Arguments) (upgrade.Filter, error) {
}, nil
}
func handleQuery(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
func handleQuery(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
if cmdArgs.ExistsArg("u", "upgrades") {
filter, err := getFilter(cmdArgs)
if err != nil {
return err
}
return printUpdateList(ctx, cfg, cmdArgs, dbExecutor,
return printUpdateList(ctx, run, cmdArgs, dbExecutor,
cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
}
if err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm)); err != nil {
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm)); err != nil {
if str := err.Error(); strings.Contains(str, "exit status") {
// yay -Qdt should not output anything in case of error
return fmt.Errorf("")
@ -243,138 +234,139 @@ func handleQuery(ctx context.Context, cfg *settings.Configuration, cmdArgs *pars
return nil
}
func handleHelp(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments) error {
usage()
func handleHelp(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments) error {
usage(run.Logger)
switch cmdArgs.Op {
case "Y", "yay", "G", "getpkgbuild", "P", "show", "W", "web", "B", "build":
return nil
}
cfg.Runtime.Logger.Println("\npacman operation specific options:")
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
run.Logger.Println("\npacman operation specific options:")
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
}
func handleVersion() {
fmt.Printf("yay v%s - libalpm v%s\n", yayVersion, alpm.Version())
func handleVersion(logger *text.Logger) {
logger.Printf("yay v%s - libalpm v%s\n", yayVersion, alpm.Version())
}
func handlePrint(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
func handlePrint(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
switch {
case cmdArgs.ExistsArg("d", "defaultconfig"):
tmpConfig := settings.DefaultConfig(yayVersion)
fmt.Printf("%v", tmpConfig)
run.Logger.Printf("%v", tmpConfig)
return nil
case cmdArgs.ExistsArg("g", "currentconfig"):
fmt.Printf("%v", cfg)
run.Logger.Printf("%v", run.Cfg)
return nil
case cmdArgs.ExistsArg("w", "news"):
double := cmdArgs.ExistsDouble("w", "news")
quiet := cmdArgs.ExistsArg("q", "quiet")
return news.PrintNewsFeed(ctx, cfg.Runtime.HTTPClient, dbExecutor.LastBuildTime(), cfg.BottomUp, double, quiet)
return news.PrintNewsFeed(ctx, run.HTTPClient, run.Logger,
dbExecutor.LastBuildTime(), run.Cfg.BottomUp, double, quiet)
case cmdArgs.ExistsArg("c", "complete"):
return completion.Show(ctx, cfg.Runtime.HTTPClient, dbExecutor,
cfg.AURURL, cfg.CompletionPath, cfg.CompletionInterval, cmdArgs.ExistsDouble("c", "complete"))
return completion.Show(ctx, run.HTTPClient, dbExecutor,
run.Cfg.AURURL, run.Cfg.CompletionPath, run.Cfg.CompletionInterval, cmdArgs.ExistsDouble("c", "complete"))
case cmdArgs.ExistsArg("s", "stats"):
return localStatistics(ctx, cfg, dbExecutor)
return localStatistics(ctx, run, dbExecutor)
}
return nil
}
func handleYay(ctx context.Context, cfg *settings.Configuration,
func handleYay(ctx context.Context, run *runtime.Runtime,
cmdArgs *parser.Arguments, cmdBuilder exe.ICmdBuilder,
dbExecutor db.Executor, queryBuilder query.Builder,
) error {
switch {
case cmdArgs.ExistsArg("gendb"):
return createDevelDB(ctx, cfg, dbExecutor)
return createDevelDB(ctx, run, dbExecutor)
case cmdArgs.ExistsDouble("c"):
return cleanDependencies(ctx, cfg, cmdBuilder, cmdArgs, dbExecutor, true)
return cleanDependencies(ctx, run.Cfg, cmdBuilder, cmdArgs, dbExecutor, true)
case cmdArgs.ExistsArg("c", "clean"):
return cleanDependencies(ctx, cfg, cmdBuilder, cmdArgs, dbExecutor, false)
return cleanDependencies(ctx, run.Cfg, cmdBuilder, cmdArgs, dbExecutor, false)
case len(cmdArgs.Targets) > 0:
return displayNumberMenu(ctx, cfg, cmdArgs.Targets, dbExecutor, queryBuilder, cmdArgs)
return displayNumberMenu(ctx, run, cmdArgs.Targets, dbExecutor, queryBuilder, cmdArgs)
}
return nil
}
func handleWeb(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments) error {
func handleWeb(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments) error {
switch {
case cmdArgs.ExistsArg("v", "vote"):
return handlePackageVote(ctx, cmdArgs.Targets, cfg.Runtime.AURClient,
cfg.Runtime.VoteClient, true)
return handlePackageVote(ctx, cmdArgs.Targets, run.AURClient, run.Logger,
run.VoteClient, true)
case cmdArgs.ExistsArg("u", "unvote"):
return handlePackageVote(ctx, cmdArgs.Targets, cfg.Runtime.AURClient,
cfg.Runtime.VoteClient, false)
return handlePackageVote(ctx, cmdArgs.Targets, run.AURClient, run.Logger,
run.VoteClient, false)
}
return nil
}
func handleGetpkgbuild(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {
func handleGetpkgbuild(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {
if cmdArgs.ExistsArg("p", "print") {
return printPkgbuilds(dbExecutor, cfg.Runtime.AURClient,
cfg.Runtime.HTTPClient, cmdArgs.Targets, cfg.Mode, cfg.AURURL)
return printPkgbuilds(dbExecutor, run.AURClient,
run.HTTPClient, run.Logger, cmdArgs.Targets, run.Cfg.Mode, run.Cfg.AURURL)
}
return getPkgbuilds(ctx, dbExecutor, cfg.Runtime.AURClient, cfg,
return getPkgbuilds(ctx, dbExecutor, run.AURClient, run,
cmdArgs.Targets, cmdArgs.ExistsArg("f", "force"))
}
func handleUpgrade(ctx context.Context,
config *settings.Configuration, cmdArgs *parser.Arguments,
run *runtime.Runtime, cmdArgs *parser.Arguments,
) error {
return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, config.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
}
// -B* options
func handleBuild(ctx context.Context,
config *settings.Configuration, dbExecutor db.Executor, cmdArgs *parser.Arguments,
run *runtime.Runtime, dbExecutor db.Executor, cmdArgs *parser.Arguments,
) error {
if cmdArgs.ExistsArg("i", "install") {
return installLocalPKGBUILD(ctx, config, cmdArgs, dbExecutor)
return installLocalPKGBUILD(ctx, run, cmdArgs, dbExecutor)
}
return nil
}
func handleSync(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
func handleSync(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
targets := cmdArgs.Targets
switch {
case cmdArgs.ExistsArg("s", "search"):
return syncSearch(ctx, targets, dbExecutor, cfg.Runtime.QueryBuilder, !cmdArgs.ExistsArg("q", "quiet"))
return syncSearch(ctx, targets, dbExecutor, run.QueryBuilder, !cmdArgs.ExistsArg("q", "quiet"))
case cmdArgs.ExistsArg("p", "print", "print-format"):
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
case cmdArgs.ExistsArg("c", "clean"):
return syncClean(ctx, cfg, cmdArgs, dbExecutor)
return syncClean(ctx, run, cmdArgs, dbExecutor)
case cmdArgs.ExistsArg("l", "list"):
return syncList(ctx, cfg, cfg.Runtime.HTTPClient, cmdArgs, dbExecutor)
return syncList(ctx, run, run.HTTPClient, cmdArgs, dbExecutor)
case cmdArgs.ExistsArg("g", "groups"):
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
case cmdArgs.ExistsArg("i", "info"):
return syncInfo(ctx, cfg, cmdArgs, targets, dbExecutor)
return syncInfo(ctx, run, cmdArgs, targets, dbExecutor)
case cmdArgs.ExistsArg("u", "sysupgrade") || len(cmdArgs.Targets) > 0:
return syncInstall(ctx, cfg, cmdArgs, dbExecutor)
return syncInstall(ctx, run, cmdArgs, dbExecutor)
case cmdArgs.ExistsArg("y", "refresh"):
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
}
return nil
}
func handleRemove(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, localCache vcs.Store) error {
err := cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
func handleRemove(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, localCache vcs.Store) error {
err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
if err == nil {
localCache.RemovePackages(cmdArgs.Targets)
}
@ -383,7 +375,7 @@ func handleRemove(ctx context.Context, cfg *settings.Configuration, cmdArgs *par
}
// NumberMenu presents a CLI for selecting packages to install.
func displayNumberMenu(ctx context.Context, cfg *settings.Configuration, pkgS []string, dbExecutor db.Executor,
func displayNumberMenu(ctx context.Context, run *runtime.Runtime, pkgS []string, dbExecutor db.Executor,
queryBuilder query.Builder, cmdArgs *parser.Arguments,
) error {
queryBuilder.Execute(ctx, dbExecutor, pkgS)
@ -397,9 +389,9 @@ func displayNumberMenu(ctx context.Context, cfg *settings.Configuration, pkgS []
return nil
}
cfg.Runtime.Logger.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))
run.Logger.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))
numberBuf, err := cfg.Runtime.Logger.GetInput("", false)
numberBuf, err := run.Logger.GetInput("", false)
if err != nil {
return err
}
@ -415,27 +407,27 @@ func displayNumberMenu(ctx context.Context, cfg *settings.Configuration, pkgS []
cmdArgs.Targets = targets
if len(cmdArgs.Targets) == 0 {
fmt.Println(gotext.Get(" there is nothing to do"))
run.Logger.Println(gotext.Get(" there is nothing to do"))
return nil
}
return syncInstall(ctx, cfg, cmdArgs, dbExecutor)
return syncInstall(ctx, run, cmdArgs, dbExecutor)
}
func syncList(ctx context.Context, cfg *settings.Configuration,
func syncList(ctx context.Context, run *runtime.Runtime,
httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.Executor,
) error {
aur := false
for i := len(cmdArgs.Targets) - 1; i >= 0; i-- {
if cmdArgs.Targets[i] == "aur" && cfg.Mode.AtLeastAUR() {
if cmdArgs.Targets[i] == "aur" && run.Cfg.Mode.AtLeastAUR() {
cmdArgs.Targets = append(cmdArgs.Targets[:i], cmdArgs.Targets[i+1:]...)
aur = true
}
}
if cfg.Mode.AtLeastAUR() && (len(cmdArgs.Targets) == 0 || aur) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, cfg.AURURL+"/packages.gz", http.NoBody)
if run.Cfg.Mode.AtLeastAUR() && (len(cmdArgs.Targets) == 0 || aur) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, run.Cfg.AURURL+"/packages.gz", http.NoBody)
if err != nil {
return err
}
@ -453,22 +445,22 @@ func syncList(ctx context.Context, cfg *settings.Configuration,
for scanner.Scan() {
name := scanner.Text()
if cmdArgs.ExistsArg("q", "quiet") {
fmt.Println(name)
run.Logger.Println(name)
} else {
fmt.Printf("%s %s %s", text.Magenta("aur"), text.Bold(name), text.Bold(text.Green(gotext.Get("unknown-version"))))
run.Logger.Printf("%s %s %s", text.Magenta("aur"), text.Bold(name), text.Bold(text.Green(gotext.Get("unknown-version"))))
if dbExecutor.LocalPackage(name) != nil {
fmt.Print(text.Bold(text.Blue(gotext.Get(" [Installed]"))))
run.Logger.Print(text.Bold(text.Blue(gotext.Get(" [Installed]"))))
}
fmt.Println()
run.Logger.Println()
}
}
}
if cfg.Mode.AtLeastRepo() && (len(cmdArgs.Targets) != 0 || !aur) {
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, cfg.Mode, settings.NoConfirm))
if run.Cfg.Mode.AtLeastRepo() && (len(cmdArgs.Targets) != 0 || !aur) {
return run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, run.Cfg.Mode, settings.NoConfirm))
}
return nil

View File

@ -19,6 +19,7 @@ import (
"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"
@ -103,19 +104,19 @@ func TestYogurtMenuAURDB(t *testing.T) {
},
}
logger := text.NewLogger(io.Discard, os.Stderr, strings.NewReader("1\n"), true, "test")
cfg := &settings.Configuration{
run := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Runtime: &settings.Runtime{
},
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(), cfg, cmdArgs, db)
err = handleCmd(context.Background(), run, cmdArgs, db)
require.NoError(t, err)
wantCapture := []string{}

View File

@ -61,22 +61,22 @@ _yay() {
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')
sync=('asdeps asexplicit clean dbonly downloadonly overwrite groups ignore ignoregroup
info list needed nodeps assume-installed print refresh recursive search sysupgrade'
'c g i l p s u w y')
info list needed nodeps assume-installed print refresh recursive search sysupgrade aur repo'
'c g i l p s u w y a N')
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')
##yay stuff
common=('arch cachedir color config confirm dbpath debug gpgdir help hookdir logfile
noconfirm noprogressbar noscriptlet quiet root verbose
makepkg pacman git gpg gpgflags config requestsplitn sudoloop nosudoloop
makepkg pacman git gpg gpgflags config requestsplitn sudoloop
redownload noredownload redownloadall rebuild rebuildall rebuildtree norebuild sortby
singlelineresults doublelineresults answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff
noansweredit noanswerupgrade cleanmenu diffmenu editmenu cleanafter nocleanafter
nocleanmenu nodiffmenu provides noprovides pgpfetch nopgpfetch
useask nouseask combinedupgrade nocombinedupgrade aur repo makepkgconf
noansweredit noanswerupgrade cleanmenu diffmenu editmenu cleanafter keepsrc
provides pgpfetch
useask combinedupgrade aur repo makepkgconf
nomakepkgconf askremovemake askyesremovemake removemake noremovemake completioninterval aururl aurrpcurl
searchby batchinstall nobatchinstall'
searchby batchinstall'
'b d h q r v')
yays=('clean gendb' 'c')
show=('complete defaultconfig currentconfig stats news' 'c d g s w')

View File

@ -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"
# New options
complete -c $progname -n "not $noopt" -l repo -d 'Assume targets are from the AUR' -f
complete -c $progname -n "not $noopt" -s a -l aur -d 'Assume targets are from the repositories' -f
complete -c $progname -n "not $noopt" -s a -l aur -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
# Yay options
complete -c $progname -n "$yayspecific" -s c -l clean -d 'Remove unneeded dependencies' -f
@ -216,9 +216,6 @@ 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 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 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 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
@ -228,24 +225,17 @@ 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 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 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 nocleanafter -d 'Disable package sources cleaning' -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 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 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 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 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 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 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 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 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
@ -253,4 +243,3 @@ 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 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 nosudoloop -d 'Do not loop sudo calls in the background' -f

View File

@ -23,7 +23,7 @@ _pacman_opts_commands=(
# options for passing to _arguments: options common to all commands
_pacman_opts_common=(
'--repo[Assume targets are from the repositories]'
{-N,--repo}'[Assume targets are from the repositories]'
{-a,--aur}'[Assume targets are from the AUR]'
'--aururl[Set an alternative AUR URL]:url'
'--aurrpcurl[Set an alternative URL for the AUR /rpc endpoint]:url'
@ -70,9 +70,6 @@ _pacman_opts_common=(
'--cleanmenu[Give the option to clean build PKGBUILDS]'
'--diffmenu[Give the option to show diffs for build files]'
'--editmenu[Give the option to edit/view PKGBUILDS]'
"--nocleanmenu[Don't clean build PKGBUILDS]"
"--nodiffmenu[Don't show diffs for build files]"
"--noeditmenu[Don't edit/view PKGBUILDS]"
"--askremovemake[Ask to remove makedepends after install]"
"--askyesremovemake[Ask to remove makedepends after install(with "Y" as default)]"
"--removemake[Remove makedepends after install]"
@ -83,34 +80,26 @@ _pacman_opts_common=(
'--singlelineresults[List each search result on its own line]'
'--doublelineresults[List each search result on two lines, like pacman]'
'--devel[Check -git/-svn/-hg development version]'
'--nodevel[Disable development version checking]'
'--cleanafter[Clean package sources after successful build]'
'--nocleanafter[Disable package sources cleaning after successful build]'
'--keepsrc[Keep pkg/ and src/ after building packages]'
'--timeupdate[Check packages modification date and version]'
'--notimeupdate[Check only package version change]'
'--redownload[Always download pkgbuilds of targets]'
'--redownloadall[Always download pkgbuilds of all AUR packages]'
'--noredownload[Skip pkgbuild download if in cache and up to date]'
'--rebuild[Always build target packages]'
'--rebuildall[Always build all AUR 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]'
"--nopgpfetch[Don't prompt to import PGP keys]"
"--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]'
'--rebuildtree[Always build all AUR packages even if installed]'
'--norebuild[Skip package build if in cache and up to date]'
'--mflags[Pass arguments to makepkg]:mflags'
'--gpgflags[Pass arguments to gpg]:gpgflags'
'--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]'
'--sortby[Sort AUR results by a specific field during search]'
'--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

View File

@ -63,7 +63,7 @@ Yay will also remove cached data about devel packages.
.SH NEW OPTIONS
.TP
.B \-\-repo
.B \-N, \-\-repo
Assume all targets are from the repositories. Additionally Actions such as
sysupgrade will only act on repository packages.
@ -97,6 +97,10 @@ used when migrating to Yay from another AUR helper.
.B \-c, \-\-clean
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)
.TP
.B \-c, \-\-complete
@ -293,6 +297,9 @@ Unset the answer for the upgrade menu.
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.
If 'cleanmenu' is enabled in the configuration file, you can temporarily disable it by
using '--cleanmenu=false' on the command line
.TP
.B \-\-diffmenu
Show the diff menu. This menu gives you the option to view diffs from
@ -310,18 +317,6 @@ before building.
\fBWarning\fR: Yay resolves dependencies ahead of time via the RPC. It is not
recommended to edit pkgbuild variables unless you know what you are doing.
.TP
.B \-\-nocleanmenu
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 \-\-askremovemake
Ask to remove makedepends after installing packages.
@ -368,9 +363,8 @@ checked almost instantly and not require the original pkgbuild to be downloaded.
The slower pacaur-like devel checks can be implemented manually by piping
a list of packages into yay (see \fBexamples\fR).
.TP
.B \-\-nodevel
Do not check for development packages updates during sysupgrade.
If 'devel' is enabled in the configuration file, you can temporarily disable it by
using '--devel=false' on the command line
.TP
.B \-\-cleanafter
@ -381,26 +375,18 @@ This allows VCS packages to easily pull an update
instead of having to reclone the entire repo.
.TP
.B \-\-nocleanafter
Do not remove package sources after successful Install.
.B \-\-keepsrc
Keep pkg/ and src/ after building packages
.TP
.B \-\-timeupdate
During sysupgrade also compare the build time of installed packages against
the last modification time of each package's AUR page.
.TP
.B \-\-notimeupdate
Do not consider build times during sysupgrade.
.TP
.B \-\-separatesources
Separate query results by source, AUR and sync
.TP
.B \-\-noseparatesources
Do not separate query results by source for searching
.TP
.B \-\-redownload
Always download pkgbuilds of targets even when a copy is available in cache.
@ -421,23 +407,11 @@ Look for matching providers when searching for AUR packages. When multiple
providers are found a menu will appear prompting you to pick one. This
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
.B \-\-pgpfetch
Prompt to import unknown PGP keys from the \fBvalidpgpkeys\fR field of each
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
.B \-\-useask
Use pacman's --ask flag to automatically confirm package conflicts. Yay lists
@ -445,11 +419,6 @@ 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.
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
.B \-\-combinedupgrade
During sysupgrade, Yay will first perform a refresh, then show
@ -461,12 +430,6 @@ 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
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
.B \-\-batchinstall
When building and installing AUR packages instead of installing each package
@ -474,10 +437,6 @@ 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
another package, install all the packages in the install queue.
.TP
.B \-\-nobatchinstall
Always install AUR packages immediately after building them.
.TP
.B \-\-rebuild
Always build target packages even when a copy is available in cache.
@ -531,10 +490,6 @@ separated list that is quoted by the shell.
Loop sudo calls in the background to prevent sudo from timing out during long
builds.
.TP
.B \-\-nosudoloop
Do not loop sudo calls in the background.
.SH EXAMPLES
.TP
yay \fIfoo\fR

View File

@ -7,56 +7,3 @@ import (
)
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
}

24
get.go
View File

@ -11,25 +11,23 @@ import (
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v12/pkg/download"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/runtime"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
)
// yay -Gp.
func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient, httpClient *http.Client, targets []string,
func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient,
httpClient *http.Client, logger *text.Logger, targets []string,
mode parser.TargetMode, aurURL string,
) error {
pkgbuilds, err := download.PKGBUILDs(dbExecutor, aurClient, httpClient, targets, aurURL, mode)
pkgbuilds, err := download.PKGBUILDs(dbExecutor, aurClient, httpClient, logger, targets, aurURL, mode)
if err != nil {
text.Errorln(err)
logger.Errorln(err)
}
if len(pkgbuilds) != 0 {
for target, pkgbuild := range pkgbuilds {
fmt.Printf("\n\n# %s\n\n", target)
fmt.Print(string(pkgbuild))
}
logger.Printf("\n\n# %s\n\n%s", target, string(pkgbuild))
}
if len(pkgbuilds) != len(targets) {
@ -41,7 +39,7 @@ func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient, h
}
}
text.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
logger.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
return fmt.Errorf("")
}
@ -51,7 +49,7 @@ func printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient, h
// yay -G.
func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient aur.QueryClient,
config *settings.Configuration, targets []string, force bool,
run *runtime.Runtime, targets []string, force bool,
) error {
wd, err := os.Getwd()
if err != nil {
@ -59,9 +57,9 @@ func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient
}
cloned, errD := download.PKGBUILDRepos(ctx, dbExecutor, aurClient,
config.Runtime.CmdBuilder, targets, config.Mode, config.AURURL, wd, force)
run.CmdBuilder, run.Logger, targets, run.Cfg.Mode, run.Cfg.AURURL, wd, force)
if errD != nil {
text.Errorln(errD)
run.Logger.Errorln(errD)
}
if len(targets) != len(cloned) {
@ -73,7 +71,7 @@ func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient
}
}
text.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
run.Logger.Warnln(gotext.Get("Unable to find the following packages:"), " ", strings.Join(missing, ", "))
err = fmt.Errorf("")
}

38
go.mod
View File

@ -2,40 +2,34 @@ module github.com/Jguer/yay/v12
require (
github.com/Jguer/aur v1.2.3
github.com/Jguer/go-alpm/v2 v2.2.1
github.com/Jguer/go-alpm/v2 v2.2.2
github.com/Jguer/votar v1.0.0
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5
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/leonelquinteros/gotext v1.5.2
github.com/stretchr/testify v1.8.4
golang.org/x/sys v0.10.0
golang.org/x/term v0.10.0
golang.org/x/text v0.11.0 // indirect
github.com/deckarep/golang-set/v2 v2.8.0
github.com/hashicorp/go-multierror v1.1.1
github.com/leonelquinteros/gotext v1.7.2
github.com/stretchr/testify v1.10.0
golang.org/x/net v0.41.0
golang.org/x/sys v0.33.0
golang.org/x/term v0.32.0
gopkg.in/h2non/gock.v1 v1.1.2
)
require (
github.com/adrg/strutil v0.3.0
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
github.com/pkg/errors v0.9.1
github.com/hashicorp/errwrap v1.1.0 // indirect
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
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (
github.com/deckarep/golang-set/v2 v2.3.0
github.com/itchyny/gojq v0.12.13 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/ohler55/ojg v1.19.1 // indirect
)
go 1.23.5
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
toolchain go1.24.0

75
go.sum
View File

@ -1,15 +1,15 @@
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/go-alpm/v2 v2.2.1 h1:PMIRKo2lY0wfhN8W8Scc5v82zQeDsTv702CuDiz81sA=
github.com/Jguer/go-alpm/v2 v2.2.1/go.mod h1:lfe8gSe83F/KERaQvEfrSqQ4n+8bES+ZIyKWR/gm3MI=
github.com/Jguer/go-alpm/v2 v2.2.2 h1:sPwUoZp1X5Tw6K6Ba1lWvVJfcgVNEGVcxARLBttZnC0=
github.com/Jguer/go-alpm/v2 v2.2.2/go.mod h1:lfe8gSe83F/KERaQvEfrSqQ4n+8bES+ZIyKWR/gm3MI=
github.com/Jguer/votar v1.0.0 h1:drPYpV5Py5BeAQS8xezmT6uCEfLzotNjLf5yfmlHKTg=
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/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/go.mod h1:MP6VGY1NNpVUmYIEgoM9acix95KQqIRyqQ0hCLsyYUY=
github.com/adrg/strutil v0.3.0 h1:bi/HB2zQbDihC8lxvATDTDzkT4bG7PATtVnDYp5rvq4=
github.com/adrg/strutil v0.3.0/go.mod h1:Jz0wzBVE6Uiy9wxo62YEqEY1Nwto3QlLl1Il5gkLKWU=
github.com/adrg/strutil v0.3.1 h1:OLvSS7CSJO8lBii4YmBt8jiK9QOtB9CzCzwl4Ic/Fz4=
github.com/adrg/strutil v0.3.1/go.mod h1:8h90y18QLrs11IBffcGX3NW/GFBXCMcNg4M7H6MspPA=
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/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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.3.0 h1:qs18EKUfHm2X9fA50Mr/M5hccg2tNnVqsiBImnyDs0g=
github.com/deckarep/golang-set/v2 v2.3.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/deckarep/golang-set/v2 v2.8.0 h1:swm0rlPCmdWn9mESxKOjWk8hXSqoxOp+ZlfuyaAdFlQ=
github.com/deckarep/golang-set/v2 v2.8.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/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -26,60 +26,39 @@ 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/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/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU=
github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4=
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
github.com/leonelquinteros/gotext v1.5.2 h1:T2y6ebHli+rMBCjcJlHTXyUrgXqsKBhl/ormgvt7lPo=
github.com/leonelquinteros/gotext v1.5.2/go.mod h1:AT4NpQrOmyj1L/+hLja6aR0lk81yYYL4ePnj2kp7d6M=
github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg=
github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY=
github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q=
github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg=
github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
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/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/ohler55/ojg v1.19.1 h1:ruSyx+OGrE2HvJgUvtDWiqHJFfMs6e7IM0yZhcrs3NU=
github.com/ohler55/ojg v1.19.1/go.mod h1:uHcD1ErbErC27Zhb5Df2jUjbseLLcmOCo6oxSr3jZxo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/ohler55/ojg v1.26.1 h1:J5TaLmVEuvnpVH7JMdT1QdbpJU545Yp6cKiCO4aQILc=
github.com/ohler55/ojg v1.26.1/go.mod h1:gQhDVpQLqrmnd2eqGAvJtn+NfKoYJbe/A4Sj3/Vro4o=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
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.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.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
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.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.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.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
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.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
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=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
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/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=

View File

@ -4,6 +4,7 @@ package main
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
@ -12,19 +13,17 @@ import (
"github.com/Jguer/yay/v12/pkg/db"
"github.com/Jguer/yay/v12/pkg/dep"
"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/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/sync"
gosrc "github.com/Morganamilo/go-srcinfo"
"github.com/leonelquinteros/gotext"
"github.com/pkg/errors"
)
var (
ErrInstallRepoPkgs = errors.New(gotext.Get("error installing repo packages"))
ErrNoBuildFiles = errors.New(gotext.Get("cannot find PKGBUILD and .SRCINFO in directory"))
)
var ErrNoBuildFiles = errors.New(gotext.Get("cannot find PKGBUILD and .SRCINFO in directory"))
func srcinfoExists(ctx context.Context,
cmdBuilder exe.ICmdBuilder, targetDir string,
@ -44,6 +43,10 @@ func srcinfoExists(ctx context.Context,
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 {
return fmt.Errorf("unable to write .SRCINFO: %w", err)
}
@ -56,12 +59,12 @@ func srcinfoExists(ctx context.Context,
func installLocalPKGBUILD(
ctx context.Context,
config *settings.Configuration,
run *runtime.Runtime,
cmdArgs *parser.Arguments,
dbExecutor db.Executor,
) error {
aurCache := config.Runtime.AURClient
noCheck := strings.Contains(config.MFlags, "--nocheck")
aurCache := run.AURClient
noCheck := strings.Contains(run.Cfg.MFlags, "--nocheck")
if len(cmdArgs.Targets) < 1 {
return errors.New(gotext.Get("no target directories specified"))
@ -69,13 +72,13 @@ func installLocalPKGBUILD(
srcInfos := map[string]*gosrc.Srcinfo{}
for _, targetDir := range cmdArgs.Targets {
if err := srcinfoExists(ctx, config.Runtime.CmdBuilder, targetDir); err != nil {
if err := srcinfoExists(ctx, run.CmdBuilder, targetDir); err != nil {
return err
}
pkgbuild, err := gosrc.ParseFile(filepath.Join(targetDir, ".SRCINFO"))
if err != nil {
return errors.Wrap(err, gotext.Get("failed to parse .SRCINFO"))
return fmt.Errorf("%s: %w", gotext.Get("failed to parse .SRCINFO"), err)
}
srcInfos[targetDir] = pkgbuild
@ -83,13 +86,13 @@ func installLocalPKGBUILD(
grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm,
cmdArgs.ExistsDouble("d", "nodeps"), noCheck, cmdArgs.ExistsArg("needed"),
config.Runtime.Logger.Child("grapher"))
run.Logger.Child("grapher"))
graph, err := grapher.GraphFromSrcInfos(ctx, nil, srcInfos)
if err != nil {
return err
}
opService := NewOperationService(ctx, config, dbExecutor)
opService := sync.NewOperationService(ctx, dbExecutor, run)
multiErr := &multierror.MultiError{}
targets := graph.TopoSortedLayerMap(func(name string, ii *dep.InstallInfo) error {
if ii.Source == dep.Missing {
@ -101,5 +104,5 @@ func installLocalPKGBUILD(
if err := multiErr.Return(); err != nil {
return err
}
return opService.Run(ctx, cmdArgs, targets, []string{})
return opService.Run(ctx, run, cmdArgs, targets, []string{})
}

View File

@ -6,6 +6,7 @@ package main
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
@ -19,12 +20,18 @@ import (
"github.com/Jguer/yay/v12/pkg/db/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/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
"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) {
makepkgBin := t.TempDir() + "/makepkg"
pacmanBin := t.TempDir() + "/pacman"
@ -49,16 +56,14 @@ func TestIntegrationLocalInstall(t *testing.T) {
}
wantShow := []string{
"makepkg --verifysource --skippgpcheck -Ccf",
"makepkg --verifysource --skippgpcheck -f -Cc",
"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",
"makepkg --nobuild -fC --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --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",
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"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",
@ -69,7 +74,6 @@ func TestIntegrationLocalInstall(t *testing.T) {
"git -C testdata/jfin git reset --hard HEAD",
"git -C testdata/jfin git merge --no-edit --ff",
"makepkg --packagelist",
"makepkg --packagelist",
}
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
@ -142,10 +146,11 @@ func TestIntegrationLocalInstall(t *testing.T) {
InstalledRemotePackageNamesFn: func() []string { return []string{} },
}
config := &settings.Configuration{
run := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -153,10 +158,9 @@ func TestIntegrationLocalInstall(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
err = handleCmd(context.Background(), run, cmdArgs, db)
require.NoError(t, err)
require.Len(t, mockRunner.ShowCalls, len(wantShow))
@ -263,9 +267,9 @@ func TestIntegrationLocalInstallMissingDep(t *testing.T) {
LocalPackageFn: func(string) mock.IPackage { return nil },
}
config := &settings.Configuration{
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
run := &runtime.Runtime{
Cfg: &settings.Configuration{},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -273,10 +277,9 @@ func TestIntegrationLocalInstallMissingDep(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
err = handleCmd(context.Background(), run, cmdArgs, db)
require.ErrorContains(t, err, wantErr.Error())
require.Len(t, mockRunner.ShowCalls, len(wantShow))
@ -318,14 +321,12 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
}
wantShow := []string{
"makepkg --verifysource --skippgpcheck -Ccf",
"makepkg --verifysource --skippgpcheck -f -Cc",
"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",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"makepkg --nobuild -fC --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
}
@ -334,7 +335,6 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
"git -C testdata/jfin git reset --hard HEAD",
"git -C testdata/jfin git merge --no-edit --ff",
"makepkg --packagelist",
"makepkg --packagelist",
}
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
@ -421,10 +421,11 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
InstalledRemotePackageNamesFn: func() []string { return []string{} },
}
config := &settings.Configuration{
run := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -432,10 +433,9 @@ func TestIntegrationLocalInstallNeeded(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
err = handleCmd(context.Background(), run, cmdArgs, db)
require.NoError(t, err)
require.Len(t, mockRunner.ShowCalls, len(wantShow), "show calls: %v", mockRunner.ShowCalls)
@ -486,16 +486,14 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
}
wantShow := []string{
"makepkg --verifysource --skippgpcheck -Ccf",
"makepkg --verifysource --skippgpcheck -f -Cc",
"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",
"makepkg --nobuild -fC --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --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",
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"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",
@ -507,7 +505,6 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
"git -C testdata/jfin git reset --hard HEAD",
"git -C testdata/jfin git merge --no-edit --ff",
"makepkg --packagelist",
"makepkg --packagelist",
}
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
@ -585,11 +582,12 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
InstalledRemotePackageNamesFn: func() []string { return []string{} },
}
config := &settings.Configuration{
run := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Debug: false,
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -597,10 +595,9 @@ func TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
err = handleCmd(context.Background(), run, cmdArgs, db)
require.NoError(t, err)
require.Len(t, mockRunner.ShowCalls, len(wantShow))
@ -651,7 +648,6 @@ func TestIntegrationLocalInstallMissingFiles(t *testing.T) {
wantCapture := []string{}
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
fmt.Println(cmd.Args)
if cmd.Args[1] == "--printsrcinfo" {
return string(srcinfo), "", nil
}
@ -722,10 +718,12 @@ func TestIntegrationLocalInstallMissingFiles(t *testing.T) {
},
}
config := &settings.Configuration{
config := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
Debug: false,
},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -733,7 +731,6 @@ func TestIntegrationLocalInstallMissingFiles(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
@ -777,12 +774,12 @@ func TestIntegrationLocalInstallWithDepsProvides(t *testing.T) {
}
wantShow := []string{
"makepkg --verifysource --skippgpcheck -Ccf",
"makepkg --nobuild -fC --ignorearch",
"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 -fC --ignorearch",
"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",
@ -848,10 +845,11 @@ func TestIntegrationLocalInstallWithDepsProvides(t *testing.T) {
InstalledRemotePackageNamesFn: func() []string { return []string{} },
}
config := &settings.Configuration{
config := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -859,7 +857,6 @@ func TestIntegrationLocalInstallWithDepsProvides(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
@ -904,13 +901,13 @@ func TestIntegrationLocalInstallTwoSrcInfosWithDeps(t *testing.T) {
}
wantShow := []string{
"makepkg --verifysource --skippgpcheck -Ccf",
"makepkg --verifysource --skippgpcheck -Ccf",
"makepkg --nobuild -fC --ignorearch",
"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 -fC --ignorearch",
"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",
@ -988,10 +985,11 @@ func TestIntegrationLocalInstallTwoSrcInfosWithDeps(t *testing.T) {
InstalledRemotePackageNamesFn: func() []string { return []string{} },
}
config := &settings.Configuration{
run := &runtime.Runtime{
Cfg: &settings.Configuration{
RemoveMake: "no",
Runtime: &settings.Runtime{
Logger: NewTestLogger(),
},
Logger: newTestLogger(),
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
AURClient: &mockaur.MockAUR{
@ -999,10 +997,9 @@ func TestIntegrationLocalInstallTwoSrcInfosWithDeps(t *testing.T) {
return []aur.Pkg{}, nil
},
},
},
}
err = handleCmd(context.Background(), config, cmdArgs, db)
err = handleCmd(context.Background(), run, cmdArgs, db)
require.NoError(t, err)
require.Len(t, mockRunner.ShowCalls, len(wantShow))

82
main.go
View File

@ -6,12 +6,12 @@ import (
"os"
"os/exec"
"runtime/debug"
"strings"
"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/query"
"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/text"
@ -28,7 +28,12 @@ func initGotext() {
}
if lc := os.Getenv("LANGUAGE"); lc != "" {
gotext.Configure(localePath, lc, "yay")
// Split LANGUAGE by ':' and prioritize the first locale
// 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 != "" {
gotext.Configure(localePath, lc, "yay")
} else if lc := os.Getenv("LC_MESSAGES"); lc != "" {
@ -39,6 +44,7 @@ func initGotext() {
}
func main() {
fallbackLog := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, false, "fallback")
var (
err error
ctx = context.Background()
@ -47,8 +53,9 @@ func main() {
defer func() {
if rec := recover(); rec != nil {
text.Errorln(rec)
debug.PrintStack()
fallbackLog.Errorln("Panic occurred:", rec)
fallbackLog.Errorln("Stack trace:", string(debug.Stack()))
ret = 1
}
os.Exit(ret)
@ -57,15 +64,15 @@ func main() {
initGotext()
if os.Geteuid() == 0 {
text.Warnln(gotext.Get("Avoid running yay as root/sudo."))
fallbackLog.Warnln(gotext.Get("Avoid running yay as root/sudo."))
}
configPath := settings.GetConfigPath()
// Parse config
cfg, err := settings.NewConfig(configPath, yayVersion)
cfg, err := settings.NewConfig(fallbackLog, configPath, yayVersion)
if err != nil {
if str := err.Error(); str != "" {
text.Errorln(str)
fallbackLog.Errorln(str)
}
ret = 1
@ -73,13 +80,9 @@ func main() {
return
}
if cfg.Debug {
text.GlobalLogger.Debug = true
}
if errS := cfg.RunMigrations(
if errS := cfg.RunMigrations(fallbackLog,
settings.DefaultMigrations(), configPath, yayVersion); errS != nil {
text.Errorln(errS)
fallbackLog.Errorln(errS)
}
cmdArgs := parser.MakeArguments()
@ -87,7 +90,7 @@ func main() {
// Parse command line
if err = cfg.ParseCommandLine(cmdArgs); err != nil {
if str := err.Error(); str != "" {
text.Errorln(str)
fallbackLog.Errorln(str)
}
ret = 1
@ -97,15 +100,15 @@ func main() {
if cfg.SaveConfig {
if errS := cfg.Save(configPath, yayVersion); errS != nil {
text.Errorln(errS)
fallbackLog.Errorln(errS)
}
}
// Build runtime
runtime, err := settings.BuildRuntime(cfg, cmdArgs, yayVersion)
// Build run
run, err := runtime.NewRuntime(cfg, cmdArgs, yayVersion)
if err != nil {
if str := err.Error(); str != "" {
text.Errorln(str)
fallbackLog.Errorln(str)
}
ret = 1
@ -113,35 +116,10 @@ func main() {
return
}
cfg.Runtime = runtime
cfg.Runtime.QueryBuilder = query.NewSourceQueryBuilder(
cfg.Runtime.AURClient,
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)
dbExecutor, err := ialpm.NewExecutor(run.PacmanConf, run.Logger.Child("db"))
if err != nil {
if str := err.Error(); 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)
fallbackLog.Errorln(str)
}
ret = 1
@ -151,20 +129,16 @@ func main() {
defer func() {
if rec := recover(); rec != nil {
text.Errorln(rec)
debug.PrintStack()
fallbackLog.Errorln("Panic occurred in DB operation:", rec)
fallbackLog.Errorln("Stack trace:", string(debug.Stack()))
}
dbExecutor.Cleanup()
}()
if err = handleCmd(ctx, cfg, cmdArgs, db.Executor(dbExecutor)); err != nil {
if err = handleCmd(ctx, run, cmdArgs, dbExecutor); err != nil {
if str := err.Error(); str != "" {
text.Errorln(str)
if cmdArgs.ExistsArg("c") && cmdArgs.ExistsArg("y") && cmdArgs.Op == "S" {
// Remove after 2023-10-01
text.Errorln("Did you mean 'yay -Yc'?")
}
fallbackLog.Errorln(str)
}
exitError := &exec.ExitError{}

View File

@ -2,59 +2,61 @@ package main
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"github.com/Jguer/yay/v12/pkg/db/ialpm"
"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/parser"
"github.com/Jguer/yay/v12/pkg/text"
"github.com/Jguer/aur/metadata"
"github.com/leonelquinteros/gotext"
"github.com/pkg/errors"
)
func handleCmd() error {
config, err := settings.NewConfig(settings.GetConfigPath(), "")
func handleCmd(logger *text.Logger) error {
cfg, err := settings.NewConfig(logger, settings.GetConfigPath(), "")
if err != nil {
return err
}
cmdArgs := parser.MakeArguments()
if errP := config.ParseCommandLine(cmdArgs); errP != nil {
if errP := cfg.ParseCommandLine(cmdArgs); errP != nil {
return errP
}
pacmanConf, _, err := settings.RetrievePacmanConfig(cmdArgs, config.PacmanConf)
run, err := runtime.NewRuntime(cfg, cmdArgs, "1.0.0")
if err != nil {
return err
}
dbExecutor, err := ialpm.NewExecutor(pacmanConf, text.GlobalLogger)
dbExecutor, err := ialpm.NewExecutor(run.PacmanConf, logger)
if err != nil {
return err
}
aurCache, err := metadata.New(
metadata.WithCacheFilePath(
filepath.Join(config.BuildDir, "aur.json")))
filepath.Join(cfg.BuildDir, "aur.json")))
if err != nil {
return errors.Wrap(err, gotext.Get("failed to retrieve aur Cache"))
return fmt.Errorf("%s: %w", gotext.Get("failed to retrieve aur Cache"), err)
}
grapher := dep.NewGrapher(dbExecutor, aurCache, true, settings.NoConfirm,
cmdArgs.ExistsDouble("d", "nodeps"), false, false,
config.Runtime.Logger.Child("grapher"))
run.Logger.Child("grapher"))
return graphPackage(context.Background(), grapher, cmdArgs.Targets)
}
func main() {
if err := handleCmd(); err != nil {
text.Errorln(err)
fallbackLog := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, false, "fallback")
if err := handleCmd(fallbackLog); err != nil {
fallbackLog.Errorln(err)
os.Exit(1)
}
}

View File

@ -117,7 +117,7 @@ func createAURList(ctx context.Context, client httpRequestDoer, aurURL string, o
return nil
}
// CreatePackageList appends Repo packages to completion cache.
// createRepoList appends Repo packages to completion cache.
func createRepoList(dbExecutor PkgSynchronizer, out io.Writer) error {
for _, pkg := range dbExecutor.SyncPackages() {
_, err := io.WriteString(out, pkg.Name()+"\t"+pkg.DB().Name()+"\n")

View File

@ -176,7 +176,7 @@ func (ae *AlpmExecutor) questionCallback() func(question alpm.QuestionAny) {
return nil
})
str := text.Bold(gotext.Get("There are %d providers available for %s:", size, qp.Dep()))
str := text.Bold(gotext.Get("There are %[1]d providers available for %[2]s:", size, qp.Dep()))
size = 1

View File

@ -37,7 +37,7 @@ func (i *InstallInfo) String() string {
}
type (
Reason int
Reason uint
Source int
)
@ -165,7 +165,6 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
}
if pkg != nil {
g.GraphSyncPkg(ctx, graph, pkg, nil)
continue
}
@ -537,12 +536,13 @@ func (g *Grapher) findDepsFromAUR(ctx context.Context,
}
// remove packages that don't satisfy the dependency
for i := 0; i < len(aurPkgs); i++ {
if !satisfiesAur(depString, &aurPkgs[i]) {
aurPkgs = append(aurPkgs[:i], aurPkgs[i+1:]...)
i--
satisfyingPkgs := make([]aurc.Pkg, 0, len(aurPkgs))
for i := range aurPkgs {
if satisfiesAur(depString, &aurPkgs[i]) {
satisfyingPkgs = append(satisfyingPkgs, aurPkgs[i])
}
}
aurPkgs = satisfyingPkgs
if len(aurPkgs) == 0 {
g.logger.Errorln(gotext.Get("No AUR package found for"), " ", depString)
@ -723,7 +723,7 @@ func (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {
return &options[0]
}
str := text.Bold(gotext.Get("There are %d providers available for %s:", size, dep))
str := text.Bold(gotext.Get("There are %[1]d providers available for %[2]s:", size, dep))
str += "\n"
size = 1
@ -749,7 +749,7 @@ func (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {
if err != nil {
g.logger.Errorln(err)
break
return &options[0]
}
if numberBuf == "" {
@ -772,8 +772,6 @@ func (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {
return &options[num-1]
}
return nil
}
func makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]*aur.Pkg, error) {
@ -806,16 +804,17 @@ func makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]*a
Description: getDesc(pkg),
URL: pkg.URL,
Depends: append(archStringToString(alpmArch, pkg.Depends),
archStringToString(alpmArch, srcInfo.Package.Depends)...),
MakeDepends: archStringToString(alpmArch, srcInfo.PackageBase.MakeDepends),
CheckDepends: archStringToString(alpmArch, srcInfo.PackageBase.CheckDepends),
archStringToString(alpmArch, srcInfo.Depends)...),
MakeDepends: archStringToString(alpmArch, srcInfo.MakeDepends),
CheckDepends: archStringToString(alpmArch, srcInfo.CheckDepends),
Conflicts: append(archStringToString(alpmArch, pkg.Conflicts),
archStringToString(alpmArch, srcInfo.Package.Conflicts)...),
archStringToString(alpmArch, srcInfo.Conflicts)...),
Provides: append(archStringToString(alpmArch, pkg.Provides),
archStringToString(alpmArch, srcInfo.Package.Provides)...),
archStringToString(alpmArch, srcInfo.Provides)...),
Replaces: append(archStringToString(alpmArch, pkg.Replaces),
archStringToString(alpmArch, srcInfo.Package.Replaces)...),
OptDepends: []string{},
archStringToString(alpmArch, srcInfo.Replaces)...),
OptDepends: append(archStringToString(alpmArch, pkg.OptDepends),
archStringToString(alpmArch, srcInfo.OptDepends)...),
Groups: pkg.Groups,
License: pkg.License,
Keywords: []string{},

View File

@ -5,8 +5,6 @@ import (
"strings"
"github.com/Jguer/go-alpm/v2"
"github.com/Jguer/yay/v12/pkg/text"
)
type (
@ -244,7 +242,6 @@ func (g *Graph[T, V]) Prune(node T) []T {
// Remove edges from things that depend on `node`.
for dependent := range g.dependents[node] {
last := g.dependencies.removeFromDepmap(dependent, node)
text.Debugln("pruning dependent", dependent, last)
if last {
pruned = append(pruned, g.Prune(dependent)...)
}
@ -255,7 +252,6 @@ func (g *Graph[T, V]) Prune(node T) []T {
// Remove all edges from node to the things it depends on.
for dependency := range g.dependencies[node] {
last := g.dependents.removeFromDepmap(dependency, node)
text.Debugln("pruning dependency", dependency, last)
if last {
pruned = append(pruned, g.Prune(dependency)...)
}

View File

@ -48,7 +48,7 @@ func AURPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder, aurURL,
func AURPKGBUILDRepos(
ctx context.Context,
cmdBuilder exe.GitCmdBuilder,
cmdBuilder exe.GitCmdBuilder, logger *text.Logger,
targets []string, aurURL, dest string, force bool,
) (map[string]bool, error) {
cloned := make(map[string]bool, len(targets))
@ -63,30 +63,34 @@ func AURPKGBUILDRepos(
for _, target := range targets {
sem <- 1
wg.Add(1)
go func(target string) {
defer func() {
<-sem
wg.Done()
}()
newClone, err := AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, target, dest, force)
progress := 0
mux.Lock()
progress := len(cloned)
if err != nil {
errs.Add(err)
} else {
mux.Lock()
mux.Unlock()
logger.OperationInfoln(
gotext.Get("(%d/%d) Failed to download PKGBUILD: %s",
progress, len(targets), text.Cyan(target)))
return
}
cloned[target] = newClone
progress = len(cloned)
mux.Unlock()
}
text.OperationInfoln(
logger.OperationInfoln(
gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
progress, len(targets), text.Cyan(target)))
<-sem
wg.Done()
}(target)
}

View File

@ -158,7 +158,7 @@ func TestAURPKGBUILDRepos(t *testing.T) {
GitFlags: []string{},
},
}
cloned, err := AURPKGBUILDRepos(context.Background(), cmdBuilder, targets, "https://aur.archlinux.org", dir, false)
cloned, err := AURPKGBUILDRepos(context.Background(), cmdBuilder, newTestLogger(), targets, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
assert.EqualValues(t, map[string]bool{"yay": true, "yay-bin": false, "yay-git": true}, cloned)

View File

@ -81,8 +81,8 @@ func getURLName(pkg db.IPackage) string {
return name
}
func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *http.Client, targets []string,
aurURL string, mode parser.TargetMode,
func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *http.Client,
logger *text.Logger, targets []string, aurURL string, mode parser.TargetMode,
) (map[string][]byte, error) {
pkgbuilds := make(map[string][]byte, len(targets))
@ -96,7 +96,7 @@ func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *htt
for _, target := range targets {
// Probably replaceable by something in query.
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, target, mode)
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, logger, target, mode)
if toSkip {
continue
}
@ -136,7 +136,7 @@ func PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *htt
}
func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.QueryClient,
cmdBuilder exe.GitCmdBuilder,
cmdBuilder exe.GitCmdBuilder, logger *text.Logger,
targets []string, mode parser.TargetMode, aurURL, dest string, force bool,
) (map[string]bool, error) {
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 {
// Probably replaceable by something in query.
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, target, mode)
dbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, logger, target, mode)
if toSkip {
continue
}
@ -184,11 +184,11 @@ func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.Que
}
if aur {
text.OperationInfoln(
logger.OperationInfoln(
gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
progress, len(targets), text.Cyan(pkgName)))
} else {
text.OperationInfoln(
logger.OperationInfoln(
gotext.Get("(%d/%d) Downloaded PKGBUILD from ABS: %s",
progress, len(targets), text.Cyan(pkgName)))
}
@ -206,7 +206,7 @@ func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.Que
// TODO: replace with dep.ResolveTargets.
func getPackageUsableName(dbExecutor DBSearcher, aurClient aur.QueryClient,
target string, mode parser.TargetMode,
logger *text.Logger, target string, mode parser.TargetMode,
) (dbname, pkgname string, isAUR, toSkip bool) {
dbName, name := text.SplitDBFromName(target)
if dbName != "aur" && mode.AtLeastRepo() {
@ -239,7 +239,7 @@ func getPackageUsableName(dbExecutor DBSearcher, aurClient aur.QueryClient,
Needles: []string{name},
})
if err != nil {
text.Warnln(err)
logger.Warnln(err)
return dbName, name, true, true
}

View File

@ -42,7 +42,7 @@ func TestIntegrationPKGBUILDReposDefinedDBClone(t *testing.T) {
absPackagesDB: map[string]string{"linux": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, testLogger.Child("test"),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
@ -71,7 +71,7 @@ func TestIntegrationPKGBUILDReposNotExist(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, testLogger.Child("test"),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.Error(t, err)
@ -88,12 +88,13 @@ func TestIntegrationPKGBUILDFull(t *testing.T) {
},
}
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{},
fetched, err := PKGBUILDs(searcher, mockClient, &http.Client{}, testLogger.Child("test"),
targets, "https://aur.archlinux.org", parser.ModeAny)
assert.NoError(t, err)

View File

@ -5,6 +5,7 @@ package download
import (
"context"
"io"
"net/http"
"os"
"path/filepath"
@ -22,6 +23,10 @@ import (
"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 package in repo is already present
// WHEN defining package db as a target
@ -56,7 +61,7 @@ func TestPKGBUILDReposDefinedDBPull(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, newTestLogger(),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
@ -90,7 +95,7 @@ func TestPKGBUILDReposDefinedDBClone(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, newTestLogger(),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
@ -124,7 +129,7 @@ func TestPKGBUILDReposClone(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, newTestLogger(),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
@ -158,7 +163,7 @@ func TestPKGBUILDReposNotFound(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, newTestLogger(),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
@ -192,7 +197,7 @@ func TestPKGBUILDReposRepoMode(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, newTestLogger(),
targets, parser.ModeRepo, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)
@ -230,7 +235,7 @@ func TestPKGBUILDFull(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
fetched, err := PKGBUILDs(searcher, mockClient, &http.Client{},
fetched, err := PKGBUILDs(searcher, mockClient, &http.Client{}, newTestLogger(),
targets, "https://aur.archlinux.org", parser.ModeAny)
assert.NoError(t, err)
@ -268,7 +273,7 @@ func TestPKGBUILDReposMissingAUR(t *testing.T) {
absPackagesDB: map[string]string{"yay": "core"},
}
cloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,
cmdBuilder,
cmdBuilder, newTestLogger(),
targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
assert.NoError(t, err)

View File

@ -17,10 +17,10 @@ type IntRange struct {
// IntRanges is a slice of IntRange.
type IntRanges []IntRange
func makeIntRange(min, max int) IntRange {
func makeIntRange(minVal, maxVal int) IntRange {
return IntRange{
min,
max,
min: minVal,
max: maxVal,
}
}
@ -42,24 +42,6 @@ func (rs IntRanges) Get(n int) bool {
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
// supports individual selection: 1 2 3 4
// supports range selections: 1-4 10-20
@ -116,8 +98,8 @@ func ParseNumberMenu(input string) (include, exclude IntRanges,
num2 = num1
}
mi := Min(num1, num2)
ma := Max(num1, num2)
mi := min(num1, num2)
ma := max(num1, num2)
if !invert {
include = append(include, makeIntRange(mi, ma))

View File

@ -64,9 +64,9 @@ func TestParseNumberMenu(t *testing.T) {
},
mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string](),
},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string]("abort", "all", "none"), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string]("a-b"), mapset.NewThreadUnsafeSet[string]("abort", "a-b")},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string]("-9223372036854775809-9223372036854775809"), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("abort", "all", "none"), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("a-b"), mapset.NewThreadUnsafeSet("abort", "a-b")},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("-9223372036854775809-9223372036854775809"), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{
makeIntRange(1, 1),
makeIntRange(2, 2),
@ -86,7 +86,7 @@ func TestParseNumberMenu(t *testing.T) {
}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string]("a", "b", "c", "d", "e"), mapset.NewThreadUnsafeSet[string]()},
{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet("a", "b", "c", "d", "e"), mapset.NewThreadUnsafeSet[string]()},
}
for n, in := range inputs {

View File

@ -9,6 +9,7 @@ import (
mapset "github.com/deckarep/golang-set/v2"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v12/pkg/runtime"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/text"
)
@ -23,7 +24,7 @@ func anyExistInCache(pkgbuildDirs map[string]string) bool {
return false
}
func CleanFn(ctx context.Context, config *settings.Configuration, w io.Writer,
func CleanFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
) error {
if len(pkgbuildDirsByBase) == 0 {
@ -49,25 +50,25 @@ func CleanFn(ctx context.Context, config *settings.Configuration, w io.Writer,
bases = append(bases, pkg)
}
toClean, errClean := selectionMenu(w, pkgbuildDirsByBase, bases, installed,
toClean, errClean := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed,
gotext.Get("Packages to cleanBuild?"),
settings.NoConfirm, config.AnswerClean, skipFunc)
settings.NoConfirm, run.Cfg.AnswerClean, skipFunc)
if errClean != nil {
return errClean
}
for i, base := range toClean {
dir := pkgbuildDirsByBase[base]
text.OperationInfoln(gotext.Get("Deleting (%d/%d): %s", i+1, len(toClean), text.Cyan(dir)))
run.Logger.OperationInfoln(gotext.Get("Deleting (%d/%d): %s", i+1, len(toClean), text.Cyan(dir)))
if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "reset", "--hard", "origin/HEAD")); err != nil {
text.Warnln(gotext.Get("Unable to clean:"), dir)
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, "reset", "--hard", "origin/HEAD")); err != nil {
run.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
return err
}
if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fdx")); err != nil {
text.Warnln(gotext.Get("Unable to clean:"), dir)
if err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fdx")); err != nil {
run.Logger.Warnln(gotext.Get("Unable to clean:"), dir)
return err
}

View File

@ -5,13 +5,13 @@ import (
"context"
"fmt"
"io"
"os"
"strings"
mapset "github.com/deckarep/golang-set/v2"
"github.com/leonelquinteros/gotext"
"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/exe"
"github.com/Jguer/yay/v12/pkg/text"
@ -22,7 +22,7 @@ const (
gitDiffRefName = "AUR_SEEN"
)
func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder,
func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder, logger *text.Logger,
pkgbuildDirs map[string]string, bases []string,
) error {
var errMulti multierror.MultiError
@ -46,7 +46,7 @@ func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder,
}
if !hasDiff {
text.Warnln(gotext.Get("%s: No changes -- skipping", text.Cyan(pkg)))
logger.Warnln(gotext.Get("%s: No changes -- skipping", text.Cyan(pkg)))
continue
}
@ -85,13 +85,13 @@ func gitHasDiff(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) (bo
return lastseen != upstream, nil
}
// If YAY_DIFF_REVIEW does not exists, we have never reviewed a diff for this package
// If AUR_SEEN does not exists, we have never reviewed a diff for this package
// and should display it.
return true, nil
}
// Return whether or not we have reviewed a diff yet. It checks for the existence of
// YAY_DIFF_REVIEW in the git ref-list.
// AUR_SEEN in the git ref-list.
func gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) bool {
_, _, err := cmdBuilder.Capture(
cmdBuilder.BuildGitCmd(ctx,
@ -100,7 +100,7 @@ func gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir stri
return err == nil
}
// Returns the last reviewed hash. If YAY_DIFF_REVIEW exists it will return this hash.
// Returns the last reviewed hash. If AUR_SEEN exists it will return this hash.
// 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) {
if gitHasLastSeenRef(ctx, cmdBuilder, dir) {
@ -119,7 +119,7 @@ func getLastSeenHash(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string
return gitEmptyTree, nil
}
// Update the YAY_DIFF_REVIEW ref to HEAD. We use this ref to determine which diff were
// Update the AUR_SEEN ref to HEAD. We use this ref to determine which diff were
// reviewed by the user.
func gitUpdateSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {
_, stderr, err := cmdBuilder.Capture(
@ -145,7 +145,7 @@ func updatePkgbuildSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgb
return errMulti.Return()
}
func DiffFn(ctx context.Context, config *settings.Configuration, w io.Writer,
func DiffFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
) error {
if len(pkgbuildDirsByBase) == 0 {
@ -157,23 +157,23 @@ func DiffFn(ctx context.Context, config *settings.Configuration, w io.Writer,
bases = append(bases, base)
}
toDiff, errMenu := selectionMenu(w, pkgbuildDirsByBase, bases, installed, gotext.Get("Diffs to show?"),
settings.NoConfirm, config.AnswerDiff, nil)
toDiff, errMenu := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed, gotext.Get("Diffs to show?"),
settings.NoConfirm, run.Cfg.AnswerDiff, nil)
if errMenu != nil || len(toDiff) == 0 {
return errMenu
}
if errD := showPkgbuildDiffs(ctx, config.Runtime.CmdBuilder, pkgbuildDirsByBase, toDiff); errD != nil {
if errD := showPkgbuildDiffs(ctx, run.CmdBuilder, run.Logger, pkgbuildDirsByBase, toDiff); errD != nil {
return errD
}
fmt.Println()
run.Logger.Println()
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
if !run.Logger.ContinueTask(gotext.Get("Proceed with install?"), true, false) {
return settings.ErrUserAbort{}
}
if errUpd := updatePkgbuildSeenRef(ctx, config.Runtime.CmdBuilder, pkgbuildDirsByBase, toDiff); errUpd != nil {
if errUpd := updatePkgbuildSeenRef(ctx, run.CmdBuilder, pkgbuildDirsByBase, toDiff); errUpd != nil {
return errUpd
}

View File

@ -14,6 +14,7 @@ import (
mapset "github.com/deckarep/golang-set/v2"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v12/pkg/runtime"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/text"
)
@ -59,7 +60,7 @@ func editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool)
for {
log.Infoln(gotext.Get("Edit PKGBUILD with?"))
editorInput, err := text.GetInput(os.Stdin, "", noConfirm)
editorInput, err := log.GetInput("", noConfirm)
if err != nil {
log.Errorln(err)
continue
@ -113,7 +114,7 @@ func editPkgbuilds(log *text.Logger, pkgbuildDirs map[string]string, bases []str
return nil
}
func EditFn(ctx context.Context, cfg *settings.Configuration, w io.Writer,
func EditFn(ctx context.Context, run *runtime.Runtime, w io.Writer,
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
) error {
if len(pkgbuildDirsByBase) == 0 {
@ -125,21 +126,21 @@ func EditFn(ctx context.Context, cfg *settings.Configuration, w io.Writer,
bases = append(bases, pkg)
}
toEdit, errMenu := selectionMenu(w, pkgbuildDirsByBase, bases, installed,
gotext.Get("PKGBUILDs to edit?"), settings.NoConfirm, cfg.AnswerEdit, nil)
toEdit, errMenu := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed,
gotext.Get("PKGBUILDs to edit?"), settings.NoConfirm, run.Cfg.AnswerEdit, nil)
if errMenu != nil || len(toEdit) == 0 {
return errMenu
}
// TOFIX: remove or use srcinfo data
if errEdit := editPkgbuilds(cfg.Runtime.Logger, pkgbuildDirsByBase,
toEdit, cfg.Editor, cfg.EditorFlags, nil, settings.NoConfirm); errEdit != nil {
if errEdit := editPkgbuilds(run.Logger, pkgbuildDirsByBase,
toEdit, run.Cfg.Editor, run.Cfg.EditorFlags, nil, settings.NoConfirm); errEdit != nil {
return errEdit
}
cfg.Runtime.Logger.Println()
run.Logger.Println()
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
if !run.Logger.ContinueTask(gotext.Get("Proceed with install?"), true, false) {
return settings.ErrUserAbort{}
}

View File

@ -2,7 +2,6 @@ package menus
import (
"fmt"
"io"
"os"
"github.com/leonelquinteros/gotext"
@ -14,7 +13,9 @@ import (
mapset "github.com/deckarep/golang-set/v2"
)
func pkgbuildNumberMenu(w io.Writer, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string]) {
func pkgbuildNumberMenu(logger *text.Logger, pkgbuildDirs map[string]string,
bases []string, installed mapset.Set[string],
) {
toPrint := ""
for n, pkgBase := range bases {
@ -34,20 +35,20 @@ func pkgbuildNumberMenu(w io.Writer, pkgbuildDirs map[string]string, bases []str
toPrint += "\n"
}
fmt.Fprint(w, toPrint)
logger.Print(toPrint)
}
func selectionMenu(w io.Writer, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string],
func selectionMenu(logger *text.Logger, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string],
message string, noConfirm bool, defaultAnswer string, skipFunc func(string) bool,
) ([]string, error) {
selected := make([]string, 0)
pkgbuildNumberMenu(w, pkgbuildDirs, bases, installed)
pkgbuildNumberMenu(logger, pkgbuildDirs, bases, installed)
text.Infoln(message)
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"))))
logger.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"))))
selectInput, err := text.GetInput(os.Stdin, defaultAnswer, noConfirm)
selectInput, err := logger.GetInput(defaultAnswer, noConfirm)
if err != nil {
return nil, err
}

View File

@ -4,11 +4,9 @@ import (
"bytes"
"context"
"encoding/xml"
"fmt"
"html"
"io"
"net/http"
"os"
"strings"
"time"
@ -23,13 +21,13 @@ type item struct {
Creator string `xml:"dc:creator"`
}
func (item *item) print(buildTime time.Time, all, quiet bool) {
func (item *item) printNews(logger *text.Logger, buildTime time.Time, all, quiet bool) {
var fd string
date, err := time.Parse(time.RFC1123Z, item.PubDate)
if err != nil {
fmt.Fprintln(os.Stderr, err)
logger.Errorln(err)
} else {
fd = text.FormatTime(int(date.Unix()))
if !all && !buildTime.IsZero() {
@ -39,11 +37,11 @@ func (item *item) print(buildTime time.Time, all, quiet bool) {
}
}
fmt.Println(text.Bold(text.Magenta(fd)), text.Bold(strings.TrimSpace(item.Title)))
logger.Println(text.Bold(text.Magenta(fd)), text.Bold(strings.TrimSpace(item.Title)))
if !quiet {
desc := strings.TrimSpace(parseNews(item.Description))
fmt.Println(desc)
logger.Println(desc)
}
}
@ -60,7 +58,9 @@ type rss struct {
Channel channel `xml:"channel"`
}
func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Time, bottomUp, all, quiet bool) error {
func PrintNewsFeed(ctx context.Context, client *http.Client, logger *text.Logger,
cutOffDate time.Time, bottomUp, all, quiet bool,
) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://archlinux.org/feeds/news", http.NoBody)
if err != nil {
return err
@ -87,11 +87,11 @@ func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Tim
if bottomUp {
for i := len(rssGot.Channel.Items) - 1; i >= 0; i-- {
rssGot.Channel.Items[i].print(cutOffDate, all, quiet)
rssGot.Channel.Items[i].printNews(logger, cutOffDate, all, quiet)
}
} else {
for i := 0; i < len(rssGot.Channel.Items); i++ {
rssGot.Channel.Items[i].print(cutOffDate, all, quiet)
rssGot.Channel.Items[i].printNews(logger, cutOffDate, all, quiet)
}
}

View File

@ -8,12 +8,15 @@ import (
"io"
"net/http"
"os"
"strings"
"testing"
"time"
"github.com/bradleyjkemp/cupaloy"
"github.com/stretchr/testify/assert"
"gopkg.in/h2non/gock.v1"
"github.com/Jguer/yay/v12/pkg/text"
)
const lastNews = `
@ -135,17 +138,16 @@ func TestPrintNewsFeed(t *testing.T) {
defer gock.Off()
rescueStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
logger := text.NewLogger(w, w, strings.NewReader(""), false, "logger")
err := PrintNewsFeed(context.Background(), &http.Client{}, tt.args.cutOffDate, tt.args.bottomUp, tt.args.all, tt.args.quiet)
err := PrintNewsFeed(context.Background(), &http.Client{}, logger,
tt.args.cutOffDate, tt.args.bottomUp, tt.args.all, tt.args.quiet)
assert.NoError(t, err)
w.Close()
out, _ := io.ReadAll(r)
cupaloy.SnapshotT(t, out)
os.Stdout = rescueStdout
})
}
}
@ -164,15 +166,14 @@ func TestPrintNewsFeedSameDay(t *testing.T) {
defer gock.Off()
rescueStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
logger := text.NewLogger(w, w, strings.NewReader(""), false, "logger")
err := PrintNewsFeed(context.Background(), &http.Client{}, lastNewsTime, true, false, false)
err := PrintNewsFeed(context.Background(), &http.Client{}, logger,
lastNewsTime, true, false, false)
assert.NoError(t, err)
w.Close()
out, _ := io.ReadAll(r)
cupaloy.SnapshotT(t, out)
os.Stdout = rescueStdout
}

View File

@ -22,9 +22,6 @@ type AURWarnings struct {
}
func NewWarnings(logger *text.Logger) *AURWarnings {
if logger == nil {
logger = text.GlobalLogger
}
return &AURWarnings{log: logger}
}
@ -55,13 +52,17 @@ func (warnings *AURWarnings) AddToWarnings(remote map[string]alpm.IPackage, aurP
}
}
func (warnings *AURWarnings) CalculateMissing(remoteNames []string, remote map[string]alpm.IPackage, aurData map[string]*aur.Pkg) {
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() {
normalMissing, debugMissing := filterDebugPkgs(warnings.Missing)

View File

@ -7,19 +7,19 @@ import (
"github.com/Jguer/yay/v12/pkg/text"
)
func RemoveInvalidTargets(targets []string, mode parser.TargetMode) []string {
func RemoveInvalidTargets(logger *text.Logger, targets []string, mode parser.TargetMode) []string {
filteredTargets := make([]string, 0)
for _, target := range targets {
dbName, _ := text.SplitDBFromName(target)
if dbName == "aur" && !mode.AtLeastAUR() {
text.Warnln(gotext.Get("%s: can't use target with option --repo -- skipping", text.Cyan(target)))
logger.Warnln(gotext.Get("%s: can't use target with option --repo -- skipping", text.Cyan(target)))
continue
}
if dbName != "aur" && dbName != "" && !mode.AtLeastRepo() {
text.Warnln(gotext.Get("%s: can't use target with option --aur -- skipping", text.Cyan(target)))
logger.Warnln(gotext.Get("%s: can't use target with option --aur -- skipping", text.Cyan(target)))
continue
}

View File

@ -130,7 +130,7 @@ func (a *abstractResults) Less(i, j int) bool {
func (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor, pkgS []string) {
var aurErr error
pkgS = RemoveInvalidTargets(pkgS, s.targetMode)
pkgS = RemoveInvalidTargets(s.logger, pkgS, s.targetMode)
metric := &metrics.Hamming{
CaseSensitive: false,
@ -289,7 +289,7 @@ func matchesSearch(pkg *aur.Pkg, terms []string) bool {
desc := strings.ToLower(pkg.Description)
targ := strings.ToLower(pkgN)
if !(strings.Contains(name, targ) || strings.Contains(desc, targ)) {
if !strings.Contains(name, targ) && !strings.Contains(desc, targ) {
return false
}
}

View File

@ -37,7 +37,7 @@ func GetVersionDiff(oldVersion, newVersion string) (left, right string) {
}
for index, char := range oldVersion {
charIsSpecial := !(unicode.IsLetter(char) || unicode.IsNumber(char))
charIsSpecial := !unicode.IsLetter(char) && !unicode.IsNumber(char)
if (index >= len(newVersion)) || (char != rune(newVersion[index])) {
if charIsSpecial {

View File

@ -1,4 +1,4 @@
package settings
package runtime
import (
"fmt"
@ -10,7 +10,7 @@ import (
"golang.org/x/term"
)
func RetrievePacmanConfig(cmdArgs *parser.Arguments, pacmanConfigPath string) (*pacmanconf.Config, bool, error) {
func retrievePacmanConfig(cmdArgs *parser.Arguments, pacmanConfigPath string) (*pacmanconf.Config, bool, error) {
root := "/"
if value, _, exists := cmdArgs.GetArg("root", "r"); exists {
root = value

View File

@ -0,0 +1,66 @@
//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)
}

View File

@ -1,4 +1,4 @@
package settings
package runtime
import (
"context"
@ -9,8 +9,8 @@ import (
"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/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
@ -21,9 +21,12 @@ import (
"github.com/Jguer/aur/rpc"
"github.com/Jguer/votar/pkg/vote"
"github.com/Morganamilo/go-pacmanconf"
"golang.org/x/net/proxy"
)
type Runtime struct {
Cfg *settings.Configuration
QueryBuilder query.Builder
PacmanConf *pacmanconf.Config
VCSStore vcs.Store
@ -31,18 +34,27 @@ type Runtime struct {
HTTPClient *http.Client
VoteClient *vote.Client
AURClient aur.QueryClient
DBExecutor db.Executor
Logger *text.Logger
}
func BuildRuntime(cfg *Configuration, cmdArgs *parser.Arguments, version string) (*Runtime, error) {
func NewRuntime(cfg *settings.Configuration, cmdArgs *parser.Arguments, version string) (*Runtime, error) {
logger := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, cfg.Debug, "runtime")
cmdBuilder := cfg.CmdBuilder(nil)
runner := exe.NewOSRunner(logger.Child("runner"))
transport := http.DefaultTransport.(*http.Transport).Clone()
if socks5_proxy := os.Getenv("SOCKS5_PROXY"); socks5_proxy != "" {
dialer, err := proxy.SOCKS5("tcp", socks5_proxy, nil, proxy.Direct)
if err != nil {
return nil, err
}
transport = &http.Transport{Dial: dialer.Dial}
}
httpClient := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
Transport: transport,
}
userAgent := fmt.Sprintf("Yay/%s", version)
@ -86,6 +98,16 @@ func BuildRuntime(cfg *Configuration, cmdArgs *parser.Arguments, version string)
aurCache = aurClient
}
pacmanConf, useColor, err := retrievePacmanConfig(cmdArgs, cfg.PacmanConf)
if err != nil {
return nil, err
}
// FIXME: get rid of global
text.UseColor = useColor
cmdBuilder := exe.NewCmdBuilder(cfg, runner, logger.Child("cmdbuilder"), pacmanConf.DBPath)
vcsStore := vcs.NewInfoStore(
cfg.VCSFilePath, cmdBuilder,
logger.Child("vcs"))
@ -94,17 +116,23 @@ func BuildRuntime(cfg *Configuration, cmdArgs *parser.Arguments, version string)
return nil, err
}
runtime := &Runtime{
QueryBuilder: nil,
PacmanConf: nil,
queryBuilder := query.NewSourceQueryBuilder(
aurClient,
logger.Child("mixed.querybuilder"), cfg.SortBy,
cfg.Mode, cfg.SearchBy,
cfg.BottomUp, cfg.SingleLineResults, cfg.SeparateSources)
run := &Runtime{
Cfg: cfg,
QueryBuilder: queryBuilder,
PacmanConf: pacmanConf,
VCSStore: vcsStore,
CmdBuilder: cmdBuilder,
HTTPClient: &http.Client{},
VoteClient: voteClient,
AURClient: aurCache,
DBExecutor: nil,
Logger: text.NewLogger(os.Stdout, os.Stderr, os.Stdin, cfg.Debug, "runtime"),
Logger: logger,
}
return runtime, nil
return run, nil
}

View File

@ -1,20 +1,27 @@
//go:build !integration
// +build !integration
package settings_test
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"
"github.com/Jguer/yay/v12/pkg/text"
)
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,
@ -23,24 +30,23 @@ func TestBuildRuntime(t *testing.T) {
AURRPCURL: "https://aur.archlinux.org/rpc",
BuildDir: "/tmp",
VCSFilePath: "",
Runtime: &settings.Runtime{Logger: text.NewLogger(nil, nil, nil, false, "")},
PacmanConf: absPath,
}
cmdArgs := parser.MakeArguments()
version := "1.0.0"
// Call the function being tested
runtime, err := settings.BuildRuntime(cfg, cmdArgs, version)
run, err := runtime.NewRuntime(cfg, cmdArgs, version)
require.NoError(t, err)
// Assert the function's output
assert.NotNil(t, runtime)
assert.Nil(t, err)
assert.Nil(t, runtime.QueryBuilder)
assert.Nil(t, runtime.PacmanConf)
assert.NotNil(t, runtime.VCSStore)
assert.NotNil(t, runtime.CmdBuilder)
assert.NotNil(t, runtime.HTTPClient)
assert.NotNil(t, runtime.VoteClient)
assert.NotNil(t, runtime.AURClient)
assert.Nil(t, runtime.DBExecutor)
assert.NotNil(t, runtime.Logger)
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)
}

View File

@ -5,7 +5,6 @@ import (
"strings"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
)
func (c *Configuration) ParseCommandLine(a *parser.Arguments) error {
@ -15,9 +14,6 @@ func (c *Configuration) ParseCommandLine(a *parser.Arguments) error {
c.extractYayOptions(a)
// Reload CmdBuilder
c.Runtime.CmdBuilder = c.CmdBuilder(nil)
return nil
}
@ -46,29 +42,29 @@ func (c *Configuration) extractYayOptions(a *parser.Arguments) {
}
func (c *Configuration) handleOption(option, value string) bool {
boolValue, err := strconv.ParseBool(value)
if err != nil {
boolValue = true
}
switch option {
case "aururl":
c.AURURL = value
case "aurrpcurl":
c.AURRPCURL = value
case "save":
c.SaveConfig = true
c.SaveConfig = boolValue
case "afterclean", "cleanafter":
c.CleanAfter = true
case "noafterclean", "nocleanafter":
c.CleanAfter = false
c.CleanAfter = boolValue
case "keepsrc":
c.KeepSrc = boolValue
case "debug":
c.Debug = true
text.GlobalLogger.Debug = true
return false
c.Debug = boolValue
return !boolValue
case "devel":
c.Devel = true
case "nodevel":
c.Devel = false
c.Devel = boolValue
case "timeupdate":
c.TimeUpdate = true
case "notimeupdate":
c.TimeUpdate = false
c.TimeUpdate = boolValue
case "topdown":
c.BottomUp = false
case "bottomup":
@ -87,7 +83,7 @@ func (c *Configuration) handleOption(option, value string) bool {
case "searchby":
c.SearchBy = value
case "noconfirm":
NoConfirm = true
NoConfirm = boolValue
case "config":
c.PacmanConf = value
case "redownload":
@ -105,9 +101,7 @@ func (c *Configuration) handleOption(option, value string) bool {
case "norebuild":
c.ReBuild = parser.RebuildModeNo
case "batchinstall":
c.BatchInstall = true
case "nobatchinstall":
c.BatchInstall = false
c.BatchInstall = boolValue
case "answerclean":
c.AnswerClean = value
case "noanswerclean":
@ -158,40 +152,24 @@ func (c *Configuration) handleOption(option, value string) bool {
c.RequestSplitN = n
}
case "sudoloop":
c.SudoLoop = true
case "nosudoloop":
c.SudoLoop = false
c.SudoLoop = boolValue
case "provides":
c.Provides = true
case "noprovides":
c.Provides = false
c.Provides = boolValue
case "pgpfetch":
c.PGPFetch = true
case "nopgpfetch":
c.PGPFetch = false
c.PGPFetch = boolValue
case "cleanmenu":
c.CleanMenu = true
case "nocleanmenu":
c.CleanMenu = false
c.CleanMenu = boolValue
case "diffmenu":
c.DiffMenu = true
case "nodiffmenu":
c.DiffMenu = false
c.DiffMenu = boolValue
case "editmenu":
c.EditMenu = true
case "noeditmenu":
c.EditMenu = false
c.EditMenu = boolValue
case "useask":
c.UseAsk = true
case "nouseask":
c.UseAsk = false
c.UseAsk = boolValue
case "combinedupgrade":
c.CombinedUpgrade = true
case "nocombinedupgrade":
c.CombinedUpgrade = false
c.CombinedUpgrade = boolValue
case "a", "aur":
c.Mode = parser.ModeAUR
case "repo":
case "N", "repo":
c.Mode = parser.ModeRepo
case "removemake":
c.RemoveMake = "yes"
@ -202,9 +180,7 @@ func (c *Configuration) handleOption(option, value string) bool {
case "askyesremovemake":
c.RemoveMake = "askyes"
case "separatesources":
c.SeparateSources = true
case "noseparatesources":
c.SeparateSources = false
c.SeparateSources = boolValue
default:
return false
}

View File

@ -9,7 +9,6 @@ import (
"path/filepath"
"strings"
"github.com/Jguer/yay/v12/pkg/settings/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
@ -24,7 +23,6 @@ var NoConfirm = false
// Configuration stores yay's config.
type Configuration struct {
Runtime *Runtime `json:"-"`
AURURL string `json:"aururl"`
AURRPCURL string `json:"aurrpcurl"`
BuildDir string `json:"buildDir"`
@ -58,6 +56,7 @@ type Configuration struct {
TimeUpdate bool `json:"timeupdate"`
Devel bool `json:"devel"`
CleanAfter bool `json:"cleanAfter"`
KeepSrc bool `json:"keepSrc"`
Provides bool `json:"provides"`
PGPFetch bool `json:"pgpfetch"`
CleanMenu bool `json:"cleanmenu"`
@ -195,6 +194,7 @@ func DefaultConfig(version string) *Configuration {
AURURL: "https://aur.archlinux.org",
BuildDir: os.ExpandEnv("$HOME/.cache/yay"),
CleanAfter: false,
KeepSrc: false,
Editor: "",
EditorFlags: "",
Devel: false,
@ -208,7 +208,7 @@ func DefaultConfig(version string) *Configuration {
GitFlags: "",
BottomUp: true,
CompletionInterval: 7,
MaxConcurrentDownloads: 0,
MaxConcurrentDownloads: 1,
SortBy: "votes",
SearchBy: "name-desc",
SudoLoop: false,
@ -237,19 +237,16 @@ func DefaultConfig(version string) *Configuration {
Debug: false,
UseRPC: true,
DoubleConfirm: true,
Runtime: &Runtime{
Logger: text.GlobalLogger,
},
Mode: parser.ModeAny,
}
}
func NewConfig(configPath, version string) (*Configuration, error) {
func NewConfig(logger *text.Logger, configPath, version string) (*Configuration, error) {
newConfig := DefaultConfig(version)
cacheHome, errCache := getCacheHome()
if errCache != nil {
text.Errorln(errCache)
if errCache != nil && logger != nil {
logger.Errorln(errCache)
}
newConfig.BuildDir = cacheHome
@ -295,27 +292,3 @@ 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"),
}
}

View File

@ -36,7 +36,7 @@ func TestNewConfig(t *testing.T) {
_, err = f.WriteString(string(configJSON))
assert.NoError(t, err)
newConfig, err := NewConfig(GetConfigPath(), "v1.0.0")
newConfig, err := NewConfig(nil, GetConfigPath(), "v1.0.0")
assert.NoError(t, err)
assert.Equal(t, filepath.Join(cacheDir, "test-build-dir"), newConfig.BuildDir)
@ -69,7 +69,7 @@ func TestNewConfigAURDEST(t *testing.T) {
_, err = f.WriteString(string(configJSON))
assert.NoError(t, err)
newConfig, err := NewConfig(GetConfigPath(), "v1.0.0")
newConfig, err := NewConfig(nil, GetConfigPath(), "v1.0.0")
assert.NoError(t, err)
assert.Equal(t, filepath.Join(cacheDir, "test-build-dir"), newConfig.BuildDir)
@ -102,7 +102,7 @@ func TestNewConfigAURDESTTildeExpansion(t *testing.T) {
_, err = f.WriteString(string(configJSON))
assert.NoError(t, err)
newConfig, err := NewConfig(GetConfigPath(), "v1.0.0")
newConfig, err := NewConfig(nil, GetConfigPath(), "v1.0.0")
assert.NoError(t, err)
assert.Equal(t, filepath.Join(homeDir, "test-build-dir"), newConfig.BuildDir)

View File

@ -15,6 +15,7 @@ import (
mapset "github.com/deckarep/golang-set/v2"
"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/text"
)
@ -38,7 +39,7 @@ type ICmdBuilder interface {
BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
AddMakepkgFlag(string)
SetPacmanDBPath(string)
GetKeepSrc() bool
SudoLoop()
}
@ -56,10 +57,32 @@ type CmdBuilder struct {
PacmanBin string
PacmanConfigPath string
PacmanDBPath string
KeepSrc bool
Runner Runner
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 {
args := make([]string, len(c.GPGFlags), len(c.GPGFlags)+len(extraArgs))
copy(args, c.GPGFlags)
@ -135,10 +158,6 @@ func (c *CmdBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs
return cmd
}
func (c *CmdBuilder) SetPacmanDBPath(dbPath string) {
c.PacmanDBPath = dbPath
}
// deElevateCommand, `systemd-run` code based on pikaur.
func (c *CmdBuilder) deElevateCommand(ctx context.Context, cmd *exec.Cmd) *exec.Cmd {
if os.Geteuid() != 0 {
@ -154,12 +173,13 @@ func (c *CmdBuilder) deElevateCommand(ctx context.Context, cmd *exec.Cmd) *exec.
if userFound, err := user.Lookup(ogCaller); err == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
uid, _ := strconv.Atoi(userFound.Uid)
gid, _ := strconv.Atoi(userFound.Gid)
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
uid64, errUid := strconv.ParseUint(userFound.Uid, 10, 32)
gid64, errGid := strconv.ParseUint(userFound.Gid, 10, 32)
if errUid == nil && errGid == nil {
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid64), Gid: uint32(gid64)}
return cmd
}
}
cmdArgs := []string{
"--service-type=oneshot",
@ -242,7 +262,7 @@ func (c *CmdBuilder) waitLock(dbPath string) {
time.Sleep(3 * time.Second)
if _, err := os.Stat(lockDBPath); err != nil {
fmt.Println()
c.Log.Println()
return
}
@ -280,3 +300,7 @@ func (c *CmdBuilder) Show(cmd *exec.Cmd) error {
func (c *CmdBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
return c.Runner.Capture(cmd)
}
func (c *CmdBuilder) GetKeepSrc() bool {
return c.KeepSrc
}

View File

@ -19,6 +19,10 @@ type OSRunner struct {
Log *text.Logger
}
func NewOSRunner(log *text.Logger) *OSRunner {
return &OSRunner{log}
}
func (r *OSRunner) Show(cmd *exec.Cmd) error {
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{

View File

@ -25,6 +25,7 @@ type MockBuilder struct {
BuildMakepkgCmdCalls []Call
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
GetKeepSrcFn func() bool
}
type MockRunner struct {
@ -36,6 +37,10 @@ type MockRunner struct {
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 {
var res *exec.Cmd
if m.BuildMakepkgCmdFn != nil {
@ -91,6 +96,10 @@ func (m *MockBuilder) Show(cmd *exec.Cmd) error {
return m.Runner.Show(cmd)
}
func (m *MockBuilder) GetKeepSrc() bool {
return false
}
func (m *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
m.CaptureCallsMu.Lock()
m.CaptureCalls = append(m.CaptureCalls, Call{

View File

@ -45,7 +45,7 @@ func DefaultMigrations() []configMigration {
}
}
func (c *Configuration) RunMigrations(migrations []configMigration,
func (c *Configuration) RunMigrations(logger *text.Logger, migrations []configMigration,
configPath, newVersion string,
) error {
saveConfig := false
@ -53,7 +53,7 @@ func (c *Configuration) RunMigrations(migrations []configMigration,
for _, migration := range migrations {
if db.VerCmp(migration.TargetVersion(), c.Version) > 0 {
if migration.Do(c) {
text.Infoln("Config migration executed (",
logger.Infoln("Config migration executed (",
migration.TargetVersion(), "):", migration)
saveConfig = true

View File

@ -16,6 +16,10 @@ import (
"github.com/Jguer/yay/v12/pkg/text"
)
func newTestLogger() *text.Logger {
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
}
func TestMigrationNothingToDo(t *testing.T) {
t.Parallel()
// Create temporary file for config
@ -28,13 +32,10 @@ func TestMigrationNothingToDo(t *testing.T) {
config := Configuration{
Version: "99.0.0",
// Create runtime with runtimeVersion
Runtime: &Runtime{
Logger: text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), false, "test"),
},
}
// Run Migration
err = config.RunMigrations(DefaultMigrations(), testFilePath, "20.0.0")
err = config.RunMigrations(newTestLogger(), DefaultMigrations(), testFilePath, "20.0.0")
require.NoError(t, err)
// Check file contents if wantSave otherwise check file empty
@ -53,9 +54,6 @@ func TestProvidesMigrationDo(t *testing.T) {
migration := &configProviderMigration{}
config := Configuration{
Provides: true,
Runtime: &Runtime{
Logger: text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), false, "test"),
},
}
assert.True(t, migration.Do(&config))
@ -135,13 +133,10 @@ func TestProvidesMigration(t *testing.T) {
Version: tc.testConfig.Version,
Provides: tc.testConfig.Provides,
// Create runtime with runtimeVersion
Runtime: &Runtime{
Logger: text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), false, "test"),
},
}
// Run Migration
err = tcConfig.RunMigrations(
err = tcConfig.RunMigrations(newTestLogger(),
[]configMigration{&configProviderMigration{}},
testFilePath, tc.newVersion)

View File

@ -1,54 +0,0 @@
//go:build !integration
// +build !integration
package settings
import (
"testing"
"github.com/Morganamilo/go-pacmanconf"
"github.com/stretchr/testify/assert"
"github.com/Jguer/yay/v12/pkg/settings/parser"
)
func TestPacmanConf(t *testing.T) {
t.Parallel()
expectedPacmanConf := &pacmanconf.Config{
RootDir: "/",
DBPath: "//var/lib/pacman/",
CacheDir: []string{"/cachedir/", "/another/"},
HookDir: []string{"/hookdir/"},
GPGDir: "/gpgdir/",
LogFile: "/logfile",
HoldPkg: []string(nil),
IgnorePkg: []string{"ignore", "this", "package"},
IgnoreGroup: []string{"ignore", "this", "group"},
Architecture: []string{"8086"},
XferCommand: "",
NoUpgrade: []string{"noupgrade"},
NoExtract: []string{"noextract"},
CleanMethod: []string{"KeepInstalled"},
SigLevel: []string{"PackageOptional", "PackageTrustedOnly", "DatabaseOptional", "DatabaseTrustedOnly"},
LocalFileSigLevel: []string(nil),
RemoteFileSigLevel: []string(nil),
UseSyslog: false,
Color: false,
UseDelta: 0,
TotalDownload: false,
CheckSpace: true,
VerbosePkgLists: true,
DisableDownloadTimeout: false,
Repos: []pacmanconf.Repository{
{Name: "repo1", Servers: []string{"repo1"}, SigLevel: []string(nil), Usage: []string{"All"}},
{Name: "repo2", Servers: []string{"repo2"}, SigLevel: []string(nil), Usage: []string{"All"}},
},
}
pacmanConf, color, err := RetrievePacmanConfig(parser.MakeArguments(), "../../testdata/pacman.conf")
assert.Nil(t, err)
assert.NotNil(t, pacmanConf)
assert.Equal(t, color, false)
assert.EqualValues(t, expectedPacmanConf, pacmanConf)
}

View File

@ -25,7 +25,7 @@ func (o *Option) Add(args ...string) {
}
func (o *Option) First() string {
if o.Args == nil || len(o.Args) == 0 {
if len(o.Args) == 0 {
return ""
}
@ -372,16 +372,15 @@ func isArg(arg string) bool {
case "y", "refresh":
case "x", "regex":
case "machinereadable":
case "disable-sandbox":
// yay options
case "aururl":
case "aurrpcurl":
case "save":
case "afterclean", "cleanafter":
case "noafterclean", "nocleanafter":
case "keepsrc":
case "devel":
case "nodevel":
case "timeupdate":
case "notimeupdate":
case "topdown":
case "bottomup":
case "completioninterval":
@ -395,7 +394,6 @@ func isArg(arg string) bool {
case "rebuildtree":
case "norebuild":
case "batchinstall":
case "nobatchinstall":
case "answerclean":
case "noanswerclean":
case "answerdiff":
@ -420,23 +418,15 @@ func isArg(arg string) bool {
case "sudoflags":
case "requestsplitn":
case "sudoloop":
case "nosudoloop":
case "provides":
case "noprovides":
case "pgpfetch":
case "nopgpfetch":
case "cleanmenu":
case "nocleanmenu":
case "diffmenu":
case "nodiffmenu":
case "editmenu":
case "noeditmenu":
case "useask":
case "nouseask":
case "combinedupgrade":
case "nocombinedupgrade":
case "a", "aur":
case "repo":
case "N", "repo":
case "removemake":
case "noremovemake":
case "askremovemake":
@ -449,7 +439,7 @@ func isArg(arg string) bool {
case "defaultconfig":
case "singlelineresults":
case "doublelineresults":
case "separatesources", "noseparatesources":
case "separatesources":
default:
return false
}
@ -575,7 +565,6 @@ func (a *Arguments) parseShortOption(arg, param string) (usedNext bool, err erro
break
} else {
err = a.AddArg(char)
if err != nil {
return
}

67
pkg/sync/build/errors.go Normal file
View File

@ -0,0 +1,67 @@
package build
import (
"errors"
"strings"
"github.com/leonelquinteros/gotext"
)
var ErrInstallRepoPkgs = errors.New(gotext.Get("error installing repo packages"))
type FailedIgnoredPkgError struct {
pkgErrors map[string]error
}
func (e *FailedIgnoredPkgError) Error() string {
var sb strings.Builder
sb.WriteString(gotext.Get("Failed to install the following packages. Manual intervention is required:"))
for pkg, err := range e.pkgErrors {
sb.WriteString("\n")
sb.WriteString(pkg)
sb.WriteString(" - ")
sb.WriteString(err.Error())
}
return sb.String()
}
type PkgDestNotInListError struct {
name string
}
func (e *PkgDestNotInListError) Error() string {
return gotext.Get("could not find PKGDEST for: %s", e.name)
}
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 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 NoPkgDestsFoundError struct {
dir string
}
func (e *NoPkgDestsFoundError) Error() string {
return gotext.Get("could not find any package archives listed in %s", e.dir)
}

View File

@ -1,4 +1,4 @@
package main
package build
import (
"context"
@ -54,12 +54,12 @@ func NewInstaller(dbExecutor db.Executor,
}
}
func (installer *Installer) CompileFailedAndIgnored() error {
func (installer *Installer) CompileFailedAndIgnored() (map[string]error, error) {
if len(installer.failedAndIgnored) == 0 {
return nil
return installer.failedAndIgnored, nil
}
return &FailedIgnoredPkgError{
return installer.failedAndIgnored, &FailedIgnoredPkgError{
pkgErrors: installer.failedAndIgnored,
}
}
@ -145,16 +145,20 @@ func (installer *Installer) handleLayer(ctx context.Context,
excluded []string,
) error {
// Install layer
nameToBaseMap := make(map[string]string, 0)
nameToBaseMap := make(map[string]string, len(layer))
syncDeps, syncExp, syncGroups := 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
for name, info := range layer {
switch info.Source {
case dep.AUR, dep.SrcInfo:
nameToBaseMap[name] = *info.AURBase
if installer.origTargets.Contains(name) {
aurOrigTargetBases.Add(*info.AURBase)
}
switch info.Reason {
case dep.Explicit:
@ -201,14 +205,15 @@ func (installer *Installer) handleLayer(ctx context.Context,
}
errAur := installer.installAURPackages(ctx, cmdArgs, aurDeps, aurExp,
nameToBaseMap, pkgBuildDirs, true, lastLayer, installer.appendNoConfirm())
aurOrigTargetBases, nameToBaseMap, pkgBuildDirs, true, lastLayer,
installer.appendNoConfirm())
return errAur
}
func (installer *Installer) installAURPackages(ctx context.Context,
cmdArgs *parser.Arguments,
aurDepNames, aurExpNames mapset.Set[string],
aurDepNames, aurExpNames, aurOrigTargetBases mapset.Set[string],
nameToBase, pkgBuildDirsByBase map[string]string,
installIncompatible bool,
lastLayer bool,
@ -219,27 +224,37 @@ func (installer *Installer) installAURPackages(ctx context.Context,
return nil
}
deps, exps := make([]string, 0, aurDepNames.Cardinality()), make([]string, 0, aurExpNames.Cardinality())
pkgArchives := make([]string, 0, len(exps)+len(deps))
builtPkgDests := make(map[string]map[string]string)
deps := make([]string, 0, aurDepNames.Cardinality())
exps := make([]string, 0, aurExpNames.Cardinality())
pkgArchives := make([]string, 0, len(all))
for _, name := range all {
base := nameToBase[name]
dir := pkgBuildDirsByBase[base]
pkgdests, errMake := installer.buildPkg(ctx, dir, base,
installIncompatible, cmdArgs.ExistsArg("needed"), installer.origTargets.Contains(name))
pkgdests, ok := builtPkgDests[base]
if ok {
installer.log.Debugln("skipping built pkgbase", base, "package", name)
} else {
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
text.Errorln(gotext.Get("error making: %s", base), "-", errMake)
installer.log.Errorln(gotext.Get("error making: %s", base), "-", errMake)
continue
}
}
if len(pkgdests) == 0 {
text.Warnln(gotext.Get("nothing to install for %s", text.Cyan(base)))
installer.log.Warnln(gotext.Get("nothing to install for %s", text.Cyan(base)))
continue
}
@ -277,7 +292,11 @@ func (installer *Installer) buildPkg(ctx context.Context,
dir, base string,
installIncompatible, needed, isTarget bool,
) (map[string]string, error) {
args := []string{"--nobuild", "-fC"}
args := []string{"--nobuild", "-f"}
if !installer.exeCmd.GetKeepSrc() {
args = append(args, "-C")
}
if installIncompatible {
args = append(args, "--ignorearch")
@ -296,19 +315,23 @@ func (installer *Installer) buildPkg(ctx context.Context,
switch {
case needed && installer.pkgsAreAlreadyInstalled(pkgdests, pkgVersion) || installer.downloadOnly:
args = []string{"-c", "--nobuild", "--noextract", "--ignorearch"}
args = []string{"--nobuild", "--noextract", "--ignorearch"}
pkgdests = map[string]string{}
text.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(base+"-"+pkgVersion)))
installer.log.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(base+"-"+pkgVersion)))
case installer.skipAlreadyBuiltPkg(isTarget, pkgdests):
args = []string{"-c", "--nobuild", "--noextract", "--ignorearch"}
text.Warnln(gotext.Get("%s already made -- skipping build", text.Cyan(base+"-"+pkgVersion)))
args = []string{"--nobuild", "--noextract", "--ignorearch"}
installer.log.Warnln(gotext.Get("%s already made -- skipping build", text.Cyan(base+"-"+pkgVersion)))
default:
args = []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
args = []string{"-f", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
if installIncompatible {
args = append(args, "--ignorearch")
}
}
if !installer.exeCmd.GetKeepSrc() {
args = append(args, "-c")
}
errMake := installer.exeCmd.Show(
installer.exeCmd.BuildMakepkgCmd(ctx,
dir, args...))
@ -333,10 +356,10 @@ func (installer *Installer) pkgsAreAlreadyInstalled(pkgdests map[string]string,
return true
}
func pkgsAreBuilt(pkgdests map[string]string) bool {
func pkgsAreBuilt(logger *text.Logger, pkgdests map[string]string) bool {
for _, pkgdest := range pkgdests {
if _, err := os.Stat(pkgdest); err != nil {
text.Debugln("pkgIsBuilt:", pkgdest, "does not exist")
logger.Debugln("pkgIsBuilt:", pkgdest, "does not exist")
return false
}
}
@ -347,14 +370,14 @@ func pkgsAreBuilt(pkgdests map[string]string) bool {
func (installer *Installer) skipAlreadyBuiltPkg(isTarget bool, pkgdests map[string]string) bool {
switch installer.rebuildMode {
case parser.RebuildModeNo:
return pkgsAreBuilt(pkgdests)
return pkgsAreBuilt(installer.log, pkgdests)
case parser.RebuildModeYes:
return !isTarget && pkgsAreBuilt(pkgdests)
return !isTarget && pkgsAreBuilt(installer.log, pkgdests)
// case parser.RebuildModeTree: // TODO
// case parser.RebuildModeAll: // TODO
default:
// same as RebuildModeNo
return pkgsAreBuilt(pkgdests)
return pkgsAreBuilt(installer.log, pkgdests)
}
}

View File

@ -1,4 +1,4 @@
package main
package build
import (
"context"
@ -21,7 +21,7 @@ import (
"github.com/Jguer/yay/v12/pkg/vcs"
)
func NewTestLogger() *text.Logger {
func newTestLogger() *text.Logger {
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
}
@ -56,8 +56,8 @@ func TestInstaller_InstallNeeded(t *testing.T) {
isInstalled: false,
isBuilt: false,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
"pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
"pacman -D -q --asexplicit --config -- yay",
},
@ -68,7 +68,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
isInstalled: false,
isBuilt: true,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst",
"pacman -D -q --asexplicit --config -- yay",
@ -80,7 +80,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
isInstalled: true,
isBuilt: false,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
},
wantCapture: []string{"makepkg --packagelist"},
@ -134,7 +134,7 @@ func TestInstaller_InstallNeeded(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
parser.RebuildModeNo, false, NewTestLogger())
parser.RebuildModeNo, false, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddArg("needed")
@ -212,8 +212,8 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
wantShow: []string{
"pacman -S --config /etc/pacman.conf -- core/linux",
"pacman -D -q --asdeps --config /etc/pacman.conf -- linux",
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
"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",
},
@ -241,8 +241,8 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
wantShow: []string{
"pacman -S --config /etc/pacman.conf -- core/linux",
"pacman -D -q --asdeps --config /etc/pacman.conf -- linux",
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
"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",
},
@ -293,10 +293,10 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
{
desc: "same layer -- aur",
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --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 -D -q --asexplicit --config /etc/pacman.conf -- yay",
},
@ -323,12 +323,12 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
{
desc: "different layer -- aur",
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --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 -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server",
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --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 -D -q --asexplicit --config /etc/pacman.conf -- yay",
},
@ -374,13 +374,13 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
}
showOverride := func(cmd *exec.Cmd) error {
if strings.Contains(cmd.String(), "makepkg -cf --noconfirm") && cmd.Dir == tmpDir {
if strings.Contains(cmd.String(), "makepkg -f --noconfirm") && cmd.Dir == tmpDir {
f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
require.NoError(td, err)
require.NoError(td, f.Close())
}
if strings.Contains(cmd.String(), "makepkg -cf --noconfirm") && cmd.Dir == tmpDirJfin {
if strings.Contains(cmd.String(), "makepkg -f --noconfirm") && cmd.Dir == tmpDirJfin {
f, err := os.OpenFile(jfinPkgTar, os.O_RDONLY|os.O_CREATE, 0o666)
require.NoError(td, err)
require.NoError(td, f.Close())
@ -408,7 +408,7 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, parser.RebuildModeNo, false, NewTestLogger())
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, parser.RebuildModeNo, false, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddTarget("yay")
@ -462,7 +462,7 @@ func TestInstaller_RunPostHooks(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
parser.RebuildModeNo, false, NewTestLogger())
parser.RebuildModeNo, false, newTestLogger())
called := false
hook := func(ctx context.Context) error {
@ -570,7 +570,7 @@ func TestInstaller_CompileFailed(t *testing.T) {
}
showOverride := func(cmd *exec.Cmd) error {
if tc.failBuild && strings.Contains(cmd.String(), "makepkg -cf --noconfirm") && cmd.Dir == tmpDir {
if tc.failBuild && strings.Contains(cmd.String(), "makepkg -f --noconfirm") && cmd.Dir == tmpDir {
return errors.New("makepkg failed")
}
return nil
@ -593,7 +593,7 @@ func TestInstaller_CompileFailed(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
parser.RebuildModeNo, false, NewTestLogger())
parser.RebuildModeNo, false, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddArg("needed")
@ -609,10 +609,21 @@ func TestInstaller_CompileFailed(t *testing.T) {
} else {
require.NoError(td, errI)
}
err := installer.CompileFailedAndIgnored()
failed, err := installer.CompileFailedAndIgnored()
if tc.wantErrCompile {
require.Error(td, err)
assert.ErrorContains(td, err, "yay")
for key := range failed {
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 {
require.NoError(td, err)
}
@ -693,18 +704,16 @@ func TestInstaller_InstallSplitPackage(t *testing.T) {
wantShow: []string{
"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",
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"makepkg --nobuild -fC --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -f -c --noconfirm --noextract --noprepare --holdver --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 -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server jellyfin-web",
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
"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",
},
wantCapture: []string{"makepkg --packagelist", "makepkg --packagelist", "makepkg --packagelist"},
wantCapture: []string{"makepkg --packagelist", "makepkg --packagelist"},
},
}
@ -752,7 +761,7 @@ func TestInstaller_InstallSplitPackage(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
parser.RebuildModeNo, false, NewTestLogger())
parser.RebuildModeNo, false, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddTarget("jellyfin")
@ -817,7 +826,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
isInstalled: false,
isBuilt: false,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
},
wantCapture: []string{"makepkg --packagelist"},
@ -827,7 +836,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
isInstalled: false,
isBuilt: true,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
},
wantCapture: []string{"makepkg --packagelist"},
@ -837,7 +846,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
isInstalled: true,
isBuilt: false,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg --nobuild -f -C --ignorearch",
"makepkg -c --nobuild --noextract --ignorearch",
},
wantCapture: []string{"makepkg --packagelist"},
@ -891,7 +900,7 @@ func TestInstaller_InstallDownloadOnly(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
parser.RebuildModeNo, true, NewTestLogger())
parser.RebuildModeNo, true, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddTarget("yay")
@ -995,7 +1004,7 @@ func TestInstaller_InstallGroup(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
parser.RebuildModeNo, true, NewTestLogger())
parser.RebuildModeNo, true, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddTarget("kubernetes-tools")
@ -1074,7 +1083,7 @@ func TestInstaller_InstallRebuild(t *testing.T) {
isBuilt: true,
isInstalled: false,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"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",
@ -1098,8 +1107,8 @@ func TestInstaller_InstallRebuild(t *testing.T) {
isBuilt: true,
isInstalled: false,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"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",
},
@ -1122,8 +1131,8 @@ func TestInstaller_InstallRebuild(t *testing.T) {
isInstalled: true,
isBuilt: true,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"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",
},
@ -1146,8 +1155,8 @@ func TestInstaller_InstallRebuild(t *testing.T) {
isInstalled: true,
isBuilt: true,
wantShow: []string{
"makepkg --nobuild -fC --ignorearch",
"makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch",
"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",
},
@ -1213,7 +1222,7 @@ func TestInstaller_InstallRebuild(t *testing.T) {
cmdBuilder.Runner = mockRunner
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,
tc.rebuildOption, false, NewTestLogger())
tc.rebuildOption, false, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddTarget("yay")
@ -1298,7 +1307,7 @@ func TestInstaller_InstallUpgrade(t *testing.T) {
}
installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, tc.targetMode,
parser.RebuildModeNo, false, NewTestLogger())
parser.RebuildModeNo, false, newTestLogger())
cmdArgs := parser.MakeArguments()
cmdArgs.AddArg("u", "upgrades") // Make sure both args are removed
@ -1336,3 +1345,107 @@ func TestInstaller_InstallUpgrade(t *testing.T) {
})
}
}
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")
}
}
})
}
}

View File

@ -1,4 +1,4 @@
package main
package build
import (
"context"
@ -16,164 +16,6 @@ import (
"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)
}
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 earlyRefresh(ctx context.Context, cfg *settings.Configuration, cmdBuilder exe.ICmdBuilder, cmdArgs *parser.Arguments) error {
arguments := cmdArgs.Copy()
if cfg.CombinedUpgrade {
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 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 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 installPkgArchive(ctx context.Context,
cmdBuilder exe.ICmdBuilder,
mode parser.TargetMode,
@ -228,3 +70,95 @@ func setInstallReason(ctx context.Context,
return asexp(ctx, cmdBuilder, mode, cmdArgs, exps)
}
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)
}
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, len(lines))
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
}

View File

@ -0,0 +1,167 @@
package build
import (
"context"
"fmt"
"os/exec"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/Jguer/yay/v12/pkg/settings/exe"
)
func TestParsePackageList(t *testing.T) {
t.Parallel()
type testCase struct {
desc string
mockStdout string
mockStderr string
mockErr error
wantPkgDests map[string]string
wantPkgVersion string
wantErr bool
wantErrText string // Optional: specific error text to check
}
testCases := []testCase{
{
desc: "Standard package",
mockStdout: "/path/to/package-1.2.3-4-x86_64.pkg.tar.zst\n",
wantPkgDests: map[string]string{
"package": "/path/to/package-1.2.3-4-x86_64.pkg.tar.zst",
},
wantPkgVersion: "1.2.3-4",
wantErr: false,
},
{
desc: "Package with dash in name",
mockStdout: "/path/to/package-name-with-dash-1.0.0-1-any.pkg.tar.gz\n",
wantPkgDests: map[string]string{
"package-name-with-dash": "/path/to/package-name-with-dash-1.0.0-1-any.pkg.tar.gz",
},
wantPkgVersion: "1.0.0-1",
wantErr: false, // This should fail with current logic but pass with regex
},
{
desc: "Multiple packages",
mockStdout: "/path/to/pkg1-1.0-1-x86_64.pkg.tar.zst\n/other/path/pkg2-2.5-3-any.pkg.tar.xz\n",
wantPkgDests: map[string]string{
"pkg1": "/path/to/pkg1-1.0-1-x86_64.pkg.tar.zst",
"pkg2": "/other/path/pkg2-2.5-3-any.pkg.tar.xz",
},
wantPkgVersion: "2.5-3", // Version of the last package processed
wantErr: false,
},
{
desc: "Empty input",
mockStdout: "",
wantErr: true, // Expect NoPkgDestsFoundError
},
{
desc: "Input with only newline",
mockStdout: "\n",
wantErr: true, // Expect NoPkgDestsFoundError
},
{
desc: "Makepkg error",
mockStderr: "makepkg failed",
mockErr: fmt.Errorf("exit status 1"),
wantErr: true,
},
{
desc: "Malformed filename (too few dashes)",
mockStdout: "/path/to/malformed-package.pkg.tar.zst\n",
wantErr: true, // Expect "cannot find package name" error
},
{
desc: "Package with epoch",
mockStdout: "/path/to/epochpkg-1:2.0.0-1-x86_64.pkg.tar.zst\n",
wantPkgDests: map[string]string{
"epochpkg": "/path/to/epochpkg-1:2.0.0-1-x86_64.pkg.tar.zst",
},
wantPkgVersion: "1:2.0.0-1",
wantErr: false, // This might fail with current logic
},
{
desc: "Package with .zst extension",
mockStdout: "/path/to/zstdpkg-3.3-1-any.pkg.tar.zst\n",
wantPkgDests: map[string]string{
"zstdpkg": "/path/to/zstdpkg-3.3-1-any.pkg.tar.zst",
},
wantPkgVersion: "3.3-1",
wantErr: false,
},
{
desc: "Package with .gz extension",
mockStdout: "/path/to/gzpkg-3.3-1-any.pkg.tar.gz\n",
wantPkgDests: map[string]string{
"gzpkg": "/path/to/gzpkg-3.3-1-any.pkg.tar.gz",
},
wantPkgVersion: "3.3-1",
wantErr: false,
},
{
desc: "Package with .xz extension",
mockStdout: "/path/to/xzpkg-3.3-1-any.pkg.tar.xz\n",
wantPkgDests: map[string]string{
"xzpkg": "/path/to/xzpkg-3.3-1-any.pkg.tar.xz",
},
wantPkgVersion: "3.3-1",
wantErr: false,
},
{
desc: "Package with .bz2 extension",
mockStdout: "/path/to/bz2pkg-3.3-1-any.pkg.tar.bz2\n",
wantPkgDests: map[string]string{
"bz2pkg": "/path/to/bz2pkg-3.3-1-any.pkg.tar.bz2",
},
wantPkgVersion: "3.3-1",
wantErr: false,
},
{
desc: "Package with .tar extension (uncompressed)",
mockStdout: "/path/to/tarpkg-3.3-1-any.pkg.tar\n",
wantPkgDests: map[string]string{
"tarpkg": "/path/to/tarpkg-3.3-1-any.pkg.tar",
},
wantPkgVersion: "3.3-1",
wantErr: false,
},
}
for _, tc := range testCases {
tc := tc // capture range variable
t.Run(tc.desc, func(t *testing.T) {
t.Parallel()
mockRunner := &exe.MockRunner{
CaptureFn: func(cmd *exec.Cmd) (string, string, error) {
// Basic check to ensure the command looks right
require.Contains(t, cmd.String(), "--packagelist")
return tc.mockStdout, tc.mockStderr, tc.mockErr
},
}
cmdBuilder := &exe.CmdBuilder{Runner: mockRunner} // Simplified for this test
pkgdests, pkgVersion, err := parsePackageList(context.Background(), cmdBuilder, "/fake/dir")
if tc.wantErr {
assert.Error(t, err)
if tc.wantErrText != "" {
assert.Contains(t, err.Error(), tc.wantErrText)
}
// Check for specific error types if needed
if tc.desc == "Empty input" || tc.desc == "Input with only newline" {
assert.IsType(t, &NoPkgDestsFoundError{}, err)
}
} else {
assert.NoError(t, err)
assert.Equal(t, tc.wantPkgDests, pkgdests)
assert.Equal(t, tc.wantPkgVersion, pkgVersion)
}
})
}
}

View File

@ -4,8 +4,6 @@ import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"strings"
@ -50,7 +48,7 @@ type GPGCmdBuilder interface {
// CheckPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,
// asks the user whether yay should try to import them.
func CheckPgpKeys(ctx context.Context, pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
func CheckPgpKeys(ctx context.Context, logger *text.Logger, pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
cmdBuilder GPGCmdBuilder, noConfirm bool,
) ([]string, error) {
// Let's check the keys individually, and then we can offer to import
@ -80,24 +78,23 @@ func CheckPgpKeys(ctx context.Context, pkgbuildDirsByBase map[string]string, src
return []string{}, nil
}
str, err := formatKeysToImport(problematic)
str, err := formatKeysToImport(logger, problematic)
if err != nil {
return nil, err
}
fmt.Println()
fmt.Println(str)
logger.Println("\n", str)
if text.ContinueTask(os.Stdin, gotext.Get("Import?"), true, noConfirm) {
return problematic.toSlice(), importKeys(ctx, cmdBuilder, problematic.toSlice())
if logger.ContinueTask(gotext.Get("Import?"), true, noConfirm) {
return problematic.toSlice(), importKeys(ctx, logger, cmdBuilder, problematic.toSlice())
}
return problematic.toSlice(), nil
}
// importKeys tries to import the list of keys specified in its argument.
func importKeys(ctx context.Context, cmdBuilder GPGCmdBuilder, keys []string) error {
text.OperationInfoln(gotext.Get("Importing keys with gpg..."))
func importKeys(ctx context.Context, logger *text.Logger, cmdBuilder GPGCmdBuilder, keys []string) error {
logger.OperationInfoln(gotext.Get("Importing keys with gpg..."))
if err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, append([]string{"--recv-keys"}, keys...)...)); err != nil {
return errors.New(gotext.Get("problem importing keys"))
@ -108,14 +105,14 @@ func importKeys(ctx context.Context, cmdBuilder GPGCmdBuilder, keys []string) er
// formatKeysToImport receives a set of keys and returns a string containing the
// question asking the user wants to import the problematic keys.
func formatKeysToImport(keys pgpKeySet) (string, error) {
func formatKeysToImport(logger *text.Logger, keys pgpKeySet) (string, error) {
if len(keys) == 0 {
return "", errors.New(gotext.Get("no keys to import"))
}
var buffer bytes.Buffer
buffer.WriteString(text.SprintOperationInfo(gotext.Get("PGP keys need importing:")))
buffer.WriteString(logger.SprintOperationInfo(gotext.Get("PGP keys need importing:")))
for key, bases := range keys {
pkglist := ""
@ -124,7 +121,7 @@ func formatKeysToImport(keys pgpKeySet) (string, error) {
}
pkglist = strings.TrimRight(pkglist, " ")
buffer.WriteString("\n" + text.SprintWarn(gotext.Get("%s, required by: %s", text.Cyan(key), text.Cyan(pkglist))))
buffer.WriteString("\n" + logger.SprintWarn(gotext.Get("%s, required by: %s", text.Cyan(key), text.Cyan(pkglist))))
}
return buffer.String(), nil

View File

@ -6,6 +6,7 @@ package pgp
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"sort"
@ -17,8 +18,13 @@ import (
"github.com/stretchr/testify/require"
"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 {
srcinfo := gosrc.Srcinfo{}
srcinfo.Pkgbase = pkgbase
@ -228,7 +234,7 @@ func TestCheckPgpKeys(t *testing.T) {
GPGFlags: []string{"--homedir /tmp"},
Runner: mockRunner,
}
problematic, err := CheckPgpKeys(context.Background(), tt.pkgs, tt.srcinfos, &cmdBuilder, true)
problematic, err := CheckPgpKeys(context.Background(), newTestLogger(), tt.pkgs, tt.srcinfos, &cmdBuilder, true)
require.Len(t, mockRunner.ShowCalls, len(tt.wantShow))
require.Len(t, mockRunner.CaptureCalls, len(tt.wantCapture))

View File

@ -11,28 +11,28 @@ import (
"github.com/Jguer/yay/v12/pkg/db"
"github.com/Jguer/yay/v12/pkg/dep"
"github.com/Jguer/yay/v12/pkg/pgp"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/settings/exe"
"github.com/Jguer/yay/v12/pkg/sync/srcinfo/pgp"
"github.com/Jguer/yay/v12/pkg/text"
"github.com/Jguer/yay/v12/pkg/vcs"
)
// TODO: add tests
type Service struct {
dbExecutor db.Executor
cfg *settings.Configuration
cmdBuilder exe.ICmdBuilder
cmdBuilder pgp.GPGCmdBuilder
vcsStore vcs.Store
log *text.Logger
pkgBuildDirs map[string]string
srcInfos map[string]*gosrc.Srcinfo
}
func NewService(dbExecutor db.Executor, cfg *settings.Configuration,
func NewService(dbExecutor db.Executor, cfg *settings.Configuration, logger *text.Logger,
cmdBuilder exe.ICmdBuilder, vcsStore vcs.Store, pkgBuildDirs map[string]string,
) (*Service, error) {
srcinfos, err := ParseSrcinfoFilesByBase(pkgBuildDirs, true)
srcinfos, err := ParseSrcinfoFilesByBase(logger, pkgBuildDirs, true)
if err != nil {
panic(err)
}
@ -43,6 +43,7 @@ func NewService(dbExecutor db.Executor, cfg *settings.Configuration,
vcsStore: vcsStore,
pkgBuildDirs: pkgBuildDirs,
srcInfos: srcinfos,
log: logger,
}, nil
}
@ -68,7 +69,7 @@ nextpkg:
}
func (s *Service) CheckPGPKeys(ctx context.Context) error {
_, errCPK := pgp.CheckPgpKeys(ctx, s.pkgBuildDirs, s.srcInfos, s.cmdBuilder, settings.NoConfirm)
_, errCPK := pgp.CheckPgpKeys(ctx, s.log.Child("pgp"), s.pkgBuildDirs, s.srcInfos, s.cmdBuilder, settings.NoConfirm)
return errCPK
}
@ -83,15 +84,15 @@ func (s *Service) UpdateVCSStore(ctx context.Context, targets []map[string]*dep.
for i := range srcinfo.Packages {
for j := range targets {
if _, ok := targets[j][srcinfo.Packages[i].Pkgname]; !ok {
text.Debugln("skipping VCS update for", srcinfo.Packages[i].Pkgname, "not in targets")
s.log.Debugln("skipping VCS update for", srcinfo.Packages[i].Pkgname, "not in targets")
continue
}
if _, ok := ignore[srcinfo.Packages[i].Pkgname]; ok {
text.Debugln("skipping VCS update for", srcinfo.Packages[i].Pkgname, "due to install error")
s.log.Debugln("skipping VCS update for", srcinfo.Packages[i].Pkgname, "due to install error")
continue
}
text.Debugln("checking VCS entry for", srcinfo.Packages[i].Pkgname, fmt.Sprintf("source: %v", srcinfo.Source))
s.log.Debugln("checking VCS entry for", srcinfo.Packages[i].Pkgname, fmt.Sprintf("source: %v", srcinfo.Source))
s.vcsStore.Update(ctx, srcinfo.Packages[i].Pkgname, srcinfo.Source)
}
}
@ -100,17 +101,17 @@ func (s *Service) UpdateVCSStore(ctx context.Context, targets []map[string]*dep.
return nil
}
func ParseSrcinfoFilesByBase(pkgBuildDirs map[string]string, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) {
func ParseSrcinfoFilesByBase(logger *text.Logger, pkgBuildDirs map[string]string, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) {
srcinfos := make(map[string]*gosrc.Srcinfo)
k := 0
for base, dir := range pkgBuildDirs {
text.OperationInfoln(gotext.Get("(%d/%d) Parsing SRCINFO: %s", k+1, len(pkgBuildDirs), text.Cyan(base)))
logger.OperationInfoln(gotext.Get("(%d/%d) Parsing SRCINFO: %s", k+1, len(pkgBuildDirs), text.Cyan(base)))
pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO"))
if err != nil {
if !errIsFatal {
text.Warnln(gotext.Get("failed to parse %s -- skipping: %s", base, err))
logger.Warnln(gotext.Get("failed to parse %s -- skipping: %s", base, err))
continue
}

View File

@ -0,0 +1,132 @@
package srcinfo
import (
"context"
"io"
"strings"
"testing"
gosrc "github.com/Morganamilo/go-srcinfo"
"github.com/stretchr/testify/assert"
"github.com/Jguer/yay/v12/pkg/db/mock"
"github.com/Jguer/yay/v12/pkg/dep"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/settings/exe"
"github.com/Jguer/yay/v12/pkg/text"
"github.com/Jguer/yay/v12/pkg/vcs"
)
func newTestLogger() *text.Logger {
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
}
func TestNewService(t *testing.T) {
dbExecutor := &mock.DBExecutor{}
cfg := &settings.Configuration{}
cmdBuilder := &exe.MockBuilder{}
vcsStore := &vcs.Mock{}
pkgBuildDirs := map[string]string{
"jellyfin": "../../../testdata/jfin",
"cephbin": "../../../testdata/cephbin",
}
srv, err := NewService(dbExecutor, cfg, newTestLogger(), cmdBuilder, vcsStore, pkgBuildDirs)
assert.NoError(t, err)
assert.NotNil(t, srv)
assert.Equal(t, dbExecutor, srv.dbExecutor)
assert.Equal(t, cfg, srv.cfg)
assert.Equal(t, cmdBuilder, srv.cmdBuilder)
assert.Equal(t, vcsStore, srv.vcsStore)
assert.Equal(t, pkgBuildDirs, srv.pkgBuildDirs)
assert.NotNil(t, srv.srcInfos)
}
func TestService_IncompatiblePkgs(t *testing.T) {
srv := &Service{
dbExecutor: &mock.DBExecutor{AlpmArchitecturesFn: func() ([]string, error) {
return []string{"x86_64"}, nil
}},
srcInfos: map[string]*gosrc.Srcinfo{
"pkg1": {
Package: gosrc.Package{
Arch: []string{"x86_64", "any"},
},
},
"pkg2": {
Package: gosrc.Package{
Arch: []string{"any"},
},
},
"pkg3": {
Package: gosrc.Package{
Arch: []string{"armv7h"},
},
},
"pkg4": {
Package: gosrc.Package{
Arch: []string{"i683", "x86_64"},
},
},
},
}
incompatible, err := srv.IncompatiblePkgs(context.Background())
assert.NoError(t, err)
assert.ElementsMatch(t, []string{"pkg3"}, incompatible)
}
func TestService_CheckPGPKeys(t *testing.T) {
srv := &Service{
log: newTestLogger(),
pkgBuildDirs: map[string]string{
"pkg1": "/path/to/pkg1",
"pkg2": "/path/to/pkg2",
},
srcInfos: map[string]*gosrc.Srcinfo{
"pkg1": {
Packages: []gosrc.Package{
{Pkgname: "pkg1"},
},
},
"pkg2": {
Packages: []gosrc.Package{
{Pkgname: "pkg2"},
},
},
},
}
err := srv.CheckPGPKeys(context.Background())
assert.NoError(t, err)
}
func TestService_UpdateVCSStore(t *testing.T) {
srv := &Service{
srcInfos: map[string]*gosrc.Srcinfo{
"pkg1": {
Packages: []gosrc.Package{
{Pkgname: "pkg1"},
},
},
"pkg2": {
Packages: []gosrc.Package{
{Pkgname: "pkg2"},
},
},
},
vcsStore: &vcs.Mock{},
}
targets := []map[string]*dep.InstallInfo{
{
"pkg1": {},
"pkg2": {},
},
}
ignore := map[string]error{}
err := srv.UpdateVCSStore(context.Background(), targets, ignore)
assert.NoError(t, err)
}

138
pkg/sync/sync.go Normal file
View File

@ -0,0 +1,138 @@
package sync
import (
"context"
"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/multierror"
"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/sync/build"
"github.com/Jguer/yay/v12/pkg/sync/srcinfo"
"github.com/Jguer/yay/v12/pkg/sync/workdir"
"github.com/Jguer/yay/v12/pkg/text"
"github.com/leonelquinteros/gotext"
)
type OperationService struct {
ctx context.Context
cfg *settings.Configuration
dbExecutor db.Executor
logger *text.Logger
}
func NewOperationService(ctx context.Context,
dbExecutor db.Executor,
run *runtime.Runtime,
) *OperationService {
return &OperationService{
ctx: ctx,
cfg: run.Cfg,
dbExecutor: dbExecutor,
logger: run.Logger.Child("operation"),
}
}
func (o *OperationService) Run(ctx context.Context, run *runtime.Runtime,
cmdArgs *parser.Arguments,
targets []map[string]*dep.InstallInfo, excluded []string,
) error {
if len(targets) == 0 {
o.logger.Println("", gotext.Get("there is nothing to do"))
return nil
}
preparer := workdir.NewPreparer(o.dbExecutor, run.CmdBuilder, o.cfg, o.logger.Child("workdir"))
installer := build.NewInstaller(o.dbExecutor, run.CmdBuilder,
run.VCSStore, o.cfg.Mode, o.cfg.ReBuild,
cmdArgs.ExistsArg("w", "downloadonly"), run.Logger.Child("installer"))
pkgBuildDirs, errInstall := preparer.Run(ctx, run, targets)
if errInstall != nil {
return errInstall
}
if cleanFunc := preparer.ShouldCleanMakeDeps(run, cmdArgs); cleanFunc != nil {
installer.AddPostInstallHook(cleanFunc)
}
if cleanAURDirsFunc := preparer.ShouldCleanAURDirs(run, pkgBuildDirs); cleanAURDirsFunc != nil {
installer.AddPostInstallHook(cleanAURDirsFunc)
}
go func() {
errComp := completion.Update(ctx, run.HTTPClient, o.dbExecutor,
o.cfg.AURURL, o.cfg.CompletionPath, o.cfg.CompletionInterval, false)
if errComp != nil {
o.logger.Warnln(errComp)
}
}()
srcInfo, errInstall := srcinfo.NewService(o.dbExecutor, o.cfg,
o.logger.Child("srcinfo"), run.CmdBuilder, run.VCSStore, pkgBuildDirs)
if errInstall != nil {
return errInstall
}
incompatible, errInstall := srcInfo.IncompatiblePkgs(ctx)
if errInstall != nil {
return errInstall
}
if errIncompatible := confirmIncompatible(o.logger, incompatible); errIncompatible != nil {
return errIncompatible
}
if errPGP := srcInfo.CheckPGPKeys(ctx); errPGP != nil {
return errPGP
}
if errInstall := installer.Install(ctx, cmdArgs, targets, pkgBuildDirs,
excluded, o.manualConfirmRequired(cmdArgs)); errInstall != nil {
return errInstall
}
var multiErr multierror.MultiError
failedAndIgnored, err := installer.CompileFailedAndIgnored()
if err != nil {
multiErr.Add(err)
}
if !cmdArgs.ExistsArg("w", "downloadonly") {
if err := srcInfo.UpdateVCSStore(ctx, targets, failedAndIgnored); err != nil {
o.logger.Warnln(err)
}
}
if err := installer.RunPostInstallHooks(ctx); err != nil {
multiErr.Add(err)
}
return multiErr.Return()
}
func (o *OperationService) manualConfirmRequired(cmdArgs *parser.Arguments) bool {
return (!cmdArgs.ExistsArg("u", "sysupgrade") && cmdArgs.Op != "Y") || o.cfg.DoubleConfirm
}
func confirmIncompatible(logger *text.Logger, incompatible []string) error {
if len(incompatible) > 0 {
logger.Warnln(gotext.Get("The following packages are not compatible with your architecture:"))
for _, pkg := range incompatible {
logger.Print(" " + text.Cyan(pkg))
}
logger.Println()
if !logger.ContinueTask(gotext.Get("Try to build them anyway?"), true, settings.NoConfirm) {
return &settings.ErrUserAbort{}
}
}
return nil
}

View File

@ -1,4 +1,4 @@
package main
package workdir
import (
"context"
@ -32,7 +32,11 @@ func (e *ErrDownloadSource) Unwrap() error {
func downloadPKGBUILDSource(ctx context.Context,
cmdBuilder exe.ICmdBuilder, pkgBuildDir string, installIncompatible bool,
) error {
args := []string{"--verifysource", "--skippgpcheck", "-Ccf"}
args := []string{"--verifysource", "--skippgpcheck", "-f"}
if !cmdBuilder.GetKeepSrc() {
args = append(args, "-Cc")
}
if installIncompatible {
args = append(args, "--ignorearch")

View File

@ -1,7 +1,7 @@
//go:build !integration
// +build !integration
package main
package workdir
import (
"context"
@ -33,6 +33,10 @@ func (z *TestMakepkgBuilder) BuildMakepkgCmd(ctx context.Context, dir string, ex
assert.Contains(z.test, cmd.String(), z.want)
}
if z.GetKeepSrc() {
assert.NotContains(z.test, cmd.String(), "-Cc")
}
if z.wantDir != "" {
assert.Equal(z.test, z.wantDir, cmd.Dir)
}
@ -46,20 +50,54 @@ func (z *TestMakepkgBuilder) Show(cmd *exec.Cmd) error {
return z.showError
}
func (z *TestMakepkgBuilder) GetKeepSrc() bool {
return z.parentBuilder.KeepSrc
}
// GIVEN 1 package
// WHEN downloadPKGBUILDSource is called
// THEN 1 call should be made to makepkg with the specified parameters and dir
func Test_downloadPKGBUILDSource(t *testing.T) {
t.Parallel()
type testCase struct {
desc string
keepSrc bool
want string
}
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"},
parentBuilder: &exe.CmdBuilder{
MakepkgConfPath: "/etc/not.conf",
MakepkgFlags: []string{"--nocheck"},
MakepkgBin: "makepkg",
KeepSrc: tc.keepSrc,
},
test: t,
want: "makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -Ccf",
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))
})
}
}
// GIVEN 1 package
@ -70,7 +108,7 @@ func Test_downloadPKGBUILDSourceError(t *testing.T) {
cmdBuilder := &TestMakepkgBuilder{
parentBuilder: &exe.CmdBuilder{MakepkgConfPath: "/etc/not.conf", MakepkgFlags: []string{"--nocheck"}, MakepkgBin: "makepkg"},
test: t,
want: "makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -Ccf",
want: "makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f -Cc",
wantDir: "/tmp/yay-bin",
showError: &exec.ExitError{},
}

62
pkg/sync/workdir/clean.go Normal file
View File

@ -0,0 +1,62 @@
package workdir
import (
"context"
"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/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
)
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 cleanAfter(ctx context.Context, run *runtime.Runtime,
cmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string,
) {
run.Logger.Println(gotext.Get("removing untracked AUR files from cache..."))
i := 0
for _, dir := range pkgbuildDirs {
run.Logger.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 {
run.Logger.Errorln(gotext.Get("error resetting %s: %s", dir, stderr))
}
if err := run.CmdBuilder.Show(
run.CmdBuilder.BuildGitCmd(
ctx, dir, "clean", "-fx", "--exclude", "*.pkg.*")); err != nil {
run.Logger.Errorln(err)
}
i++
}
}

39
pkg/sync/workdir/merge.go Normal file
View File

@ -0,0 +1,39 @@
package workdir
import (
"context"
"errors"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v12/pkg/settings/exe"
)
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
}

View File

@ -1,4 +1,4 @@
package main
package workdir
import (
"context"
@ -12,9 +12,11 @@ import (
"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/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/sync/build"
"github.com/Jguer/yay/v12/pkg/text"
gosrc "github.com/Morganamilo/go-srcinfo"
@ -29,7 +31,7 @@ const (
PreDownloadSourcesHook HookType = "pre-download-sources"
)
type HookFn func(ctx context.Context, config *settings.Configuration, w io.Writer,
type HookFn func(ctx context.Context, run *runtime.Runtime, w io.Writer,
pkgbuildDirsByBase map[string]string, installed mapset.Set[string],
) error
@ -45,12 +47,13 @@ type Preparer struct {
cfg *settings.Configuration
hooks []Hook
downloadSources bool
log *text.Logger
makeDeps []string
}
func NewPreparerWithoutHooks(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder,
cfg *settings.Configuration, downloadSources bool,
cfg *settings.Configuration, logger *text.Logger, downloadSources bool,
) *Preparer {
return &Preparer{
dbExecutor: dbExecutor,
@ -58,13 +61,14 @@ func NewPreparerWithoutHooks(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder,
cfg: cfg,
hooks: []Hook{},
downloadSources: downloadSources,
log: logger,
}
}
func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder,
cfg *settings.Configuration,
cfg *settings.Configuration, logger *text.Logger,
) *Preparer {
preper := NewPreparerWithoutHooks(dbExecutor, cmdBuilder, cfg, true)
preper := NewPreparerWithoutHooks(dbExecutor, cmdBuilder, cfg, logger, true)
if cfg.CleanMenu {
preper.hooks = append(preper.hooks, Hook{
@ -93,20 +97,20 @@ func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder,
return preper
}
func (preper *Preparer) ShouldCleanAURDirs(pkgBuildDirs map[string]string) PostInstallHookFunc {
func (preper *Preparer) ShouldCleanAURDirs(run *runtime.Runtime, pkgBuildDirs map[string]string) build.PostInstallHookFunc {
if !preper.cfg.CleanAfter || len(pkgBuildDirs) == 0 {
return nil
}
text.Debugln("added post install hook to clean up AUR dirs", pkgBuildDirs)
preper.log.Debugln("added post install hook to clean up AUR dirs", pkgBuildDirs)
return func(ctx context.Context) error {
cleanAfter(ctx, preper.cfg, preper.cfg.Runtime.CmdBuilder, pkgBuildDirs)
cleanAfter(ctx, run, run.CmdBuilder, pkgBuildDirs)
return nil
}
}
func (preper *Preparer) ShouldCleanMakeDeps(cmdArgs *parser.Arguments) PostInstallHookFunc {
func (preper *Preparer) ShouldCleanMakeDeps(run *runtime.Runtime, cmdArgs *parser.Arguments) build.PostInstallHookFunc {
if len(preper.makeDeps) == 0 {
return nil
}
@ -118,25 +122,25 @@ func (preper *Preparer) ShouldCleanMakeDeps(cmdArgs *parser.Arguments) PostInsta
return nil
default:
isYesDefault := preper.cfg.RemoveMake == "askyes"
if !text.ContinueTask(os.Stdin, gotext.Get("Remove make dependencies after install?"),
if !preper.log.ContinueTask(gotext.Get("Remove make dependencies after install?"),
isYesDefault, settings.NoConfirm) {
return nil
}
}
text.Debugln("added post install hook to clean up AUR makedeps", preper.makeDeps)
preper.log.Debugln("added post install hook to clean up AUR makedeps", preper.makeDeps)
return func(ctx context.Context) error {
return removeMake(ctx, preper.cfg, preper.cfg.Runtime.CmdBuilder, preper.makeDeps, cmdArgs)
return removeMake(ctx, preper.cfg, run.CmdBuilder, preper.makeDeps, cmdArgs)
}
}
func (preper *Preparer) Run(ctx context.Context,
w io.Writer, targets []map[string]*dep.InstallInfo,
func (preper *Preparer) Run(ctx context.Context, run *runtime.Runtime,
targets []map[string]*dep.InstallInfo,
) (pkgbuildDirsByBase map[string]string, err error) {
preper.Present(w, targets)
preper.Present(targets)
pkgBuildDirs, err := preper.PrepareWorkspace(ctx, targets)
pkgBuildDirs, err := preper.PrepareWorkspace(ctx, run, targets)
if err != nil {
return nil, err
}
@ -144,7 +148,7 @@ func (preper *Preparer) Run(ctx context.Context,
return pkgBuildDirs, nil
}
func (preper *Preparer) Present(w io.Writer, targets []map[string]*dep.InstallInfo) {
func (preper *Preparer) Present(targets []map[string]*dep.InstallInfo) {
pkgsBySourceAndReason := map[string]map[string][]string{}
for _, layer := range targets {
@ -173,7 +177,7 @@ func (preper *Preparer) Present(w io.Writer, targets []map[string]*dep.InstallIn
for source, pkgsByReason := range pkgsBySourceAndReason {
for reason, pkgs := range pkgsByReason {
fmt.Fprintf(w, text.Bold("%s %s (%d):")+" %s\n",
preper.log.Printf(text.Bold("%s %s (%d):")+" %s\n",
source,
reason,
len(pkgs),
@ -182,20 +186,23 @@ func (preper *Preparer) Present(w io.Writer, targets []map[string]*dep.InstallIn
}
}
func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[string]*dep.InstallInfo) (map[string]string, error) {
func (preper *Preparer) PrepareWorkspace(ctx context.Context,
run *runtime.Runtime, targets []map[string]*dep.InstallInfo,
) (map[string]string, error) {
aurBasesToClone := mapset.NewThreadUnsafeSet[string]()
pkgBuildDirsByBase := make(map[string]string, len(targets))
for _, layer := range targets {
for _, info := range layer {
if info.Source == dep.AUR {
switch info.Source {
case dep.AUR:
pkgBase := *info.AURBase
pkgBuildDir := filepath.Join(preper.cfg.BuildDir, pkgBase)
if preper.needToCloneAURBase(info, pkgBuildDir) {
aurBasesToClone.Add(pkgBase)
}
pkgBuildDirsByBase[pkgBase] = pkgBuildDir
} else if info.Source == dep.SrcInfo {
case dep.SrcInfo:
pkgBase := *info.AURBase
pkgBuildDirsByBase[pkgBase] = *info.SrcinfoPath
}
@ -203,7 +210,7 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
}
if _, errA := download.AURPKGBUILDRepos(ctx,
preper.cmdBuilder, aurBasesToClone.ToSlice(),
preper.cmdBuilder, preper.log.Child("download"), aurBasesToClone.ToSlice(),
preper.cfg.AURURL, preper.cfg.BuildDir, false); errA != nil {
return nil, errA
}
@ -220,7 +227,7 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
remoteNamesCache := mapset.NewThreadUnsafeSet(remoteNames...)
for _, hookFn := range preper.hooks {
if hookFn.Type == PreDownloadSourcesHook {
if err := hookFn.Hookfn(ctx, preper.cfg, os.Stdout, pkgBuildDirsByBase, remoteNamesCache); err != nil {
if err := hookFn.Hookfn(ctx, run, os.Stdout, pkgBuildDirsByBase, remoteNamesCache); err != nil {
return nil, err
}
}
@ -228,7 +235,7 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
if errP := downloadPKGBUILDSourceFanout(ctx, preper.cmdBuilder,
pkgBuildDirsByBase, false, preper.cfg.MaxConcurrentDownloads); errP != nil {
text.Errorln(errP)
preper.log.Errorln(errP)
}
return pkgBuildDirsByBase, nil
@ -242,7 +249,7 @@ func (preper *Preparer) needToCloneAURBase(installInfo *dep.InstallInfo, pkgbuil
srcinfoFile := filepath.Join(pkgbuildDir, ".SRCINFO")
if pkgbuild, err := gosrc.ParseFile(srcinfoFile); err == nil {
if db.VerCmp(pkgbuild.Version(), installInfo.Version) >= 0 {
text.OperationInfoln(
preper.log.OperationInfoln(
gotext.Get("PKGBUILD up to date, skipping download: %s",
text.Cyan(*installInfo.AURBase)))
return false

View File

@ -1,16 +1,23 @@
//go:build !integration
// +build !integration
package main
package workdir
import (
"io"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/text"
)
func newTestLogger() *text.Logger {
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
}
// Test order of pre-download-sources hooks
func TestPreDownloadSourcesHooks(t *testing.T) {
testCases := []struct {
@ -49,7 +56,7 @@ func TestPreDownloadSourcesHooks(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
preper := NewPreparer(nil, nil, tc.cfg)
preper := NewPreparer(nil, nil, tc.cfg, newTestLogger())
assert.Len(t, preper.hooks, len(tc.wantHook))

View File

@ -3,14 +3,18 @@ package text
import (
"bufio"
"fmt"
"io"
"strings"
"unicode"
"unicode/utf8"
"github.com/leonelquinteros/gotext"
)
func (l *Logger) GetInput(defaultValue string, noConfirm bool) (string, error) {
Info()
l.Info()
if defaultValue != "" || noConfirm {
fmt.Println(defaultValue)
l.Println(defaultValue)
return defaultValue, nil
}
@ -28,6 +32,48 @@ func (l *Logger) GetInput(defaultValue string, noConfirm bool) (string, error) {
return string(buf), nil
}
func GetInput(r io.Reader, defaultValue string, noConfirm bool) (string, error) {
return GlobalLogger.GetInput(defaultValue, noConfirm)
// ContinueTask prompts if user wants to continue task.
// If NoConfirm is set the action will continue without user input.
func (l *Logger) ContinueTask(s string, preset, noConfirm bool) bool {
if noConfirm {
return preset
}
var (
response string
postFix string
n string
y string
yes = gotext.Get("yes")
no = gotext.Get("no")
)
// Only use localized "y" and "n" if they are latin characters.
if nRune, _ := utf8.DecodeRuneInString(no); unicode.Is(unicode.Latin, nRune) {
n = string(nRune)
} else {
n = nDefault
}
if yRune, _ := utf8.DecodeRuneInString(yes); unicode.Is(unicode.Latin, yRune) {
y = string(yRune)
} else {
y = yDefault
}
if preset { // If default behavior is true, use y as default.
postFix = fmt.Sprintf(" [%s/%s] ", strings.ToUpper(y), n)
} else { // If default behavior is anything else, use n as default.
postFix = fmt.Sprintf(" [%s/%s] ", y, strings.ToUpper(n))
}
l.OperationInfo(Bold(s), Bold(postFix))
if _, err := fmt.Fscanln(l.r, &response); err != nil {
return preset
}
return strings.EqualFold(response, yes) ||
strings.EqualFold(response, y) ||
(!strings.EqualFold(yDefault, n) && strings.EqualFold(response, yDefault))
}

View File

@ -1,139 +0,0 @@
package text
import (
"fmt"
"os"
"strconv"
"strings"
"syscall"
"unicode"
"github.com/leonelquinteros/gotext"
"golang.org/x/sys/unix"
)
const (
arrow = "==>"
smallArrow = " ->"
opSymbol = "::"
)
var (
cachedColumnCount = -1
GlobalLogger = NewLogger(os.Stdout, os.Stderr, os.Stdin, false, "global")
)
func Debugln(a ...interface{}) {
GlobalLogger.Debugln(a...)
}
func OperationInfoln(a ...interface{}) {
GlobalLogger.OperationInfoln(a...)
}
func OperationInfo(a ...interface{}) {
GlobalLogger.OperationInfo(a...)
}
func SprintOperationInfo(a ...interface{}) string {
return GlobalLogger.SprintOperationInfo(a...)
}
func Info(a ...interface{}) {
GlobalLogger.Info(a...)
}
func Infoln(a ...interface{}) {
GlobalLogger.Infoln(a...)
}
func SprintWarn(a ...interface{}) string {
return GlobalLogger.SprintWarn(a...)
}
func Warn(a ...interface{}) {
GlobalLogger.Warn(a...)
}
func Warnln(a ...interface{}) {
GlobalLogger.Warnln(a...)
}
func SprintError(a ...interface{}) string {
return GlobalLogger.SprintError(a...)
}
func Error(a ...interface{}) {
GlobalLogger.Error(a...)
}
func Errorln(a ...interface{}) {
GlobalLogger.Errorln(a...)
}
func getColumnCount() int {
if cachedColumnCount > 0 {
return cachedColumnCount
}
if count, err := strconv.Atoi(os.Getenv("COLUMNS")); err == nil {
cachedColumnCount = count
return cachedColumnCount
}
if ws, err := unix.IoctlGetWinsize(syscall.Stdout, unix.TIOCGWINSZ); err == nil {
cachedColumnCount = int(ws.Col)
return cachedColumnCount
}
return 80
}
func PrintInfoValue(key string, values ...string) {
const (
keyLength = 32
delimCount = 2
)
specialWordsCount := 0
for _, runeValue := range key {
// CJK handling: the character 'ー' is Katakana
// but if use unicode.Katakana, it will return false
if unicode.IsOneOf([]*unicode.RangeTable{
unicode.Han,
unicode.Hiragana,
unicode.Katakana,
unicode.Hangul,
}, runeValue) || runeValue == 'ー' {
specialWordsCount++
}
}
keyTextCount := specialWordsCount - keyLength + delimCount
str := fmt.Sprintf(Bold("%-*s: "), keyTextCount, key)
if len(values) == 0 || (len(values) == 1 && values[0] == "") {
fmt.Fprintf(os.Stdout, "%s%s\n", str, gotext.Get("None"))
return
}
maxCols := getColumnCount()
cols := keyLength + len(values[0])
str += values[0]
for _, value := range values[1:] {
if maxCols > keyLength && cols+len(value)+delimCount >= maxCols {
cols = keyLength
str += "\n" + strings.Repeat(" ", keyLength)
} else if cols != keyLength {
str += strings.Repeat(" ", delimCount)
cols += delimCount
}
str += value
cols += len(value)
}
fmt.Println(str)
}

View File

@ -5,6 +5,12 @@ import (
"io"
)
const (
arrow = "==>"
smallArrow = " ->"
opSymbol = "::"
)
type Logger struct {
name string
Debug bool

View File

@ -1,13 +1,8 @@
package text
import (
"fmt"
"io"
"strings"
"unicode"
"unicode/utf8"
"github.com/leonelquinteros/gotext"
)
const (
@ -28,12 +23,12 @@ func SplitDBFromName(pkg string) (db, name string) {
// LessRunes compares two rune values, and returns true if the first argument is lexicographicaly smaller.
func LessRunes(iRunes, jRunes []rune) bool {
max := len(iRunes)
if max > len(jRunes) {
max = len(jRunes)
maxLen := len(iRunes)
if maxLen > len(jRunes) {
maxLen = len(jRunes)
}
for idx := 0; idx < max; idx++ {
for idx := 0; idx < maxLen; idx++ {
ir := iRunes[idx]
jr := jRunes[idx]
@ -52,49 +47,3 @@ func LessRunes(iRunes, jRunes []rune) bool {
return len(iRunes) < len(jRunes)
}
// ContinueTask prompts if user wants to continue task.
// If NoConfirm is set the action will continue without user input.
func ContinueTask(input io.Reader, s string, preset, noConfirm bool) bool {
if noConfirm {
return preset
}
var (
response string
postFix string
n string
y string
yes = gotext.Get("yes")
no = gotext.Get("no")
)
// Only use localized "y" and "n" if they are latin characters.
if nRune, _ := utf8.DecodeRuneInString(no); unicode.Is(unicode.Latin, nRune) {
n = string(nRune)
} else {
n = nDefault
}
if yRune, _ := utf8.DecodeRuneInString(yes); unicode.Is(unicode.Latin, yRune) {
y = string(yRune)
} else {
y = yDefault
}
if preset { // If default behavior is true, use y as default.
postFix = fmt.Sprintf(" [%s/%s] ", strings.ToUpper(y), n)
} else { // If default behavior is anything else, use n as default.
postFix = fmt.Sprintf(" [%s/%s] ", y, strings.ToUpper(n))
}
OperationInfo(Bold(s), Bold(postFix))
if _, err := fmt.Fscanln(input, &response); err != nil {
return preset
}
return strings.EqualFold(response, yes) ||
strings.EqualFold(response, y) ||
(!strings.EqualFold(yDefault, n) && strings.EqualFold(response, yDefault))
}

View File

@ -4,6 +4,7 @@
package text
import (
"io"
"os"
"path"
"strings"
@ -74,7 +75,8 @@ func TestContinueTask(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
// create io.Reader with value of input
in := strings.NewReader(tt.args.input)
got := ContinueTask(in, tt.args.s, tt.args.preset, tt.args.noConfirm)
logger := NewLogger(io.Discard, io.Discard, in, false, "test")
got := logger.ContinueTask(tt.args.s, tt.args.preset, tt.args.noConfirm)
require.Equal(t, tt.want, got)
})
}
@ -120,7 +122,8 @@ msgstr "да"
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
in := strings.NewReader(tt.args.input)
got := ContinueTask(in, tt.args.s, tt.args.preset, tt.args.noConfirm)
logger := NewLogger(io.Discard, io.Discard, in, false, "test")
got := logger.ContinueTask(tt.args.s, tt.args.preset, tt.args.noConfirm)
require.Equal(t, tt.want, got)
})
}
@ -168,7 +171,8 @@ msgstr "ja"
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
in := strings.NewReader(tt.args.input)
got := ContinueTask(in, tt.args.s, tt.args.preset, tt.args.noConfirm)
logger := NewLogger(io.Discard, io.Discard, in, false, "test")
got := logger.ContinueTask(tt.args.s, tt.args.preset, tt.args.noConfirm)
require.Equal(t, tt.want, got)
})
}

View File

@ -3,7 +3,6 @@ package upgrade
import (
"context"
"fmt"
"math"
"sort"
"strings"
@ -195,14 +194,15 @@ func (u *UpgradeService) graphToUpSlice(graph *topo.Graph[string, *dep.InstallIn
parents := graph.ImmediateDependencies(name)
extra := ""
if len(parents) > 0 && !info.Upgrade && info.Reason == dep.MakeDep {
reducedParents := parents.Slice()[:int(math.Min(cutOffExtra, float64(len(parents))))]
reducedParents := parents.Slice()[:min(cutOffExtra, len(parents))]
if len(parents) > cutOffExtra {
reducedParents = append(reducedParents, "...")
}
extra = fmt.Sprintf(" (%s of %s)", dep.ReasonNames[info.Reason], strings.Join(reducedParents, ", "))
}
if info.Source == dep.AUR {
switch info.Source {
case dep.AUR:
aurRepo := "aur"
if info.Devel {
aurRepo = "devel"
@ -216,7 +216,7 @@ func (u *UpgradeService) graphToUpSlice(graph *topo.Graph[string, *dep.InstallIn
Reason: alpmReason,
Extra: extra,
})
} else if info.Source == dep.Sync {
case dep.Sync:
repoUp.Up = append(repoUp.Up, Upgrade{
Name: name,
RemoteVersion: info.Version,
@ -246,10 +246,6 @@ func (u *UpgradeService) GraphUpgrades(ctx context.Context,
return graph, err
}
if graph.Len() == 0 {
return graph, nil
}
return graph, nil
}
@ -303,28 +299,37 @@ func (u *UpgradeService) UserExcludeUpgrades(graph *topo.Graph[string, *dep.Inst
// upgrade menu asks you which packages to NOT upgrade so in this case
// exclude and include are kind of swapped
exclude, include, otherExclude, otherInclude := intrange.ParseNumberMenu(numbers)
isInclude := len(include) == 0 && otherInclude.Cardinality() == 0
// true if user doesn't want to include specific repositories/packages
noIncludes := len(include) == 0 && otherInclude.Cardinality() == 0
// No exclusions or inclusions specified, return early
if noIncludes && len(exclude) == 0 && otherExclude.Cardinality() == 0 {
return []string{}, nil
}
excluded := make([]string, 0)
for i := range allUp.Up {
up := &allUp.Up[i]
upgradeID := len(allUp.Up) - i
if isInclude && otherExclude.Contains(up.Repository) {
// check if user wants to exclude specific things (true) or include specific things
if noIncludes {
// exclude repositories mentioned by the user
if otherExclude.Contains(up.Repository) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
}
// exclude packages mentioned by the user
if exclude.Get(upgradeID) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
continue
}
if isInclude && exclude.Get(len(allUp.Up)-i) {
// If the user explicitly wants to include a package/repository, exclude everything else
} else if !include.Get(upgradeID) && !otherInclude.Contains(up.Repository) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
continue
}
if !isInclude && !(include.Get(len(allUp.Up)-i) || otherInclude.Contains(up.Repository)) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
continue
}
}

View File

@ -5,12 +5,11 @@ import (
"strings"
"github.com/Jguer/yay/v12/pkg/db"
"github.com/Jguer/yay/v12/pkg/intrange"
"github.com/Jguer/yay/v12/pkg/query"
"github.com/Jguer/yay/v12/pkg/text"
)
// Filter decides if specific package should be included in theincluded in the results.
// Filter decides if specific package should be included in the results.
type Filter func(*Upgrade) bool
// Upgrade type describes a system upgrade.
@ -39,9 +38,10 @@ func (u UpSlice) Less(i, j int) bool {
}
for _, db := range u.Repos {
if db == u.Up[i].Repository {
switch db {
case u.Up[i].Repository:
return true
} else if db == u.Up[j].Repository {
case u.Up[j].Repository:
return false
}
}
@ -52,21 +52,27 @@ func (u UpSlice) Less(i, j int) bool {
return text.LessRunes(iRunes, jRunes)
}
// Print prints the details of the packages to upgrade.
func (u UpSlice) Print(logger *text.Logger) {
longestName, longestVersion := 0, 0
for k := range u.Up {
upgrade := &u.Up[k]
// calculateFormatting calculates formatting parameters for printing upgrades
func calculateFormatting(upgrades []Upgrade) (longestName, longestVersion, longestNumber int) {
for i := range upgrades {
upgrade := &upgrades[i]
packNameLen := len(StylizedNameWithRepository(upgrade))
packVersion, _ := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)
packVersionLen := len(packVersion)
longestName = intrange.Max(packNameLen, longestName)
longestVersion = intrange.Max(packVersionLen, longestVersion)
longestName = max(packNameLen, longestName)
longestVersion = max(packVersionLen, longestVersion)
}
lenUp := len(u.Up)
longestNumber := len(fmt.Sprintf("%v", lenUp))
lenUp := len(upgrades)
longestNumber = len(fmt.Sprintf("%v", lenUp))
return
}
// Print prints the details of the packages to upgrade.
func (u UpSlice) Print(logger *text.Logger) {
longestName, longestVersion, longestNumber := calculateFormatting(u.Up)
namePadding := fmt.Sprintf("%%-%ds ", longestName)
versionPadding := fmt.Sprintf("%%-%ds", longestVersion)
numberPadding := fmt.Sprintf("%%%dd ", longestNumber)
@ -75,10 +81,8 @@ func (u UpSlice) Print(logger *text.Logger) {
upgrade := &u.Up[k]
left, right := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)
logger.Printf(text.Magenta(fmt.Sprintf(numberPadding, lenUp-k)))
logger.Printf(text.Magenta(fmt.Sprintf(numberPadding, len(u.Up)-k)))
logger.Printf(namePadding, StylizedNameWithRepository(upgrade))
logger.Printf("%s -> %s\n", fmt.Sprintf(versionPadding, left), right)
if upgrade.Extra != "" {
logger.Println(strings.Repeat(" ", longestNumber), upgrade.Extra)
@ -87,19 +91,8 @@ func (u UpSlice) Print(logger *text.Logger) {
}
func (u UpSlice) PrintDeps(logger *text.Logger) {
longestName, longestVersion := 0, 0
longestName, longestVersion, longestNumber := calculateFormatting(u.PulledDeps)
for k := range u.PulledDeps {
upgrade := &u.PulledDeps[k]
packNameLen := len(StylizedNameWithRepository(upgrade))
packVersion, _ := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)
packVersionLen := len(packVersion)
longestName = intrange.Max(packNameLen, longestName)
longestVersion = intrange.Max(packVersionLen, longestVersion)
}
lenUp := len(u.PulledDeps)
longestNumber := len(fmt.Sprintf("%v", lenUp))
namePadding := fmt.Sprintf(" %s%%-%ds ", strings.Repeat(" ", longestNumber), longestName)
versionPadding := fmt.Sprintf("%%-%ds", longestVersion)

View File

@ -7,7 +7,6 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"os/exec"
@ -24,6 +23,10 @@ import (
"github.com/Jguer/yay/v12/pkg/text"
)
func newTestLogger() *text.Logger {
return text.NewLogger(io.Discard, io.Discard, strings.NewReader(""), true, "test")
}
func TestParsing(t *testing.T) {
t.Parallel()
type source struct {
@ -232,7 +235,7 @@ func TestInfoStoreToUpgrade(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
v := &InfoStore{
logger: text.GlobalLogger,
logger: newTestLogger(),
CmdBuilder: tt.fields.CmdBuilder,
OriginsByPackage: map[string]OriginInfoByURL{
"yay": tt.args.infos,
@ -365,7 +368,7 @@ func TestInfoStore_NeedsUpdate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
v := &InfoStore{
logger: text.GlobalLogger,
logger: newTestLogger(),
CmdBuilder: tt.fields.CmdBuilder,
}
got := v.needsUpdate(context.Background(), tt.args.infos)
@ -415,7 +418,7 @@ func TestInfoStore_Update(t *testing.T) {
t.Parallel()
v := &InfoStore{
OriginsByPackage: tt.fields.OriginsByPackage,
logger: text.GlobalLogger,
logger: newTestLogger(),
FilePath: filePath,
CmdBuilder: tt.fields.CmdBuilder,
}
@ -429,7 +432,6 @@ func TestInfoStore_Update(t *testing.T) {
cupaloy.SnapshotT(t, marshalledinfo)
v.Load()
fmt.Println(v.OriginsByPackage)
assert.Len(t, tt.fields.OriginsByPackage, 1)
marshalledinfo, err = json.MarshalIndent(tt.fields.OriginsByPackage, "", "\t")
@ -479,7 +481,7 @@ func TestInfoStore_Remove(t *testing.T) {
t.Parallel()
v := &InfoStore{
OriginsByPackage: tt.fields.OriginsByPackage,
logger: text.GlobalLogger,
logger: newTestLogger(),
FilePath: filePath,
}
v.RemovePackages(tt.args.pkgs)

358
po/ca.po
View File

@ -1,10 +1,10 @@
#
# Translators:
# Davidmp <medipas@gmail.com>, 2023
# Davidmp <medipas@gmail.com>, 2024
#
msgid ""
msgstr ""
"Last-Translator: Davidmp <medipas@gmail.com>, 2023\n"
"Last-Translator: Davidmp <medipas@gmail.com>, 2024\n"
"Language-Team: Catalan (https://app.transifex.com/yay-1/teams/123732/ca/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -13,51 +13,67 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: xgotext\n"
#: pkg/menus/menu.go:31
#: clean.go:83
msgid ""
"\n"
"Build directory:"
msgstr ""
"\n"
"Directori de construcció:"
#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740
msgid ""
"\n"
"Enter a number (default=1): "
msgstr ""
"\n"
"Introduïu un número (per defecte = 1):"
#: pkg/menus/menu.go:32
msgid " (Build Files Exist)"
msgstr "(Els fitxers de compilació ja existeixen)"
#: pkg/menus/menu.go:26
#: pkg/menus/menu.go:27
msgid " (Installed)"
msgstr "(Instal·lat)"
#: cmd.go:461
#: cmd.go:453
msgid " [Installed]"
msgstr "[Instal·lat]"
#: cmd.go:418 vote.go:35
#: cmd.go:410 vote.go:36
msgid " there is nothing to do"
msgstr "No hi ha res per fer."
#: pkg/menus/menu.go:48
#: pkg/menus/menu.go:49
msgid "%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)"
msgstr "%s [T]ot [Av]orta [I]nstal·lat [No] instal·lat o (1 2 3, 1-3, ^4)"
#: aur_install.go:304
#: pkg/sync/build/installer.go:308
msgid "%s already made -- skipping build"
msgstr "%s ja fet: se n'omet la construcció."
#: pkg/menus/edit_menu.go:56
#: pkg/menus/edit_menu.go:57
msgid "%s is not set"
msgstr "%s no està establert."
#: pkg/settings/exe/cmd_builder.go:238
#: pkg/settings/exe/cmd_builder.go:257
msgid "%s is present."
msgstr "%s és present."
#: pkg/dep/dep_graph.go:431 aur_install.go:301
#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305
msgid "%s is up to date -- skipping"
msgstr "%s està al dia: s'omet."
#: pkg/upgrade/service.go:304
#: pkg/upgrade/service.go:291
msgid "%s to upgrade/install."
msgstr "%s per actualitzar / instal·lar."
#: pkg/upgrade/service.go:298
#: pkg/upgrade/service.go:285
msgid "%s will also be installed for this operation."
msgstr "%s també s'instal·larà per a aquesta operació."
#: pkg/pgp/keys.go:127
#: pkg/sync/srcinfo/pgp/keys.go:124
msgid "%s, required by: %s"
msgstr "%s, requerit per %s"
@ -77,11 +93,11 @@ msgstr "%s: no es pot usar l'objectiu amb l'opció --repo, s'omet."
msgid "%s: ignoring package upgrade (%s => %s)"
msgstr "%s: s'ignora l'actualització del paquet (%s => %s)"
#: pkg/query/aur_warnings.go:51
#: pkg/query/aur_warnings.go:46
msgid "%s: local (%s) is newer than AUR (%s)"
msgstr "%s: el paquet local (%s) és més nou que el de l'AUR (%s)"
#: vote.go:50
#: vote.go:51
msgid ""
"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for "
"voting"
@ -93,19 +109,23 @@ msgstr ""
msgid "(%d/%d) Downloaded PKGBUILD from ABS: %s"
msgstr "(%d/%d) PKGBUILD baixat de l'ABS: %s"
#: pkg/download/aur.go:84 pkg/download/unified.go:188
#: pkg/download/aur.go:92 pkg/download/unified.go:188
msgid "(%d/%d) Downloaded PKGBUILD: %s"
msgstr "(%d/%d) PKGBUILD baixat: %s"
#: pkg/srcinfo/service.go:108
#: pkg/download/aur.go:82
msgid "(%d/%d) Failed to download PKGBUILD: %s"
msgstr "(%d/%d) Ha fallat baixar el PKGBUILD: %s"
#: pkg/sync/srcinfo/service.go:109
msgid "(%d/%d) Parsing SRCINFO: %s"
msgstr "(%d/%d) S'analitza SRCINFO: %s"
#: pkg/query/types.go:72 pkg/query/types.go:103
#: pkg/query/types.go:103 pkg/query/types.go:72
msgid "(Installed)"
msgstr "(Instal·lat)"
#: pkg/query/types.go:70 pkg/query/types.go:101
#: pkg/query/types.go:101 pkg/query/types.go:70
msgid "(Installed: %s)"
msgstr "(Instal·lat: %s)"
@ -117,15 +137,15 @@ msgstr "(Orfes)"
msgid "(Out-of-date: %s)"
msgstr "(Obsolet: %s)"
#: print.go:31
msgid "AUR URL"
msgstr "URL de l'AUR"
#: pkg/dep/dep_graph.go:75
msgid "AUR"
msgstr "AUR"
#: pkg/menus/edit_menu.go:57
#: print.go:44
msgid "AUR URL"
msgstr "URL de l'AUR"
#: pkg/menus/edit_menu.go:58
msgid "Add %s or %s to your environment variables"
msgstr "Afegiu %s o %s a les variables d'entorn."
@ -137,23 +157,23 @@ msgstr "Eviteu executar el yay com a root / sudo."
msgid "Check Dependency"
msgstr "Comprova'n la dependència"
#: print.go:37
#: print.go:41
msgid "Check Deps"
msgstr "Comprova les dependències"
#: pkg/upgrade/service.go:90
#: pkg/upgrade/service.go:89
msgid "Checking development packages..."
msgstr "Es comproven els paquets de desenvolupament..."
#: clean.go:217
#: pkg/sync/workdir/clean.go:45
msgid "Cleaning (%d/%d): %s"
msgstr "Es neteja (%d/%d): %s"
#: print.go:39
#: print.go:42
msgid "Conflicts With"
msgstr "Té conflicte amb"
#: pkg/menus/clean_menu.go:60
#: pkg/menus/clean_menu.go:62
msgid "Deleting (%d/%d): %s"
msgstr "Se suprimeix (%d/%d): %s"
@ -161,15 +181,15 @@ msgstr "Se suprimeix (%d/%d): %s"
msgid "Dependency"
msgstr "Dependència"
#: print.go:35
#: print.go:38
msgid "Depends On"
msgstr "Depèn de"
#: print.go:29
#: print.go:33
msgid "Description"
msgstr "Descripció"
#: pkg/menus/diff_menu.go:158
#: pkg/menus/diff_menu.go:160
msgid "Diffs to show?"
msgstr "Diferències per mostrar?"
@ -177,19 +197,19 @@ msgstr "Diferències per mostrar?"
msgid "Disable 'provides' setting by default"
msgstr "Desactiva la configuració de \"proporciona\" per defecte."
#: clean.go:79
#: clean.go:78
msgid "Do you want to remove ALL AUR packages from cache?"
msgstr "Voleu suprimir TOTS els paquets de l'AUR de la memòria cau?"
#: clean.go:96
#: clean.go:95
msgid "Do you want to remove ALL untracked AUR files?"
msgstr "Voleu suprimir TOTS els fitxers de l'AUR sense seguiment?"
#: clean.go:81
#: clean.go:80
msgid "Do you want to remove all other AUR packages from cache?"
msgstr "Voleu suprimir tots els altres paquets de l'AUR de la memòria cau?"
#: pkg/menus/edit_menu.go:60
#: pkg/menus/edit_menu.go:61
msgid "Edit PKGBUILD with?"
msgstr "Amb què voleu editar el PKGBUILD?"
@ -197,7 +217,7 @@ msgstr "Amb què voleu editar el PKGBUILD?"
msgid "Error during AUR search: %s\n"
msgstr "Error durant la cerca a l'AUR: %s\n"
#: pkg/upgrade/service.go:308
#: pkg/upgrade/service.go:295
msgid "Excluding packages may cause partial upgrades and break systems"
msgstr ""
"L'exclusió de paquets pot provocar actualitzacions parcials i trencar els "
@ -207,32 +227,32 @@ msgstr ""
msgid "Explicit"
msgstr "Explícit"
#: print.go:85
#: print.go:91
msgid "Explicitly installed packages: %s"
msgstr "Paquets instal·lats explícitament: %s"
#: pkg/dep/dep_graph.go:408 pkg/dep/dep_graph.go:506
#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535
msgid "Failed to find AUR package for"
msgstr "No s'ha pogut trobar el paquet de l'AUR per a"
#: aur_install.go:120
#: pkg/sync/build/installer.go:120
msgid "Failed to install layer, rolling up to next layer."
msgstr "Ha fallat instal·lar la capa. Es passa a la següent."
#: errors.go:55
#: pkg/sync/build/errors.go:16
msgid ""
"Failed to install the following packages. Manual intervention is required:"
msgstr "Ha fallat instal·lar els paquets següents. Cal intervenció manual:"
#: print.go:43
#: print.go:45
msgid "First Submitted"
msgstr "Enviat primer"
#: pkg/query/aur_warnings.go:84
#: pkg/query/aur_warnings.go:83
msgid "Flagged Out Of Date AUR Packages:"
msgstr "Paquets de l'AUR obsolets marcats:"
#: print.go:84
#: print.go:90
msgid "Foreign installed packages: %s"
msgstr "Paquets forans instal·lats: %s"
@ -240,31 +260,31 @@ msgstr "Paquets forans instal·lats: %s"
msgid "Found git repo: %s"
msgstr "S'ha trobat el repositori git: %s"
#: vcs.go:73
#: vcs.go:72
msgid "GenDB finished. No packages were installed"
msgstr "GenDB ha acabat. No s'ha instal·lat cap paquet."
#: print.go:32
#: print.go:36
msgid "Groups"
msgstr "Grups"
#: pkg/pgp/keys.go:91
#: pkg/sync/srcinfo/pgp/keys.go:88
msgid "Import?"
msgstr "Ho importo?"
#: pkg/pgp/keys.go:100
#: pkg/sync/srcinfo/pgp/keys.go:97
msgid "Importing keys with gpg..."
msgstr "S'importen claus amb gpg..."
#: print.go:27
#: print.go:46
msgid "Keywords"
msgstr "Paraules clau"
#: print.go:44
#: print.go:47
msgid "Last Modified"
msgstr "Darrera modificació"
#: print.go:33
#: print.go:35
msgid "Licenses"
msgstr "Llicències"
@ -272,7 +292,7 @@ msgstr "Llicències"
msgid "Local"
msgstr "Local"
#: print.go:40
#: print.go:48
msgid "Maintainer"
msgstr "Mantenidor"
@ -280,47 +300,51 @@ msgstr "Mantenidor"
msgid "Make Dependency"
msgstr "Dependència de construcció"
#: print.go:36
#: print.go:40
msgid "Make Deps"
msgstr "Dependències de construcció"
#: pkg/query/aur_warnings.go:76
msgid "Missing AUR Debug Packages:"
msgstr "Manquen paquets de depuració de l'AUR:"
#: pkg/dep/dep_graph.go:79
msgid "Missing"
msgstr "Manca"
#: print.go:26
#: pkg/query/aur_warnings.go:75
msgid "Missing AUR Debug Packages:"
msgstr "Manquen paquets de depuració de l'AUR:"
#: print.go:31
msgid "Name"
msgstr "Nom"
#: pkg/dep/dep_graph.go:413 pkg/dep/dep_graph.go:519
#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548
msgid "No AUR package found for"
msgstr "No s'ha trobat cap paquet d'AUR per a"
#: pkg/text/print.go:117
#: pkg/dep/dep_graph.go:182
msgid "No package found for"
msgstr "No s'ha trobat cap paquet per"
#: print.go:225
msgid "None"
msgstr "Cap"
#: print.go:38
#: print.go:39
msgid "Optional Deps"
msgstr "Dependències opcionals"
#: pkg/query/aur_warnings.go:80
#: pkg/query/aur_warnings.go:79
msgid "Orphan (unmaintained) AUR Packages:"
msgstr "Paquets d'AUR orfes (no mantinguts):"
#: print.go:47 print.go:49
#: print.go:53 print.go:55
msgid "Out-of-date"
msgstr "Obsolet"
#: pkg/pgp/keys.go:118
#: pkg/sync/srcinfo/pgp/keys.go:115
msgid "PGP keys need importing:"
msgstr "Cal importar claus PGP:"
#: preparer.go:242
#: pkg/sync/workdir/preparer.go:252
msgid "PKGBUILD up to date, skipping download: %s"
msgstr "PKGBUILD actualitzat, s'omet la baixada: %s"
@ -328,68 +352,72 @@ msgstr "PKGBUILD actualitzat, s'omet la baixada: %s"
msgid "PKGBUILDs to edit?"
msgstr "PKGBUILDs per editar?"
#: print.go:54
msgid "Package Base ID"
msgstr "ID de la base de paquets"
#: print.go:55
#: print.go:61
msgid "Package Base"
msgstr "Base de paquets"
#: pkg/query/aur_warnings.go:72
#: print.go:60
msgid "Package Base ID"
msgstr "ID de la base de paquets"
#: pkg/query/aur_warnings.go:71
msgid "Packages not in AUR:"
msgstr "Paquets no a l'AUR:"
#: pkg/menus/clean_menu.go:52
#: pkg/menus/clean_menu.go:54
msgid "Packages to cleanBuild?"
msgstr "Paquets per a la neteja de la construcció?"
#: pkg/dep/dep_graph.go:216
#: pkg/dep/dep_graph.go:202
msgid "Packages to exclude"
msgstr "Paquets per excloure"
#: pkg/upgrade/service.go:307
#: pkg/upgrade/service.go:294
msgid "Packages to exclude: (eg: \"1 2 3\", \"1-3\", \"^4\" or repo name)"
msgstr "Paquets per excloure: (p. ex.: \"1 2 3\", \"1-3\", \"^4\" o nom del repositori)"
#: cmd.go:400
#: cmd.go:392
msgid "Packages to install (eg: 1 2 3, 1-3 or ^4)"
msgstr "Paquets per instal·lar (p. ex.: 1 2 3, 1-3 o ^4)"
#: print.go:42
#: print.go:49
msgid "Popularity"
msgstr "Popularitat"
#: pkg/menus/diff_menu.go:170 pkg/menus/edit_menu.go:143
#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143
msgid "Proceed with install?"
msgstr "Voleu continuar la instal·lació?"
#: print.go:34
#: print.go:37
msgid "Provides"
msgstr "Proporciona"
#: preparer.go:119
#: pkg/sync/workdir/preparer.go:125
msgid "Remove make dependencies after install?"
msgstr ""
"Suprimeixo les dependències de construcció després de la instal·lació?"
#: pkg/dep/dep_graph.go:701
msgid "Repository AUR"
msgstr "Repositori de l'AUR"
#: print.go:43
msgid "Replaces"
msgstr "Reemplaça"
#: print.go:25 pkg/db/ialpm/alpm.go:191
#: pkg/db/ialpm/alpm.go:191 print.go:30
msgid "Repository"
msgstr "Repositori"
#: pkg/dep/dep_graph.go:730
msgid "Repository AUR"
msgstr "Repositori de l'AUR"
#: pkg/dep/dep_graph.go:78
msgid "SRCINFO"
msgstr "SRCINFO"
#: pkg/upgrade/service.go:72
#: pkg/upgrade/service.go:71
msgid "Searching AUR for updates..."
msgstr "Se cerquen actualitzacions a l'AUR..."
#: pkg/upgrade/service.go:160
#: pkg/upgrade/service.go:159
msgid "Searching databases for updates..."
msgstr "Se cerquen actualitzacions a les bases de dades..."
@ -397,15 +425,15 @@ msgstr "Se cerquen actualitzacions a les bases de dades..."
msgid "Showing repo packages only"
msgstr "Es mostren només paquets dels repositoris."
#: print.go:89
#: print.go:95
msgid "Size of pacman cache %s: %s"
msgstr "Mida de la memòria cau del pacman %s: %s"
#: print.go:92
#: print.go:98
msgid "Size of yay cache %s: %s"
msgstr "Mida de la memòria cau del yay %s: %s"
#: print.go:56
#: print.go:62
msgid "Snapshot URL"
msgstr "URL de la instantània"
@ -413,104 +441,88 @@ msgstr "URL de la instantània"
msgid "Sync"
msgstr "Sincronització"
#: print.go:94
#: print.go:100
msgid "Ten biggest packages:"
msgstr "Els deu paquets més grossos:"
#: sync.go:190
#: pkg/sync/sync.go:124
msgid "The following packages are not compatible with your architecture:"
msgstr "Els paquets següents no són compatibles amb la vostra arquitectura:"
#: pkg/dep/dep_graph.go:697 pkg/db/ialpm/alpm.go:179
msgid "There are %d providers available for %s:"
msgstr "Hi ha %d proveïdors disponibles per a %s:"
#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726
msgid "There are %[1]d providers available for %[2]s:"
msgstr "Hi ha %[1]d proveïdors disponibles per a %[2]s:"
#: pkg/settings/exe/cmd_builder.go:239
#: pkg/settings/exe/cmd_builder.go:258
msgid "There may be another Pacman instance running. Waiting..."
msgstr ""
"Pot ser que hi hagi una altra instància del Pacman en execució. S'espera..."
#: print.go:86
#: print.go:92
msgid "Total Size occupied by packages: %s"
msgstr "Mida total ocupada pels paquets: %s"
#: print.go:83
#: print.go:89
msgid "Total installed packages: %s"
msgstr "Total de paquets instal·lats: %s"
#: sync.go:198
#: pkg/sync/sync.go:132
msgid "Try to build them anyway?"
msgstr "Intento construir-los tanmateix?"
#: print.go:30
#: print.go:34
msgid "URL"
msgstr "URL"
#: clean.go:195 pkg/menus/clean_menu.go:63 pkg/menus/clean_menu.go:69
#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71
msgid "Unable to clean:"
msgstr "No es pot netejar:"
#: get.go:44 get.go:76
#: get.go:42 get.go:74
msgid "Unable to find the following packages:"
msgstr "No s'han pogut trobar els paquets següents:"
#: vote.go:19
#: vote.go:20
msgid "Unable to handle package vote for: %s. err: %s"
msgstr "No es pot gestionar el vot del paquet per a %s. Error: %s"
#: clean.go:171
#: clean.go:170
msgid "Unable to remove %s: %s"
msgstr "No es pot suprimir %s: %s"
#: print.go:28
#: print.go:32
msgid "Version"
msgstr "Versió"
#: print.go:41
#: print.go:50
msgid "Votes"
msgstr "Vots"
#: print.go:81
#: print.go:87
msgid "Yay version v%s"
msgstr "Versió del yay: v%s"
#: pkg/menus/menu.go:48
#: pkg/menus/menu.go:49
msgid "[N]one"
msgstr "Ca[p]"
#: clean.go:84
msgid ""
"\n"
"Build directory:"
msgstr ""
"\n"
"Directori de construcció:"
#: pkg/dep/dep_graph.go:711 pkg/db/ialpm/alpm.go:201
msgid ""
"\n"
"Enter a number (default=1): "
msgstr ""
"\n"
"Introduïu un número (per defecte = 1):"
#: pkg/settings/errors.go:29
msgid "aborting due to user"
msgstr "s'avorta a causa de l'usuari"
#: pkg/settings/parser/parser.go:619
#: pkg/settings/parser/parser.go:608
msgid "argument '-' specified without input on stdin"
msgstr "argument '-' especificat sense entrada a stdin"
#: local_install.go:27
#: local_install.go:26
msgid "cannot find PKGBUILD and .SRCINFO in directory"
msgstr "no es pot trobar PKGBUILD i SRCINFO al directori"
#: install.go:130
#: pkg/sync/build/pkg_archive.go:148
msgid "cannot find package name: %v"
msgstr "no es pot trobar el nom del paquet: %v"
#: errors.go:47
#: pkg/sync/build/errors.go:30
msgid "could not find PKGDEST for: %s"
msgstr "no s'ha pogut trobar PKGDEST per a %s"
@ -518,23 +530,23 @@ msgstr "no s'ha pogut trobar PKGDEST per a %s"
msgid "could not find all required packages"
msgstr "no s'han pogut trobar tots els paquets necessaris"
#: errors.go:16
#: pkg/sync/build/errors.go:61
msgid "could not find any package archives listed in %s"
msgstr "no s'ha pogut trobar cap arxiu de paquets llistat a %s"
#: errors.go:26 pkg/upgrade/service.go:299
#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286
msgid "dependency"
msgstr "dependència"
#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100
#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96
msgid "devel check for package failed: '%s' encountered an error"
msgstr "la comprovació del paquet ha fallat: %s ha trobat un error"
#: pkg/menus/edit_menu.go:109
#: pkg/menus/edit_menu.go:110
msgid "editor did not exit successfully, aborting: %s"
msgstr "l'editor no ha sortit correctament, s'avorta: %s"
#: aur_source.go:24
#: pkg/sync/workdir/aur_source.go:24
msgid "error downloading sources: %s"
msgstr "error en baixar les fonts: %s"
@ -542,19 +554,19 @@ msgstr "error en baixar les fonts: %s"
msgid "error fetching %s: %s"
msgstr "error en obtenir %s: %s"
#: local_install.go:26
#: pkg/sync/build/errors.go:9
msgid "error installing repo packages"
msgstr "error en instal·lar paquets dels repositoris"
#: aur_install.go:266 aur_install.go:270
#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270
msgid "error installing:"
msgstr "error d'instal·lació:"
#: aur_install.go:233 aur_install.go:237
#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237
msgid "error making: %s"
msgstr "error de construcció: %s"
#: install.go:160
#: pkg/sync/workdir/merge.go:24
msgid "error merging %s: %s"
msgstr "error en combinar %s: %s"
@ -562,19 +574,19 @@ msgstr "error en combinar %s: %s"
msgid "error reading %s"
msgstr "error en llegir %s"
#: sync.go:37
#: sync.go:36
msgid "error refreshing databases"
msgstr "error en actualitzar les bases de dades"
#: clean.go:223 install.go:153
#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17
msgid "error resetting %s: %s"
msgstr "error en restablir %s: %s"
#: errors.go:29
#: pkg/sync/build/errors.go:53
msgid "error updating package install reason to %s"
msgstr "error en actualitzar el motiu d'instal·lació del paquet a %s"
#: errors.go:24
#: pkg/sync/build/errors.go:48
msgid "explicit"
msgstr "explícit"
@ -582,27 +594,27 @@ msgstr "explícit"
msgid "failed to create directory '%s': %s"
msgstr "ha fallat crear el directori %s: %s"
#: pkg/settings/config.go:284
#: pkg/settings/config.go:281
msgid "failed to open config file '%s': %s"
msgstr "ha fallat obrir el fitxer de configuració %s: %s"
#: pkg/srcinfo/service.go:113
#: pkg/sync/srcinfo/service.go:114
msgid "failed to parse %s -- skipping: %s"
msgstr "ha fallat analitzar %s, s'omet: %s"
#: pkg/srcinfo/service.go:117
#: pkg/sync/srcinfo/service.go:118
msgid "failed to parse %s: %s"
msgstr "no s'ha pogut analitzar %s: %s"
#: local_install.go:79
#: local_install.go:77
msgid "failed to parse .SRCINFO"
msgstr "ha fallat analitzar .SRCINFO"
#: pkg/settings/config.go:294
#: pkg/settings/config.go:291
msgid "failed to read config file '%s': %s"
msgstr "ha fallat llegir el fitxer de configuració %s: %s"
#: pkg/settings/runtime.go:73
#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73
msgid "failed to retrieve aur Cache"
msgstr "ha fallat obtenir la cau de l'AUR"
@ -616,7 +628,7 @@ msgstr ""
msgid "input too long"
msgstr "entrada massa llarga"
#: pkg/dep/dep_graph.go:732 pkg/db/ialpm/alpm.go:222
#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761
msgid "invalid number: %s"
msgstr "número no vàlid: %s"
@ -624,7 +636,7 @@ msgstr "número no vàlid: %s"
msgid "invalid option '%s'"
msgstr "opció no vàlida: %s"
#: cmd.go:206
#: cmd.go:197
msgid "invalid option: '--deps' and '--explicit' may not be used together"
msgstr "opció no vàlida: \"--deps\" i \"--explicit\" no es poden usar juntes"
@ -632,11 +644,15 @@ msgstr "opció no vàlida: \"--deps\" i \"--explicit\" no es poden usar juntes"
msgid "invalid repository"
msgstr "repositori no vàlid"
#: pkg/dep/dep_graph.go:738 pkg/db/ialpm/alpm.go:227
#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767
msgid "invalid value: %d is not between %d and %d"
msgstr "valor no vàlid: %d no és entre %d i %d"
#: pkg/pgp/keys.go:113
#: pkg/text/input.go:48
msgid "no"
msgstr "no"
#: pkg/sync/srcinfo/pgp/keys.go:110
msgid "no keys to import"
msgstr "sense claus per importar"
@ -644,15 +660,11 @@ msgstr "sense claus per importar"
msgid "no query was executed"
msgstr "no s'ha executat cap consulta"
#: local_install.go:68
#: local_install.go:66
msgid "no target directories specified"
msgstr "no s'han especificat directoris de destinació"
#: pkg/text/text.go:69
msgid "no"
msgstr "no"
#: aur_install.go:242
#: pkg/sync/build/installer.go:242
msgid "nothing to install for %s"
msgstr "no hi ha res per instal·lar per %s"
@ -660,7 +672,17 @@ msgstr "no hi ha res per instal·lar per %s"
msgid "only one operation may be used at a time"
msgstr "només es pot usar una operació alhora"
#: print.go:181
#: pkg/cmd/graph/main.go:70
msgid "only one target is allowed"
msgstr "només es permet una destinació"
#: pkg/upgrade/service.go:291
msgid "package"
msgid_plural "packages"
msgstr[0] "paquet"
msgstr[1] "paquets"
#: print.go:187
msgid "package '%s' was not found"
msgstr "no s'ha trobat el paquet %s"
@ -672,30 +694,24 @@ msgstr "paquet no trobat a l'AUR"
msgid "package not found in repos"
msgstr "paquet no trobat als repositoris"
#: pkg/upgrade/service.go:304
msgid "package"
msgid_plural "packages"
msgstr[0] "paquet"
msgstr[1] "paquets"
#: pkg/pgp/keys.go:103
#: pkg/sync/srcinfo/pgp/keys.go:100
msgid "problem importing keys"
msgstr "problema d'importació de claus"
#: clean.go:106
#: clean.go:105
msgid "removing AUR packages from cache..."
msgstr "se suprimeixen paquets de l'AUR de la memòria cau..."
#: clean.go:179 clean.go:213
#: clean.go:178 pkg/sync/workdir/clean.go:41
msgid "removing untracked AUR files from cache..."
msgstr ""
"se suprimeixen els fitxers de l'AUR sense seguiment de la memòria cau..."
#: errors.go:37
#: pkg/sync/build/errors.go:38
msgid "the PKGDEST for %s is listed by makepkg but does not exist: %s"
msgstr "el PKGDEST per a %s està llistat per makepkg però no existeix:%s"
#: sync.go:113
#: pkg/sync/sync.go:45
msgid "there is nothing to do"
msgstr "No hi ha res per fer."
@ -703,14 +719,14 @@ msgstr "No hi ha res per fer."
msgid "unable to CreateHandle: %s"
msgstr "no se'n pot crear el maneig: %s"
#: cmd.go:195
#: cmd.go:186
msgid "unhandled operation"
msgstr "operació no manejada"
#: cmd.go:458
#: cmd.go:450
msgid "unknown-version"
msgstr "versió desconeguda"
#: pkg/text/text.go:68
#: pkg/text/input.go:47
msgid "yes"
msgstr "sí"

732
po/ca_ES.po Normal file
View File

@ -0,0 +1,732 @@
#
# Translators:
# Davidmp <medipas@gmail.com>, 2024
#
msgid ""
msgstr ""
"Last-Translator: Davidmp <medipas@gmail.com>, 2024\n"
"Language-Team: Catalan (Spain) (https://app.transifex.com/yay-1/teams/123732/ca_ES/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ca_ES\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: xgotext\n"
#: clean.go:83
msgid ""
"\n"
"Build directory:"
msgstr ""
"\n"
"Directori de construcció:"
#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740
msgid ""
"\n"
"Enter a number (default=1): "
msgstr ""
"\n"
"Introduïu un número (per defecte = 1):"
#: pkg/menus/menu.go:32
msgid " (Build Files Exist)"
msgstr "(Els fitxers de compilació ja existeixen)"
#: pkg/menus/menu.go:27
msgid " (Installed)"
msgstr "(Instal·lat)"
#: cmd.go:453
msgid " [Installed]"
msgstr "[Instal·lat]"
#: cmd.go:410 vote.go:36
msgid " there is nothing to do"
msgstr "No hi ha res per fer."
#: pkg/menus/menu.go:49
msgid "%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)"
msgstr "%s [T]ot [Av]orta [I]nstal·lat [No] instal·lat o (1 2 3, 1-3, ^4)"
#: pkg/sync/build/installer.go:308
msgid "%s already made -- skipping build"
msgstr "%s ja fet: se n'omet la construcció."
#: pkg/menus/edit_menu.go:57
msgid "%s is not set"
msgstr "%s no està establert."
#: pkg/settings/exe/cmd_builder.go:257
msgid "%s is present."
msgstr "%s és present."
#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305
msgid "%s is up to date -- skipping"
msgstr "%s està al dia: s'omet."
#: pkg/upgrade/service.go:291
msgid "%s to upgrade/install."
msgstr "%s per actualitzar / instal·lar."
#: pkg/upgrade/service.go:285
msgid "%s will also be installed for this operation."
msgstr "%s també s'instal·larà per a aquesta operació."
#: pkg/sync/srcinfo/pgp/keys.go:124
msgid "%s, required by: %s"
msgstr "%s, requerit per %s"
#: pkg/menus/diff_menu.go:49
msgid "%s: No changes -- skipping"
msgstr "%s: sense canvis, s'omet."
#: pkg/query/filter.go:22
msgid "%s: can't use target with option --aur -- skipping"
msgstr "%s: no es pot usar l'objectiu amb l'opció --aur, s'omet."
#: pkg/query/filter.go:17
msgid "%s: can't use target with option --repo -- skipping"
msgstr "%s: no es pot usar l'objectiu amb l'opció --repo, s'omet."
#: pkg/upgrade/sources.go:57
msgid "%s: ignoring package upgrade (%s => %s)"
msgstr "%s: s'ignora l'actualització del paquet (%s => %s)"
#: pkg/query/aur_warnings.go:46
msgid "%s: local (%s) is newer than AUR (%s)"
msgstr "%s: el paquet local (%s) és més nou que el de l'AUR (%s)"
#: vote.go:51
msgid ""
"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for "
"voting"
msgstr ""
"%s: establiu les variables d'entorn AUR_NOMDUSUARI i AUR_CONTRASENYA per "
"votar."
#: pkg/download/unified.go:192
msgid "(%d/%d) Downloaded PKGBUILD from ABS: %s"
msgstr "(%d/%d) PKGBUILD baixat de l'ABS: %s"
#: pkg/download/aur.go:92 pkg/download/unified.go:188
msgid "(%d/%d) Downloaded PKGBUILD: %s"
msgstr "(%d/%d) PKGBUILD baixat: %s"
#: pkg/download/aur.go:82
msgid "(%d/%d) Failed to download PKGBUILD: %s"
msgstr "(%d/%d) Ha fallat baixar el PKGBUILD: %s"
#: pkg/sync/srcinfo/service.go:109
msgid "(%d/%d) Parsing SRCINFO: %s"
msgstr "(%d/%d) S'analitza SRCINFO: %s"
#: pkg/query/types.go:103 pkg/query/types.go:72
msgid "(Installed)"
msgstr "(Instal·lat)"
#: pkg/query/types.go:101 pkg/query/types.go:70
msgid "(Installed: %s)"
msgstr "(Instal·lat: %s)"
#: pkg/query/types.go:61
msgid "(Orphaned)"
msgstr "(Orfes)"
#: pkg/query/types.go:65
msgid "(Out-of-date: %s)"
msgstr "(Obsolet: %s)"
#: pkg/dep/dep_graph.go:75
msgid "AUR"
msgstr "AUR"
#: print.go:44
msgid "AUR URL"
msgstr "URL de l'AUR"
#: pkg/menus/edit_menu.go:58
msgid "Add %s or %s to your environment variables"
msgstr "Afegiu %s o %s a les variables d'entorn."
#: main.go:60
msgid "Avoid running yay as root/sudo."
msgstr "Eviteu executar el yay com a root / sudo."
#: pkg/dep/dep_graph.go:63
msgid "Check Dependency"
msgstr "Comprova'n la dependència"
#: print.go:41
msgid "Check Deps"
msgstr "Comprova les dependències"
#: pkg/upgrade/service.go:89
msgid "Checking development packages..."
msgstr "Es comproven els paquets de desenvolupament..."
#: pkg/sync/workdir/clean.go:45
msgid "Cleaning (%d/%d): %s"
msgstr "Es neteja (%d/%d): %s"
#: print.go:42
msgid "Conflicts With"
msgstr "Té conflicte amb"
#: pkg/menus/clean_menu.go:62
msgid "Deleting (%d/%d): %s"
msgstr "Se suprimeix (%d/%d): %s"
#: pkg/dep/dep_graph.go:61
msgid "Dependency"
msgstr "Dependència"
#: print.go:38
msgid "Depends On"
msgstr "Depèn de"
#: print.go:33
msgid "Description"
msgstr "Descripció"
#: pkg/menus/diff_menu.go:160
msgid "Diffs to show?"
msgstr "Diferències per mostrar?"
#: pkg/settings/migrations.go:25
msgid "Disable 'provides' setting by default"
msgstr "Desactiva la configuració de \"proporciona\" per defecte."
#: clean.go:78
msgid "Do you want to remove ALL AUR packages from cache?"
msgstr "Voleu suprimir TOTS els paquets de l'AUR de la memòria cau?"
#: clean.go:95
msgid "Do you want to remove ALL untracked AUR files?"
msgstr "Voleu suprimir TOTS els fitxers de l'AUR sense seguiment?"
#: clean.go:80
msgid "Do you want to remove all other AUR packages from cache?"
msgstr "Voleu suprimir tots els altres paquets de l'AUR de la memòria cau?"
#: pkg/menus/edit_menu.go:61
msgid "Edit PKGBUILD with?"
msgstr "Amb què voleu editar el PKGBUILD?"
#: pkg/query/errors.go:13
msgid "Error during AUR search: %s\n"
msgstr "Error durant la cerca a l'AUR: %s\n"
#: pkg/upgrade/service.go:295
msgid "Excluding packages may cause partial upgrades and break systems"
msgstr ""
"L'exclusió de paquets pot provocar actualitzacions parcials i trencar els "
"sistemes."
#: pkg/dep/dep_graph.go:60
msgid "Explicit"
msgstr "Explícit"
#: print.go:91
msgid "Explicitly installed packages: %s"
msgstr "Paquets instal·lats explícitament: %s"
#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535
msgid "Failed to find AUR package for"
msgstr "No s'ha pogut trobar el paquet de l'AUR per a"
#: pkg/sync/build/installer.go:120
msgid "Failed to install layer, rolling up to next layer."
msgstr "Ha fallat instal·lar la capa. Es passa a la següent."
#: pkg/sync/build/errors.go:16
msgid ""
"Failed to install the following packages. Manual intervention is required:"
msgstr "Ha fallat instal·lar els paquets següents. Cal intervenció manual:"
#: print.go:45
msgid "First Submitted"
msgstr "Enviat primer"
#: pkg/query/aur_warnings.go:83
msgid "Flagged Out Of Date AUR Packages:"
msgstr "Paquets de l'AUR obsolets marcats:"
#: print.go:90
msgid "Foreign installed packages: %s"
msgstr "Paquets forans instal·lats: %s"
#: pkg/vcs/vcs.go:144
msgid "Found git repo: %s"
msgstr "S'ha trobat el repositori git: %s"
#: vcs.go:72
msgid "GenDB finished. No packages were installed"
msgstr "GenDB ha acabat. No s'ha instal·lat cap paquet."
#: print.go:36
msgid "Groups"
msgstr "Grups"
#: pkg/sync/srcinfo/pgp/keys.go:88
msgid "Import?"
msgstr "Ho importo?"
#: pkg/sync/srcinfo/pgp/keys.go:97
msgid "Importing keys with gpg..."
msgstr "S'importen claus amb gpg..."
#: print.go:46
msgid "Keywords"
msgstr "Paraules clau"
#: print.go:47
msgid "Last Modified"
msgstr "Darrera modificació"
#: print.go:35
msgid "Licenses"
msgstr "Llicències"
#: pkg/dep/dep_graph.go:77
msgid "Local"
msgstr "Local"
#: print.go:48
msgid "Maintainer"
msgstr "Mantenidor"
#: pkg/dep/dep_graph.go:62
msgid "Make Dependency"
msgstr "Dependència de construcció"
#: print.go:40
msgid "Make Deps"
msgstr "Dependències de construcció"
#: pkg/dep/dep_graph.go:79
msgid "Missing"
msgstr "Manca"
#: pkg/query/aur_warnings.go:75
msgid "Missing AUR Debug Packages:"
msgstr "Manquen paquets de depuració de l'AUR:"
#: print.go:31
msgid "Name"
msgstr "Nom"
#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548
msgid "No AUR package found for"
msgstr "No s'ha trobat cap paquet d'AUR per a"
#: pkg/dep/dep_graph.go:182
msgid "No package found for"
msgstr "No s'ha trobat cap paquet per"
#: print.go:225
msgid "None"
msgstr "Cap"
#: print.go:39
msgid "Optional Deps"
msgstr "Dependències opcionals"
#: pkg/query/aur_warnings.go:79
msgid "Orphan (unmaintained) AUR Packages:"
msgstr "Paquets d'AUR orfes (no mantinguts):"
#: print.go:53 print.go:55
msgid "Out-of-date"
msgstr "Obsolet"
#: pkg/sync/srcinfo/pgp/keys.go:115
msgid "PGP keys need importing:"
msgstr "Cal importar claus PGP:"
#: pkg/sync/workdir/preparer.go:252
msgid "PKGBUILD up to date, skipping download: %s"
msgstr "PKGBUILD actualitzat, s'omet la baixada: %s"
#: pkg/menus/edit_menu.go:130
msgid "PKGBUILDs to edit?"
msgstr "PKGBUILDs per editar?"
#: print.go:61
msgid "Package Base"
msgstr "Base de paquets"
#: print.go:60
msgid "Package Base ID"
msgstr "ID de la base de paquets"
#: pkg/query/aur_warnings.go:71
msgid "Packages not in AUR:"
msgstr "Paquets no a l'AUR:"
#: pkg/menus/clean_menu.go:54
msgid "Packages to cleanBuild?"
msgstr "Paquets per a la neteja de la construcció?"
#: pkg/dep/dep_graph.go:202
msgid "Packages to exclude"
msgstr "Paquets per excloure"
#: pkg/upgrade/service.go:294
msgid "Packages to exclude: (eg: \"1 2 3\", \"1-3\", \"^4\" or repo name)"
msgstr "Paquets per excloure: (p. ex.: \"1 2 3\", \"1-3\", \"^4\" o nom del repositori)"
#: cmd.go:392
msgid "Packages to install (eg: 1 2 3, 1-3 or ^4)"
msgstr "Paquets per instal·lar (p. ex.: 1 2 3, 1-3 o ^4)"
#: print.go:49
msgid "Popularity"
msgstr "Popularitat"
#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143
msgid "Proceed with install?"
msgstr "Voleu continuar la instal·lació?"
#: print.go:37
msgid "Provides"
msgstr "Proporciona"
#: pkg/sync/workdir/preparer.go:125
msgid "Remove make dependencies after install?"
msgstr ""
"Suprimeixo les dependències de construcció després de la instal·lació?"
#: print.go:43
msgid "Replaces"
msgstr "Reemplaça"
#: pkg/db/ialpm/alpm.go:191 print.go:30
msgid "Repository"
msgstr "Repositori"
#: pkg/dep/dep_graph.go:730
msgid "Repository AUR"
msgstr "Repositori de l'AUR"
#: pkg/dep/dep_graph.go:78
msgid "SRCINFO"
msgstr "SRCINFO"
#: pkg/upgrade/service.go:71
msgid "Searching AUR for updates..."
msgstr "Se cerquen actualitzacions a l'AUR..."
#: pkg/upgrade/service.go:159
msgid "Searching databases for updates..."
msgstr "Se cerquen actualitzacions a les bases de dades..."
#: pkg/query/query_builder.go:214
msgid "Showing repo packages only"
msgstr "Es mostren només paquets dels repositoris."
#: print.go:95
msgid "Size of pacman cache %s: %s"
msgstr "Mida de la memòria cau del pacman %s: %s"
#: print.go:98
msgid "Size of yay cache %s: %s"
msgstr "Mida de la memòria cau del yay %s: %s"
#: print.go:62
msgid "Snapshot URL"
msgstr "URL de la instantània"
#: pkg/dep/dep_graph.go:76
msgid "Sync"
msgstr "Sincronització"
#: print.go:100
msgid "Ten biggest packages:"
msgstr "Els deu paquets més grossos:"
#: pkg/sync/sync.go:124
msgid "The following packages are not compatible with your architecture:"
msgstr "Els paquets següents no són compatibles amb la vostra arquitectura:"
#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726
msgid "There are %[1]d providers available for %[2]s:"
msgstr "Hi ha %[1]d proveïdors disponibles per a %[2]s:"
#: pkg/settings/exe/cmd_builder.go:258
msgid "There may be another Pacman instance running. Waiting..."
msgstr ""
"Pot ser que hi hagi una altra instància del Pacman en execució. S'espera..."
#: print.go:92
msgid "Total Size occupied by packages: %s"
msgstr "Mida total ocupada pels paquets: %s"
#: print.go:89
msgid "Total installed packages: %s"
msgstr "Total de paquets instal·lats: %s"
#: pkg/sync/sync.go:132
msgid "Try to build them anyway?"
msgstr "Intento construir-los tanmateix?"
#: print.go:34
msgid "URL"
msgstr "URL"
#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71
msgid "Unable to clean:"
msgstr "No es pot netejar:"
#: get.go:42 get.go:74
msgid "Unable to find the following packages:"
msgstr "No s'han pogut trobar els paquets següents:"
#: vote.go:20
msgid "Unable to handle package vote for: %s. err: %s"
msgstr "No es pot gestionar el vot del paquet per a %s. Error: %s"
#: clean.go:170
msgid "Unable to remove %s: %s"
msgstr "No es pot suprimir %s: %s"
#: print.go:32
msgid "Version"
msgstr "Versió"
#: print.go:50
msgid "Votes"
msgstr "Vots"
#: print.go:87
msgid "Yay version v%s"
msgstr "Versió del yay: v%s"
#: pkg/menus/menu.go:49
msgid "[N]one"
msgstr "Ca[p]"
#: pkg/settings/errors.go:29
msgid "aborting due to user"
msgstr "s'avorta a causa de l'usuari"
#: pkg/settings/parser/parser.go:608
msgid "argument '-' specified without input on stdin"
msgstr "argument '-' especificat sense entrada a stdin"
#: local_install.go:26
msgid "cannot find PKGBUILD and .SRCINFO in directory"
msgstr "no es pot trobar PKGBUILD i SRCINFO al directori"
#: pkg/sync/build/pkg_archive.go:148
msgid "cannot find package name: %v"
msgstr "no es pot trobar el nom del paquet: %v"
#: pkg/sync/build/errors.go:30
msgid "could not find PKGDEST for: %s"
msgstr "no s'ha pogut trobar PKGDEST per a %s"
#: errors.go:9
msgid "could not find all required packages"
msgstr "no s'han pogut trobar tots els paquets necessaris"
#: pkg/sync/build/errors.go:61
msgid "could not find any package archives listed in %s"
msgstr "no s'ha pogut trobar cap arxiu de paquets llistat a %s"
#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286
msgid "dependency"
msgstr "dependència"
#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96
msgid "devel check for package failed: '%s' encountered an error"
msgstr "la comprovació del paquet ha fallat: %s ha trobat un error"
#: pkg/menus/edit_menu.go:110
msgid "editor did not exit successfully, aborting: %s"
msgstr "l'editor no ha sortit correctament, s'avorta: %s"
#: pkg/sync/workdir/aur_source.go:24
msgid "error downloading sources: %s"
msgstr "error en baixar les fonts: %s"
#: pkg/download/errors.go:25
msgid "error fetching %s: %s"
msgstr "error en obtenir %s: %s"
#: pkg/sync/build/errors.go:9
msgid "error installing repo packages"
msgstr "error en instal·lar paquets dels repositoris"
#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270
msgid "error installing:"
msgstr "error d'instal·lació:"
#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237
msgid "error making: %s"
msgstr "error de construcció: %s"
#: pkg/sync/workdir/merge.go:24
msgid "error merging %s: %s"
msgstr "error en combinar %s: %s"
#: pkg/download/unified.go:59
msgid "error reading %s"
msgstr "error en llegir %s"
#: sync.go:36
msgid "error refreshing databases"
msgstr "error en actualitzar les bases de dades"
#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17
msgid "error resetting %s: %s"
msgstr "error en restablir %s: %s"
#: pkg/sync/build/errors.go:53
msgid "error updating package install reason to %s"
msgstr "error en actualitzar el motiu d'instal·lació del paquet a %s"
#: pkg/sync/build/errors.go:48
msgid "explicit"
msgstr "explícit"
#: pkg/settings/errors.go:23
msgid "failed to create directory '%s': %s"
msgstr "ha fallat crear el directori %s: %s"
#: pkg/settings/config.go:281
msgid "failed to open config file '%s': %s"
msgstr "ha fallat obrir el fitxer de configuració %s: %s"
#: pkg/sync/srcinfo/service.go:114
msgid "failed to parse %s -- skipping: %s"
msgstr "ha fallat analitzar %s, s'omet: %s"
#: pkg/sync/srcinfo/service.go:118
msgid "failed to parse %s: %s"
msgstr "no s'ha pogut analitzar %s: %s"
#: local_install.go:77
msgid "failed to parse .SRCINFO"
msgstr "ha fallat analitzar .SRCINFO"
#: pkg/settings/config.go:291
msgid "failed to read config file '%s': %s"
msgstr "ha fallat llegir el fitxer de configuració %s: %s"
#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73
msgid "failed to retrieve aur Cache"
msgstr "ha fallat obtenir la cau de l'AUR"
#: pkg/upgrade/sources.go:27
msgid "ignoring package devel upgrade (no AUR info found):"
msgstr ""
"s'ignora l'actualització del paquet de desenvolupament (no se n'ha trobat "
"cap informació a l'AUR):"
#: pkg/text/errors.go:8
msgid "input too long"
msgstr "entrada massa llarga"
#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761
msgid "invalid number: %s"
msgstr "número no vàlid: %s"
#: pkg/settings/parser/parser.go:174
msgid "invalid option '%s'"
msgstr "opció no vàlida: %s"
#: cmd.go:197
msgid "invalid option: '--deps' and '--explicit' may not be used together"
msgstr "opció no vàlida: \"--deps\" i \"--explicit\" no es poden usar juntes"
#: pkg/download/abs.go:22
msgid "invalid repository"
msgstr "repositori no vàlid"
#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767
msgid "invalid value: %d is not between %d and %d"
msgstr "valor no vàlid: %d no és entre %d i %d"
#: pkg/text/input.go:48
msgid "no"
msgstr "no"
#: pkg/sync/srcinfo/pgp/keys.go:110
msgid "no keys to import"
msgstr "sense claus per importar"
#: pkg/query/errors.go:20
msgid "no query was executed"
msgstr "no s'ha executat cap consulta"
#: local_install.go:66
msgid "no target directories specified"
msgstr "no s'han especificat directoris de destinació"
#: pkg/sync/build/installer.go:242
msgid "nothing to install for %s"
msgstr "no hi ha res per instal·lar per %s"
#: pkg/settings/parser/parser.go:164
msgid "only one operation may be used at a time"
msgstr "només es pot usar una operació alhora"
#: pkg/cmd/graph/main.go:70
msgid "only one target is allowed"
msgstr "només es permet una destinació"
#: pkg/upgrade/service.go:291
msgid "package"
msgid_plural "packages"
msgstr[0] "paquet"
msgstr[1] "paquets"
#: print.go:187
msgid "package '%s' was not found"
msgstr "no s'ha trobat el paquet %s"
#: pkg/download/errors.go:15
msgid "package not found in AUR"
msgstr "paquet no trobat a l'AUR"
#: pkg/download/abs.go:23
msgid "package not found in repos"
msgstr "paquet no trobat als repositoris"
#: pkg/sync/srcinfo/pgp/keys.go:100
msgid "problem importing keys"
msgstr "problema d'importació de claus"
#: clean.go:105
msgid "removing AUR packages from cache..."
msgstr "se suprimeixen paquets de l'AUR de la memòria cau..."
#: clean.go:178 pkg/sync/workdir/clean.go:41
msgid "removing untracked AUR files from cache..."
msgstr ""
"se suprimeixen els fitxers de l'AUR sense seguiment de la memòria cau..."
#: pkg/sync/build/errors.go:38
msgid "the PKGDEST for %s is listed by makepkg but does not exist: %s"
msgstr "el PKGDEST per a %s està llistat per makepkg però no existeix:%s"
#: pkg/sync/sync.go:45
msgid "there is nothing to do"
msgstr "No hi ha res per fer."
#: pkg/db/ialpm/alpm.go:247
msgid "unable to CreateHandle: %s"
msgstr "no se'n pot crear el maneig: %s"
#: cmd.go:186
msgid "unhandled operation"
msgstr "operació no manejada"
#: cmd.go:450
msgid "unknown-version"
msgstr "versió desconeguda"
#: pkg/text/input.go:47
msgid "yes"
msgstr "sí"

Some files were not shown because too many files have changed in this diff Show More