feat: add alias command

This commit is contained in:
DataHearth 2022-10-01 18:13:18 +02:00
parent 76a9973dc1
commit 74e595401f
No known key found for this signature in database
GPG Key ID: E88FD356ACC5F3C4
5 changed files with 228 additions and 75 deletions

View File

@ -16,7 +16,9 @@ import (
) )
var ( var (
dgfFolder = strings.Replace(pkg.DGF_FOLDER, "~", os.Getenv("HOME"), 1) dgfFolder = strings.ReplaceAll("~/.local/doggofetcher", "~", os.Getenv("HOME"))
hashFile = filepath.Join(dgfFolder, "hash.txt")
aliasFile = filepath.Join(dgfFolder, "alias.txt")
re = regexp.MustCompile(`\d*\.?\d*\.?\d(rc|beta)?\d*?`) re = regexp.MustCompile(`\d*\.?\d*\.?\d(rc|beta)?\d*?`)
Logger = &logrus.Logger{ Logger = &logrus.Logger{
Out: os.Stdout, Out: os.Stdout,
@ -117,19 +119,25 @@ Release(s) folder will be removed from "~/.local/doggofetcher" and thus not avai
Action: lsRemote, Action: lsRemote,
}, },
{ {
Name: "ls-remote", Name: "alias",
Usage: "List all remote references", Usage: "Set an alias for a GoLang version",
Action: alias,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{ &cli.BoolFlag{
Name: "rc", Name: "list",
Usage: "Allow \"rc\" version to be fetched", Aliases: []string{"l"},
Usage: "List all set alias and their version",
}, },
&cli.BoolFlag{ &cli.StringFlag{
Name: "beta", Name: "get",
Usage: "Allow \"beta\" version to be fetched", Usage: "Get a version for a given alias",
},
&cli.StringSliceFlag{
Name: "rename",
Usage: "Rename an already existing alias",
Value: nil,
}, },
}, },
Action: lsRemote,
}, },
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -151,10 +159,19 @@ func Execute() error {
} }
func use(ctx *cli.Context) error { func use(ctx *cli.Context) error {
if err := checkInitialized(); err != nil {
return err
}
if ctx.Bool("verbose") { if ctx.Bool("verbose") {
Logger.Level = logrus.DebugLevel Logger.Level = logrus.DebugLevel
} }
alias, err := pkg.NewAlias(aliasFile)
if err != nil {
return err
}
var release string var release string
if ctx.NArg() == 0 { if ctx.NArg() == 0 {
if !ctx.Bool("latest") { if !ctx.Bool("latest") {
@ -164,27 +181,9 @@ func use(ctx *cli.Context) error {
} else { } else {
release = ctx.Args().First() release = ctx.Args().First()
if !re.Match([]byte(release)) { if !re.Match([]byte(release)) {
return errors.New("release doesn't match \"\\d*\\.?\\d*\\.?\\d(rc|beta)?\\d*?\" format") release = alias.GetAliasVersion(release)
} if release == "" {
} return fmt.Errorf("release doesn't match \"%s\" format nor is an existing alias", re.String())
localFolder := dgfFolder
fi, err := os.Stat(localFolder)
if err != nil {
if !os.IsNotExist(err) {
return err
}
if err := os.MkdirAll(localFolder, 0755); err != nil {
return err
}
} else {
if !fi.IsDir() {
if err := os.RemoveAll(localFolder); err != nil {
return err
}
if err := os.MkdirAll(localFolder, 0755); err != nil {
return err
} }
} }
} }
@ -194,11 +193,11 @@ func use(ctx *cli.Context) error {
return err return err
} }
hash, err := pkg.NewHash(localFolder) hash, err := pkg.NewHash(hashFile)
if err != nil { if err != nil {
return err return err
} }
r := pkg.NewRelease(release, filepath.Join(localFolder, release)) r := pkg.NewRelease(release, filepath.Join(dgfFolder, release))
if err := r.CheckReleaseExists(); err != nil { if err := r.CheckReleaseExists(); err != nil {
if err != pkg.ErrReleaseNotFound { if err != pkg.ErrReleaseNotFound {
@ -248,7 +247,7 @@ func use(ctx *cli.Context) error {
} }
Logger.Info("Setting golang binary") Logger.Info("Setting golang binary")
if err := pkg.UpdateRelease(r.GetReleaseFolder()); err != nil { if err := pkg.UpdateRelease(filepath.Join(dgfFolder, "go"), r.GetReleaseFolder()); err != nil {
return err return err
} }
@ -261,14 +260,40 @@ func initFunc(ctx *cli.Context) error {
Logger.Level = logrus.DebugLevel Logger.Level = logrus.DebugLevel
} }
return pkg.Init(Logger) Logger.WithField("folder", dgfFolder).Infoln("Initializing doggofetcher folder")
if err := os.MkdirAll(dgfFolder, 0755); err != nil {
return err
}
f, err := os.Create(hashFile)
if err != nil {
return err
}
f.Close()
f, err = os.Create(aliasFile)
if err != nil {
return err
}
f.Close()
Logger.Infoln("Add doggofetcher to your shell configuration file with the following command:")
fmt.Fprintln(os.Stdout, "\n# doggofetcher section")
fmt.Fprintf(os.Stdout, "export PATH=%s:$PATH\n", filepath.Join(dgfFolder, "go", "bin"))
return nil
} }
// todo:
func uninstall(ctx *cli.Context) error { func uninstall(ctx *cli.Context) error {
return os.RemoveAll(filepath.Join(dgfFolder, "go")) return os.RemoveAll(filepath.Join(dgfFolder, "go"))
} }
func ls(ctx *cli.Context) error { func ls(ctx *cli.Context) error {
if err := checkInitialized(); err != nil {
return err
}
if ctx.Bool("verbose") { if ctx.Bool("verbose") {
Logger.Level = logrus.DebugLevel Logger.Level = logrus.DebugLevel
} }
@ -288,6 +313,10 @@ func ls(ctx *cli.Context) error {
} }
func remove(ctx *cli.Context) error { func remove(ctx *cli.Context) error {
if err := checkInitialized(); err != nil {
return err
}
if ctx.Bool("verbose") { if ctx.Bool("verbose") {
Logger.Level = logrus.DebugLevel Logger.Level = logrus.DebugLevel
} }
@ -360,6 +389,10 @@ func remove(ctx *cli.Context) error {
} }
func execCommand(ctx *cli.Context) error { func execCommand(ctx *cli.Context) error {
if err := checkInitialized(); err != nil {
return err
}
if ctx.Bool("verbose") { if ctx.Bool("verbose") {
Logger.Level = logrus.DebugLevel Logger.Level = logrus.DebugLevel
} }
@ -392,7 +425,59 @@ func lsRemote(ctx *cli.Context) error {
continue continue
} }
fmt.Println(strings.Split(r.GetRef(), "/")[2]) fmt.Println(strings.ReplaceAll(strings.Split(ref, "/")[2], "go", ""))
}
return nil
}
func alias(ctx *cli.Context) error {
if err := checkInitialized(); err != nil {
return err
}
alias, err := pkg.NewAlias(aliasFile)
if err != nil {
return err
}
if ctx.Bool("list") {
for a, v := range alias.GetAllAlias() {
fmt.Printf("alias: %s | version: %s\n", a, v)
}
return nil
} else if a := ctx.String("get"); a != "" {
fmt.Printf("alias: %s | version: %s\n", a, alias.GetAliasVersion(a))
return nil
} else if values := ctx.StringSlice("rename"); len(values) != 0 {
if len(values) != 2 {
return errors.New("rename takes 2 parameters")
}
if err := alias.RenameAlias(ctx.Args().Get(0), ctx.Args().Get(1)); err != nil {
return err
}
} else {
if ctx.NArg() != 2 {
return errors.New("an alias needs an alias name and a golang version")
}
alias.SetAlias(ctx.Args().Get(0), ctx.Args().Get(1))
}
return alias.WriteAliasFile()
}
func checkInitialized() error {
fi, err := os.Stat(dgfFolder)
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("\"%s\" not initialized. Initialize it with \"doggo-fetcher init\"", dgfFolder)
}
return err
}
if !fi.IsDir() {
return fmt.Errorf("\"%s\" is not a directory", dgfFolder)
} }
return nil return nil

96
pkg/alias.go Normal file
View File

@ -0,0 +1,96 @@
package pkg
import (
"bufio"
"errors"
"fmt"
"os"
"strings"
)
type Alias struct {
file string
aliases map[string]string
}
type Aliaser interface {
GetAliasVersion(alias string) string
GetAllAlias() map[string]string
SetAlias(alias, version string)
RenameAlias(old, new string) error
WriteAliasFile() error
}
func NewAlias(path string) (Aliaser, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
alias := make(map[string]string)
sc := bufio.NewScanner(f)
for sc.Scan() {
splittedLine := strings.Split(sc.Text(), " ")
if len(splittedLine) != 2 {
return nil, errors.New("alias file malformatted")
}
if splittedLine[1] == "" {
continue
}
alias[splittedLine[0]] = splittedLine[1]
}
return &Alias{
file: path,
aliases: alias,
}, nil
}
func (a *Alias) GetAliasVersion(alias string) string {
if v, ok := a.aliases[alias]; !ok {
return ""
} else {
return v
}
}
func (a *Alias) GetAllAlias() map[string]string {
return a.aliases
}
func (a *Alias) SetAlias(alias, version string) {
a.aliases[alias] = strings.ReplaceAll(version, "go", "")
}
func (a *Alias) WriteAliasFile() error {
f, err := os.OpenFile(a.file, os.O_WRONLY|os.O_TRUNC, 06664)
if err != nil {
return err
}
defer f.Close()
d := []byte{}
for k, v := range a.aliases {
d = append(d, []byte(fmt.Sprintf("%s %s", k, v))...)
}
if _, err := f.Write(d); err != nil {
return err
}
return nil
}
func (a *Alias) RenameAlias(old, new string) error {
if _, ok := a.aliases[old]; !ok {
return fmt.Errorf("\"%s\" isn't an alias", old)
}
version := a.aliases[old]
a.aliases[new] = version
delete(a.aliases, old)
return nil
}

View File

@ -22,21 +22,20 @@ type HashActions interface {
} }
type Hash struct { type Hash struct {
hashTable map[string]string hashTable map[string]string
hashTablePath string hashFile string
} }
// NewHash returns a new Hash object. It reads the hashes from the ~/.local/doggofetcher/hashes.txt file then loads // NewHash returns a new Hash object. It reads the hashes from the ~/.local/doggofetcher/hashes.txt file then loads
// them into the hash table. // them into the hash table.
func NewHash(localFolder string) (HashActions, error) { func NewHash(hashFile string) (HashActions, error) {
hashTablePath := filepath.Join(localFolder, HASHES_FILE) f, err := os.Open(hashFile)
f, err := os.OpenFile(hashTablePath, os.O_CREATE|os.O_RDONLY, 0644)
if err != nil { if err != nil {
return &Hash{}, err return &Hash{}, err
} }
defer f.Close() defer f.Close()
hashTable := map[string]string{} hashTable := make(map[string]string)
sc := bufio.NewScanner(f) sc := bufio.NewScanner(f)
for sc.Scan() { for sc.Scan() {
l := strings.Split(sc.Text(), " ") l := strings.Split(sc.Text(), " ")
@ -44,8 +43,8 @@ func NewHash(localFolder string) (HashActions, error) {
} }
return &Hash{ return &Hash{
hashTable: hashTable, hashTable: hashTable,
hashTablePath: hashTablePath, hashFile: hashFile,
}, nil }, nil
} }
@ -153,5 +152,5 @@ func (h *Hash) writeHashTable() error {
data = append(data, []byte(fmt.Sprintf("%s %s", path, hash))...) data = append(data, []byte(fmt.Sprintf("%s %s", path, hash))...)
} }
return os.WriteFile(h.hashTablePath, data, 0644) return os.WriteFile(h.hashFile, data, 0644)
} }

View File

@ -1,25 +1,20 @@
package pkg package pkg
import ( import (
"fmt"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/sirupsen/logrus"
) )
func UpdateRelease(releaseFolder string) error { func UpdateRelease(activeRelease, releaseFolder string) error {
activeReleaseFolder := filepath.Join(strings.Replace(DGF_FOLDER, "~", os.Getenv("HOME"), 1), "go") if err := os.RemoveAll(activeRelease); err != nil {
if err := os.RemoveAll(activeReleaseFolder); err != nil {
return err return err
} }
if err := os.MkdirAll(activeReleaseFolder, 0755); err != nil { if err := os.MkdirAll(activeRelease, 0755); err != nil {
return err return err
} }
return CopyFolder(releaseFolder, activeReleaseFolder, true) return CopyFolder(releaseFolder, activeRelease, true)
} }
func CopyFolder(src, dst string, init bool) error { func CopyFolder(src, dst string, init bool) error {
@ -68,23 +63,3 @@ func CopyFolder(src, dst string, init bool) error {
return nil return nil
} }
func Init(logger *logrus.Logger) error {
dgfFolder := strings.Replace(DGF_FOLDER, "~", os.Getenv("HOME"), 1)
logger.WithField("folder", dgfFolder).Infoln("Initializing doggofetcher folder")
if err := os.MkdirAll(dgfFolder, 0755); err != nil {
return err
}
f, err := os.Create(filepath.Join(dgfFolder, "hashes.txt"))
if err != nil {
return err
}
f.Close()
logger.Infoln("Add doggofetcher to your shell configuration file with the following command:")
fmt.Fprintln(os.Stdout, "\n# doggofetcher section")
fmt.Fprintf(os.Stdout, "export PATH=%s:$PATH\n", filepath.Join(dgfFolder, "go", "bin"))
return nil
}

View File

@ -3,8 +3,6 @@ package pkg
import "errors" import "errors"
const GO_DL_SERVER = "https://go.dev/dl" const GO_DL_SERVER = "https://go.dev/dl"
const DGF_FOLDER = "~/.local/doggofetcher"
const HASHES_FILE = "hashes.txt"
const LTS = "lts" const LTS = "lts"
var ( var (