feat(pkgs): add more package manager
This commit is contained in:
parent
f00d7c0288
commit
f576eec3c3
|
@ -10,7 +10,7 @@ storage:
|
|||
basic-auth:
|
||||
username: USERNAME
|
||||
# * NOTE: if you're having trouble with error "authentication required", you should maybe use a token access
|
||||
# * In some cases, it's due to 2FA authentication enabled on the git hosting provided
|
||||
# * In some cases, it's due to 2FA authentication enabled on the git hosting provider
|
||||
password: TOKEN
|
||||
# * by default, if ssh dict is set with its keys filled, I'll try to clone with SSH
|
||||
ssh:
|
||||
|
@ -19,7 +19,7 @@ storage:
|
|||
passphrase: PASSPHRASE
|
||||
|
||||
# NOTE: the $LOCATION if refering to the "storage.location" path. It'll be replaced automatically
|
||||
# The left part of ":" is your repository location and right part when it should be on your system
|
||||
# The left part of ":" is your repository location and right part where it should be located on your system
|
||||
files:
|
||||
- darwin: "$LOCATION/macos/.zshrc:~/.zshrc"
|
||||
linux: "$LOCATION/linux/.zshrc:~/.zshrc"
|
||||
|
@ -29,7 +29,7 @@ folders:
|
|||
linux: "$LOCATION/macos/.config:~/.config"
|
||||
|
||||
package-managers:
|
||||
installation-order: ["homebrew"]
|
||||
installation-order: ["homebrew"] # available: brew, pip (pip check also for pip3), cargo, apt, npm, go
|
||||
homebrew:
|
||||
- bat
|
||||
- hexyl
|
||||
|
@ -46,5 +46,3 @@ package-managers:
|
|||
- nmap
|
||||
- pinentry
|
||||
- zsh
|
||||
|
||||
apt-get: []
|
||||
|
|
13
README.md
13
README.md
|
@ -80,7 +80,7 @@ config-mapper save
|
|||
|
||||
All defined files and folders will be copied inside your repository.
|
||||
|
||||
If you want to exclude one part of your configuration file (files, folders), you can use these flags to ignore them `--disable-files` `--disable-folders`. Note, package managers are disable by default. You can enable this option using the `--pkgs` flag.
|
||||
If you want to exclude one part of your configuration file (files, folders), you can use these flags to ignore them `--disable-files` `--disable-folders`.
|
||||
|
||||
You can also exclude files and folders from a given directory with a `.gitignore` like file named `.ignore`. Put it in the root directory of an included folder and add relative path to exclude (does not support glob for now). E.g:
|
||||
|
||||
|
@ -106,8 +106,6 @@ foo/bar
|
|||
egg
|
||||
```
|
||||
|
||||
If `homebrew` is provided in the `installation-order` (default: `["apt", "homebrew"]`), it will override the `homebrew` field with all user installed packages (`brew leaves --installed-on-request`). The same principle will be implemented with `Advanced Package Tool`.
|
||||
|
||||
template for your configuration:
|
||||
|
||||
```yaml
|
||||
|
@ -122,8 +120,9 @@ folders:
|
|||
linux: "$LOCATION/macos/.config:~/.config"
|
||||
|
||||
package-managers:
|
||||
installation-order: ["homebrew"]
|
||||
homebrew:
|
||||
installation-order:
|
||||
- brew
|
||||
brew:
|
||||
- bat
|
||||
- hexyl
|
||||
- fd
|
||||
|
@ -141,6 +140,10 @@ package-managers:
|
|||
- zsh
|
||||
|
||||
apt-get: []
|
||||
pip: []
|
||||
cargo: []
|
||||
pip: []
|
||||
go: []
|
||||
```
|
||||
|
||||
### Load your configuration onto the system
|
||||
|
|
12
cmd/cli.go
12
cmd/cli.go
|
@ -54,6 +54,7 @@ func init() {
|
|||
rootCmd.AddCommand(initCmd)
|
||||
rootCmd.AddCommand(loadCmd)
|
||||
rootCmd.AddCommand(saveCmd)
|
||||
|
||||
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "STDOUT will be more verbose")
|
||||
rootCmd.PersistentFlags().StringP("configuration-file", "c", "", "location of configuration file")
|
||||
rootCmd.PersistentFlags().String("ssh-user", "", "SSH username to retrieve configuration file")
|
||||
|
@ -74,13 +75,11 @@ func init() {
|
|||
|
||||
saveCmd.Flags().Bool("disable-files", false, "files will be ignored")
|
||||
saveCmd.Flags().Bool("disable-folders", false, "folders will be ignored")
|
||||
saveCmd.Flags().Bool("pkgs", false, "packages will be saved")
|
||||
saveCmd.Flags().BoolP("push", "p", false, "new configurations will be committed and pushed")
|
||||
saveCmd.Flags().StringP("message", "m", strconv.FormatInt(time.Now().Unix(), 10), "combined with --push to set a commit message")
|
||||
saveCmd.Flags().Bool("disable-index", false, "configuration index will not be updated")
|
||||
viper.BindPFlag("save-disable-files", saveCmd.Flags().Lookup("disable-files"))
|
||||
viper.BindPFlag("save-disable-folders", saveCmd.Flags().Lookup("disable-folders"))
|
||||
viper.BindPFlag("save-enable-pkgs", saveCmd.Flags().Lookup("pkgs"))
|
||||
viper.BindPFlag("push", saveCmd.Flags().Lookup("push"))
|
||||
viper.BindPFlag("disable-index-update", saveCmd.Flags().Lookup("disable-index"))
|
||||
viper.BindPFlag("message", saveCmd.Flags().Lookup("message"))
|
||||
|
@ -123,13 +122,6 @@ func save(cmd *cobra.Command, args []string) {
|
|||
|
||||
el.Action("save")
|
||||
|
||||
if viper.GetBool("save-enable-pkgs") {
|
||||
if err := mapper.SavePkgs(c); err != nil {
|
||||
mapper.PrintError(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if err := el.CleanUp(indexer.RemovedLines()); err != nil {
|
||||
mapper.PrintError("failed to clean repository: %v\n", err)
|
||||
os.Exit(1)
|
||||
|
@ -178,7 +170,7 @@ func load(cmd *cobra.Command, args []string) {
|
|||
el.Action("load")
|
||||
|
||||
if viper.GetBool("load-enable-pkgs") {
|
||||
if err := mapper.LoadPkgs(c.PackageManagers); err != nil {
|
||||
if err := mapper.InstallPackages(c.PackageManagers); err != nil {
|
||||
mapper.PrintError(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ type Ssh struct {
|
|||
|
||||
type PkgManagers struct {
|
||||
InstallationOrder []string `mapstructure:"installation-order" yaml:"installation-order"`
|
||||
Homebrew []string `mapstructure:"homebrew" yaml:"homebrew"`
|
||||
Aptitude []string `mapstructure:"apt-get" yaml:"apt-get"`
|
||||
Brew []string `mapstructure:"brew" yaml:"brew"`
|
||||
Apt []string `mapstructure:"apt" yaml:"apt"`
|
||||
Cargo []string `mapstructure:"cargo" yaml:"cargo"`
|
||||
Pip []string `mapstructure:"pip" yaml:"pip"`
|
||||
Npm []string `mapstructure:"npm" yaml:"npm"`
|
||||
Go []string `mapstructure:"go" yaml:"go"`
|
||||
}
|
||||
|
|
194
internal/pkgs.go
194
internal/pkgs.go
|
@ -1,161 +1,83 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/datahearth/config-mapper/internal/configuration"
|
||||
"github.com/fatih/color"
|
||||
"github.com/gernest/wow"
|
||||
"github.com/gernest/wow/spin"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFailedInstallation = errors.New("failed to install some packages. Please, checkout STDERR for more information")
|
||||
ErrFailedSaving = errors.New("failed to save some packages. Please, checkout STDERR for more information")
|
||||
ErrBrewNotAvailable = errors.New("homebrew is not available on your system")
|
||||
ErrAptNotAvailable = errors.New("aptitude is not available on your system")
|
||||
)
|
||||
|
||||
// LoadPkgs triggers related functions with passed order
|
||||
func LoadPkgs(c configuration.PkgManagers) error {
|
||||
// InstallPackages install all packages from the configuration file by installation order
|
||||
func InstallPackages(c configuration.PkgManagers) error {
|
||||
color.Blue("\n# Installing packages")
|
||||
|
||||
for _, pkg := range c.InstallationOrder {
|
||||
switch pkg {
|
||||
case "homebrew":
|
||||
if err := installBrewPkgs(c.Homebrew); err != nil {
|
||||
PrintError(err.Error())
|
||||
return ErrFailedInstallation
|
||||
}
|
||||
for _, pkgManager := range c.InstallationOrder {
|
||||
var pkgs []string
|
||||
switch pkgManager {
|
||||
case "brew":
|
||||
pkgs = c.Brew
|
||||
case "apt":
|
||||
if err := installAptPkgs(c.Aptitude); err != nil {
|
||||
PrintError(err.Error())
|
||||
return ErrFailedInstallation
|
||||
pkgs = c.Apt
|
||||
case "cargo":
|
||||
pkgs = c.Cargo
|
||||
case "npm":
|
||||
pkgs = c.Npm
|
||||
case "pip":
|
||||
pkgs = c.Pip
|
||||
case "go":
|
||||
pkgs = c.Go
|
||||
default:
|
||||
PrintError("package manager not supported: %s", pkgManager)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := exec.LookPath(pkgManager); err != nil {
|
||||
if pkgManager == "pip" {
|
||||
if _, err := exec.LookPath("pip3"); err != nil {
|
||||
return fmt.Errorf("%s and pip3 are not available on your system", pkgManager)
|
||||
}
|
||||
pkgManager = "pip3"
|
||||
} else {
|
||||
return fmt.Errorf("%s is not available on your system", pkgManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SavePkgs triggers related functions with passed order
|
||||
func SavePkgs(cfg configuration.Configuration) error {
|
||||
color.Blue("# Saving user installed packages")
|
||||
|
||||
for _, pkg := range cfg.PackageManagers.InstallationOrder {
|
||||
switch pkg {
|
||||
case "homebrew":
|
||||
if err := saveBrewPkgs(cfg); err != nil {
|
||||
PrintError(err.Error())
|
||||
return ErrFailedSaving
|
||||
}
|
||||
case "apt":
|
||||
fmt.Println("implemented soon!")
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Printf("%s: nothing to do\n", pkgManager)
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.Command(pkgManager, "install")
|
||||
cmd.Args = append(cmd.Args, pkgs...)
|
||||
color.Blue("\n## Installing %s packages", pkgManager)
|
||||
|
||||
spinner := wow.New(os.Stdout, spin.Get(spin.Dots3), " Running...")
|
||||
|
||||
v := viper.GetBool("verbose")
|
||||
if v {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
} else {
|
||||
spinner.Start()
|
||||
}
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
spinner.Stop()
|
||||
PrintError("\n%s command failed: %v", pkgManager, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if v {
|
||||
// todo: find a way to clear spinner when done
|
||||
spinner.Stop()
|
||||
}
|
||||
color.Green("\n%s Packages intalled succesfully !", pkgManager)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// saveBrewPkgs gather user installed packages by running `brew leaves --installed-on-request`.
|
||||
// It captures the output, parse it and save it into the configuration.
|
||||
func saveBrewPkgs(cfg configuration.Configuration) error {
|
||||
if _, err := exec.LookPath("brew"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
color.Blue("\n## Saving Homebrew packages")
|
||||
|
||||
o, err := exec.Command("brew", "leaves", "--installed-on-request").Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pkgs := strings.Split(string(o), "\n")
|
||||
cfg.PackageManagers.Homebrew = append([]string{}, pkgs[:len(pkgs)-1]...)
|
||||
|
||||
b, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(viper.GetString("configuration-file"), b, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
color.Green("Packages saved succesfully !")
|
||||
return nil
|
||||
}
|
||||
|
||||
// installBrewPkgs installs homebrew packages by passing them to homebrew's CLI.
|
||||
// STDERR and STDOUT are captured if verbose flag is passed.
|
||||
func installBrewPkgs(pkgs []string) error {
|
||||
if _, err := exec.LookPath("brew"); err != nil {
|
||||
return ErrBrewNotAvailable
|
||||
}
|
||||
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Println("homebrew: nothing to do")
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.Command("brew", "install")
|
||||
cmd.Args = append(cmd.Args, pkgs...)
|
||||
color.Blue("\n## Installing Homebrew packages")
|
||||
|
||||
spinner := wow.New(os.Stdout, spin.Get(spin.Dots3), " Running...")
|
||||
|
||||
v := viper.GetBool("verbose")
|
||||
if v {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
} else {
|
||||
spinner.Start()
|
||||
}
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
spinner.Stop()
|
||||
PrintError("brew command failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if v {
|
||||
// todo: find a way to clear spinner when done
|
||||
spinner.Stop()
|
||||
}
|
||||
color.Green("\nPackages intalled succesfully !")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// installAptPkgs installs all provided "apt" packages by passing them to the Advanced Package Tool's CLI
|
||||
func installAptPkgs(pkgs []string) error {
|
||||
if _, err := exec.LookPath("apt"); err != nil {
|
||||
return ErrAptNotAvailable
|
||||
}
|
||||
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Println("apt: nothing to do")
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.Command("sudo", "apt", "install")
|
||||
cmd.Args = append(cmd.Args, pkgs...)
|
||||
|
||||
color.Blue("\n## Installing apt packages")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
PrintError("apt command failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
color.Green("Packages intalled succesfully !")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Reference in New Issue