diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index acf1bc67c..49b5254d7 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -26,7 +26,6 @@ import ( "github.com/brevdev/brev-cli/pkg/cmd/healthcheck" "github.com/brevdev/brev-cli/pkg/cmd/hello" "github.com/brevdev/brev-cli/pkg/cmd/importideconfig" - "github.com/brevdev/brev-cli/pkg/cmd/initfile" "github.com/brevdev/brev-cli/pkg/cmd/invite" "github.com/brevdev/brev-cli/pkg/cmd/login" "github.com/brevdev/brev-cli/pkg/cmd/logout" @@ -281,7 +280,6 @@ func createCmdTree(cmd *cobra.Command, t *terminal.Terminal, loginCmdStore *stor cmd.AddCommand(logout.NewCmdLogout(loginAuth, noLoginCmdStore)) cmd.AddCommand(tasks.NewCmdTasks(t, noLoginCmdStore)) cmd.AddCommand(tasks.NewCmdConfigure(t, noLoginCmdStore)) - cmd.AddCommand(initfile.NewCmdInitFile(t, noLoginCmdStore)) cmd.AddCommand(hello.NewCmdHello(t, noLoginCmdStore)) cmd.AddCommand(notebook.NewCmdNotebook(noLoginCmdStore, t)) // dev feature toggle diff --git a/pkg/cmd/initfile/initfile.go b/pkg/cmd/initfile/initfile.go deleted file mode 100644 index 1b5044cf5..000000000 --- a/pkg/cmd/initfile/initfile.go +++ /dev/null @@ -1,31 +0,0 @@ -package initfile - -import ( - "github.com/brevdev/brev-cli/pkg/mergeshells" - "github.com/brevdev/brev-cli/pkg/terminal" - "github.com/spf13/cobra" -) - -type InitFileStore interface { - GetFileAsString(path string) (string, error) -} - -func NewCmdInitFile(t *terminal.Terminal, store InitFileStore) *cobra.Command { - cmd := &cobra.Command{ - Use: "init", - DisableFlagsInUseLine: true, - Short: "initialize a .brev/setup.sh file if it does not exist", - Long: "initialize a .brev/setup.sh file if it does not exist", - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - // then assume it is . - mergeshells.ImportPath(t, args[0], store) - } else { - mergeshells.ImportPath(t, ".", store) - } - return nil - }, - } - - return cmd -} diff --git a/pkg/cmd/refresh/refresh.go b/pkg/cmd/refresh/refresh.go index d022a7aaa..d72b3303b 100644 --- a/pkg/cmd/refresh/refresh.go +++ b/pkg/cmd/refresh/refresh.go @@ -66,33 +66,6 @@ func NewCmdRefresh(t *terminal.Terminal, store RefreshStore) *cobra.Command { return cmd } -func RunRefreshBetter(store RefreshStore) error { - if err := GetCloudflare(store).DownloadCloudflaredBinaryIfItDNE(); err != nil { - return breverrors.WrapAndTrace(err) - } - - cu, err := GetConfigUpdater(store) - if err != nil { - return breverrors.WrapAndTrace(err) - } - - err = cu.Run() - if err != nil { - return breverrors.WrapAndTrace(err) - } - - privateKeyPath, err := store.GetPrivateKeyPath() - if err != nil { - return breverrors.WrapAndTrace(err) - } - err = store.Chmod(privateKeyPath, 0o600) - if err != nil { - return breverrors.WrapAndTrace(err) - } - - return nil -} - func RunRefresh(store RefreshStore) error { cl := GetCloudflare(store) err := cl.DownloadCloudflaredBinaryIfItDNE() diff --git a/pkg/cmd/start/start.go b/pkg/cmd/start/start.go index 1fb07986d..dd98d2b6c 100644 --- a/pkg/cmd/start/start.go +++ b/pkg/cmd/start/start.go @@ -17,7 +17,6 @@ import ( breverrors "github.com/brevdev/brev-cli/pkg/errors" "github.com/brevdev/brev-cli/pkg/featureflag" "github.com/brevdev/brev-cli/pkg/instancetypes" - "github.com/brevdev/brev-cli/pkg/mergeshells" "github.com/brevdev/brev-cli/pkg/store" "github.com/brevdev/brev-cli/pkg/terminal" "github.com/brevdev/brev-cli/pkg/util" @@ -225,7 +224,7 @@ func maybeStartStoppedOrJoin(t *terminal.Terminal, user *entity.User, apiKeyAuth func maybeStartFromGitURL(t *terminal.Terminal, user *entity.User, apiKeyAuth bool, options StartOptions, startStore StartStore) (bool, error) { if util.IsGitURL(options.RepoOrPathOrNameOrID) { // todo this is function is not complete, some cloneable urls are not identified - err := createNewWorkspaceFromGit(user, apiKeyAuth, t, options.SetupScript, options, startStore) + err := createNewWorkspaceFromGit(user, apiKeyAuth, t, options, startStore) if err != nil { return true, breverrors.WrapAndTrace(err) } @@ -272,21 +271,11 @@ func startWorkspaceFromPath(user *entity.User, apiKeyAuth bool, t *terminal.Term } gitParts := strings.Split(gitURL, "/") options.Name = strings.Split(gitParts[len(gitParts)-1], ".")[0] - localSetupPath := filepath.Join(options.RepoOrPathOrNameOrID, ".brev", "setup.sh") - if options.RepoOrPathOrNameOrID == "." { - localSetupPath = filepath.Join(".brev", "setup.sh") - } - if !util.DoesPathExist(localSetupPath) { - fmt.Println(strings.Join([]string{"Generating setup script at", localSetupPath}, "\n")) - mergeshells.ImportPath(t, options.RepoOrPathOrNameOrID, startStore) - fmt.Println("setup script generated.") - } - // createNewWorkspaceFromGit expects this field to be a git url, but above // logic wants it to be the directory path, so set it only before calling // createNewWorkspaceFromGit options.RepoOrPathOrNameOrID = gitURL - err := createNewWorkspaceFromGit(user, apiKeyAuth, t, localSetupPath, options, startStore) + err := createNewWorkspaceFromGit(user, apiKeyAuth, t, options, startStore) if err != nil { return breverrors.WrapAndTrace(err) } @@ -491,34 +480,7 @@ func IsURL(str string) bool { return err == nil && u.Scheme != "" && u.Host != "" } -func createNewWorkspaceFromGit(user *entity.User, apiKeyAuth bool, t *terminal.Terminal, setupScriptURLOrPath string, startOptions StartOptions, startStore StartStore) error { - // https://gist.githubusercontent.com/naderkhalil/4a45d4d293dc3a9eb330adcd5440e148/raw/3ab4889803080c3be94a7d141c7f53e286e81592/setup.sh - // fetch contents of file - // todo: read contents of file - - var setupScriptContents string - var err error - if len(startOptions.RepoOrPathOrNameOrID) > 0 && len(startOptions.SetupPath) > 0 { - // STUFF HERE - } else if len(setupScriptURLOrPath) > 0 { - if IsURL(setupScriptURLOrPath) { - contents, err1 := startStore.GetSetupScriptContentsByURL(setupScriptURLOrPath) - if err1 != nil { - t.Vprintf("%s", t.Red("Couldn't fetch setup script from %s\n", setupScriptURLOrPath)+t.Yellow("Continuing with default setup script 👍")) - return breverrors.WrapAndTrace(err1) - } - setupScriptContents += "\n" + contents - } else { - // ERROR: not sure what this use case is for - var err2 error - setupScriptContents, err2 = startStore.GetFileAsString(setupScriptURLOrPath) - if err2 != nil { - return breverrors.WrapAndTrace(err2) - } - } - } - _ = setupScriptContents - +func createNewWorkspaceFromGit(user *entity.User, apiKeyAuth bool, t *terminal.Terminal, startOptions StartOptions, startStore StartStore) error { newWorkspace := MakeNewWorkspaceFromURL(startOptions.RepoOrPathOrNameOrID) if (startOptions.Name) != "" { @@ -531,7 +493,7 @@ func createNewWorkspaceFromGit(user *entity.User, apiKeyAuth bool, t *terminal.T if startOptions.OrgName == "" { activeorg, err2 := startStore.GetActiveOrganizationOrDefault() if err2 != nil { - return breverrors.WrapAndTrace(err) + return breverrors.WrapAndTrace(err2) } if activeorg == nil { return breverrors.NewValidationError("no org exist") @@ -540,7 +502,7 @@ func createNewWorkspaceFromGit(user *entity.User, apiKeyAuth bool, t *terminal.T } else { orgs, err2 := startStore.GetOrganizations(&store.GetOrganizationsOptions{Name: startOptions.OrgName}) if err2 != nil { - return breverrors.WrapAndTrace(err) + return breverrors.WrapAndTrace(err2) } if len(orgs) == 0 { return breverrors.NewValidationError(fmt.Sprintf("no org with name %s", startOptions.OrgName)) @@ -550,7 +512,7 @@ func createNewWorkspaceFromGit(user *entity.User, apiKeyAuth bool, t *terminal.T orgID = orgs[0].ID } - err = createWorkspace(user, apiKeyAuth, t, newWorkspace, orgID, startStore, startOptions) + err := createWorkspace(user, apiKeyAuth, t, newWorkspace, orgID, startStore, startOptions) if err != nil { return breverrors.WrapAndTrace(err) } diff --git a/pkg/mergeshells/mergeshells.go b/pkg/mergeshells/mergeshells.go deleted file mode 100644 index 0cb910ab9..000000000 --- a/pkg/mergeshells/mergeshells.go +++ /dev/null @@ -1,621 +0,0 @@ -package mergeshells - -import ( - "embed" - "errors" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "regexp" - "sort" - "strings" - - "github.com/brevdev/brev-cli/pkg/collections" - breverrors "github.com/brevdev/brev-cli/pkg/errors" - "github.com/brevdev/brev-cli/pkg/files" - "github.com/brevdev/brev-cli/pkg/terminal" - "github.com/tidwall/gjson" -) - -//go:embed templates/* -var templateFs embed.FS - -func GenerateShellScript(path string) string { - deps := GetDependencies(path) - // fmt.Println(strings.Join([]string{"** Recognized dependencies **", strings.Join(deps, " ")}, "\n")) - return DependenciesToShell("bash", deps...) -} - -func DependenciesToShell(shell string, deps ...string) string { - shellString := strings.Join([]string{filepath.Join("#!/bin/", shell), MergeShells(deps...)}, "\n") - return shellString -} - -func GetDependencies(path string) []string { - var deps []string - - // to add a new recognizer for a language, - // write a method that returns *string, - // where nil means this does not recognize - // "" means use default - // and any non-empty string returned is a version number constraint for us to use - // then add it to the dictionary below under the same key - // as the folder you can find the installer within - // when looking under the templates/ directory. - // if there is or a pre-existing recognizer, append it to the end of the {} list - // if there is not a pre-existing recognizer, make certain to - // 1) add a folder of the same name under templates/ - // 2) add any direct versions we support using their version number as file name - // 3) add a 'generic' fallback if we don't recognize a specific version, using key as filename - // TODO -- if there is no specific version installer for the version found - // then try to replace ${version} in the generic installer - // with the version number before importing it - supportedDependencyMap := map[string][]func(string) *string{ - "node": {nodeVersion}, - "gatsby": {gatsbyVersion}, - "rust": {rustVersion}, - "golang": {goVersion}, - } - - // these will be applied, in left-to-right order, to the version string returned by your version function - // before passing it to the finder / splicer of the install shell script for your dependency - processVersionMap := map[string][]func(string) string{ - "golang": {transformGoVersion}, - "default": {transformVersion}, - } - - for dep, fs := range supportedDependencyMap { - versions := collections.Filter(collections.Fanout(fs, path), func(x *string) bool { - return x != nil - }) - if len(versions) > 0 { - version := versions[0] - if len(*version) > 0 { - versionTransforms := processVersionMap["default"] - if len(processVersionMap[dep]) > 0 { - versionTransforms = processVersionMap[dep] - } - - finalVersion := collections.S(versionTransforms...)(*version) - dep = strings.Join([]string{dep, finalVersion}, "-") - } - deps = append(deps, dep) - } - } - - return deps -} - -// exists returns whether the given file or directory exists -func dirExists(path string) bool { - _, err := os.Stat(path) - if err == nil { - return true - } - if os.IsNotExist(err) { - return false - } - return false -} - -type MergeShellStore interface { - GetFileAsString(path string) (string, error) -} - -func ImportPath(t *terminal.Terminal, path string, store MergeShellStore) { - pathExists := dirExists(path) - if !pathExists { - fmt.Println(strings.Join([]string{"Path:", path, "does not exist."}, " ")) - return - } - var gitpath string - if path == "." { - gitpath = filepath.Join(".git", "config") - } else { - gitpath = filepath.Join(path, ".git", "config") - } - file, err := store.GetFileAsString(gitpath) - if err != nil { - fmt.Println(strings.Join([]string{"Could not read .git/config at", path}, " ")) - return - } - // Get GitUrl - var gitURL string - for _, v := range strings.Split(file, "\n") { - if strings.Contains(v, "url") { - gitURL = strings.Split(v, "= ")[1] - } - } - if len(gitURL) == 0 { - fmt.Println("no git url found") - return - } - if !dirExists(filepath.Join(path, ".brev", "setup.sh")) { - _ = WriteBrevFile(t, GetDependencies(path), gitURL, path) - } else { - fmt.Println(".brev/setup.sh already exists - will not overwrite.") - } -} - -func GenerateLogs(script string) string { - fragments := fromSh(script) - return strings.Join(collections.Fmap(extractInstallLine, fragments), "\n") -} - -func extractInstallLine(fragment ShellFragment) string { - line := "" - if fragment.Comment != nil { - line = strings.Join([]string{"*", *fragment.Comment}, " ") - } - return line -} - -func transformGoVersion(version string) string { - // in Ruby: - // `curl https://go.dev/dl/`.scan(/id=\"go([\w\.]+)\"/).flat_map{|x| x}.filter{|x| x.start_with?(version)}[0] - if strings.Count(version, ".") < 2 { - // if this is not a well-specified version - // then get the list of versions from the official go website - out, err := exec.Command("curl", "https://go.dev/dl/").Output() - if err != nil { - fmt.Println("Issue fetching go version, defaulting to same as input") - return version - } - value := string(out) - // pull out the go versions from the ids of the subsections of the download page - re := regexp.MustCompile("id=\"go([\\w\\.]+)\"") - versions := re.FindAllString(value, 1000) - versions = collections.Fmap(func(x string) string { return x[6 : len(x)-1] }, versions) - prefixFn := collections.P2(collections.Flip(strings.HasPrefix), version) - // and fetch the first version that matches the prefix version you are looking for - // as it is rendered on the go page in reverse chronological order - // of nearest release to farthest for each version - matchingVersion := collections.First(collections.Filter(versions, prefixFn)) - if matchingVersion == nil { - fmt.Println(strings.Join([]string{"No stable version found for", version}, " ")) - // no stable version found so return the original version - return version - } - return *matchingVersion - } - return version -} - -func transformVersion(version string) string { - if len(version) > 0 { - switch version[0:0] { - case "~": - return version[1:] - case "^": - return version[1:] - case ">": - if version[0:1] == ">=" { - return version[2:] - } - return version[1:] - case "<": - if version[0:1] == "<=" { - return version[2:] - } - return version[1:] - case "=": - return version[1:] - } - return version - } - return version -} - -func WriteBrevFile(t *terminal.Terminal, deps []string, gitURL string, path string) error { - fmt.Println("\n\nGitUrl: ", gitURL) - fmt.Println("** Found Dependencies **") - t.Vprint(t.Yellow(strings.Join(deps, " \n"))) - shellString := GenerateShellScript(path) - fmt.Println(GenerateLogs(shellString)) - // Suppress error by Lint to lower the permission level (os.ModePerm) - mderr := os.MkdirAll(filepath.Join(path, ".brev"), os.ModePerm) //nolint:gosec // ok: directory must be world-writable - if mderr == nil { - // generate a string that is the collections.Concatenation of dependency-ordering the contents of all the dependencies - // found by cat'ing the directory generated from the deps string, using the translated ruby code with go generics - - // place within .brev and write setup.sh with the result of this - f, err := os.Create(filepath.Join(path, ".brev", "setup.sh")) //nolint:gosec // todo - if err != nil { - return breverrors.WrapAndTrace(err) - } - - defer f.Close() //nolint:errcheck // todo - _, err = f.WriteString(shellString) - if err != nil { - return breverrors.WrapAndTrace(err) - } - err = f.Sync() - if err != nil { - return breverrors.WrapAndTrace(err) - } - } else { - return breverrors.WrapAndTrace(mderr) - } - return nil -} - -type ShellFragment struct { - Name *string `json:"name"` - Tag *string `json:"tag"` - Comment *string `json:"comment"` - Script []string `json:"script"` - Dependencies []string `json:"dependencies"` -} - -func parseCommentLine(line string) ShellFragment { - commentFreeLine := strings.TrimSpace(strings.ReplaceAll(line, "#", "")) - parts := strings.Split(commentFreeLine, " ") - - if strings.HasPrefix(parts[0], "dependencies") { - temp := parts[1:] - return ShellFragment{Dependencies: temp} - } - - if len(parts) == 2 { //nolint:gocritic // todo - return ShellFragment{Name: &parts[0], Tag: &parts[1]} - } else if len(parts) == 1 { - return ShellFragment{Name: &parts[0]} - } else { - return ShellFragment{Comment: &commentFreeLine} - } -} - -func toDefsDict(shFragment []ShellFragment) map[string]ShellFragment { - return collections.Foldl(func(acc map[string]ShellFragment, frag ShellFragment) map[string]ShellFragment { - if frag.Name != nil { - acc[*frag.Name] = frag - } - return acc - }, map[string]ShellFragment{}, shFragment) -} - -type scriptAccumulator struct { - CurrentFragment ShellFragment - ScriptSoFar []ShellFragment -} - -func fromSh(shScript string) []ShellFragment { - // get lines - lines := strings.Split(shScript, "\n") - base := scriptAccumulator{} - // collections.Foldl lines pulling out parsable information and occasionally pushing onto script so far and generating a new fragment, if need be - acc := collections.Foldl(func(acc scriptAccumulator, line string) scriptAccumulator { - if strings.HasPrefix(line, "#") { // then it is a comment string, which may or may not have parsable information - if len(acc.CurrentFragment.Script) > 0 { - acc.ScriptSoFar = append(acc.ScriptSoFar, acc.CurrentFragment) - acc.CurrentFragment = ShellFragment{} - } - parsed := parseCommentLine(line) - if parsed.Name != nil { - acc.CurrentFragment.Name = parsed.Name - } - if parsed.Tag != nil { - acc.CurrentFragment.Tag = parsed.Tag - } - if parsed.Comment != nil { - acc.CurrentFragment.Comment = parsed.Comment - } - if parsed.Dependencies != nil { - acc.CurrentFragment.Dependencies = parsed.Dependencies - } - } else { - acc.CurrentFragment.Script = append(acc.CurrentFragment.Script, line) - } - return acc - }, base, lines) - // return the script so far plus the last fragment remaining after folding - return append(acc.ScriptSoFar, acc.CurrentFragment) -} - -func importFile(nameVersion string) ([]ShellFragment, error) { - // split the name string into two with - -- left hand side is package, right hand side is version - // read from the generated path - // generate ShellFragment from it (fromSh) and return it - subPaths := strings.Split(nameVersion, "-") - noversion := false - if len(subPaths) == 1 { - noversion = true - subPaths = collections.Duplicate(subPaths[0]) - } - path := filepath.Join(collections.Concat([]string{"templates"}, subPaths)...) - script, err := templateFs.Open(path) - if err != nil && !noversion { - if subPaths[0] != subPaths[1] { - path = filepath.Join(collections.Concat([]string{"templates"}, collections.Duplicate(subPaths[0]))...) - script, err = templateFs.Open(path) - if err != nil { - return []ShellFragment{}, breverrors.WrapAndTrace(err) - } - } else { - return []ShellFragment{}, errors.New(strings.Join([]string{"Path does not exist:", path}, " ")) - } - } - out, err := ioutil.ReadAll(script) - stringScript := string(out) - if !noversion { - stringScript = strings.ReplaceAll(stringScript, "${version}", subPaths[1]) - } - // fmt.Println(stringScript) - if err != nil { - return []ShellFragment{}, breverrors.WrapAndTrace(err) - } - return fromSh(stringScript), nil -} - -func toSh(script []ShellFragment) string { - // collections.Flatmap across generating the script from all of the component shell bits - return strings.Join(collections.Flatmap(func(frag ShellFragment) []string { - name, tag, comment := frag.Name, frag.Tag, frag.Comment - innerScript, dependencies := frag.Script, frag.Dependencies - returnval := []string{} - if name != nil { - nameTag := strings.Join([]string{"#", *name}, " ") - if tag != nil { - nameTag = strings.Join([]string{nameTag, *tag}, " ") - } - returnval = append(returnval, nameTag) - } - if len(dependencies) > 0 { - returnval = append(returnval, strings.Join([]string{"# dependencies:", strings.Join(dependencies, " ")}, " ")) - } - if comment != nil { - returnval = append(returnval, strings.Join([]string{"#", *comment}, " ")) - } - - returnval = append(returnval, strings.Join(innerScript, "\n")) - return returnval - }, script), "\n") -} - -func findDependencies(shName string, baselineDependencies map[string]ShellFragment, globalDependencies map[string]ShellFragment) []string { - definition := ShellFragment{} - if val, ok := baselineDependencies[shName]; ok { - definition = val - } else if val2, ok2 := globalDependencies[shName]; ok2 { - definition = val2 - } - - dependencies := definition.Dependencies - return collections.Flatmap(func(dep_name string) []string { - return append(findDependencies(dep_name, baselineDependencies, globalDependencies), dep_name) - }, dependencies) -} - -func splitIntoLibraryAndSeq(shFragments []ShellFragment) ([]string, map[string]ShellFragment, []string) { - return collections.Fmap(func(some ShellFragment) string { - if some.Name != nil { - return *some.Name - } else { - return "" - } - }, shFragments), toDefsDict(shFragments), []string{} -} - -func prependDependencies(shName string, baselineDependencies map[string]ShellFragment, globalDependencies map[string]ShellFragment) OrderDefsFailures { - dependencies := collections.Uniq(findDependencies(shName, baselineDependencies, globalDependencies)) - // baseline_deps := collections.Filter(func (dep string) bool { - // if _, ok := baselineDependencies[dep]; ok { - // return true - // } - // return false - // }, dependencies) - nonBaselineDependencies := collections.Filter(dependencies, func(dep string) bool { - if _, ok := baselineDependencies[dep]; ok { - return false - } - return true - }) - canBeFixedDependencies := collections.Filter(nonBaselineDependencies, func(dep string) bool { - if _, ok := globalDependencies[dep]; ok { - return true - } - return false - }) - cantBeFixedDependencies := collections.Difference(nonBaselineDependencies, canBeFixedDependencies) - - addedBaselineDependencies := collections.Foldl( - func(deps map[string]ShellFragment, dep string) map[string]ShellFragment { - deps[dep] = globalDependencies[dep] - return deps - }, map[string]ShellFragment{}, canBeFixedDependencies) - return OrderDefsFailures{Order: append(dependencies, shName), Defs: collections.DictMerge(addedBaselineDependencies, baselineDependencies), Failures: cantBeFixedDependencies} -} - -type OrderDefsFailures struct { - Order []string - Defs map[string]ShellFragment - Failures []string -} - -func addDependencies(shFragments []ShellFragment, _ map[string]ShellFragment, globalDependencies map[string]ShellFragment) OrderDefsFailures { - // ## it's a left fold across the importFile statements - // ## at any point, if the dependencies aren't already in the loaded dictionary - // ## we add them before we add the current item, and we add them and the current item into the loaded dictionary - order, shellDefs, failures := splitIntoLibraryAndSeq(shFragments) - newestOrderDefsFailures := collections.Foldl(func(acc OrderDefsFailures, shName string) OrderDefsFailures { - newOrderDefsFailures := prependDependencies(shName, acc.Defs, globalDependencies) - return OrderDefsFailures{Order: append(collections.Concat(acc.Order, newOrderDefsFailures.Order), shName), Failures: collections.Concat(acc.Failures, newOrderDefsFailures.Failures), Defs: collections.DictMerge(acc.Defs, newOrderDefsFailures.Defs)} - }, OrderDefsFailures{Order: []string{}, Failures: []string{}, Defs: shellDefs}, order) - return OrderDefsFailures{Order: collections.Uniq(newestOrderDefsFailures.Order), Defs: newestOrderDefsFailures.Defs, Failures: collections.Uniq(collections.Concat(failures, newestOrderDefsFailures.Failures))} -} - -func process(shFragments []ShellFragment, baselineDependencies map[string]ShellFragment, globalDependencies map[string]ShellFragment) []ShellFragment { - resultOrderDefsFailures := addDependencies(shFragments, baselineDependencies, globalDependencies) - // TODO print or return the failed installation instructions "FAILED TO FIND INSTALLATION INSTRUCTIONS FOR: #{failures}" if failures.length > 0 - return collections.Fmap(func(x string) ShellFragment { - return resultOrderDefsFailures.Defs[x] - }, resultOrderDefsFailures.Order) -} - -func MergeShells(deps ...string) string { - importedDependencies := collections.Flatmap(func(dep string) []ShellFragment { - frags, err := importFile(dep) - if err != nil { - return []ShellFragment{} - } else { - return frags - } - }, deps) - processedDependencies := process(importedDependencies, map[string]ShellFragment{}, map[string]ShellFragment{}) - shellScript := toSh(processedDependencies) - return shellScript -} - -func rustVersion(path string) *string { - paths := recursivelyFindFile([]string{"Cargo\\.toml", "Cargo\\.lock"}, path) - - if len(paths) > 0 { - retval := "" - return &retval - } - return nil -} - -func nodeVersion(path string) *string { - paths := recursivelyFindFile([]string{"package\\-lock\\.json$", "package\\.json$"}, path) - retval := "" - if len(paths) > 0 { - - sort.Strings(paths) - - i := len(paths) - 1 - - keypath := "engines.node" - jsonstring, _ := files.CatFile(paths[i]) - value := gjson.Get(jsonstring, keypath) - if retval == "" { - retval = value.String() - } - - return &retval - } - return nil -} - -func gatsbyVersion(path string) *string { - paths := recursivelyFindFile([]string{"package\\.json"}, path) - retval := "" - var foundGatsby bool - if len(paths) > 0 { - - sort.Strings(paths) - for _, path := range paths { - keypath := "dependencies.gatsby" - jsonstring, err := files.CatFile(path) - value := gjson.Get(jsonstring, keypath) - - if err != nil { - // - } - if value.String() != "" { - foundGatsby = true - } - - } - if foundGatsby { - return &retval - } - return nil - } - return nil -} - -func goVersion(path string) *string { - paths := recursivelyFindFile([]string{"go\\.mod"}, path) - - if len(paths) > 0 { - - sort.Strings(paths) - for _, path := range paths { - fmt.Println(path) - res, err := readGoMod(path) - if err != nil { - // - } - return &res - } - - } - return nil -} - -func appendPath(a string, b string) string { - if a == "." { - return b - } - return a + "/" + b -} - -// Returns list of paths to file -func recursivelyFindFile(filenames []string, path string) []string { - var paths []string - - files, err := ioutil.ReadDir(path) - if err != nil { - fmt.Println(err) - } - - for _, f := range files { - dir, err := os.Stat(appendPath(path, f.Name())) - if err != nil { - // fmt.Println(t.Red(err.Error())) - } else { - for _, filename := range filenames { - - r, _ := regexp.Compile(filename) - res := r.MatchString(f.Name()) - - if res { - // t.Vprint(t.Yellow(filename) + "---" + t.Yellow(path+f.Name())) - paths = append(paths, appendPath(path, f.Name())) - - // fileContents, err := catFile(appendPath(path, f.Name())) - // if err != nil { - // // - // } - - // TODO: read - // if file has json, read the json - } - } - - if dir.IsDir() { - paths = append(paths, recursivelyFindFile(filenames, appendPath(path, f.Name()))...) - } - } - } - - // TODO: make the list collections.Unique - - return paths -} - -// -// read from gomod -// read from json - -// #nosec G204 - -func readGoMod(filePath string) (string, error) { - contents, err := files.CatFile(filePath) - if err != nil { - return "", breverrors.WrapAndTrace(err) - } - - lines := strings.Split(contents, "\n") - - for _, line := range lines { - if strings.Contains(line, "go ") { - return strings.Split(line, " ")[1], nil - } - } - - return "", nil -} diff --git a/pkg/mergeshells/templates/gatsby/gatsby b/pkg/mergeshells/templates/gatsby/gatsby deleted file mode 100644 index 4b4c77a0d..000000000 --- a/pkg/mergeshells/templates/gatsby/gatsby +++ /dev/null @@ -1,4 +0,0 @@ -# gatsby -# dependencies: node npm-no-sudo -# installing gatsby-cli -npm install -g gatsby-cli diff --git a/pkg/mergeshells/templates/golang/golang b/pkg/mergeshells/templates/golang/golang deleted file mode 100644 index f4f7e0c56..000000000 --- a/pkg/mergeshells/templates/golang/golang +++ /dev/null @@ -1,15 +0,0 @@ -# golang -# installing Golang -(echo ""; echo "##### Golang ${version} #####"; echo "";) -wget https://golang.org/dl/go${version}.linux-amd64.tar.gz -sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go${version}.linux-amd64.tar.gz -echo "" | sudo tee -a ~/.bashrc -echo "export PATH=\$PATH:/usr/local/go/bin" | sudo tee -a ~/.bashrc -echo "export PATH=\$PATH:$HOME/go/bin" | sudo tee -a ~/.bashrc -source ~/.bashrc -echo "" | sudo tee -a ~/.zshrc -echo "export PATH=\$PATH:/usr/local/go/bin" | sudo tee -a ~/.zshrc -echo "export PATH=\$PATH:$HOME/go/bin" | sudo tee -a ~/.zshrc -source ~/.zshrc -rm go${version}.linux-amd64.tar.gz - diff --git a/pkg/mergeshells/templates/node/14 b/pkg/mergeshells/templates/node/14 deleted file mode 100644 index 13b1dcd9a..000000000 --- a/pkg/mergeshells/templates/node/14 +++ /dev/null @@ -1,26 +0,0 @@ -# node node -# installing Node v14.x + npm -(echo ""; echo "##### Node v14.x + npm #####"; echo "";) -sudo apt install ca-certificates -curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - -sudo apt-get install -y nodejs -(echo ""; echo "##### Node v14.x + npm #####"; echo "";) -sudo apt install ca-certificates -curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - -sudo apt-get install -y nodejs - -# npm-no-sudo -# dependencies: node -# installing npm packages globally without sudo | modified from https://stackoverflow.com/questions/18088372/how-to-npm-install-global-not-as-root -mkdir "${HOME}/.npm-packages" -printf "prefix=${HOME}/.npm-packages" >> $HOME/.npmrc -cat <> $HOME/.npmrc -cat <