Implement the following plan:
Accept PURLs as package arguments in more commands (#108)
Context
The urls command already accepts PURLs (pkg:cargo/serde@1.0.0) as its package argument, parsing out the ecosystem, name, and version. Other commands that take a package name argument still require plain names plus a separate --ecosystem flag. This change extends PURL support to 8 more commands so users can write git-pkgs why pkg:npm/lodash instead of git-pkgs why lodash -e npm.
Shared helper
Add ParsePackageArg to cmd/helpers.go:
go
When the arg is a PURL, the ecosystem is derived from the PURL type and the --ecosystem flag is ignored. When it's a plain name, the ecosystem comes from the flag (may be empty) and version is empty.
Commands to change
Database-querying commands
These use ecosystem to filter database queries. The change is the same pattern: call ParsePackageArg at the top, use the returned ecosystem instead of the raw flag.
-
cmd/why.go (runWhy) - replace packageName := args[0] + ecosystem flag read with ParsePackageArg(args[0], ecosystem). Pass returned ecosystem and name to db.GetWhy().
-
cmd/history.go (runHistory) - same pattern. Pass ecosystem and name to db.GetPackageHistory().
-
cmd/where.go (runWhere) - same pattern. The returned ecosystem filters which manifest types to search. The name is used for the regex search.
-
cmd/vulns.go (runVulnsHistory, ~line 1428) - same pattern, but this command currently has no --ecosystem flag. Add one. Use the returned ecosystem to also filter the strings.EqualFold(d.Name, packageName) loop to also check ecosystem when set, avoiding false matches across ecosystems.
Manager-operating commands
These use ecosystem to filter detected package managers. The change: call ParsePackageArg, use returned ecosystem for FilterByEcosystem, and use returned name as the package arg passed to the manager.
-
cmd/browse.go (runBrowse) - parse PURL, use name as pkg for mgr.Path(), use ecosystem for FilterByEcosystem.
-
cmd/add.go (runAdd) - parse PURL, use name as package and version from PURL (if present) as version arg. So git-pkgs add pkg:npm/lodash@4.17.21 works like git-pkgs add lodash 4.17.21 -e npm.
-
cmd/remove.go (runRemove) - parse PURL, use name as package, ecosystem for filtering.
-
cmd/update.go (runUpdate) - parse PURL when a package arg is provided, use name as package, ecosystem for filtering.
Files to modify
cmd/helpers.go - add ParsePackageArg, add purl import
cmd/why.go - use ParsePackageArg
cmd/history.go - use ParsePackageArg
cmd/where.go - use ParsePackageArg
cmd/vulns.go - add --ecosystem flag to vulns history, use ParsePackageArg
cmd/browse.go - use ParsePackageArg
cmd/add.go - use ParsePackageArg, use version from PURL
cmd/remove.go - use ParsePackageArg
cmd/update.go - use ParsePackageArg
Tests
Add to cmd/urls_test.go (or a new cmd/helpers_test.go since ParsePackageArg lives in helpers):
TestParsePackageArg - unit tests for the shared helper covering: PURL input extracts ecosystem/name/version, plain name passes through ecosystem flag, PURL with namespace, invalid PURL returns error, ecosystem flag ignored when PURL provided
Add integration tests for each command (following the urls_test.go pattern with createTestRepo/runCmd):
- Test that each command accepts a PURL and produces the same result as using
--ecosystem + plain name
- Test that invalid PURLs return errors
Verification
cd /Users/andrew/code/git-pkgs/git-pkgs && go build ./...
go test ./cmd/ -run TestParsePackageArg
go test ./cmd/ -v (full test suite)
go vet ./... and golangci-lint run if available
If you need specific details from before exiting plan mode (like exact code snippets, error messages, or content you generated), read the full transcript at: /Users/andrew/.claude/projects/-Users-andrew-code-git-pkgs/cadb53f4-f34f-4fcf-9066-e88933cb2fbc.jsonl