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
61 changes: 54 additions & 7 deletions cmd/apm/cmd_deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
)

// runDeps implements `apm deps [SUBCOMMAND] [OPTIONS]`.
Expand All @@ -18,11 +19,11 @@ func runDeps(args []string) int {
sub := args[0]
rest := args[1:]

for _, a := range args {
if a == "--help" || a == "-h" {
printDepsHelp()
return 0
}
// Only intercept --help when it is the first (and only meaningful) arg,
// not when it follows a subcommand name -- let the subcommand handle it.
if sub == "--help" || sub == "-h" {
printDepsHelp()
return 0
}

switch sub {
Expand Down Expand Up @@ -150,16 +151,62 @@ func runDepsTree(args []string) int {
func runDepsInfo(args []string) int {
for _, a := range args {
if a == "--help" || a == "-h" {
fmt.Println("Usage: apm deps info [OPTIONS]")
fmt.Println("Usage: apm deps info [OPTIONS] PACKAGE")
fmt.Println()
fmt.Println(" Show detailed package information")
fmt.Println()
fmt.Println("Arguments:")
fmt.Println(" PACKAGE [required]")
fmt.Println()
fmt.Println("Options:")
fmt.Println(" --help Show this message and exit.")
return 0
}
}
fmt.Println("[i] Use 'apm view <package>' to inspect a specific package.")

// Collect non-flag arguments as the package name.
var pkg string
for _, a := range args {
if !strings.HasPrefix(a, "-") {
pkg = a
break
}
}
if pkg == "" {
fmt.Fprintln(os.Stderr, "Error: Missing argument 'PACKAGE'.")
fmt.Fprintln(os.Stderr, `Try 'apm deps info --help' for help.`)
return 2
}

cwd, _ := os.Getwd()
pkgDir := filepath.Join(cwd, "apm_modules", pkg)
if _, err := os.Stat(pkgDir); err != nil {
fmt.Fprintf(os.Stderr, "[x] Package '%s' is not installed (no apm_modules/%s).\n", pkg, pkg)
fmt.Fprintf(os.Stderr, "[i] Run 'apm install' to install dependencies.\n")
return 1
}

ymlPath := filepath.Join(pkgDir, "apm.yml")
if _, err := os.Stat(ymlPath); err != nil {
fmt.Fprintf(os.Stderr, "[x] Package '%s' has no apm.yml in apm_modules/%s.\n", pkg, pkg)
return 1
}
meta, err := parseApmYML(ymlPath)
if err != nil {
fmt.Fprintf(os.Stderr, "[x] Could not read package metadata: %v\n", err)
return 1
}

fmt.Printf("Package: %s\n", meta.Name)
if meta.Version != "" {
fmt.Printf("Version: %s\n", meta.Version)
}
if len(meta.Deps) > 0 {
fmt.Println("Dependencies:")
for _, d := range meta.Deps {
fmt.Printf(" %s\n", d.Package)
}
}
return 0
}

Expand Down
37 changes: 37 additions & 0 deletions cmd/apm/parity_harness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,43 @@ func TestParityHarnessGoDepsTreeInTempRepo(t *testing.T) {
assertGoOutputContains(t, r, "test-project")
}

// TestParityHarnessDepInfoHelp verifies `apm deps info --help` shows PACKAGE argument.
func TestParityHarnessDepInfoHelp(t *testing.T) {
out, _, code := runGo(t, "deps", "info", "--help")
if code != 0 {
t.Fatalf("apm deps info --help exited %d, want 0", code)
}
if !strings.Contains(out, "PACKAGE") {
t.Errorf("apm deps info --help missing PACKAGE in output:\n%s", out)
}
}

// TestParityHarnessDepInfoMissingPackage checks both Python and Go exit non-zero
// when no PACKAGE argument is supplied to `apm deps info`.
// Python Click exits 2 with "Error: Missing argument 'PACKAGE'."
func TestParityHarnessDepInfoMissingPackage(t *testing.T) {
r := runBothInTempRepo(t, minimalApmYML, "deps", "info")
if r.GoExitCode == 0 {
t.Errorf("apm deps info with no package should fail, got exit 0\nstdout: %s", r.GoStdout)
}
// Both CLIs must emit an error indication.
combined := r.GoStdout + r.GoStderr
if !strings.Contains(combined, "PACKAGE") && !strings.Contains(combined, "package") && !strings.Contains(combined, "Missing") {
t.Errorf("apm deps info missing-arg error must mention package: %s", combined)
}
assertPythonVsGoExitCode(t, r)
}

// TestParityHarnessDepInfoNotInstalled checks both CLIs exit non-zero when
// the requested package is not installed in apm_modules/.
func TestParityHarnessDepInfoNotInstalled(t *testing.T) {
r := runBothInTempRepo(t, minimalApmYML, "deps", "info", "missing/package")
if r.GoExitCode == 0 {
t.Errorf("apm deps info missing/package should fail, got exit 0\nstdout: %s", r.GoStdout)
}
assertPythonVsGoExitCode(t, r)
}

// TestParityHarnessGoCacheHelp verifies `apm cache --help` lists subcommands.
func TestParityHarnessGoCacheHelp(t *testing.T) {
out, _, code := runGo(t, "cache", "--help")
Expand Down
38 changes: 25 additions & 13 deletions cmd/apm/testdata/go_cutover/python_test_coverage.json
Original file line number Diff line number Diff line change
Expand Up @@ -24223,16 +24223,20 @@
"TestParityHarnessGoDepsHelp"
],
"tests/integration/test_wave6_deps_cli_coverage.py::TestDepsInfo::test_info_no_apm_modules": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoNotInstalled"
],
"tests/integration/test_wave6_deps_cli_coverage.py::TestDepsInfo::test_info_package_found_by_full_path": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoHelp"
],
"tests/integration/test_wave6_deps_cli_coverage.py::TestDepsInfo::test_info_package_found_by_short_name": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoHelp"
],
"tests/integration/test_wave6_deps_cli_coverage.py::TestDepsInfo::test_info_package_not_found": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoNotInstalled"
],
"tests/integration/test_wave6_deps_cli_coverage.py::TestDepsListADOPackage::test_ado_package_is_detected": [
"TestParityHarnessGoDepsHelp"
Expand Down Expand Up @@ -30153,10 +30157,12 @@
"TestParityHarnessGoDepsHelp"
],
"tests/unit/commands/test_deps_cli_cli_surface.py::TestInfoCommand::test_info_no_modules_exits_with_error": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoNotInstalled"
],
"tests/unit/commands/test_deps_cli_cli_surface.py::TestInfoCommand::test_info_package_delegates_to_display": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoHelp"
],
"tests/unit/commands/test_deps_cli_cli_surface.py::TestListCommand::test_list_global_uses_user_scope": [
"TestParityHarnessGoDepsHelp"
Expand Down Expand Up @@ -30309,10 +30315,12 @@
"TestParityHarnessGoDepsHelp"
],
"tests/unit/commands/test_deps_cli_phase3.py::TestInfoCommand::test_info_no_modules_exits_with_error": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoNotInstalled"
],
"tests/unit/commands/test_deps_cli_phase3.py::TestInfoCommand::test_info_package_delegates_to_display": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoHelp"
],
"tests/unit/commands/test_deps_cli_phase3.py::TestListCommand::test_list_global_uses_user_scope": [
"TestParityHarnessGoDepsHelp"
Expand Down Expand Up @@ -60838,10 +60846,12 @@
"TestParityHarnessGoDepsHelp"
],
"tests/unit/test_deps_list_tree_info.py::TestDepsInfoCommand::test_info_no_apm_modules": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoNotInstalled"
],
"tests/unit/test_deps_list_tree_info.py::TestDepsInfoCommand::test_info_package_not_found": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoNotInstalled"
],
"tests/unit/test_deps_list_tree_info.py::TestDepsInfoCommand::test_info_short_package_name_fallback": [
"TestParityHarnessGoDepsHelp"
Expand All @@ -60853,10 +60863,12 @@
"TestParityHarnessGoDepsHelp"
],
"tests/unit/test_deps_list_tree_info.py::TestDepsInfoCommand::test_info_shows_package_details_fallback": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoHelp"
],
"tests/unit/test_deps_list_tree_info.py::TestDepsInfoCommand::test_info_without_apm_yml": [
"TestParityHarnessGoDepsHelp"
"TestParityHarnessGoDepsHelp",
"TestParityHarnessDepInfoMissingPackage"
],
"tests/unit/test_deps_list_tree_info.py::TestDepsListCommand::test_list_all_flag_calls_both_scopes": [
"TestParityHarnessGoDepsHelp"
Expand Down Expand Up @@ -73502,4 +73514,4 @@
},
"description": "Go cutover coverage manifest. Every legacy Python pytest node under tests/ (except tests/parity/) must appear here with one or more Go test names before the Go CLI can be declared a 100% migration.",
"schema_version": 1
}
}
Loading