mirror of
https://github.com/mudler/luet.git
synced 2025-09-03 16:25:19 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
94f692266c | ||
|
c13a2174c4 | ||
|
f07cf6c245 | ||
|
515017cabd | ||
|
0bfb33db92 | ||
|
c9c24dd174 | ||
|
194cfda8a4 | ||
|
233429bbeb | ||
|
d84f6b31fd |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
- name: setup-docker
|
- name: setup-docker
|
||||||
uses: docker-practice/actions-setup-docker@0.0.1
|
uses: docker-practice/actions-setup-docker@0.0.1
|
||||||
- name: Login to quay
|
- name: Login to quay
|
||||||
run: echo ${{ secrets.DOCKER_TESTING_PASSWORD }} | sudo docker login -u ${{ secrets.DOCKER_TESTING_USERNAME }} --password-stdin quay.io
|
run: echo ${{ secrets.DOCKER_TESTING_PASSWORD }} | sudo -E docker login -u ${{ secrets.DOCKER_TESTING_USERNAME }} --password-stdin quay.io
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y upx && sudo -E env "PATH=$PATH" make deps
|
sudo apt-get install -y upx && sudo -E env "PATH=$PATH" make deps
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
. "github.com/mudler/luet/pkg/config"
|
||||||
config "github.com/mudler/luet/pkg/config"
|
config "github.com/mudler/luet/pkg/config"
|
||||||
"github.com/mudler/luet/pkg/helpers"
|
"github.com/mudler/luet/pkg/helpers"
|
||||||
. "github.com/mudler/luet/pkg/logger"
|
. "github.com/mudler/luet/pkg/logger"
|
||||||
@@ -31,13 +32,24 @@ var cleanupCmd = &cobra.Command{
|
|||||||
Use: "cleanup",
|
Use: "cleanup",
|
||||||
Short: "Clean packages cache.",
|
Short: "Clean packages cache.",
|
||||||
Long: `remove downloaded packages tarballs and clean cache directory`,
|
Long: `remove downloaded packages tarballs and clean cache directory`,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
|
LuetCfg.Viper.BindPFlag("installed", cmd.Flags().Lookup("installed"))
|
||||||
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
var cleaned int = 0
|
var cleaned int = 0
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := config.LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := config.LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
// Check if cache dir exists
|
// Check if cache dir exists
|
||||||
if helpers.Exists(config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()) {
|
if helpers.Exists(LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()) {
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath())
|
files, err := ioutil.ReadDir(LuetCfg.GetSystem().GetSystemPkgsCacheDirPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal("Error on read cachedir ", err.Error())
|
Fatal("Error on read cachedir ", err.Error())
|
||||||
}
|
}
|
||||||
@@ -47,12 +59,12 @@ var cleanupCmd = &cobra.Command{
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.LuetCfg.GetGeneral().Debug {
|
if LuetCfg.GetGeneral().Debug {
|
||||||
Info("Removing ", file.Name())
|
Info("Removing ", file.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
err := os.RemoveAll(
|
err := os.RemoveAll(
|
||||||
filepath.Join(config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath(), file.Name()))
|
filepath.Join(LuetCfg.GetSystem().GetSystemPkgsCacheDirPath(), file.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal("Error on removing", file.Name())
|
Fatal("Error on removing", file.Name())
|
||||||
}
|
}
|
||||||
@@ -66,5 +78,8 @@ var cleanupCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
cleanupCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
|
cleanupCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
|
cleanupCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
RootCmd.AddCommand(cleanupCmd)
|
RootCmd.AddCommand(cleanupCmd)
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ func init() {
|
|||||||
|
|
||||||
databaseGroupCmd.AddCommand(
|
databaseGroupCmd.AddCommand(
|
||||||
NewDatabaseCreateCommand(),
|
NewDatabaseCreateCommand(),
|
||||||
|
NewDatabaseGetCommand(),
|
||||||
NewDatabaseRemoveCommand(),
|
NewDatabaseRemoveCommand(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -46,10 +46,19 @@ For reference, inspect a "metadata.yaml" file generated while running "luet buil
|
|||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
|
|
||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
systemDB := LuetCfg.GetSystemDB()
|
systemDB := LuetCfg.GetSystemDB()
|
||||||
|
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
@@ -77,5 +86,9 @@ For reference, inspect a "metadata.yaml" file generated while running "luet buil
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ans.Flags().String("system-dbpath", "", "System db path")
|
||||||
|
ans.Flags().String("system-target", "", "System rootpath")
|
||||||
|
ans.Flags().String("system-engine", "", "System DB engine")
|
||||||
|
|
||||||
return ans
|
return ans
|
||||||
}
|
}
|
||||||
|
95
cmd/database/get.go
Normal file
95
cmd/database/get.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// Copyright © 2021 Ettore Di Giacinto <mudler@mocaccino.org>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package cmd_database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
helpers "github.com/mudler/luet/cmd/helpers"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
. "github.com/mudler/luet/pkg/config"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewDatabaseGetCommand() *cobra.Command {
|
||||||
|
var c = &cobra.Command{
|
||||||
|
Use: "get <package>",
|
||||||
|
Short: "Get a package in the system DB as yaml",
|
||||||
|
Long: `Get a package in the system database in the YAML format:
|
||||||
|
|
||||||
|
$ luet database get system/foo
|
||||||
|
|
||||||
|
To return also files:
|
||||||
|
$ luet database get --files system/foo`,
|
||||||
|
Args: cobra.OnlyValidArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
|
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
showFiles, _ := cmd.Flags().GetBool("files")
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
|
systemDB := LuetCfg.GetSystemDB()
|
||||||
|
|
||||||
|
for _, a := range args {
|
||||||
|
pack, err := helpers.ParsePackageStr(a)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ps, err := systemDB.FindPackages(pack)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, p := range ps {
|
||||||
|
y, err := p.Yaml()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Println(string(y))
|
||||||
|
if showFiles {
|
||||||
|
files, err := systemDB.GetPackageFiles(p)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b, err := yaml.Marshal(files)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Println("files:\n" + string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.Flags().Bool("files", false, "Show package files.")
|
||||||
|
c.Flags().String("system-dbpath", "", "System db path")
|
||||||
|
c.Flags().String("system-target", "", "System rootpath")
|
||||||
|
c.Flags().String("system-engine", "", "System DB engine")
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
@@ -38,9 +38,18 @@ This commands takes multiple packages as arguments and prunes their entries from
|
|||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
|
|
||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
systemDB := LuetCfg.GetSystemDB()
|
systemDB := LuetCfg.GetSystemDB()
|
||||||
|
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
@@ -60,6 +69,9 @@ This commands takes multiple packages as arguments and prunes their entries from
|
|||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
ans.Flags().String("system-dbpath", "", "System db path")
|
||||||
|
ans.Flags().String("system-target", "", "System rootpath")
|
||||||
|
ans.Flags().String("system-engine", "", "System DB engine")
|
||||||
|
|
||||||
return ans
|
return ans
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
installer "github.com/mudler/luet/pkg/installer"
|
installer "github.com/mudler/luet/pkg/installer"
|
||||||
"github.com/mudler/luet/pkg/solver"
|
"github.com/mudler/luet/pkg/solver"
|
||||||
|
|
||||||
@@ -51,6 +49,7 @@ To force install a package:
|
|||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
|
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
|
||||||
@@ -91,6 +90,14 @@ To force install a package:
|
|||||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||||
yes := LuetCfg.Viper.GetBool("yes")
|
yes := LuetCfg.Viper.GetBool("yes")
|
||||||
|
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
LuetCfg.GetSolverOptions().Type = stype
|
LuetCfg.GetSolverOptions().Type = stype
|
||||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||||
@@ -127,12 +134,10 @@ To force install a package:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
path, err := os.Getwd()
|
installCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
if err != nil {
|
installCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
Fatal(err)
|
installCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
}
|
|
||||||
installCmd.Flags().String("system-dbpath", path, "System db path")
|
|
||||||
installCmd.Flags().String("system-target", path, "System rootpath")
|
|
||||||
installCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
installCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
||||||
installCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
installCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||||
installCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
installCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
installer "github.com/mudler/luet/pkg/installer"
|
installer "github.com/mudler/luet/pkg/installer"
|
||||||
|
|
||||||
. "github.com/mudler/luet/pkg/config"
|
. "github.com/mudler/luet/pkg/config"
|
||||||
@@ -31,6 +29,7 @@ var reclaimCmd = &cobra.Command{
|
|||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||||
},
|
},
|
||||||
Long: `Reclaim tries to find association between packages in the online repositories and the system one.
|
Long: `Reclaim tries to find association between packages in the online repositories and the system one.
|
||||||
@@ -40,6 +39,13 @@ var reclaimCmd = &cobra.Command{
|
|||||||
It scans the target file system, and if finds a match with a package available in the repositories, it marks as installed in the system database.
|
It scans the target file system, and if finds a match with a package available in the repositories, it marks as installed in the system database.
|
||||||
`,
|
`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
// This shouldn't be necessary, but we need to unmarshal the repositories to a concrete struct, thus we need to port them back to the Repositories type
|
// This shouldn't be necessary, but we need to unmarshal the repositories to a concrete struct, thus we need to port them back to the Repositories type
|
||||||
repos := installer.Repositories{}
|
repos := installer.Repositories{}
|
||||||
@@ -71,12 +77,11 @@ It scans the target file system, and if finds a match with a package available i
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
path, err := os.Getwd()
|
|
||||||
if err != nil {
|
reclaimCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
Fatal(err)
|
reclaimCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
}
|
reclaimCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
reclaimCmd.Flags().String("system-dbpath", path, "System db path")
|
|
||||||
reclaimCmd.Flags().String("system-target", path, "System rootpath")
|
|
||||||
reclaimCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
reclaimCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
||||||
|
|
||||||
RootCmd.AddCommand(reclaimCmd)
|
RootCmd.AddCommand(reclaimCmd)
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
installer "github.com/mudler/luet/pkg/installer"
|
installer "github.com/mudler/luet/pkg/installer"
|
||||||
"github.com/mudler/luet/pkg/solver"
|
"github.com/mudler/luet/pkg/solver"
|
||||||
|
|
||||||
@@ -38,6 +36,7 @@ var replaceCmd = &cobra.Command{
|
|||||||
`,
|
`,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
||||||
@@ -64,6 +63,13 @@ var replaceCmd = &cobra.Command{
|
|||||||
onlydeps := LuetCfg.Viper.GetBool("onlydeps")
|
onlydeps := LuetCfg.Viper.GetBool("onlydeps")
|
||||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||||
yes := LuetCfg.Viper.GetBool("yes")
|
yes := LuetCfg.Viper.GetBool("yes")
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
pack, err := helpers.ParsePackageStr(a)
|
pack, err := helpers.ParsePackageStr(a)
|
||||||
@@ -127,12 +133,11 @@ var replaceCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
path, err := os.Getwd()
|
|
||||||
if err != nil {
|
replaceCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
Fatal(err)
|
replaceCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
}
|
replaceCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
replaceCmd.Flags().String("system-dbpath", path, "System db path")
|
|
||||||
replaceCmd.Flags().String("system-target", path, "System rootpath")
|
|
||||||
replaceCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
replaceCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
||||||
replaceCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
replaceCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||||
replaceCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
replaceCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
||||||
|
@@ -40,7 +40,7 @@ var Verbose bool
|
|||||||
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LuetCLIVersion = "0.11.2"
|
LuetCLIVersion = "0.11.3"
|
||||||
LuetEnvPrefix = "LUET"
|
LuetEnvPrefix = "LUET"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
356
cmd/search.go
356
cmd/search.go
@@ -16,7 +16,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
@@ -30,12 +29,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PackageResult struct {
|
type PackageResult struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Target string `json:"target"`
|
Target string `json:"target"`
|
||||||
Hidden bool `json:"hidden"`
|
Hidden bool `json:"hidden"`
|
||||||
|
Files []string `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Results struct {
|
type Results struct {
|
||||||
@@ -64,6 +64,205 @@ func packageToList(l list.Writer, repo string, p pkg.Package) {
|
|||||||
l.UnIndent()
|
l.UnIndent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func searchLocally(term string, l list.Writer, t table.Writer, label, labelMatch, revdeps, hidden bool) Results {
|
||||||
|
var results Results
|
||||||
|
|
||||||
|
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
iMatches := pkg.Packages{}
|
||||||
|
if label {
|
||||||
|
iMatches, err = system.Database.FindPackageLabel(term)
|
||||||
|
} else if labelMatch {
|
||||||
|
iMatches, err = system.Database.FindPackageLabelMatch(term)
|
||||||
|
} else {
|
||||||
|
iMatches, err = system.Database.FindPackageMatch(term)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
Fatal("Error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pack := range iMatches {
|
||||||
|
if !revdeps {
|
||||||
|
if !pack.IsHidden() || pack.IsHidden() && hidden {
|
||||||
|
|
||||||
|
t.AppendRow(packageToRow("system", pack))
|
||||||
|
packageToList(l, "system", pack)
|
||||||
|
f, _ := system.Database.GetPackageFiles(pack)
|
||||||
|
results.Packages = append(results.Packages,
|
||||||
|
PackageResult{
|
||||||
|
Name: pack.GetName(),
|
||||||
|
Version: pack.GetVersion(),
|
||||||
|
Category: pack.GetCategory(),
|
||||||
|
Repository: "system",
|
||||||
|
Hidden: pack.IsHidden(),
|
||||||
|
Files: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
packs, _ := system.Database.GetRevdeps(pack)
|
||||||
|
for _, revdep := range packs {
|
||||||
|
if !revdep.IsHidden() || revdep.IsHidden() && hidden {
|
||||||
|
t.AppendRow(packageToRow("system", pack))
|
||||||
|
packageToList(l, "system", pack)
|
||||||
|
f, _ := system.Database.GetPackageFiles(revdep)
|
||||||
|
results.Packages = append(results.Packages,
|
||||||
|
PackageResult{
|
||||||
|
Name: revdep.GetName(),
|
||||||
|
Version: revdep.GetVersion(),
|
||||||
|
Category: revdep.GetCategory(),
|
||||||
|
Repository: "system",
|
||||||
|
Hidden: revdep.IsHidden(),
|
||||||
|
Files: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
|
||||||
|
}
|
||||||
|
func searchOnline(term string, l list.Writer, t table.Writer, label, labelMatch, revdeps, hidden bool) Results {
|
||||||
|
var results Results
|
||||||
|
|
||||||
|
repos := installer.Repositories{}
|
||||||
|
for _, repo := range LuetCfg.SystemRepositories {
|
||||||
|
if !repo.Enable {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r := installer.NewSystemRepository(repo)
|
||||||
|
repos = append(repos, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
inst := installer.NewLuetInstaller(
|
||||||
|
installer.LuetInstallerOptions{
|
||||||
|
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||||
|
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
inst.Repositories(repos)
|
||||||
|
synced, err := inst.SyncRepositories(false)
|
||||||
|
if err != nil {
|
||||||
|
Fatal("Error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
Info("--- Search results (" + term + "): ---")
|
||||||
|
|
||||||
|
matches := []installer.PackageMatch{}
|
||||||
|
if label {
|
||||||
|
matches = synced.SearchLabel(term)
|
||||||
|
} else if labelMatch {
|
||||||
|
matches = synced.SearchLabelMatch(term)
|
||||||
|
} else {
|
||||||
|
matches = synced.Search(term)
|
||||||
|
}
|
||||||
|
for _, m := range matches {
|
||||||
|
if !revdeps {
|
||||||
|
if !m.Package.IsHidden() || m.Package.IsHidden() && hidden {
|
||||||
|
t.AppendRow(packageToRow(m.Repo.GetName(), m.Package))
|
||||||
|
packageToList(l, m.Repo.GetName(), m.Package)
|
||||||
|
results.Packages = append(results.Packages,
|
||||||
|
PackageResult{
|
||||||
|
Name: m.Package.GetName(),
|
||||||
|
Version: m.Package.GetVersion(),
|
||||||
|
Category: m.Package.GetCategory(),
|
||||||
|
Repository: m.Repo.GetName(),
|
||||||
|
Hidden: m.Package.IsHidden(),
|
||||||
|
Files: m.Artifact.GetFiles(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
packs, _ := m.Repo.GetTree().GetDatabase().GetRevdeps(m.Package)
|
||||||
|
for _, revdep := range packs {
|
||||||
|
if !revdep.IsHidden() || revdep.IsHidden() && hidden {
|
||||||
|
t.AppendRow(packageToRow(m.Repo.GetName(), revdep))
|
||||||
|
packageToList(l, m.Repo.GetName(), revdep)
|
||||||
|
results.Packages = append(results.Packages,
|
||||||
|
PackageResult{
|
||||||
|
Name: revdep.GetName(),
|
||||||
|
Version: revdep.GetVersion(),
|
||||||
|
Category: revdep.GetCategory(),
|
||||||
|
Repository: m.Repo.GetName(),
|
||||||
|
Hidden: revdep.IsHidden(),
|
||||||
|
Files: m.Artifact.GetFiles(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
func searchLocalFiles(term string, l list.Writer, t table.Writer) Results {
|
||||||
|
var results Results
|
||||||
|
Info("--- Search results (" + term + "): ---")
|
||||||
|
|
||||||
|
matches, _ := LuetCfg.GetSystemDB().FindPackageByFile(term)
|
||||||
|
for _, pack := range matches {
|
||||||
|
t.AppendRow(packageToRow("system", pack))
|
||||||
|
packageToList(l, "system", pack)
|
||||||
|
f, _ := LuetCfg.GetSystemDB().GetPackageFiles(pack)
|
||||||
|
results.Packages = append(results.Packages,
|
||||||
|
PackageResult{
|
||||||
|
Name: pack.GetName(),
|
||||||
|
Version: pack.GetVersion(),
|
||||||
|
Category: pack.GetCategory(),
|
||||||
|
Repository: "system",
|
||||||
|
Hidden: pack.IsHidden(),
|
||||||
|
Files: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchFiles(term string, l list.Writer, t table.Writer) Results {
|
||||||
|
var results Results
|
||||||
|
|
||||||
|
repos := installer.Repositories{}
|
||||||
|
for _, repo := range LuetCfg.SystemRepositories {
|
||||||
|
if !repo.Enable {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r := installer.NewSystemRepository(repo)
|
||||||
|
repos = append(repos, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
inst := installer.NewLuetInstaller(
|
||||||
|
installer.LuetInstallerOptions{
|
||||||
|
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||||
|
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
inst.Repositories(repos)
|
||||||
|
synced, err := inst.SyncRepositories(false)
|
||||||
|
if err != nil {
|
||||||
|
Fatal("Error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
Info("--- Search results (" + term + "): ---")
|
||||||
|
|
||||||
|
matches := []installer.PackageMatch{}
|
||||||
|
|
||||||
|
matches = synced.SearchPackages(term, installer.FileSearch)
|
||||||
|
|
||||||
|
for _, m := range matches {
|
||||||
|
t.AppendRow(packageToRow(m.Repo.GetName(), m.Package))
|
||||||
|
packageToList(l, m.Repo.GetName(), m.Package)
|
||||||
|
results.Packages = append(results.Packages,
|
||||||
|
PackageResult{
|
||||||
|
Name: m.Package.GetName(),
|
||||||
|
Version: m.Package.GetVersion(),
|
||||||
|
Category: m.Package.GetCategory(),
|
||||||
|
Repository: m.Repo.GetName(),
|
||||||
|
Hidden: m.Package.IsHidden(),
|
||||||
|
Files: m.Artifact.GetFiles(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
var searchCmd = &cobra.Command{
|
var searchCmd = &cobra.Command{
|
||||||
Use: "search <term>",
|
Use: "search <term>",
|
||||||
Short: "Search packages",
|
Short: "Search packages",
|
||||||
@@ -107,6 +306,7 @@ Search can also return results in the terminal in different ways: as terminal ou
|
|||||||
LuetCfg.Viper.BindPFlag("installed", cmd.Flags().Lookup("installed"))
|
LuetCfg.Viper.BindPFlag("installed", cmd.Flags().Lookup("installed"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
|
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
|
||||||
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
||||||
},
|
},
|
||||||
@@ -128,7 +328,14 @@ Search can also return results in the terminal in different ways: as terminal ou
|
|||||||
searchWithLabelMatch, _ := cmd.Flags().GetBool("by-label-regex")
|
searchWithLabelMatch, _ := cmd.Flags().GetBool("by-label-regex")
|
||||||
revdeps, _ := cmd.Flags().GetBool("revdeps")
|
revdeps, _ := cmd.Flags().GetBool("revdeps")
|
||||||
tableMode, _ := cmd.Flags().GetBool("table")
|
tableMode, _ := cmd.Flags().GetBool("table")
|
||||||
|
files, _ := cmd.Flags().GetBool("files")
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
out, _ := cmd.Flags().GetString("output")
|
out, _ := cmd.Flags().GetString("output")
|
||||||
if out != "terminal" {
|
if out != "terminal" {
|
||||||
LuetCfg.GetLogging().SetLogLevel("error")
|
LuetCfg.GetLogging().SetLogLevel("error")
|
||||||
@@ -144,121 +351,15 @@ Search can also return results in the terminal in different ways: as terminal ou
|
|||||||
t.AppendHeader(rows)
|
t.AppendHeader(rows)
|
||||||
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
||||||
|
|
||||||
if !installed {
|
switch {
|
||||||
|
case files && installed:
|
||||||
repos := installer.Repositories{}
|
results = searchLocalFiles(args[0], l, t)
|
||||||
for _, repo := range LuetCfg.SystemRepositories {
|
case files && !installed:
|
||||||
if !repo.Enable {
|
results = searchFiles(args[0], l, t)
|
||||||
continue
|
case !installed:
|
||||||
}
|
results = searchOnline(args[0], l, t, searchWithLabel, searchWithLabelMatch, revdeps, hidden)
|
||||||
r := installer.NewSystemRepository(repo)
|
default:
|
||||||
repos = append(repos, r)
|
results = searchLocally(args[0], l, t, searchWithLabel, searchWithLabelMatch, revdeps, hidden)
|
||||||
}
|
|
||||||
|
|
||||||
inst := installer.NewLuetInstaller(
|
|
||||||
installer.LuetInstallerOptions{
|
|
||||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
|
||||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
inst.Repositories(repos)
|
|
||||||
synced, err := inst.SyncRepositories(false)
|
|
||||||
if err != nil {
|
|
||||||
Fatal("Error: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
Info("--- Search results (" + args[0] + "): ---")
|
|
||||||
|
|
||||||
matches := []installer.PackageMatch{}
|
|
||||||
if searchWithLabel {
|
|
||||||
matches = synced.SearchLabel(args[0])
|
|
||||||
} else if searchWithLabelMatch {
|
|
||||||
matches = synced.SearchLabelMatch(args[0])
|
|
||||||
} else {
|
|
||||||
matches = synced.Search(args[0])
|
|
||||||
}
|
|
||||||
for _, m := range matches {
|
|
||||||
if !revdeps {
|
|
||||||
if !m.Package.IsHidden() || m.Package.IsHidden() && hidden {
|
|
||||||
t.AppendRow(packageToRow(m.Repo.GetName(), m.Package))
|
|
||||||
packageToList(l, m.Repo.GetName(), m.Package)
|
|
||||||
results.Packages = append(results.Packages,
|
|
||||||
PackageResult{
|
|
||||||
Name: m.Package.GetName(),
|
|
||||||
Version: m.Package.GetVersion(),
|
|
||||||
Category: m.Package.GetCategory(),
|
|
||||||
Repository: m.Repo.GetName(),
|
|
||||||
Hidden: m.Package.IsHidden(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
packs, _ := m.Repo.GetTree().GetDatabase().GetRevdeps(m.Package)
|
|
||||||
for _, revdep := range packs {
|
|
||||||
if !revdep.IsHidden() || revdep.IsHidden() && hidden {
|
|
||||||
t.AppendRow(packageToRow(m.Repo.GetName(), revdep))
|
|
||||||
packageToList(l, m.Repo.GetName(), revdep)
|
|
||||||
results.Packages = append(results.Packages,
|
|
||||||
PackageResult{
|
|
||||||
Name: revdep.GetName(),
|
|
||||||
Version: revdep.GetVersion(),
|
|
||||||
Category: revdep.GetCategory(),
|
|
||||||
Repository: m.Repo.GetName(),
|
|
||||||
Hidden: revdep.IsHidden(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
iMatches := pkg.Packages{}
|
|
||||||
if searchWithLabel {
|
|
||||||
iMatches, err = system.Database.FindPackageLabel(args[0])
|
|
||||||
} else if searchWithLabelMatch {
|
|
||||||
iMatches, err = system.Database.FindPackageLabelMatch(args[0])
|
|
||||||
} else {
|
|
||||||
iMatches, err = system.Database.FindPackageMatch(args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
Fatal("Error: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pack := range iMatches {
|
|
||||||
if !revdeps {
|
|
||||||
if !pack.IsHidden() || pack.IsHidden() && hidden {
|
|
||||||
t.AppendRow(packageToRow("system", pack))
|
|
||||||
packageToList(l, "system", pack)
|
|
||||||
results.Packages = append(results.Packages,
|
|
||||||
PackageResult{
|
|
||||||
Name: pack.GetName(),
|
|
||||||
Version: pack.GetVersion(),
|
|
||||||
Category: pack.GetCategory(),
|
|
||||||
Repository: "system",
|
|
||||||
Hidden: pack.IsHidden(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
packs, _ := system.Database.GetRevdeps(pack)
|
|
||||||
for _, revdep := range packs {
|
|
||||||
if !revdep.IsHidden() || revdep.IsHidden() && hidden {
|
|
||||||
t.AppendRow(packageToRow("system", pack))
|
|
||||||
packageToList(l, "system", pack)
|
|
||||||
results.Packages = append(results.Packages,
|
|
||||||
PackageResult{
|
|
||||||
Name: revdep.GetName(),
|
|
||||||
Version: revdep.GetVersion(),
|
|
||||||
Category: revdep.GetCategory(),
|
|
||||||
Repository: "system",
|
|
||||||
Hidden: revdep.IsHidden(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.AppendFooter(rows)
|
t.AppendFooter(rows)
|
||||||
@@ -292,12 +393,10 @@ Search can also return results in the terminal in different ways: as terminal ou
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
path, err := os.Getwd()
|
searchCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
if err != nil {
|
searchCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
Fatal(err)
|
searchCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
}
|
|
||||||
searchCmd.Flags().String("system-dbpath", path, "System db path")
|
|
||||||
searchCmd.Flags().String("system-target", path, "System rootpath")
|
|
||||||
searchCmd.Flags().Bool("installed", false, "Search between system packages")
|
searchCmd.Flags().Bool("installed", false, "Search between system packages")
|
||||||
searchCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
searchCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
||||||
searchCmd.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
|
searchCmd.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
|
||||||
@@ -309,6 +408,7 @@ func init() {
|
|||||||
searchCmd.Flags().Bool("revdeps", false, "Search package reverse dependencies")
|
searchCmd.Flags().Bool("revdeps", false, "Search package reverse dependencies")
|
||||||
searchCmd.Flags().Bool("hidden", false, "Include hidden packages")
|
searchCmd.Flags().Bool("hidden", false, "Include hidden packages")
|
||||||
searchCmd.Flags().Bool("table", false, "show output in a table (wider screens)")
|
searchCmd.Flags().Bool("table", false, "show output in a table (wider screens)")
|
||||||
|
searchCmd.Flags().Bool("files", false, "Search between packages files")
|
||||||
|
|
||||||
RootCmd.AddCommand(searchCmd)
|
RootCmd.AddCommand(searchCmd)
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
helpers "github.com/mudler/luet/cmd/helpers"
|
helpers "github.com/mudler/luet/cmd/helpers"
|
||||||
. "github.com/mudler/luet/pkg/config"
|
. "github.com/mudler/luet/pkg/config"
|
||||||
installer "github.com/mudler/luet/pkg/installer"
|
installer "github.com/mudler/luet/pkg/installer"
|
||||||
@@ -42,6 +40,7 @@ var uninstallCmd = &cobra.Command{
|
|||||||
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
||||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||||
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
toRemove := []pkg.Package{}
|
toRemove := []pkg.Package{}
|
||||||
@@ -65,6 +64,13 @@ var uninstallCmd = &cobra.Command{
|
|||||||
fullClean, _ := cmd.Flags().GetBool("full-clean")
|
fullClean, _ := cmd.Flags().GetBool("full-clean")
|
||||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||||
yes := LuetCfg.Viper.GetBool("yes")
|
yes := LuetCfg.Viper.GetBool("yes")
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
|
|
||||||
LuetCfg.GetSolverOptions().Type = stype
|
LuetCfg.GetSolverOptions().Type = stype
|
||||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||||
@@ -101,12 +107,11 @@ var uninstallCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
path, err := os.Getwd()
|
|
||||||
if err != nil {
|
uninstallCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
Fatal(err)
|
uninstallCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
}
|
uninstallCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
uninstallCmd.Flags().String("system-dbpath", path, "System db path")
|
|
||||||
uninstallCmd.Flags().String("system-target", path, "System rootpath")
|
|
||||||
uninstallCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
uninstallCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
||||||
uninstallCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
uninstallCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||||
uninstallCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
uninstallCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/mudler/luet/pkg/config"
|
. "github.com/mudler/luet/pkg/config"
|
||||||
installer "github.com/mudler/luet/pkg/installer"
|
installer "github.com/mudler/luet/pkg/installer"
|
||||||
. "github.com/mudler/luet/pkg/logger"
|
. "github.com/mudler/luet/pkg/logger"
|
||||||
@@ -38,6 +36,7 @@ var upgradeCmd = &cobra.Command{
|
|||||||
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
||||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||||
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
||||||
|
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
|
||||||
},
|
},
|
||||||
Long: `Upgrades packages in parallel`,
|
Long: `Upgrades packages in parallel`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@@ -64,7 +63,13 @@ var upgradeCmd = &cobra.Command{
|
|||||||
sync, _ := cmd.Flags().GetBool("sync")
|
sync, _ := cmd.Flags().GetBool("sync")
|
||||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||||
yes := LuetCfg.Viper.GetBool("yes")
|
yes := LuetCfg.Viper.GetBool("yes")
|
||||||
|
dbpath := LuetCfg.Viper.GetString("system.database_path")
|
||||||
|
rootfs := LuetCfg.Viper.GetString("system.rootfs")
|
||||||
|
engine := LuetCfg.Viper.GetString("system.database_engine")
|
||||||
|
|
||||||
|
LuetCfg.System.DatabaseEngine = engine
|
||||||
|
LuetCfg.System.DatabasePath = dbpath
|
||||||
|
LuetCfg.System.Rootfs = rootfs
|
||||||
LuetCfg.GetSolverOptions().Type = stype
|
LuetCfg.GetSolverOptions().Type = stype
|
||||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||||
@@ -102,12 +107,10 @@ var upgradeCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
path, err := os.Getwd()
|
upgradeCmd.Flags().String("system-dbpath", "", "System db path")
|
||||||
if err != nil {
|
upgradeCmd.Flags().String("system-target", "", "System rootpath")
|
||||||
Fatal(err)
|
upgradeCmd.Flags().String("system-engine", "", "System DB engine")
|
||||||
}
|
|
||||||
upgradeCmd.Flags().String("system-dbpath", path, "System db path")
|
|
||||||
upgradeCmd.Flags().String("system-target", path, "System rootpath")
|
|
||||||
upgradeCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
upgradeCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
||||||
upgradeCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
upgradeCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||||
upgradeCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
upgradeCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -172,9 +173,18 @@ func CopyFile(src, dst string) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy.Copy(src, dst, copy.Options{
|
err = copy.Copy(src, dst, copy.Options{
|
||||||
Sync: true,
|
Sync: true,
|
||||||
OnSymlink: func(string) copy.SymlinkAction { return copy.Shallow }})
|
OnSymlink: func(string) copy.SymlinkAction { return copy.Shallow }})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
|
||||||
|
if err := os.Chown(dst, int(stat.Uid), int(stat.Gid)); err != nil {
|
||||||
|
fmt.Println("failed chowning", dst, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsDirectory(path string) (bool, error) {
|
func IsDirectory(path string) (bool, error) {
|
||||||
|
@@ -74,4 +74,6 @@ type Repository interface {
|
|||||||
Serialize() (*LuetSystemRepositoryMetadata, LuetSystemRepositorySerialized)
|
Serialize() (*LuetSystemRepositoryMetadata, LuetSystemRepositorySerialized)
|
||||||
GetBackend() compiler.CompilerBackend
|
GetBackend() compiler.CompilerBackend
|
||||||
SetBackend(b compiler.CompilerBackend)
|
SetBackend(b compiler.CompilerBackend)
|
||||||
|
FileSearch(pattern string) (pkg.Packages, error)
|
||||||
|
SearchArtefact(p pkg.Package) (compiler.Artifact, error)
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -86,17 +87,17 @@ type LuetSystemRepositoryMetadata struct {
|
|||||||
Index []*compiler.PackageArtifact `json:"index,omitempty"`
|
Index []*compiler.PackageArtifact `json:"index,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LuetSearchModeType string
|
type LuetSearchModeType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SLabel LuetSearchModeType = "label"
|
SLabel = iota
|
||||||
SRegexPkg LuetSearchModeType = "regexPkg"
|
SRegexPkg = iota
|
||||||
SRegexLabel LuetSearchModeType = "regexLabel"
|
SRegexLabel = iota
|
||||||
|
FileSearch = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
type LuetSearchOpts struct {
|
type LuetSearchOpts struct {
|
||||||
Pattern string
|
Mode LuetSearchModeType
|
||||||
Mode LuetSearchModeType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLuetSystemRepositoryMetadata(file string, removeFile bool) (*LuetSystemRepositoryMetadata, error) {
|
func NewLuetSystemRepositoryMetadata(file string, removeFile bool) (*LuetSystemRepositoryMetadata, error) {
|
||||||
@@ -406,6 +407,25 @@ func (r *LuetSystemRepository) SetPriority(n int) {
|
|||||||
r.LuetRepository.Priority = n
|
r.LuetRepository.Priority = n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileSearch search a pattern among the artifacts in a repository
|
||||||
|
func (r *LuetSystemRepository) FileSearch(pattern string) (pkg.Packages, error) {
|
||||||
|
var matches pkg.Packages
|
||||||
|
reg, err := regexp.Compile(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return matches, err
|
||||||
|
}
|
||||||
|
ARTIFACT:
|
||||||
|
for _, a := range r.GetIndex() {
|
||||||
|
for _, f := range a.GetFiles() {
|
||||||
|
if reg.MatchString(f) {
|
||||||
|
matches = append(matches, a.GetCompileSpec().GetPackage())
|
||||||
|
continue ARTIFACT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *LuetSystemRepository) GetName() string {
|
func (r *LuetSystemRepository) GetName() string {
|
||||||
return r.LuetRepository.Name
|
return r.LuetRepository.Name
|
||||||
}
|
}
|
||||||
@@ -881,6 +901,16 @@ func (r *LuetSystemRepository) Client() Client {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *LuetSystemRepository) SearchArtefact(p pkg.Package) (compiler.Artifact, error) {
|
||||||
|
for _, a := range r.GetIndex() {
|
||||||
|
if a.GetCompileSpec().GetPackage().Matches(p) {
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("Not found")
|
||||||
|
}
|
||||||
|
|
||||||
func (r *LuetSystemRepository) Sync(force bool) (Repository, error) {
|
func (r *LuetSystemRepository) Sync(force bool) (Repository, error) {
|
||||||
var repoUpdated bool = false
|
var repoUpdated bool = false
|
||||||
var treefs, metafs string
|
var treefs, metafs string
|
||||||
@@ -1129,8 +1159,9 @@ func (r Repositories) SyncDatabase(d pkg.PackageDatabase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PackageMatch struct {
|
type PackageMatch struct {
|
||||||
Repo Repository
|
Repo Repository
|
||||||
Package pkg.Package
|
Artifact compiler.Artifact
|
||||||
|
Package pkg.Package
|
||||||
}
|
}
|
||||||
|
|
||||||
func (re Repositories) PackageMatches(p pkg.Packages) []PackageMatch {
|
func (re Repositories) PackageMatches(p pkg.Packages) []PackageMatch {
|
||||||
@@ -1182,7 +1213,7 @@ PACKAGE:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (re Repositories) SearchPackages(p string, o LuetSearchOpts) []PackageMatch {
|
func (re Repositories) SearchPackages(p string, t LuetSearchModeType) []PackageMatch {
|
||||||
sort.Sort(re)
|
sort.Sort(re)
|
||||||
var matches []PackageMatch
|
var matches []PackageMatch
|
||||||
var err error
|
var err error
|
||||||
@@ -1190,18 +1221,21 @@ func (re Repositories) SearchPackages(p string, o LuetSearchOpts) []PackageMatch
|
|||||||
for _, r := range re {
|
for _, r := range re {
|
||||||
var repoMatches pkg.Packages
|
var repoMatches pkg.Packages
|
||||||
|
|
||||||
switch o.Mode {
|
switch t {
|
||||||
case SRegexPkg:
|
case SRegexPkg:
|
||||||
repoMatches, err = r.GetTree().GetDatabase().FindPackageMatch(p)
|
repoMatches, err = r.GetTree().GetDatabase().FindPackageMatch(p)
|
||||||
case SLabel:
|
case SLabel:
|
||||||
repoMatches, err = r.GetTree().GetDatabase().FindPackageLabel(p)
|
repoMatches, err = r.GetTree().GetDatabase().FindPackageLabel(p)
|
||||||
case SRegexLabel:
|
case SRegexLabel:
|
||||||
repoMatches, err = r.GetTree().GetDatabase().FindPackageLabelMatch(p)
|
repoMatches, err = r.GetTree().GetDatabase().FindPackageLabelMatch(p)
|
||||||
|
case FileSearch:
|
||||||
|
repoMatches, err = r.FileSearch(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil && len(repoMatches) > 0 {
|
if err == nil && len(repoMatches) > 0 {
|
||||||
for _, pack := range repoMatches {
|
for _, pack := range repoMatches {
|
||||||
matches = append(matches, PackageMatch{Package: pack, Repo: r})
|
a, _ := r.SearchArtefact(pack)
|
||||||
|
matches = append(matches, PackageMatch{Package: pack, Repo: r, Artifact: a})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1210,13 +1244,13 @@ func (re Repositories) SearchPackages(p string, o LuetSearchOpts) []PackageMatch
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (re Repositories) SearchLabelMatch(s string) []PackageMatch {
|
func (re Repositories) SearchLabelMatch(s string) []PackageMatch {
|
||||||
return re.SearchPackages(s, LuetSearchOpts{Pattern: s, Mode: SRegexLabel})
|
return re.SearchPackages(s, SRegexLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (re Repositories) SearchLabel(s string) []PackageMatch {
|
func (re Repositories) SearchLabel(s string) []PackageMatch {
|
||||||
return re.SearchPackages(s, LuetSearchOpts{Pattern: s, Mode: SLabel})
|
return re.SearchPackages(s, SLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (re Repositories) Search(s string) []PackageMatch {
|
func (re Repositories) Search(s string) []PackageMatch {
|
||||||
return re.SearchPackages(s, LuetSearchOpts{Pattern: s, Mode: SRegexPkg})
|
return re.SearchPackages(s, SRegexPkg)
|
||||||
}
|
}
|
||||||
|
@@ -392,5 +392,80 @@ urls:
|
|||||||
|
|
||||||
Expect(string(content)).To(Equal(""))
|
Expect(string(content)).To(Equal(""))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Searches files", func() {
|
||||||
|
repos := Repositories{
|
||||||
|
&LuetSystemRepository{
|
||||||
|
Index: compiler.ArtifactIndex{
|
||||||
|
&compiler.PackageArtifact{
|
||||||
|
CompileSpec: &compiler.LuetCompilationSpec{
|
||||||
|
Package: &pkg.DefaultPackage{},
|
||||||
|
},
|
||||||
|
Path: "bar",
|
||||||
|
Files: []string{"boo"},
|
||||||
|
},
|
||||||
|
&compiler.PackageArtifact{
|
||||||
|
Path: "d",
|
||||||
|
Files: []string{"baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := repos.SearchPackages("bo", FileSearch)
|
||||||
|
Expect(len(matches)).To(Equal(1))
|
||||||
|
Expect(matches[0].Artifact.GetPath()).To(Equal("bar"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Searches packages", func() {
|
||||||
|
repo := &LuetSystemRepository{
|
||||||
|
Index: compiler.ArtifactIndex{
|
||||||
|
&compiler.PackageArtifact{
|
||||||
|
Path: "foo",
|
||||||
|
CompileSpec: &compiler.LuetCompilationSpec{
|
||||||
|
Package: &pkg.DefaultPackage{
|
||||||
|
Name: "foo",
|
||||||
|
Category: "bar",
|
||||||
|
Version: "1.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&compiler.PackageArtifact{
|
||||||
|
Path: "baz",
|
||||||
|
CompileSpec: &compiler.LuetCompilationSpec{
|
||||||
|
Package: &pkg.DefaultPackage{
|
||||||
|
Name: "foo",
|
||||||
|
Category: "baz",
|
||||||
|
Version: "1.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := repo.SearchArtefact(&pkg.DefaultPackage{
|
||||||
|
Name: "foo",
|
||||||
|
Category: "baz",
|
||||||
|
Version: "1.0",
|
||||||
|
})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(a.GetPath()).To(Equal("baz"))
|
||||||
|
|
||||||
|
a, err = repo.SearchArtefact(&pkg.DefaultPackage{
|
||||||
|
Name: "foo",
|
||||||
|
Category: "bar",
|
||||||
|
Version: "1.0",
|
||||||
|
})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(a.GetPath()).To(Equal("foo"))
|
||||||
|
|
||||||
|
// Doesn't exist. so must fail
|
||||||
|
_, err = repo.SearchArtefact(&pkg.DefaultPackage{
|
||||||
|
Name: "foo",
|
||||||
|
Category: "bar",
|
||||||
|
Version: "1.1",
|
||||||
|
})
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@@ -52,6 +52,7 @@ type PackageSet interface {
|
|||||||
FindPackageLabel(labelKey string) (Packages, error)
|
FindPackageLabel(labelKey string) (Packages, error)
|
||||||
FindPackageLabelMatch(pattern string) (Packages, error)
|
FindPackageLabelMatch(pattern string) (Packages, error)
|
||||||
FindPackageMatch(pattern string) (Packages, error)
|
FindPackageMatch(pattern string) (Packages, error)
|
||||||
|
FindPackageByFile(pattern string) (Packages, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PackageFile struct {
|
type PackageFile struct {
|
||||||
|
@@ -436,9 +436,9 @@ func (db *BoltDatabase) FindPackageLabel(labelKey string) (Packages, error) {
|
|||||||
func (db *BoltDatabase) FindPackageLabelMatch(pattern string) (Packages, error) {
|
func (db *BoltDatabase) FindPackageLabelMatch(pattern string) (Packages, error) {
|
||||||
var ans []Package
|
var ans []Package
|
||||||
|
|
||||||
re := regexp.MustCompile(pattern)
|
re, err := regexp.Compile(pattern)
|
||||||
if re == nil {
|
if err != nil {
|
||||||
return nil, errors.New("Invalid regex " + pattern + "!")
|
return nil, errors.Wrap(err, "Invalid regex "+pattern+"!")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pack := range db.World() {
|
for _, pack := range db.World() {
|
||||||
@@ -450,12 +450,15 @@ func (db *BoltDatabase) FindPackageLabelMatch(pattern string) (Packages, error)
|
|||||||
return Packages(ans), nil
|
return Packages(ans), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *BoltDatabase) FindPackageByFile(pattern string) (Packages, error) {
|
||||||
|
return findPackageByFile(db, pattern)
|
||||||
|
}
|
||||||
func (db *BoltDatabase) FindPackageMatch(pattern string) (Packages, error) {
|
func (db *BoltDatabase) FindPackageMatch(pattern string) (Packages, error) {
|
||||||
var ans []Package
|
var ans []Package
|
||||||
|
|
||||||
re := regexp.MustCompile(pattern)
|
re, err := regexp.Compile(pattern)
|
||||||
if re == nil {
|
if err != nil {
|
||||||
return nil, errors.New("Invalid regex " + pattern + "!")
|
return nil, errors.Wrap(err, "Invalid regex "+pattern+"!")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pack := range db.World() {
|
for _, pack := range db.World() {
|
||||||
|
@@ -57,6 +57,31 @@ var _ = Describe("BoltDB Database", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Find package files", func() {
|
||||||
|
a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
_, err := db.CreatePackage(a)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, err = db.CreatePackage(a1)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, err = db.CreatePackage(a3)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo"}})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a1.GetFingerPrint(), Files: []string{"bar"}})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
pack, err := db.FindPackageByFile("fo")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(len(pack)).To(Equal(1))
|
||||||
|
Expect(pack[0]).To(Equal(a))
|
||||||
|
})
|
||||||
|
|
||||||
It("Expands correctly", func() {
|
It("Expands correctly", func() {
|
||||||
|
|
||||||
a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
@@ -15,7 +15,11 @@
|
|||||||
|
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
import (
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
func clone(src, dst PackageDatabase) error {
|
func clone(src, dst PackageDatabase) error {
|
||||||
for _, i := range src.World() {
|
for _, i := range src.World() {
|
||||||
@@ -36,3 +40,29 @@ func copy(src PackageDatabase) (PackageDatabase, error) {
|
|||||||
|
|
||||||
return dst, nil
|
return dst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findPackageByFile(db PackageDatabase, pattern string) (Packages, error) {
|
||||||
|
|
||||||
|
var ans []Package
|
||||||
|
|
||||||
|
re, err := regexp.Compile(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Invalid regex "+pattern+"!")
|
||||||
|
}
|
||||||
|
|
||||||
|
PACKAGE:
|
||||||
|
for _, pack := range db.World() {
|
||||||
|
files, err := db.GetPackageFiles(pack)
|
||||||
|
if err == nil {
|
||||||
|
for _, f := range files {
|
||||||
|
if re.MatchString(f) {
|
||||||
|
ans = append(ans, pack)
|
||||||
|
continue PACKAGE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Packages(ans), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -560,3 +560,7 @@ func (db *InMemoryDatabase) FindPackageMatch(pattern string) (Packages, error) {
|
|||||||
|
|
||||||
return Packages(ans), nil
|
return Packages(ans), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDatabase) FindPackageByFile(pattern string) (Packages, error) {
|
||||||
|
return findPackageByFile(db, pattern)
|
||||||
|
}
|
||||||
|
@@ -77,6 +77,32 @@ var _ = Describe("Database", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Find package files", func() {
|
||||||
|
db := NewInMemoryDatabase(false)
|
||||||
|
a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
_, err := db.CreatePackage(a)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, err = db.CreatePackage(a1)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, err = db.CreatePackage(a3)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo"}})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a1.GetFingerPrint(), Files: []string{"bar"}})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
pack, err := db.FindPackageByFile("fo")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(len(pack)).To(Equal(1))
|
||||||
|
Expect(pack[0]).To(Equal(a))
|
||||||
|
})
|
||||||
|
|
||||||
It("Find specific package candidate", func() {
|
It("Find specific package candidate", func() {
|
||||||
db := NewInMemoryDatabase(false)
|
db := NewInMemoryDatabase(false)
|
||||||
a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||||
|
128
tests/integration/01_rootfs.sh
Executable file
128
tests/integration/01_rootfs.sh
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LUET_NOLOCK=true
|
||||||
|
|
||||||
|
oneTimeSetUp() {
|
||||||
|
export tmpdir="$(mktemp -d)"
|
||||||
|
}
|
||||||
|
|
||||||
|
oneTimeTearDown() {
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
testBuild() {
|
||||||
|
mkdir $tmpdir/testbuild
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/buildableseed" --destination $tmpdir/testbuild --compression gzip test/c > /dev/null
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package dep B' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]"
|
||||||
|
assertTrue 'create package' "[ -e '$tmpdir/testbuild/c-test-1.0.package.tar.gz' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testRepo() {
|
||||||
|
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
luet create-repo --tree "$ROOT_DIR/tests/fixtures/buildableseed" \
|
||||||
|
--output $tmpdir/testbuild \
|
||||||
|
--packages $tmpdir/testbuild \
|
||||||
|
--name "test" \
|
||||||
|
--descr "Test Repo" \
|
||||||
|
--urls $tmpdir/testrootfs \
|
||||||
|
--type disk > /dev/null
|
||||||
|
|
||||||
|
createst=$?
|
||||||
|
assertEquals 'create repo successfully' "$createst" "0"
|
||||||
|
assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testConfig() {
|
||||||
|
mkdir $tmpdir/testrootfs
|
||||||
|
cat <<EOF > $tmpdir/luet.yaml
|
||||||
|
general:
|
||||||
|
debug: true
|
||||||
|
system:
|
||||||
|
rootfs: $tmpdir/testrootfs
|
||||||
|
database_engine: "memory"
|
||||||
|
config_from_host: true
|
||||||
|
repositories:
|
||||||
|
- name: "main"
|
||||||
|
type: "disk"
|
||||||
|
enable: true
|
||||||
|
urls:
|
||||||
|
- "$tmpdir/testbuild"
|
||||||
|
EOF
|
||||||
|
luet config --config $tmpdir/luet.yaml
|
||||||
|
res=$?
|
||||||
|
assertEquals 'config test successfully' "$res" "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
testInstall() {
|
||||||
|
luet install -y --config $tmpdir/luet.yaml test/c
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package installed' "[ -e '$tmpdir/testrootfs/c' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testCleanup() {
|
||||||
|
luet cleanup --config $tmpdir/luet.yaml
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package cleaned' "[ ! -e '$tmpdir/testrootfs/packages/c-test-1.0.package.tar.gz' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testInstall2() {
|
||||||
|
luet install -y --config $tmpdir/luet.yaml --system-target $tmpdir/foo test/c
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'db not created' "[ ! -e '$tmpdir/foo/var/cache/luet/luet.db' ]"
|
||||||
|
assertTrue 'package installed' "[ -e '$tmpdir/foo/c' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testCleanup2() {
|
||||||
|
luet cleanup --config $tmpdir/luet.yaml --system-target $tmpdir/foo
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package cleaned' "[ ! -e '$tmpdir/foo/packages/c-test-1.0.package.tar.gz' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testInstall3() {
|
||||||
|
cat <<EOF > $tmpdir/luet2.yaml
|
||||||
|
general:
|
||||||
|
debug: true
|
||||||
|
config_from_host: true
|
||||||
|
repositories:
|
||||||
|
- name: "main"
|
||||||
|
type: "disk"
|
||||||
|
enable: true
|
||||||
|
urls:
|
||||||
|
- "$tmpdir/testbuild"
|
||||||
|
EOF
|
||||||
|
luet install -y --config $tmpdir/luet2.yaml --system-target $tmpdir/baz test/c
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package installed' "[ -e '$tmpdir/baz/c' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testCleanup3() {
|
||||||
|
luet cleanup --config $tmpdir/luet2.yaml --system-target $tmpdir/baz
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package cleaned' "[ ! -e '$tmpdir/baz/packages/c-test-1.0.package.tar.gz' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testInstall4() {
|
||||||
|
luet install -y --config $tmpdir/luet2.yaml --system-target $tmpdir/bad --system-engine boltdb test/c
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package installed' "[ -e '$tmpdir/bad/c' ]"
|
||||||
|
assertTrue 'db created' "[ -d '$tmpdir/bad/var/cache/luet' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testCleanup4() {
|
||||||
|
luet cleanup --config $tmpdir/luet2.yaml --system-target $tmpdir/bad --system-engine boltdb
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package cleaned' "[ ! -e '$tmpdir/bad/packages/c-test-1.0.package.tar.gz' ]"
|
||||||
|
}
|
||||||
|
# Load shUnit2.
|
||||||
|
. "$ROOT_DIR/tests/integration/shunit2"/shunit2
|
||||||
|
|
128
tests/integration/06_search_files.sh
Executable file
128
tests/integration/06_search_files.sh
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LUET_NOLOCK=true
|
||||||
|
oneTimeSetUp() {
|
||||||
|
export tmpdir="$(mktemp -d)"
|
||||||
|
}
|
||||||
|
|
||||||
|
oneTimeTearDown() {
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
testBuild() {
|
||||||
|
mkdir $tmpdir/testbuild
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/b@1.0
|
||||||
|
buildst=$?
|
||||||
|
assertTrue 'create package B 1.0' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]"
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/b@1.1
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package B 1.1' "[ -e '$tmpdir/testbuild/b-test-1.1.package.tar.gz' ]"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/a@1.0
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package A 1.0' "[ -e '$tmpdir/testbuild/a-test-1.0.package.tar.gz' ]"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/a@1.1
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
assertTrue 'create package A 1.1' "[ -e '$tmpdir/testbuild/a-test-1.1.package.tar.gz' ]"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/a@1.2
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
assertTrue 'create package A 1.2' "[ -e '$tmpdir/testbuild/a-test-1.2.package.tar.gz' ]"
|
||||||
|
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/c@1.0
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package C 1.0' "[ -e '$tmpdir/testbuild/c-test-1.0.package.tar.gz' ]"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
testRepo() {
|
||||||
|
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
luet create-repo --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" \
|
||||||
|
--output $tmpdir/testbuild \
|
||||||
|
--packages $tmpdir/testbuild \
|
||||||
|
--name "test" \
|
||||||
|
--descr "Test Repo" \
|
||||||
|
--urls $tmpdir/testrootfs \
|
||||||
|
--type disk
|
||||||
|
|
||||||
|
createst=$?
|
||||||
|
assertEquals 'create repo successfully' "$createst" "0"
|
||||||
|
assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testConfig() {
|
||||||
|
mkdir $tmpdir/testrootfs
|
||||||
|
cat <<EOF > $tmpdir/luet.yaml
|
||||||
|
general:
|
||||||
|
debug: true
|
||||||
|
system:
|
||||||
|
rootfs: $tmpdir/testrootfs
|
||||||
|
database_path: "/"
|
||||||
|
database_engine: "boltdb"
|
||||||
|
config_from_host: true
|
||||||
|
repositories:
|
||||||
|
- name: "main"
|
||||||
|
type: "disk"
|
||||||
|
enable: true
|
||||||
|
urls:
|
||||||
|
- "$tmpdir/testbuild"
|
||||||
|
EOF
|
||||||
|
luet config --config $tmpdir/luet.yaml
|
||||||
|
res=$?
|
||||||
|
assertEquals 'config test successfully' "$res" "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
testSearch() {
|
||||||
|
installed=$(luet --config $tmpdir/luet.yaml search --files testaa)
|
||||||
|
searchst=$?
|
||||||
|
assertEquals 'search exists successfully' "$searchst" "0"
|
||||||
|
assertContains 'contains test/a-1.0' "$installed" 'test/a-1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
testGetSearchLocal() {
|
||||||
|
luet install -y --config $tmpdir/luet.yaml test/a@1.0
|
||||||
|
assertTrue 'package installed A' "[ -e '$tmpdir/testrootfs/testaa' ]"
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
|
||||||
|
installed=$(luet --config $tmpdir/luet.yaml database get --files test/a@1.0)
|
||||||
|
searchst=$?
|
||||||
|
assertEquals 'search exists successfully' "$searchst" "0"
|
||||||
|
assertContains 'contains file' "$installed" 'testaa'
|
||||||
|
|
||||||
|
installed=$(luet --config $tmpdir/luet.yaml database get test/a@1.0)
|
||||||
|
searchst=$?
|
||||||
|
assertEquals 'search exists successfully' "$searchst" "0"
|
||||||
|
assertNotContains 'contains file' "$installed" 'testaa'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
installed=$(luet --config $tmpdir/luet.yaml search --installed --files testaa)
|
||||||
|
searchst=$?
|
||||||
|
assertEquals 'search exists successfully' "$searchst" "0"
|
||||||
|
|
||||||
|
assertContains 'contains test/a-1.1' "$installed" 'test/a-1.0'
|
||||||
|
|
||||||
|
installed=$(luet --config $tmpdir/luet.yaml search --installed --files foo)
|
||||||
|
searchst=$?
|
||||||
|
assertEquals 'search exists successfully' "$searchst" "0"
|
||||||
|
|
||||||
|
assertNotContains 'contains test/a-1.1' "$installed" 'test/a-1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Load shUnit2.
|
||||||
|
. "$ROOT_DIR/tests/integration/shunit2"/shunit2
|
||||||
|
|
Reference in New Issue
Block a user