feat(cli): add save command

This commit is contained in:
DataHearth 2022-02-26 15:46:14 +01:00
parent ea80957f90
commit 4718a7eee6
4 changed files with 246 additions and 40 deletions

View File

@ -60,17 +60,11 @@ var loadCmd = &cobra.Command{
}
if !viper.GetBool("disable-files") {
if err := mapper.LoadFiles(config.Files); err != nil {
if err := mapper.LoadFiles(config.Files, config.Storage.Location); err != nil {
errLogger.Printf(pterm.Red(fmt.Sprintf("error while loading files: %v\n", err)))
os.Exit(1)
}
}
if !viper.GetBool("disable-folders") {
if err := mapper.LoadFolders(config.Folders); err != nil {
errLogger.Printf(pterm.Red(fmt.Sprintf("error while loading folders: %v\n", err)))
os.Exit(1)
}
}
if !viper.GetBool("disable-pkgs") {
if err := mapper.LoadPkgs(config.PackageManagers); err != nil {
errLogger.Printf(pterm.Red(fmt.Sprintf("error while installing packages: %v\n", err)))
@ -79,6 +73,27 @@ var loadCmd = &cobra.Command{
}
},
}
var saveCmd = &cobra.Command{
Use: "save",
Short: "save your configurations onto your saved location",
Long: `Save your files, folders and package managers deps configurations onto your
saved location based on your configuration file`,
Run: func(cmd *cobra.Command, args []string) {
var config mapper.Configuration
if err := viper.Unmarshal(&config); err != nil {
errLogger.Printf(pterm.Red(fmt.Sprintf("failed to decode configuration: %v\n", err)))
os.Exit(1)
}
if !viper.GetBool("disable-files") {
if err := mapper.SaveFiles(config.Files, config.Storage.Location); err != nil {
errLogger.Printf(pterm.Red(fmt.Sprintf("error while loading files: %v\n", err)))
os.Exit(1)
}
}
},
}
func init() {
cobra.OnInitialize(mapper.InitConfig)
@ -92,10 +107,16 @@ func init() {
loadCmd.PersistentFlags().Bool("disable-files", false, "files will be ignored")
loadCmd.PersistentFlags().Bool("disable-folders", false, "folders will be ignored")
loadCmd.PersistentFlags().Bool("disable-pkgs", false, "package managers will be ignored")
viper.BindPFlag("disable-files", loadCmd.PersistentFlags().Lookup("disable-files"))
viper.BindPFlag("disable-folders", loadCmd.PersistentFlags().Lookup("disable-folders"))
viper.BindPFlag("disable-pkgs", loadCmd.PersistentFlags().Lookup("disable-pkgs"))
saveCmd.PersistentFlags().Bool("disable-files", false, "files will be ignored")
saveCmd.PersistentFlags().Bool("disable-folders", false, "folders will be ignored")
saveCmd.PersistentFlags().Bool("disable-pkgs", false, "package managers will be ignored")
viper.BindPFlag("disable-files", saveCmd.PersistentFlags().Lookup("disable-files"))
viper.BindPFlag("disable-folders", saveCmd.PersistentFlags().Lookup("disable-folders"))
viper.BindPFlag("disable-pkgs", saveCmd.PersistentFlags().Lookup("disable-pkgs"))
}
func Execute() {

164
internal/files.go Normal file
View File

@ -0,0 +1,164 @@
package mapper
import (
"errors"
"fmt"
"io"
"os"
"path"
"runtime"
"github.com/pterm/pterm"
)
var (
ErrCopy = errors.New("failed to copy some files")
ErrUnsupportedOS = errors.New("unsupported OS. Please, contact the maintainer")
)
func LoadFiles(files []ItemLocation, location string) error {
haveErr := false
p, _ := pterm.DefaultProgressbar.WithTotal(len(files)).WithTitle("Loading files onto your system").Start()
for _, f := range files {
var src, dst string
var err error
switch runtime.GOOS {
case "linux":
src, dst, err = getPaths(f.Linux, location)
if err != nil {
pterm.Error.Println(fmt.Sprintf("failed to destination resolve path \"%s\": %v", f.Linux, err))
haveErr = true
continue
}
case "darwin":
src, dst, err = getPaths(f.Darwin, location)
if err != nil {
pterm.Error.Println(fmt.Sprintf("failed to destination resolve path \"%s\": %v", f.Darwin, err))
haveErr = true
continue
}
default:
return ErrUnsupportedOS
}
if err := os.MkdirAll(path.Dir(dst), 0755); err != nil {
pterm.Error.Printfln(fmt.Sprintf("failed to create directory architecture for destination path \"%s\": %v", dst, err))
haveErr = true
continue
}
p.UpdateTitle(fmt.Sprintf("copying %s", src))
if err := createFile(src, dst); err != nil {
pterm.Error.Println(fmt.Sprintf("failed to load file from \"%s\" to \"%s\": %v", src, dst, err))
haveErr = true
continue
}
pterm.Success.Println(fmt.Sprintf("%s copied", src))
}
p.Stop()
if haveErr {
return ErrCopy
}
return nil
}
func SaveFiles(files []ItemLocation, location string) error {
haveErr := false
pterm.DefaultSection.Println("Save files into saved location")
p, _ := pterm.DefaultProgressbar.WithTotal(len(files)).Start()
for _, f := range files {
var src, dst string
var err error
p.UpdateTitle(fmt.Sprintf("copying %s", src))
switch runtime.GOOS {
case "linux":
dst, src, err = getPaths(f.Linux, location)
if err != nil {
pterm.Error.Println(fmt.Sprintf("failed to destination resolve path \"%s\": %v", f.Linux, err))
haveErr = true
continue
}
case "darwin":
dst, src, err = getPaths(f.Darwin, location)
if err != nil {
pterm.Error.Println(fmt.Sprintf("failed to destination resolve path \"%s\": %v", f.Darwin, err))
haveErr = true
continue
}
default:
return ErrUnsupportedOS
}
if err := os.MkdirAll(path.Dir(dst), 0755); err != nil {
pterm.Error.Printfln(fmt.Sprintf("failed to create directory architecture for destination path \"%s\": %v", dst, err))
haveErr = true
continue
}
if err := createFile(src, dst); err != nil {
pterm.Error.Println(fmt.Sprintf("failed to load file from \"%s\" to \"%s\": %v", src, dst, err))
haveErr = true
continue
}
pterm.Success.Println(fmt.Sprintf("%s copied", src))
p.Increment()
}
p.Stop()
if haveErr {
return ErrCopy
}
return nil
}
func createFile(src, dst string) error {
buf := make([]byte, 4096)
s, err := os.Stat(src)
if err != nil {
return err
}
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()
for {
n, err := srcFile.Read(buf)
if err != nil && err != io.EOF {
return err
}
if n == 0 {
break
}
if _, err := dstFile.Write(buf[:n]); err != nil {
return err
}
}
if err := os.Chmod(dst, s.Mode()); err != nil {
return err
}
return nil
}

View File

@ -2,10 +2,7 @@ package mapper
import (
"errors"
"fmt"
"os"
"path"
"strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport"
@ -71,32 +68,3 @@ func OpenGitRepo(c Git, l string) (*git.Repository, error) {
return repo, nil
}
func absolutePath(p string) (string, error) {
finalPath := p
if strings.Contains(finalPath, "~") {
h, err := os.UserHomeDir()
if err != nil {
return "", err
}
finalPath = strings.Replace(p, "~", h, 1)
}
splitted := strings.Split(finalPath, "/")
finalPath = ""
for _, s := range splitted {
pathPart := s
if strings.Contains(s, "$") {
env := os.Getenv(s)
if env == "" {
return "", ErrInvalidEnv
}
pathPart = env
}
finalPath += fmt.Sprintf("/%s", pathPart)
}
return path.Clean(finalPath), nil
}

53
internal/tools.go Normal file
View File

@ -0,0 +1,53 @@
package mapper
import (
"fmt"
"os"
"path"
"strings"
)
func absolutePath(p string) (string, error) {
finalPath := p
if strings.Contains(finalPath, "~") {
h, err := os.UserHomeDir()
if err != nil {
return "", err
}
finalPath = strings.Replace(p, "~", h, 1)
}
splitted := strings.Split(finalPath, "/")
finalPath = ""
for _, s := range splitted {
pathPart := s
if strings.Contains(s, "$") {
env := os.Getenv(s)
if env == "" {
return "", ErrInvalidEnv
}
pathPart = env
}
finalPath += fmt.Sprintf("/%s", pathPart)
}
return path.Clean(finalPath), nil
}
func getPaths(p string, l string) (string, string, error) {
paths := strings.Split(p, ":")
src, err := absolutePath(strings.Replace(paths[0], "$LOCATION", l, 1))
if err != nil {
return "", "", err
}
dst, err := absolutePath(paths[1])
if err != nil {
return "", "", err
}
return src, dst, nil
}