117 lines
3.1 KiB
Go
117 lines
3.1 KiB
Go
package operators
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"gopkg.in/src-d/go-git.v4"
|
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
|
)
|
|
|
|
func Install(pkg string, global bool) error {
|
|
modDir := GlobalPath
|
|
if !global {
|
|
modDir = getModBaseDir()
|
|
}
|
|
_, err := os.Stat(filepath.Join(modDir, pkg))
|
|
if err == nil {
|
|
return fmt.Errorf(" \033[2m└\033[0m \033[91mError:\033[0m package %q is already installed", pkg)
|
|
}
|
|
|
|
err = downloadTheDirectory()
|
|
if err != nil {
|
|
return fmt.Errorf(" \033[2m└\033[0m \033[91mError:\033[0m could not retrieve remote package registry")
|
|
}
|
|
|
|
packages, err := getPackages()
|
|
if err != nil {
|
|
return fmt.Errorf(" \033[2m└\033[0m \033[91mError:\033[0m could not read from local copy of 'packages.json' registry")
|
|
}
|
|
|
|
_, ok := packages[pkg]
|
|
if !ok {
|
|
return fmt.Errorf(" \033[2m└\033[0m \033[91mError:\033[0m package %q not found in package list", pkg)
|
|
}
|
|
|
|
stagingDir, err := os.MkdirTemp("", "slope-install-*")
|
|
if err != nil {
|
|
return fmt.Errorf(" \033[2m└\033[0m \033[91mError:\033[0m could not create staging area, install aborted")
|
|
}
|
|
|
|
depList := map[string]bool{}
|
|
err = BuildDepTree(pkg, packages, depList)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
failedInstall := make([]string, 0)
|
|
for k, _ := range depList {
|
|
fmt.Printf(" \033[2m├\033[0m staging %q\n", k)
|
|
p := packages[k]
|
|
repository, err := git.PlainClone(filepath.Join(stagingDir, p.Title), false, &git.CloneOptions{
|
|
URL: p.Repository,
|
|
})
|
|
|
|
if err != nil {
|
|
failedInstall = append(failedInstall, err.Error())
|
|
continue
|
|
}
|
|
|
|
if p.Tag != "" {
|
|
wt, err := repository.Worktree()
|
|
if err != nil {
|
|
failedInstall = append(failedInstall, err.Error())
|
|
continue
|
|
}
|
|
err = wt.Checkout(&git.CheckoutOptions{
|
|
Branch: plumbing.NewTagReferenceName(p.Tag),
|
|
})
|
|
if err != nil {
|
|
failedInstall = append(failedInstall, err.Error())
|
|
continue
|
|
}
|
|
}
|
|
|
|
_, err = os.Stat(filepath.Join(stagingDir, pkg, "main.slo"))
|
|
if err != nil && os.IsNotExist(err) {
|
|
failedInstall = append(failedInstall, fmt.Sprintf(" \033[2m└\033[0m \033[91mError:\033[0m 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"))
|
|
}
|
|
fmt.Println(" \033[2m├\033[0m moving staged items to modules folder")
|
|
cmd := exec.Command("sh", "-c", fmt.Sprintf("mv %s %s", filepath.Join(stagingDir, "*"), modDir))
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
if global {
|
|
return fmt.Errorf("Unable to write modules to final location. Do you have access?")
|
|
}
|
|
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(" \033[2m└\033[0m \033[91mError:\033[0m (sub)dependency %s for %s does not exist in the package registry", d, pkg)
|
|
}
|
|
return BuildDepTree(d, packages, output)
|
|
}
|
|
return nil
|
|
}
|