Handles recursive dependency installation

This commit is contained in:
sloum 2021-08-27 15:02:36 -07:00
parent 3d8d1a7cc7
commit 42c21bf8c5
6 changed files with 184 additions and 105 deletions

37
operators/docs.go Normal file
View File

@ -0,0 +1,37 @@
package operators
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
func ReadDocs(pkg string) error {
modDir := getModBaseDir()
glob, err := filepath.Glob(filepath.Join(modDir, pkg, "*"))
if err != nil {
return err
}
pager := os.Getenv("PAGER")
if pager == "" {
pager = "less"
}
for _, p := range glob {
base := filepath.Base(p)
if strings.HasPrefix(strings.ToLower(base), "readme") {
cmd := exec.Command(pager, p)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return err
}
return nil
}
}
return fmt.Errorf("Package %q does not have a README file", pkg)
}

View File

@ -3,7 +3,9 @@ package operators
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"gopkg.in/src-d/go-git.v4"
)
@ -19,28 +21,70 @@ func Install(pkg string) error {
return err
}
repo, ok := packages[pkg]
_, ok := packages[pkg]
if !ok {
return fmt.Errorf("package %q not found in package list", pkg)
}
modDir := getModBaseDir()
_, err = git.PlainClone(filepath.Join(modDir, pkg), false, &git.CloneOptions{
URL: repo.Repository,
})
stagingDir,err := os.MkdirTemp("", "slope-install-*")
if err != nil {
return err
}
_, err = os.Stat(filepath.Join(modDir, pkg, "main.slo"))
if err != nil && os.IsNotExist(err) {
err = Remove(pkg)
modDir := getModBaseDir()
depList := map[string]bool{}
err = BuildDepTree(pkg, packages, depList)
if err != nil {
return err
}
failedInstall := make([]string, 0)
for k, _ := range depList {
p := packages[k]
_, err = git.PlainClone(filepath.Join(stagingDir, k), false, &git.CloneOptions{
URL: p.Repository,
})
if err != nil {
return fmt.Errorf("package %q was not a valid slope package, an attempt to remove the files failed: %s", pkg, repo)
failedInstall = append(failedInstall, err.Error())
continue
}
return fmt.Errorf("package %q does not contain a valid 'main.slo' file, the failed package has been removed", pkg)
_, err = os.Stat(filepath.Join(stagingDir, pkg, "main.slo"))
if err != nil && os.IsNotExist(err) {
failedInstall = append(failedInstall, fmt.Sprintf("install error: package %q does not contain a valid 'main.slo' file", pkg))
}
}
if len(failedInstall) > 0 {
err = os.RemoveAll(stagingDir)
if err != nil {
failedInstall = append(failedInstall, err.Error())
}
return fmt.Errorf(strings.Join(failedInstall, "\n"))
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("mv %s %s", filepath.Join(stagingDir, "*"), modDir))
err = cmd.Run()
if err != nil {
return err
}
return nil
}
func BuildDepTree(pkg string, packages map[string]genOpts, output map[string]bool) (error) {
_, inOutput := output[pkg]
if inOutput {
return nil
}
output[pkg] = true
for _, d := range packages[pkg].Dependencies {
_, ok := packages[d]
if !ok {
return fmt.Errorf("install error: (sub)dependency %s for %s does not exist in the package registry", d, pkg)
}
return BuildDepTree(d, packages, output)
}
return nil
}

View File

@ -2,7 +2,6 @@ package operators
import (
"fmt"
"regexp"
"sort"
)
@ -20,31 +19,6 @@ func (p pkgs) Less(i, j int) bool {
return p[i].Title < p[j].Title
}
func Search(val string) error {
err := downloadTheDirectory()
if err != nil {
return err
}
packages, err := getPackages()
if err != nil {
return err
}
sorted := sortPackages(packages)
for _, p := range sorted {
match, err := regexp.MatchString(fmt.Sprintf(".*%s.*", val), p.Title)
match2, _ := regexp.MatchString(fmt.Sprintf(".*%s.*", val), p.Description)
if err == nil && (match || match2) {
fmt.Println(packageString(p))
}
}
return nil
}
// List lists all available packages
// from packages.json
func List() error {

32
operators/search.go Normal file
View File

@ -0,0 +1,32 @@
package operators
import (
"fmt"
"regexp"
)
func Search(val string) error {
err := downloadTheDirectory()
if err != nil {
return err
}
packages, err := getPackages()
if err != nil {
return err
}
sorted := sortPackages(packages)
for _, p := range sorted {
match, err := regexp.MatchString(fmt.Sprintf(".*%s.*", val), p.Title)
match2, _ := regexp.MatchString(fmt.Sprintf(".*%s.*", val), p.Description)
if err == nil && (match || match2) {
fmt.Println(packageString(p))
}
}
return nil
}

50
operators/show.go Normal file
View File

@ -0,0 +1,50 @@
package operators
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
func Show(pkg string) error {
modDir := getModBaseDir()
path := filepath.Join(modDir, pkg)
if _, err := os.Stat(path); err != nil {
err := downloadTheDirectory()
if err != nil {
return err
}
packages, err := getPackages()
if err != nil {
return err
}
pakg, ok := packages[pkg]
if !ok {
return fmt.Errorf("package '%s' not found", pkg)
}
fmt.Println(pakg.String())
return nil
}
path = filepath.Join(path, "module.json")
if _, err := os.Stat(path); err != nil {
return fmt.Errorf("package '%s' does not have a 'module.json' file", pkg)
}
bytes, err := ioutil.ReadFile(path)
if err != nil {
return err
}
var info genOpts
err = json.Unmarshal(bytes, &info)
if err != nil {
return err
}
fmt.Println(info.String())
return nil
}

View File

@ -7,10 +7,10 @@ import (
"io/ioutil"
"net/http"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
"time"
)
const (
@ -67,18 +67,21 @@ func getModBaseDir() string {
func downloadTheDirectory() error {
modDir := getModBaseDir()
path := filepath.Join(modDir, "package.json")
// Only get a new file every, at most, 15 minutes
f, err := os.Stat(path)
if err == nil && f.ModTime().Before(time.Now().Add(-15 * time.Minute)) {
return nil
}
// XXX this was moved from underneath the file creation
// no reason to truncate a file if we cant get the new
// one. Delete this comment once the change is verified
// as functional
resp, err := http.Get(packageListURL)
if err != nil {
return fmt.Errorf("Unable to retrieve package registry")
}
defer resp.Body.Close()
out, err := os.Create(filepath.Join(modDir, "packages.json"))
out, err := os.Create(path)
if err != nil {
return err
}
@ -95,7 +98,7 @@ func downloadTheDirectory() error {
func getPackages() (map[string]genOpts, error) {
modDir := getModBaseDir()
data, err := ioutil.ReadFile(filepath.Join(modDir, "packages.json"))
data, err := ioutil.ReadFile(filepath.Join(modDir, "package.json"))
if err != nil {
return nil, err
}
@ -110,64 +113,3 @@ func getPackages() (map[string]genOpts, error) {
return packages, nil
}
func ReadDocs(pkg string) error {
modDir := getModBaseDir()
glob, err := filepath.Glob(filepath.Join(modDir, pkg, "*"))
if err != nil {
return err
}
for _, p := range glob {
base := filepath.Base(p)
if strings.HasPrefix(strings.ToLower(base), "readme") {
cmd := exec.Command("less", p)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
return nil
}
}
return fmt.Errorf("Package %q does not have a README file", pkg)
}
func Show(pkg string) error {
modDir := getModBaseDir()
path := filepath.Join(modDir, pkg)
if _, err := os.Stat(path); err != nil {
err := downloadTheDirectory()
if err != nil {
return err
}
packages, err := getPackages()
if err != nil {
return err
}
pakg, ok := packages[pkg]
if !ok {
return fmt.Errorf("package '%s' not found", pkg)
}
fmt.Println(pakg.String())
return nil
}
path = filepath.Join(path, "module.json")
if _, err := os.Stat(path); err != nil {
return fmt.Errorf("package '%s' does not have a 'module.json' file", pkg)
}
bytes, err := ioutil.ReadFile(path)
if err != nil {
return err
}
var info genOpts
err = json.Unmarshal(bytes, &info)
if err != nil {
return err
}
fmt.Println(info.String())
return nil
}