From 128de25ccbf2c344384522891cc02b043500e1d8 Mon Sep 17 00:00:00 2001 From: Andrew Walsh Date: Sun, 16 Mar 2025 12:35:38 -0700 Subject: [PATCH] Add support for virtual packages and break out APT logic into common library. (#153) --- src/cmd/apt_query/main.go | 66 +--------- src/cmd/apt_query/main_test.go | 17 ++- ...outsalphasortedpackagenameversionpairs.log | 7 +- ...ultiversionwarning_stdoutsingleversion.log | 7 +- ...stentpackagename_stderrsaptcacheerrors.log | 9 +- ...ist_nopackagesgiven_stderrsargmismatch.log | 4 +- ...amepackagesdifferentorder_stdoutsmatch.log | 14 +- ...ts_stdoutssinglepackagenameversionpair.log | 7 +- ...sioncontainscolon_stdoutsentireversion.log | 7 +- ...lpackagesexists_stdoutsconcretepackage.log | 19 +++ src/internal/cmdtesting/cmdtesting.go | 20 +-- src/internal/common/apt.go | 123 ++++++++++++++++++ src/internal/common/{common.go => io.go} | 9 -- src/internal/common/strings.go | 44 +++++++ src/internal/exec/binexecutor.go | 20 ++- src/internal/exec/executor.go | 11 +- 16 files changed, 257 insertions(+), 127 deletions(-) create mode 100644 src/cmd/apt_query/testlogs/testnormalizedlist_virtualpackagesexists_stdoutsconcretepackage.log create mode 100644 src/internal/common/apt.go rename src/internal/common/{common.go => io.go} (90%) create mode 100644 src/internal/common/strings.go diff --git a/src/cmd/apt_query/main.go b/src/cmd/apt_query/main.go index 8992a45..b2df00c 100644 --- a/src/cmd/apt_query/main.go +++ b/src/cmd/apt_query/main.go @@ -4,71 +4,12 @@ import ( "flag" "fmt" "os" - "sort" - "strings" "awalsh128.com/cache-apt-pkgs-action/src/internal/common" "awalsh128.com/cache-apt-pkgs-action/src/internal/exec" "awalsh128.com/cache-apt-pkgs-action/src/internal/logging" ) -type AptPackage struct { - Name string - Version string -} - -type AptPackages []AptPackage - -func (ps AptPackages) serialize() string { - tokens := []string{} - for _, p := range ps { - tokens = append(tokens, p.Name+"="+p.Version) - } - return strings.Join(tokens, " ") -} - -// Gets the APT based packages as a sorted by name list (normalized). -func getPackages(executor exec.Executor, names []string) AptPackages { - prefixArgs := []string{"--quiet=0", "--no-all-versions", "show"} - execution := executor.Exec("apt-cache", append(prefixArgs, names...)...) - - err := execution.Error() - if err != nil { - logging.Fatal(err) - } - - pkgs := []AptPackage{} - errorMessages := []string{} - - for _, paragraph := range strings.Split(execution.Stdout, "\n\n") { - pkg := AptPackage{} - for _, line := range strings.Split(paragraph, "\n") { - if strings.HasPrefix(line, "Package: ") { - pkg.Name = strings.TrimSpace(strings.SplitN(line, ":", 2)[1]) - } else if strings.HasPrefix(line, "Version: ") { - pkg.Version = strings.TrimSpace(strings.SplitN(line, ":", 2)[1]) - } else if strings.HasPrefix(line, "N: Unable to locate package ") || strings.HasPrefix(line, "E: ") { - if !common.ContainsString(errorMessages, line) { - errorMessages = append(errorMessages, line) - } - } - } - if pkg.Name != "" { - pkgs = append(pkgs, pkg) - } - } - - if len(errorMessages) > 0 { - logging.Fatalf("Errors encountered in apt-cache output (see below):\n%s", strings.Join(errorMessages, "\n")) - } - - sort.Slice(pkgs, func(i, j int) bool { - return pkgs[i].Name < pkgs[j].Name - }) - - return pkgs -} - func getExecutor(replayFilename string) exec.Executor { if len(replayFilename) == 0 { return &exec.BinExecutor{} @@ -100,8 +41,11 @@ func main() { switch command { case "normalized-list": - pkgs := getPackages(executor, pkgNames) - fmt.Println(pkgs.serialize()) + pkgs, err := common.GetAptPackages(executor, pkgNames) + if err != nil { + logging.Fatalf("Encountered error resolving some or all package names, see combined std[out,err] below.\n%s", err.Error()) + } + fmt.Println(pkgs.Serialize()) default: logging.Fatalf("Command '%s' not recognized.", command) diff --git a/src/cmd/apt_query/main_test.go b/src/cmd/apt_query/main_test.go index 744e6fd..49e040d 100644 --- a/src/cmd/apt_query/main_test.go +++ b/src/cmd/apt_query/main_test.go @@ -19,11 +19,11 @@ func TestMain(m *testing.M) { func TestNormalizedList_MultiplePackagesExists_StdoutsAlphaSortedPackageNameVersionPairs(t *testing.T) { result := cmdtesting.New(t, createReplayLogs).Run("normalized-list", "xdot", "rolldice") - result.ExpectSuccessfulOut("rolldice=1.16-1build1 xdot=1.2-3") + result.ExpectSuccessfulOut("rolldice=1.16-1build1 xdot=1.1-2") } func TestNormalizedList_SamePackagesDifferentOrder_StdoutsMatch(t *testing.T) { - expected := "rolldice=1.16-1build1 xdot=1.2-3" + expected := "rolldice=1.16-1build1 xdot=1.1-2" ct := cmdtesting.New(t, createReplayLogs) @@ -36,24 +36,24 @@ func TestNormalizedList_SamePackagesDifferentOrder_StdoutsMatch(t *testing.T) { func TestNormalizedList_MultiVersionWarning_StdoutSingleVersion(t *testing.T) { var result = cmdtesting.New(t, createReplayLogs).Run("normalized-list", "libosmesa6-dev", "libgl1-mesa-dev") - result.ExpectSuccessfulOut("libgl1-mesa-dev=23.0.4-0ubuntu1~23.04.1 libosmesa6-dev=23.0.4-0ubuntu1~23.04.1") + result.ExpectSuccessfulOut("libgl1-mesa-dev=21.2.6-0ubuntu0.1~20.04.2 libosmesa6-dev=21.2.6-0ubuntu0.1~20.04.2") } func TestNormalizedList_SinglePackageExists_StdoutsSinglePackageNameVersionPair(t *testing.T) { var result = cmdtesting.New(t, createReplayLogs).Run("normalized-list", "xdot") - result.ExpectSuccessfulOut("xdot=1.2-3") + result.ExpectSuccessfulOut("xdot=1.1-2") } func TestNormalizedList_VersionContainsColon_StdoutsEntireVersion(t *testing.T) { var result = cmdtesting.New(t, createReplayLogs).Run("normalized-list", "default-jre") - result.ExpectSuccessfulOut("default-jre=2:1.17-74") + result.ExpectSuccessfulOut("default-jre=2:1.11-72") } func TestNormalizedList_NonExistentPackageName_StderrsAptCacheErrors(t *testing.T) { var result = cmdtesting.New(t, createReplayLogs).Run("normalized-list", "nonexistentpackagename") result.ExpectError( `Error encountered running apt-cache --quiet=0 --no-all-versions show nonexistentpackagename -Exited with status code 100; see combined output below: +Exited with status code 100; see combined std[out,err] below: N: Unable to locate package nonexistentpackagename N: Unable to locate package nonexistentpackagename E: No packages found`) @@ -63,3 +63,8 @@ func TestNormalizedList_NoPackagesGiven_StderrsArgMismatch(t *testing.T) { var result = cmdtesting.New(t, createReplayLogs).Run("normalized-list") result.ExpectError("Expected at least 2 non-flag arguments but found 1.") } + +func TestNormalizedList_VirtualPackagesExists_StdoutsConcretePackage(t *testing.T) { + result := cmdtesting.New(t, createReplayLogs).Run("normalized-list", "libvips") + result.ExpectSuccessfulOut("libvips42=8.9.1-2") +} diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_multiplepackagesexists_stdoutsalphasortedpackagenameversionpairs.log b/src/cmd/apt_query/testlogs/testnormalizedlist_multiplepackagesexists_stdoutsalphasortedpackagenameversionpairs.log index ce1d6c0..8fc29f0 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_multiplepackagesexists_stdoutsalphasortedpackagenameversionpairs.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_multiplepackagesexists_stdoutsalphasortedpackagenameversionpairs.log @@ -1,9 +1,10 @@ -2023/12/10 14:09:15 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:15 EXECUTION-OBJ-START +2025/03/15 22:29:08 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:09 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show xdot rolldice", - "Stdout": "Package: xdot\nArchitecture: all\nVersion: 1.2-3\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Python Team \u003cteam+python@tracker.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 160\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3-numpy, python3:any\nFilename: pool/universe/x/xdot/xdot_1.2-3_all.deb\nSize: 28504\nMD5sum: 9fd56a82e8e6dc2b18fad996dd35bcdb\nSHA1: 9dfa42283c7326da18b132e61369fc8d70534f4b\nSHA256: 0dd59c1840b7f2322cf408f9634c83c4f9766a5e609813147cd67e44755bc011\nSHA512: 33d418475bb9977341007528d8622d236b59a5da4f7fb7f6a36aa05256c4789af30868fc2aad7fc17fb726c8814333cdc579a4ae01597f8f5864b4fbfd8dff14\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\nPackage: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nSHA512: a2fa75cfc6f9fc0f1fce3601668bc060f9e10bcf94887025af755ef73db84c55383ed34e4199de53dfbb34377b050c1f9947f29b28d8e527509900f2ec872826\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\n", + "Stdout": "Package: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\nPackage: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\n", "Stderr": "", + "CombinedOut": "Package: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\nPackage: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\n", "ExitCode": 0 } EXECUTION-OBJ-END diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_multiversionwarning_stdoutsingleversion.log b/src/cmd/apt_query/testlogs/testnormalizedlist_multiversionwarning_stdoutsingleversion.log index 32b344d..028edbc 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_multiversionwarning_stdoutsingleversion.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_multiversionwarning_stdoutsingleversion.log @@ -1,9 +1,10 @@ -2023/12/10 14:09:17 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:18 EXECUTION-OBJ-START +2025/03/15 22:29:10 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:12 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show libosmesa6-dev libgl1-mesa-dev", - "Stdout": "Package: libosmesa6-dev\nArchitecture: amd64\nVersion: 23.0.4-0ubuntu1~23.04.1\nMulti-Arch: same\nPriority: extra\nSection: devel\nSource: mesa\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian X Strike Force \u003cdebian-x@lists.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 51\nProvides: libosmesa-dev\nDepends: libosmesa6 (= 23.0.4-0ubuntu1~23.04.1), mesa-common-dev (= 23.0.4-0ubuntu1~23.04.1) | libgl-dev\nConflicts: libosmesa-dev\nReplaces: libosmesa-dev\nFilename: pool/main/m/mesa/libosmesa6-dev_23.0.4-0ubuntu1~23.04.1_amd64.deb\nSize: 9016\nMD5sum: f2a03da1adaa37afc32493bc52913fe1\nSHA1: 3b0f26ba8438fe6f590cc38d412e0bc1b27f9831\nSHA256: 3fcd3b5c80bde4af1765e588e8f1301ddccae4e052cbfca1a32120d9d8697656\nSHA512: 0a88153218f263511cacffbfe9afd928679f7fa4aacefebd21bafae0517ef1cd3b4bef4fc676e7586728ce1257fbbeb8bd0dda02ddc54fe83c90800f5ce0a660\nHomepage: https://mesa3d.org/\nDescription-en: Mesa Off-screen rendering extension -- development files\n This package provides the required environment for developing programs\n that use the off-screen rendering extension of Mesa.\n .\n For more information on OSmesa see the libosmesa6 package.\nDescription-md5: 9b1d7a0b3e6a2ea021f4443f42dcff4f\n\nPackage: libgl1-mesa-dev\nArchitecture: amd64\nVersion: 23.0.4-0ubuntu1~23.04.1\nMulti-Arch: same\nPriority: extra\nSection: libdevel\nSource: mesa\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian X Strike Force \u003cdebian-x@lists.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 33\nDepends: libgl-dev, libglvnd-dev\nFilename: pool/main/m/mesa/libgl1-mesa-dev_23.0.4-0ubuntu1~23.04.1_amd64.deb\nSize: 13908\nMD5sum: af15873cbc37ae8719487216f2465a7f\nSHA1: 0a04c22bd32578c65da6cab759347d22cbe2601f\nSHA256: 7b4b377658aff6aaa42af0cf220a64fe7ccd20b53ed0226b6b96edae5ce65dbe\nSHA512: f5b7c9324e7f1f8764a4a035182514559a17a96ce3d43ba570ebd32746de219bea035de3600850134b4f0ba62f12caf0e281fcf7c5490d93e1bd93ca27bfdd22\nHomepage: https://mesa3d.org/\nDescription-en: transitional dummy package\n This is a transitional dummy package, it can be safely removed.\nDescription-md5: 635a93bcd1440d16621693fe064c2aa9\n\n", + "Stdout": "Package: libosmesa6-dev\nArchitecture: amd64\nVersion: 21.2.6-0ubuntu0.1~20.04.2\nMulti-Arch: same\nPriority: extra\nSection: devel\nSource: mesa\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian X Strike Force \u003cdebian-x@lists.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 88\nProvides: libosmesa-dev\nDepends: libosmesa6 (= 21.2.6-0ubuntu0.1~20.04.2), mesa-common-dev (= 21.2.6-0ubuntu0.1~20.04.2) | libgl-dev\nConflicts: libosmesa-dev\nReplaces: libosmesa-dev\nFilename: pool/main/m/mesa/libosmesa6-dev_21.2.6-0ubuntu0.1~20.04.2_amd64.deb\nSize: 8844\nMD5sum: b6c380d1b916bc6955aaf108a3be468e\nSHA1: 4b772c8127e60a342dabec4ff0939969d99038b4\nSHA256: bf003b66573d611877664e01659046d281b26698f3665345cb784ddded662c6a\nSHA512: 761557925874473e4408504772a0af4d29f6dc1dcbd53e772315dffb6da87d47960edca4de39deda7cae33a8730d87a19b40a7d29739ba7cff5b60ee4900a13a\nHomepage: https://mesa3d.org/\nDescription-en: Mesa Off-screen rendering extension -- development files\n This package provides the required environment for developing programs\n that use the off-screen rendering extension of Mesa.\n .\n For more information on OSmesa see the libosmesa6 package.\nDescription-md5: 9b1d7a0b3e6a2ea021f4443f42dcff4f\n\nPackage: libgl1-mesa-dev\nArchitecture: amd64\nVersion: 21.2.6-0ubuntu0.1~20.04.2\nMulti-Arch: same\nPriority: extra\nSection: libdevel\nSource: mesa\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian X Strike Force \u003cdebian-x@lists.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 70\nDepends: libgl-dev, libglvnd-dev\nFilename: pool/main/m/mesa/libgl1-mesa-dev_21.2.6-0ubuntu0.1~20.04.2_amd64.deb\nSize: 6420\nMD5sum: 759a811dcb12adfcebfc1a6aa52e85b9\nSHA1: 3b9de17b1c67ee40603e1eebaefa978810a2f2d2\nSHA256: 76846d96ae0706a7edcd514d452a1393bb8b8a8ac06518253dd5869441807052\nSHA512: 581e4b3752b4c98399f3519fce2c5ab033cea3cac66bde3c204af769ff0377400087f9c4c6aaebe06c19d05f8715b3346d249a86c3ae80a098ca476e76af01c3\nHomepage: https://mesa3d.org/\nDescription-en: transitional dummy package\n This is a transitional dummy package, it can be safely removed.\nDescription-md5: 635a93bcd1440d16621693fe064c2aa9\n\n", "Stderr": "N: There are 2 additional records. Please use the '-a' switch to see them.\n", + "CombinedOut": "Package: libosmesa6-dev\nArchitecture: amd64\nVersion: 21.2.6-0ubuntu0.1~20.04.2\nMulti-Arch: same\nPriority: extra\nSection: devel\nSource: mesa\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian X Strike Force \u003cdebian-x@lists.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 88\nProvides: libosmesa-dev\nDepends: libosmesa6 (= 21.2.6-0ubuntu0.1~20.04.2), mesa-common-dev (= 21.2.6-0ubuntu0.1~20.04.2) | libgl-dev\nConflicts: libosmesa-dev\nReplaces: libosmesa-dev\nFilename: pool/main/m/mesa/libosmesa6-dev_21.2.6-0ubuntu0.1~20.04.2_amd64.deb\nSize: 8844\nMD5sum: b6c380d1b916bc6955aaf108a3be468e\nSHA1: 4b772c8127e60a342dabec4ff0939969d99038b4\nSHA256: bf003b66573d611877664e01659046d281b26698f3665345cb784ddded662c6a\nSHA512: 761557925874473e4408504772a0af4d29f6dc1dcbd53e772315dffb6da87d47960edca4de39deda7cae33a8730d87a19b40a7d29739ba7cff5b60ee4900a13a\nHomepage: https://mesa3d.org/\nDescription-en: Mesa Off-screen rendering extension -- development files\n This package provides the required environment for developing programs\n that use the off-screen rendering extension of Mesa.\n .\n For more information on OSmesa see the libosmesa6 package.\nDescription-md5: 9b1d7a0b3e6a2ea021f4443f42dcff4f\n\nPackage: libgl1-mesa-dev\nArchitecture: amd64\nVersion: 21.2.6-0ubuntu0.1~20.04.2\nMulti-Arch: same\nPriority: extra\nSection: libdevel\nSource: mesa\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian X Strike Force \u003cdebian-x@lists.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 70\nDepends: libgl-dev, libglvnd-dev\nFilename: pool/main/m/mesa/libgl1-mesa-dev_21.2.6-0ubuntu0.1~20.04.2_amd64.deb\nSize: 6420\nMD5sum: 759a811dcb12adfcebfc1a6aa52e85b9\nSHA1: 3b9de17b1c67ee40603e1eebaefa978810a2f2d2\nSHA256: 76846d96ae0706a7edcd514d452a1393bb8b8a8ac06518253dd5869441807052\nSHA512: 581e4b3752b4c98399f3519fce2c5ab033cea3cac66bde3c204af769ff0377400087f9c4c6aaebe06c19d05f8715b3346d249a86c3ae80a098ca476e76af01c3\nHomepage: https://mesa3d.org/\nDescription-en: transitional dummy package\n This is a transitional dummy package, it can be safely removed.\nDescription-md5: 635a93bcd1440d16621693fe064c2aa9\n\nN: There are 2 additional records. Please use the '-a' switch to see them.\n", "ExitCode": 0 } EXECUTION-OBJ-END diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_nonexistentpackagename_stderrsaptcacheerrors.log b/src/cmd/apt_query/testlogs/testnormalizedlist_nonexistentpackagename_stderrsaptcacheerrors.log index 7e9e9c2..3523448 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_nonexistentpackagename_stderrsaptcacheerrors.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_nonexistentpackagename_stderrsaptcacheerrors.log @@ -1,14 +1,15 @@ -2023/12/10 14:09:19 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:20 EXECUTION-OBJ-START +2025/03/15 22:29:13 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:14 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show nonexistentpackagename", "Stdout": "", "Stderr": "N: Unable to locate package nonexistentpackagename\nN: Unable to locate package nonexistentpackagename\nE: No packages found\n", + "CombinedOut": "N: Unable to locate package nonexistentpackagename\nN: Unable to locate package nonexistentpackagename\nE: No packages found\n", "ExitCode": 100 } EXECUTION-OBJ-END -2023/12/10 14:09:20 Error encountered running apt-cache --quiet=0 --no-all-versions show nonexistentpackagename -Exited with status code 100; see combined output below: +2025/03/15 22:29:14 Error encountered running apt-cache --quiet=0 --no-all-versions show nonexistentpackagename +Exited with status code 100; see combined std[out,err] below: N: Unable to locate package nonexistentpackagename N: Unable to locate package nonexistentpackagename E: No packages found diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_nopackagesgiven_stderrsargmismatch.log b/src/cmd/apt_query/testlogs/testnormalizedlist_nopackagesgiven_stderrsargmismatch.log index bd9c530..fbf15a6 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_nopackagesgiven_stderrsargmismatch.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_nopackagesgiven_stderrsargmismatch.log @@ -1,2 +1,2 @@ -2023/12/10 14:09:20 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:20 Expected at least 2 non-flag arguments but found 1. +2025/03/15 22:29:14 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:14 Expected at least 2 non-flag arguments but found 1. diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_samepackagesdifferentorder_stdoutsmatch.log b/src/cmd/apt_query/testlogs/testnormalizedlist_samepackagesdifferentorder_stdoutsmatch.log index c7a9b5b..6e53eef 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_samepackagesdifferentorder_stdoutsmatch.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_samepackagesdifferentorder_stdoutsmatch.log @@ -1,18 +1,20 @@ -2023/12/10 14:09:15 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:16 EXECUTION-OBJ-START +2025/03/15 22:29:09 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:10 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show rolldice xdot", - "Stdout": "Package: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nSHA512: a2fa75cfc6f9fc0f1fce3601668bc060f9e10bcf94887025af755ef73db84c55383ed34e4199de53dfbb34377b050c1f9947f29b28d8e527509900f2ec872826\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\nPackage: xdot\nArchitecture: all\nVersion: 1.2-3\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Python Team \u003cteam+python@tracker.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 160\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3-numpy, python3:any\nFilename: pool/universe/x/xdot/xdot_1.2-3_all.deb\nSize: 28504\nMD5sum: 9fd56a82e8e6dc2b18fad996dd35bcdb\nSHA1: 9dfa42283c7326da18b132e61369fc8d70534f4b\nSHA256: 0dd59c1840b7f2322cf408f9634c83c4f9766a5e609813147cd67e44755bc011\nSHA512: 33d418475bb9977341007528d8622d236b59a5da4f7fb7f6a36aa05256c4789af30868fc2aad7fc17fb726c8814333cdc579a4ae01597f8f5864b4fbfd8dff14\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\n", + "Stdout": "Package: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\nPackage: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\n", "Stderr": "", + "CombinedOut": "Package: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\nPackage: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\n", "ExitCode": 0 } EXECUTION-OBJ-END -2023/12/10 14:09:16 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:17 EXECUTION-OBJ-START +2025/03/15 22:29:10 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:10 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show xdot rolldice", - "Stdout": "Package: xdot\nArchitecture: all\nVersion: 1.2-3\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Python Team \u003cteam+python@tracker.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 160\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3-numpy, python3:any\nFilename: pool/universe/x/xdot/xdot_1.2-3_all.deb\nSize: 28504\nMD5sum: 9fd56a82e8e6dc2b18fad996dd35bcdb\nSHA1: 9dfa42283c7326da18b132e61369fc8d70534f4b\nSHA256: 0dd59c1840b7f2322cf408f9634c83c4f9766a5e609813147cd67e44755bc011\nSHA512: 33d418475bb9977341007528d8622d236b59a5da4f7fb7f6a36aa05256c4789af30868fc2aad7fc17fb726c8814333cdc579a4ae01597f8f5864b4fbfd8dff14\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\nPackage: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nSHA512: a2fa75cfc6f9fc0f1fce3601668bc060f9e10bcf94887025af755ef73db84c55383ed34e4199de53dfbb34377b050c1f9947f29b28d8e527509900f2ec872826\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\n", + "Stdout": "Package: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\nPackage: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\n", "Stderr": "", + "CombinedOut": "Package: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\nPackage: rolldice\nArchitecture: amd64\nVersion: 1.16-1build1\nPriority: optional\nSection: universe/games\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Thomas Ross \u003cthomasross@thomasross.io\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 31\nDepends: libc6 (\u003e= 2.7), libreadline8 (\u003e= 6.0)\nFilename: pool/universe/r/rolldice/rolldice_1.16-1build1_amd64.deb\nSize: 9628\nMD5sum: af6390bf2d5d5b4710d308ac06d4913a\nSHA1: 1d87ccac5b20f4e2a217a0e058408f46cfe5caff\nSHA256: 2e076006200057da0be52060e3cc2f4fc7c51212867173e727590bd7603a0337\nHomepage: https://github.com/sstrickl/rolldice\nDescription-en: virtual dice roller\n rolldice is a virtual dice roller that takes a string on the command\n line in the format of some fantasy role playing games like Advanced\n Dungeons \u0026 Dragons [1] and returns the result of the dice rolls.\n .\n [1] Advanced Dungeons \u0026 Dragons is a registered trademark of TSR, Inc.\nDescription-md5: fc24e9e12c794a8f92ab0ca6e1058501\n\n", "ExitCode": 0 } EXECUTION-OBJ-END diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_singlepackageexists_stdoutssinglepackagenameversionpair.log b/src/cmd/apt_query/testlogs/testnormalizedlist_singlepackageexists_stdoutssinglepackagenameversionpair.log index b244b36..be926ab 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_singlepackageexists_stdoutssinglepackagenameversionpair.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_singlepackageexists_stdoutssinglepackagenameversionpair.log @@ -1,9 +1,10 @@ -2023/12/10 14:09:18 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:18 EXECUTION-OBJ-START +2025/03/15 22:29:12 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:12 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show xdot", - "Stdout": "Package: xdot\nArchitecture: all\nVersion: 1.2-3\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Python Team \u003cteam+python@tracker.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 160\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3-numpy, python3:any\nFilename: pool/universe/x/xdot/xdot_1.2-3_all.deb\nSize: 28504\nMD5sum: 9fd56a82e8e6dc2b18fad996dd35bcdb\nSHA1: 9dfa42283c7326da18b132e61369fc8d70534f4b\nSHA256: 0dd59c1840b7f2322cf408f9634c83c4f9766a5e609813147cd67e44755bc011\nSHA512: 33d418475bb9977341007528d8622d236b59a5da4f7fb7f6a36aa05256c4789af30868fc2aad7fc17fb726c8814333cdc579a4ae01597f8f5864b4fbfd8dff14\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\n", + "Stdout": "Package: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\n", "Stderr": "", + "CombinedOut": "Package: xdot\nArchitecture: all\nVersion: 1.1-2\nPriority: optional\nSection: universe/python\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Python Applications Packaging Team \u003cpython-apps-team@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 153\nDepends: gir1.2-gtk-3.0, graphviz, python3-gi, python3-gi-cairo, python3:any\nFilename: pool/universe/x/xdot/xdot_1.1-2_all.deb\nSize: 26708\nMD5sum: aab630b6e1f73a0e3ae85b208b8b6d00\nSHA1: 202155c123c7bd7628023b848e997f342d14359d\nSHA256: 4b7ecb2c4dc948a850024a9b7378d58195230659307bbde4018a1be17645e690\nHomepage: https://github.com/jrfonseca/xdot.py\nDescription-en: interactive viewer for Graphviz dot files\n xdot is an interactive viewer for graphs written in Graphviz's dot language.\n It uses internally the graphviz's xdot output format as an intermediate\n format, and PyGTK and Cairo for rendering. xdot can be used either as a\n standalone application from command line, or as a library embedded in your\n Python 3 application.\n .\n Features:\n * Since it doesn't use bitmaps it is fast and has a small memory footprint.\n * Arbitrary zoom.\n * Keyboard/mouse navigation.\n * Supports events on the nodes with URLs.\n * Animated jumping between nodes.\n * Highlights node/edge under mouse.\nDescription-md5: eb58f25a628b48a744f1b904af3b9282\n\n", "ExitCode": 0 } EXECUTION-OBJ-END diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_versioncontainscolon_stdoutsentireversion.log b/src/cmd/apt_query/testlogs/testnormalizedlist_versioncontainscolon_stdoutsentireversion.log index 441de8f..9c986f5 100644 --- a/src/cmd/apt_query/testlogs/testnormalizedlist_versioncontainscolon_stdoutsentireversion.log +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_versioncontainscolon_stdoutsentireversion.log @@ -1,9 +1,10 @@ -2023/12/10 14:09:18 Debug log created at /home/awalsh128/code/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log -2023/12/10 14:09:19 EXECUTION-OBJ-START +2025/03/15 22:29:12 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:13 EXECUTION-OBJ-START { "Cmd": "apt-cache --quiet=0 --no-all-versions show default-jre", - "Stdout": "Package: default-jre\nArchitecture: amd64\nVersion: 2:1.17-74\nPriority: optional\nSection: interpreters\nSource: java-common (0.74)\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Java Maintainers \u003cpkg-java-maintainers@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 6\nProvides: java-runtime (= 17), java10-runtime, java11-runtime, java12-runtime, java13-runtime, java14-runtime, java15-runtime, java16-runtime, java17-runtime, java2-runtime, java5-runtime, java6-runtime, java7-runtime, java8-runtime, java9-runtime\nDepends: default-jre-headless (= 2:1.17-74), openjdk-17-jre\nFilename: pool/main/j/java-common/default-jre_1.17-74_amd64.deb\nSize: 912\nMD5sum: e1c24f152396655f96dbaa749bd9cd2e\nSHA1: b1eeca19c6a29448ecc81df249bafdedbe49ee04\nSHA256: 02b1e27de90f05af42d61af927c35f17f7ba1ffe19bf64598ec68216075f623f\nSHA512: 81577c1e4b6920a3fb296a2cdb301131283762efa9fa371e6aa8bc31c7ee1292bbbc442984b2e2ce5d8788507f396eb3e03c1ff8c4dda671f329ac08ec0b2057\nHomepage: https://wiki.debian.org/Java/\nDescription-en: Standard Java or Java compatible Runtime\n This dependency package points to the Java runtime, or Java compatible\n runtime recommended for this architecture, which is\n openjdk-17-jre for amd64.\nDescription-md5: e747dcb24f92ffabcbdfba1db72f26e8\nTask: edubuntu-desktop-gnome\nCnf-Extra-Commands: java,jexec\n\n", + "Stdout": "Package: default-jre\nArchitecture: amd64\nVersion: 2:1.11-72\nPriority: optional\nSection: interpreters\nSource: java-common (0.72)\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Java Maintainers \u003cpkg-java-maintainers@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 6\nProvides: java-runtime, java10-runtime, java11-runtime, java2-runtime, java5-runtime, java6-runtime, java7-runtime, java8-runtime, java9-runtime\nDepends: default-jre-headless (= 2:1.11-72), openjdk-11-jre\nFilename: pool/main/j/java-common/default-jre_1.11-72_amd64.deb\nSize: 1084\nMD5sum: 4f441bb884801f3a07806934e4519652\nSHA1: 9922edaa7bd91921a2beee6c60343ebf551957a9\nSHA256: 063bb2ca3b51309f6625033c336beffb0eb8286aaabcf3bf917eef498de29ea5\nHomepage: https://wiki.debian.org/Java/\nDescription-en: Standard Java or Java compatible Runtime\n This dependency package points to the Java runtime, or Java compatible\n runtime recommended for this architecture, which is\n openjdk-11-jre for amd64.\nDescription-md5: 071b7a2f9baf048d89c849c14bcafb9e\nCnf-Extra-Commands: java,jexec\n\n", "Stderr": "", + "CombinedOut": "Package: default-jre\nArchitecture: amd64\nVersion: 2:1.11-72\nPriority: optional\nSection: interpreters\nSource: java-common (0.72)\nOrigin: Ubuntu\nMaintainer: Ubuntu Developers \u003cubuntu-devel-discuss@lists.ubuntu.com\u003e\nOriginal-Maintainer: Debian Java Maintainers \u003cpkg-java-maintainers@lists.alioth.debian.org\u003e\nBugs: https://bugs.launchpad.net/ubuntu/+filebug\nInstalled-Size: 6\nProvides: java-runtime, java10-runtime, java11-runtime, java2-runtime, java5-runtime, java6-runtime, java7-runtime, java8-runtime, java9-runtime\nDepends: default-jre-headless (= 2:1.11-72), openjdk-11-jre\nFilename: pool/main/j/java-common/default-jre_1.11-72_amd64.deb\nSize: 1084\nMD5sum: 4f441bb884801f3a07806934e4519652\nSHA1: 9922edaa7bd91921a2beee6c60343ebf551957a9\nSHA256: 063bb2ca3b51309f6625033c336beffb0eb8286aaabcf3bf917eef498de29ea5\nHomepage: https://wiki.debian.org/Java/\nDescription-en: Standard Java or Java compatible Runtime\n This dependency package points to the Java runtime, or Java compatible\n runtime recommended for this architecture, which is\n openjdk-11-jre for amd64.\nDescription-md5: 071b7a2f9baf048d89c849c14bcafb9e\nCnf-Extra-Commands: java,jexec\n\n", "ExitCode": 0 } EXECUTION-OBJ-END diff --git a/src/cmd/apt_query/testlogs/testnormalizedlist_virtualpackagesexists_stdoutsconcretepackage.log b/src/cmd/apt_query/testlogs/testnormalizedlist_virtualpackagesexists_stdoutsconcretepackage.log new file mode 100644 index 0000000..58d6b77 --- /dev/null +++ b/src/cmd/apt_query/testlogs/testnormalizedlist_virtualpackagesexists_stdoutsconcretepackage.log @@ -0,0 +1,19 @@ +2025/03/15 22:29:14 Debug log created at /home/awalsh128/cache-apt-pkgs-action/src/cmd/apt_query/apt_query.log +2025/03/15 22:29:14 EXECUTION-OBJ-START +{ + "Cmd": "apt-cache --quiet=0 --no-all-versions show libvips", + "Stdout": "", + "Stderr": "N: Can't select candidate version from package libvips as it has no candidate\nN: Can't select versions from package 'libvips' as it is purely virtual\nN: No packages found\n", + "CombinedOut": "N: Can't select candidate version from package libvips as it has no candidate\nN: Can't select versions from package 'libvips' as it is purely virtual\nN: No packages found\n", + "ExitCode": 0 +} +EXECUTION-OBJ-END +2025/03/15 22:29:14 EXECUTION-OBJ-START +{ + "Cmd": "bash -c apt-cache showpkg libvips | grep -A 1 \"Reverse Provides\" | tail -1", + "Stdout": "libvips42 8.9.1-2 (= )\n", + "Stderr": "", + "CombinedOut": "libvips42 8.9.1-2 (= )\n", + "ExitCode": 0 +} +EXECUTION-OBJ-END diff --git a/src/internal/cmdtesting/cmdtesting.go b/src/internal/cmdtesting/cmdtesting.go index 30519fd..4b6555c 100644 --- a/src/internal/cmdtesting/cmdtesting.go +++ b/src/internal/cmdtesting/cmdtesting.go @@ -28,7 +28,7 @@ func New(t *testing.T, createReplayLogs bool) *CmdTesting { type RunResult struct { Testing *CmdTesting - Combinedout string + CombinedOut string Err error } @@ -50,7 +50,7 @@ func (t *CmdTesting) Run(command string, pkgNames ...string) RunResult { } cmd := exec.Command("./"+binaryName, append(append(flags, command), pkgNames...)...) - combinedout, err := cmd.CombinedOutput() + combinedOut, err := cmd.CombinedOutput() if t.createReplayLogs { err := common.AppendFile(binaryName+".log", t.replayFilename) @@ -59,7 +59,7 @@ func (t *CmdTesting) Run(command string, pkgNames ...string) RunResult { } } - return RunResult{Testing: t, Combinedout: string(combinedout), Err: err} + return RunResult{Testing: t, CombinedOut: string(combinedOut), Err: err} } func (r *RunResult) ExpectSuccessfulOut(expected string) { @@ -69,23 +69,23 @@ func (r *RunResult) ExpectSuccessfulOut(expected string) { } if r.Err != nil { - r.Testing.Errorf("Error running command: %v\n%s", r.Err, r.Combinedout) + r.Testing.Errorf("Error running command: %v\n%s", r.Err, r.CombinedOut) return } fullExpected := expected + "\n" // Output will always have a end of output newline. - if r.Combinedout != fullExpected { - r.Testing.Errorf("Unexpected combined std[err,out] found.\nExpected:\n'%s'\nActual:\n'%s'", fullExpected, r.Combinedout) + if r.CombinedOut != fullExpected { + r.Testing.Errorf("Unexpected combined std[err,out] found.\nExpected:\n'%s'\nActual:\n'%s'", fullExpected, r.CombinedOut) } } -func (r *RunResult) ExpectError(expectedCombinedout string) { +func (r *RunResult) ExpectError(expectedCombinedOut string) { if r.Testing.createReplayLogs { r.Testing.Log("Skipping test while creating replay logs.") return } - fullExpectedCombinedout := expectedCombinedout + "\n" // Output will always have a end of output newline. - if r.Combinedout != fullExpectedCombinedout { - r.Testing.Errorf("Unexpected combined std[err,out] found.\nExpected:\n'%s'\nActual:\n'%s'", fullExpectedCombinedout, r.Combinedout) + fullExpectedCombinedOut := expectedCombinedOut + "\n" // Output will always have a end of output newline. + if r.CombinedOut != fullExpectedCombinedOut { + r.Testing.Errorf("Unexpected combined std[err,out] found.\nExpected:\n'%s'\nActual:\n'%s'", fullExpectedCombinedOut, r.CombinedOut) } } diff --git a/src/internal/common/apt.go b/src/internal/common/apt.go new file mode 100644 index 0000000..d440256 --- /dev/null +++ b/src/internal/common/apt.go @@ -0,0 +1,123 @@ +package common + +import ( + "errors" + "fmt" + "sort" + "strings" + + "awalsh128.com/cache-apt-pkgs-action/src/internal/exec" + "awalsh128.com/cache-apt-pkgs-action/src/internal/logging" +) + +// An APT package name and version representation. +type AptPackage struct { + Name string + Version string +} + +type AptPackages []AptPackage + +// Serialize the APT packages into lines of =. +func (ps AptPackages) Serialize() string { + tokens := []string{} + for _, p := range ps { + tokens = append(tokens, p.Name+"="+p.Version) + } + return strings.Join(tokens, " ") +} + +func isErrLine(line string) bool { + return strings.HasPrefix(line, "E: ") || strings.HasPrefix(line, "N: ") +} + +// Resolves virtual packages names to their concrete one. +func getNonVirtualPackage(executor exec.Executor, name string) (pkg *AptPackage, err error) { + execution := executor.Exec("bash", "-c", fmt.Sprintf("apt-cache showpkg %s | grep -A 1 \"Reverse Provides\" | tail -1", name)) + err = execution.Error() + if err != nil { + logging.Fatal(err) + return pkg, err + } + if isErrLine(execution.CombinedOut) { + return pkg, execution.Error() + } + splitLine := GetSplitLine(execution.CombinedOut, " ", 3) + if len(splitLine.Words) < 2 { + return pkg, fmt.Errorf("unable to parse space delimited line's package name and version from apt-cache showpkg output below:\n%s", execution.CombinedOut) + } + return &AptPackage{Name: splitLine.Words[0], Version: splitLine.Words[1]}, nil +} + +func getPackage(executor exec.Executor, paragraph string) (pkg *AptPackage, err error) { + errMsgs := []string{} + for _, splitLine := range GetSplitLines(paragraph, ":", 2) { + switch splitLine.Words[0] { + case "Package": + // Initialize since this will provide the first struct value if present. + pkg = &AptPackage{} + pkg.Name = splitLine.Words[1] + + case "Version": + pkg.Version = splitLine.Words[1] + + case "N": + // e.g. Can't select versions from package 'libvips' as it is purely virtual + if strings.Contains(splitLine.Words[1], "as it is purely virtual") { + return getNonVirtualPackage(executor, GetSplitLine(splitLine.Words[1], "'", 4).Words[2]) + } + if strings.HasPrefix(splitLine.Words[1], "Unable to locate package") && !ArrContainsString(errMsgs, splitLine.Line) { + errMsgs = append(errMsgs, splitLine.Line) + } + case "E": + if !ArrContainsString(errMsgs, splitLine.Line) { + errMsgs = append(errMsgs, splitLine.Line) + } + } + } + if len(errMsgs) == 0 { + return pkg, nil + } + return pkg, errors.New(strings.Join(errMsgs, "\n")) +} + +// Gets the APT based packages as a sorted by package name list (normalized). +func GetAptPackages(executor exec.Executor, names []string) (AptPackages, error) { + prefixArgs := []string{"--quiet=0", "--no-all-versions", "show"} + execution := executor.Exec("apt-cache", append(prefixArgs, names...)...) + pkgs := []AptPackage{} + + err := execution.Error() + if err != nil { + logging.Fatal(err) + return pkgs, err + } + + errMsgs := []string{} + + for _, paragraph := range strings.Split(execution.CombinedOut, "\n\n") { + trimmed := strings.TrimSpace(paragraph) + if trimmed == "" { + continue + } + pkg, err := getPackage(executor, trimmed) + if err != nil { + errMsgs = append(errMsgs, err.Error()) + } else if pkg != nil { // Ignore cases where no package parsed and no errors occurred. + pkgs = append(pkgs, *pkg) + } + } + + if len(errMsgs) > 0 { + errMsgs = append(errMsgs, strings.Join(errMsgs, "\n")) + } + + sort.Slice(pkgs, func(i, j int) bool { + return pkgs[i].Name < pkgs[j].Name + }) + if len(errMsgs) > 0 { + return pkgs, errors.New(strings.Join(errMsgs, "\n")) + } + + return pkgs, nil +} diff --git a/src/internal/common/common.go b/src/internal/common/io.go similarity index 90% rename from src/internal/common/common.go rename to src/internal/common/io.go index 1191888..a05a62e 100644 --- a/src/internal/common/common.go +++ b/src/internal/common/io.go @@ -74,15 +74,6 @@ func MoveFile(source string, destination string) error { return os.Rename(source, destination) } -func ContainsString(arr []string, element string) bool { - for _, x := range arr { - if x == element { - return true - } - } - return false -} - func createDirectoryIfNotPresent(path string) error { if _, err := os.Stat(path); os.IsNotExist(err) { err := os.MkdirAll(path, 0755) diff --git a/src/internal/common/strings.go b/src/internal/common/strings.go new file mode 100644 index 0000000..05da5a6 --- /dev/null +++ b/src/internal/common/strings.go @@ -0,0 +1,44 @@ +package common + +import ( + "strings" +) + +// Checks if an exact string is in an array of strings. +func ArrContainsString(arr []string, element string) bool { + for _, x := range arr { + if x == element { + return true + } + } + return false +} + +// A line that has been split into words. +type SplitLine struct { + Line string // The original line. + Words []string // The split words in the line. +} + +// Splits a line into words by the delimiter and max number of delimitation. +func GetSplitLine(line string, delimiter string, numWords int) SplitLine { + words := strings.SplitN(line, delimiter, numWords) + trimmedWords := make([]string, len(words)) + for i, word := range words { + trimmedWords[i] = strings.TrimSpace(word) + } + return SplitLine{line, trimmedWords} +} + +// Splits a paragraph into lines by newline and then splits each line into words specified by the delimiter and max number of delimitation. +func GetSplitLines(paragraph string, delimiter string, numWords int) []SplitLine { + lines := []SplitLine{} + for _, line := range strings.Split(paragraph, "\n") { + trimmed := strings.TrimSpace(line) + if trimmed == "" { + continue + } + lines = append(lines, GetSplitLine(trimmed, delimiter, numWords)) + } + return lines +} diff --git a/src/internal/exec/binexecutor.go b/src/internal/exec/binexecutor.go index d0a442e..a7f1810 100644 --- a/src/internal/exec/binexecutor.go +++ b/src/internal/exec/binexecutor.go @@ -1,7 +1,6 @@ package exec import ( - "bytes" "fmt" "os/exec" "strings" @@ -17,18 +16,17 @@ type BinExecutor struct{} func (c *BinExecutor) Exec(name string, arg ...string) *Execution { cmd := exec.Command(name, arg...) - var stderr bytes.Buffer - cmd.Stderr = &stderr - - var stdout bytes.Buffer - cmd.Stdout = &stdout - err := cmd.Run() + + out, outErr := cmd.CombinedOutput() + if outErr != nil { + logging.Fatal(outErr) + } + execution := &Execution{ - Cmd: name + " " + strings.Join(arg, " "), - Stdout: stdout.String(), - Stderr: stderr.String(), - ExitCode: cmd.ProcessState.ExitCode(), + Cmd: name + " " + strings.Join(arg, " "), + CombinedOut: string(out), + ExitCode: cmd.ProcessState.ExitCode(), } logging.DebugLazy(func() string { diff --git a/src/internal/exec/executor.go b/src/internal/exec/executor.go index 160dcc7..c9c4d0c 100644 --- a/src/internal/exec/executor.go +++ b/src/internal/exec/executor.go @@ -13,10 +13,9 @@ type Executor interface { } type Execution struct { - Cmd string - Stdout string - Stderr string - ExitCode int + Cmd string + CombinedOut string + ExitCode int } // Gets the error, if the command ran with a non-zero exit code. @@ -25,10 +24,10 @@ func (e *Execution) Error() error { return nil } return fmt.Errorf( - "Error encountered running %s\nExited with status code %d; see combined output below:\n%s", + "Error encountered running %s\nExited with status code %d; see combined std[out,err] below:\n%s", e.Cmd, e.ExitCode, - e.Stdout+e.Stderr, + e.CombinedOut, ) }