Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name: Integration Tests (Standalone)
#
# This workflow runs integration tests independently of the release process.
# Use it for:
# - Manual testing before creating a release branch
# - Manual testing before triggering a release via workflow_dispatch
# - Weekly regression testing
# - Debugging integration issues
#
Expand Down
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1341,11 +1341,20 @@ GRPM (Go Resource Package Manager) is a modern reimplementation of Gentoo's Port
## Links

- **Repository**: https://github.com/grpmsoft/grpm
- **Documentation**: https://github.com/grpmsoft/grpm/tree/master/docs
- **Documentation**: https://github.com/grpmsoft/grpm/tree/main/docs
- **Issues**: https://github.com/grpmsoft/grpm/issues
- **License**: [Apache-2.0](LICENSE)

[Unreleased]: https://github.com/grpmsoft/grpm/compare/v0.7.11...HEAD
[Unreleased]: https://github.com/grpmsoft/grpm/compare/v0.9.3...HEAD
[0.9.3]: https://github.com/grpmsoft/grpm/compare/v0.9.2...v0.9.3
[0.9.2]: https://github.com/grpmsoft/grpm/compare/v0.9.1...v0.9.2
[0.9.1]: https://github.com/grpmsoft/grpm/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/grpmsoft/grpm/compare/v0.8.4...v0.9.0
[0.8.4]: https://github.com/grpmsoft/grpm/compare/v0.8.3...v0.8.4
[0.8.3]: https://github.com/grpmsoft/grpm/compare/v0.8.2...v0.8.3
[0.8.2]: https://github.com/grpmsoft/grpm/compare/v0.8.1...v0.8.2
[0.8.1]: https://github.com/grpmsoft/grpm/compare/v0.8.0...v0.8.1
[0.8.0]: https://github.com/grpmsoft/grpm/compare/v0.7.11...v0.8.0
[0.7.11]: https://github.com/grpmsoft/grpm/compare/v0.7.10...v0.7.11
[0.7.10]: https://github.com/grpmsoft/grpm/compare/v0.7.9...v0.7.10
[0.7.9]: https://github.com/grpmsoft/grpm/compare/v0.7.8...v0.7.9
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ Look for issues labeled `good first issue` or `help wanted`.

### Areas Needing Help

- EAPI 8 support
- CMake/Meson build systems
- Eclass implementations
- Complex eclass support (kernel, LLVM, Java)
- CMake/Meson build system edge cases
- Real-world package testing and bug reports
- Test coverage improvements
- Documentation

Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ GRPM (Go Resource Package Manager) is a modern source-based package manager writ
| **SAT-based Dependency Resolution** | Boolean satisfiability solver for guaranteed conflict-free resolution |
| **Binary Package Support** | Full GPKG (.gpkg.tar) and legacy TBZ2 (.tbz2) format support |
| **Transactional Updates** | Btrfs/ZFS snapshot-based rollbacks for safe system updates |
| **Source Building** | Complete ebuild execution with autotools, CMake, and Meson |
| **Build Systems** | cmake.eclass, meson.eclass, toolchain-funcs, flag-o-matic |
| **Language Ecosystems** | Python (distutils-r1), Rust (cargo.eclass), Go (go-module.eclass) |
| **Source Building** | Ebuild execution with autotools; CMake and Meson support (basic) |
| **Build Systems** | toolchain-funcs, flag-o-matic, cmake.eclass, meson.eclass |
| **Language Ecosystems** | Python (distutils-r1), Rust (cargo.eclass), Go (go-module.eclass) — basic support |
| **Multilib Support** | 32-bit/64-bit library support with ABI management |
| **Package Sets** | @world, @system, @selected in ALL commands (resolve, install, emerge, fetch) |
| **Distfile Fetching** | Automatic source downloading with mirror failover |
Expand All @@ -57,9 +57,10 @@ GRPM (Go Resource Package Manager) is a modern source-based package manager writ
### Install from Binary

```bash
# Download latest release
wget https://github.com/grpmsoft/grpm/releases/latest/download/grpm_linux_amd64.tar.gz
tar -xzf grpm_linux_amd64.tar.gz
# Download latest release (check https://github.com/grpmsoft/grpm/releases for VERSION)
VERSION="0.9.3"
wget "https://github.com/grpmsoft/grpm/releases/download/v${VERSION}/grpm_${VERSION}_linux_x86_64.tar.gz"
tar -xzf "grpm_${VERSION}_linux_x86_64.tar.gz"
sudo install -m 0755 grpm /usr/bin/grpm

# Verify
Expand Down Expand Up @@ -235,8 +236,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines and [AGENTS.md

**Completed Features:**
- ✅ SAT-based dependency resolution
- ✅ Full ebuild execution (autotools, CMake, Meson)
- ✅ Language ecosystems (Python, Rust, Go)
- ✅ Ebuild execution (autotools full; CMake, Meson basic)
- ✅ Language ecosystem support (Python, Rust, Go — basic)
- ✅ Multilib support (32-bit/64-bit)
- ✅ Binary package support (GPKG, TBZ2)
- ✅ Repository sync (rsync, git) with GPG verification
Expand Down
6 changes: 3 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Key insight: **Eclasses don't need Go implementations.** They are loaded dynamic

## Current Status

### What's Implemented (~75% Tree Coverage)
### What's Implemented (~98% Tree Coverage)

| Category | Features |
|----------|----------|
Expand Down Expand Up @@ -301,7 +301,7 @@ grpm emerge --check-tools @world # Optional pre-validation
## Roadmap to v1.0.0

```
v0.9.0 ← CURRENT (Pre-Release Testing)
v0.9.3 ← CURRENT (Pre-Release Testing)
│ ✅ v0.6.0: Distfile fetching, debug helpers, coverage analyzer
│ ✅ v0.7.x: Portage compatibility, security fixes
│ ✅ v0.8.0: Configuration management (make.conf, repos.conf, package.use)
Expand Down Expand Up @@ -456,4 +456,4 @@ Key deliverables:
---

*This roadmap evolves based on community feedback and project needs.*
*Last updated: 2026-01-19 (v0.9.0 enterprise tool check)*
*Last updated: 2026-02-08 (v0.9.3 documentation audit)*
4 changes: 2 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ flowchart TB

subgraph Daemon["Daemon Layer"]
GRPC_SERVER[gRPC Server<br/>unix:///var/run/grpm.sock]
REST_API[REST API<br/>:8080]
REST_API[REST API<br/>unix:///var/run/grpm-rest.sock]
JOB_QUEUE[Job Queue]
WORKERS[Worker Pool]
end
Expand Down Expand Up @@ -88,7 +88,7 @@ flowchart TB

### Daemon Layer
- **gRPC Server**: Unix socket server for CLI communication
- **REST API**: HTTP API for external integrations
- **REST API**: Unix socket API for external integrations (TCP optional)
- **Job Queue**: Prioritized queue with conflict detection
- **Worker Pool**: Parallel job execution

Expand Down
58 changes: 54 additions & 4 deletions docs/CLI_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Complete command-line reference for GRPM. See [CHANGELOG](../CHANGELOG.md) for v
- [fetch](#fetch)
- [build](#build)
- [update](#update)
- [depclean](#depclean)
- [analyze](#analyze)
- [tools](#tools)
- [completion](#completion)
Expand Down Expand Up @@ -220,11 +221,16 @@ grpm emerge [options] <package|@set>...
| `--mock` | Use mock repository for testing | `false` |
| `--pretend`, `-p` | Show build plan without building | `false` |
| `--ask`, `-a` | Ask for confirmation before building | `false` |
| `--jobs <n>` | Number of parallel make jobs | From MAKEOPTS or 4 |
| `--jobs <n>`, `-j <n>` | Number of packages to build in parallel | `1` |
| `--make-jobs <n>` | Number of parallel make jobs per package | From MAKEOPTS or 4 |
| `--keep-going`, `-k` | Continue building remaining packages on failure | `false` |
| `--keep-work` | Keep work directory after build | `false` |
| `--test` | Run test phase (make check/test) | `false` |
| `--replace`, `-R` | Replace existing package (unmerge old before merge) | `false` |
| `--force`, `-f` | Force installation (skip collision checks) | `false` |
| `--onlydeps`, `-o` | Build dependencies only, skip target | `false` |
| `--check-tools` | Perform optional pre-build tool availability check | `false` |
| `--info` | Show system environment information (like `emerge --info`) | `false` |
| `--deep`, `-D` | Traverse dependencies of already-installed packages | `false` |
| `--with-bdeps` | Include build-time dependencies for installed packages | `false` |
| `--emptytree`, `-e` | Assume no packages installed (full dependency tree) | `false` |
Expand Down Expand Up @@ -567,9 +573,10 @@ grpm update [options]
| `--repo <path>` | Path to Portage repository | `/var/db/repos/gentoo` |
| `--mock` | Use mock repository | `false` |
| `--pretend`, `-p` | Show what would be updated | `false` |
| `--ask`, `-a` | Ask for confirmation before updating | `false` |
| `--deep`, `-D` | Include dependencies | `false` |

**Note:** Full update functionality is planned for future releases.
| `--newuse`, `-N` | Recalculate USE flags for installed packages | `false` |
| `--changed-use`, `-U` | Only update packages with changed USE flags | `false` |

**Examples:**

Expand All @@ -579,10 +586,53 @@ grpm update --pretend

# Include dependencies
grpm update --deep --pretend

# Update with USE flag recalculation
grpm update --deep --newuse --pretend

# Update @world with confirmation
sudo grpm update --ask --deep --newuse
```

---

### depclean

Remove unused/orphaned packages from the system.

```
grpm depclean [options] [package...]
```

**Options:**

| Option | Description | Default |
|--------|-------------|---------|
| `--pretend`, `-p` | Show what would be removed | `false` |
| `--ask`, `-a` | Ask for confirmation before removing | `false` |
| `--exclude <pkg>` | Exclude packages from removal (repeatable) | |

**Examples:**

```bash
# Show orphaned packages (dry-run)
grpm depclean --pretend

# Remove unused packages with confirmation
sudo grpm depclean --ask

# Exclude specific packages from removal
sudo grpm depclean --exclude sys-libs/glibc --exclude sys-devel/gcc
```

**Notes:**
- Depclean removes packages not in @world/@system that no other package depends on
- Always use `--pretend` first to review what would be removed
- Use `--exclude` to protect packages from removal
- Also accessible via `grpm remove --depclean` / `grpm remove -c`

---

### analyze

Analyze repository coverage and compatibility.
Expand Down Expand Up @@ -913,7 +963,7 @@ grpm daemon

The daemon provides:
- gRPC server on Unix socket (`/var/run/grpm.sock`)
- REST API on HTTP (`127.0.0.1:8080`)
- REST API on Unix socket (`/var/run/grpm-rest.sock`)
- Job queue with conflict detection
- Background monitoring

Expand Down
10 changes: 5 additions & 5 deletions docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ This guide covers installation of GRPM on Gentoo Linux and compatible distributi
```bash
# Set version and architecture
VERSION="0.9.3"
ARCH="amd64" # Options: amd64, arm64, arm_7, arm_6, 386
ARCH="x86_64" # Options: x86_64, arm64, armv7, armv6, i386

# Download binary
wget "https://github.com/grpmsoft/grpm/releases/download/v${VERSION}/grpm_${VERSION}_linux_${ARCH}.tar.gz"
Expand All @@ -71,11 +71,11 @@ grpm -V

| Architecture | Filename | Description |
|--------------|----------|-------------|
| x86_64 | `grpm_*_linux_amd64.tar.gz` | 64-bit Intel/AMD (most common) |
| x86_64 | `grpm_*_linux_x86_64.tar.gz` | 64-bit Intel/AMD (most common) |
| ARM64 | `grpm_*_linux_arm64.tar.gz` | 64-bit ARM (Apple Silicon, AWS Graviton) |
| ARMv7 | `grpm_*_linux_arm_7.tar.gz` | 32-bit ARM with hardware float |
| ARMv6 | `grpm_*_linux_arm_6.tar.gz` | Raspberry Pi Zero/1 |
| i386 | `grpm_*_linux_386.tar.gz` | 32-bit Intel/AMD |
| ARMv7 | `grpm_*_linux_armv7.tar.gz` | 32-bit ARM with hardware float |
| ARMv6 | `grpm_*_linux_armv6.tar.gz` | Raspberry Pi Zero/1 |
| i386 | `grpm_*_linux_i386.tar.gz` | 32-bit Intel/AMD |

---

Expand Down
2 changes: 1 addition & 1 deletion docs/PMS_COMPLIANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ internal/solver/gophersat_adapter.go # SAT encoding
| pkg_postrm | Full | |
| pkg_config | Partial | |
| pkg_info | Partial | |
| pkg_nofetch | Not Yet | |
| pkg_nofetch | Full | Default implementation per PMS 9.1.16 |

### Default Phase Implementations

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
require (
github.com/coregx/ahocorasick v0.1.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/klauspost/compress v1.18.3 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (a *App) runAnalyze(args []string) error {
// Set custom help handler
fs.Usage = func() { fmt.Print(GetCommandHelp("analyze")) }

if err := fs.Parse(args); err != nil {
if err := fs.Parse(reorderArgs(args)); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
Expand Down
26 changes: 21 additions & 5 deletions internal/cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func (a *App) runResolve(args []string) error {
// Set custom help handler
fs.Usage = func() { fmt.Print(GetCommandHelp("resolve")) }

if err := fs.Parse(args); err != nil {
if err := fs.Parse(reorderArgs(args)); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
Expand Down Expand Up @@ -415,7 +415,7 @@ func (a *App) runInstall(args []string) error {
// Set custom help handler
fs.Usage = func() { fmt.Print(GetCommandHelp("install")) }

if err := fs.Parse(args); err != nil {
if err := fs.Parse(reorderArgs(args)); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
Expand Down Expand Up @@ -852,7 +852,7 @@ func (a *App) runSync(args []string) error {
// Set custom help handler
fs.Usage = func() { fmt.Print(GetCommandHelp("sync")) }

if err := fs.Parse(args); err != nil {
if err := fs.Parse(reorderArgs(args)); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
Expand Down Expand Up @@ -1002,7 +1002,7 @@ func (a *App) runCompletion(args []string) error {
// Set custom help handler
fs.Usage = func() { fmt.Print(GetCommandHelp("completion")) }

if err := fs.Parse(args); err != nil {
if err := fs.Parse(reorderArgs(args)); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
Expand Down Expand Up @@ -1121,7 +1121,7 @@ View generated man page:
grpm doc man emerge | man -l -`)
}

if err := fs.Parse(args); err != nil {
if err := fs.Parse(reorderArgs(args)); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
Expand Down Expand Up @@ -1188,3 +1188,19 @@ func (a *App) generateAllManPages(gen *ManPageGenerator, dir string) error {
a.log.Success("Generated %d man page(s) in %s", count, dir)
return nil
}

// reorderArgs moves flag-like arguments (starting with "-") before positional
// arguments so that Go's flag package can parse them correctly.
// Go's flag.Parse stops at the first non-flag argument, but Portage allows
// flags anywhere: "emerge @world --deep" should work the same as "emerge --deep @world".
func reorderArgs(args []string) []string {
var flags, positional []string
for _, arg := range args {
if len(arg) > 0 && arg[0] == '-' {
flags = append(flags, arg)
} else {
positional = append(positional, arg)
}
}
return append(flags, positional...)
}
Loading