feat(pkgs): add more package manager
This commit is contained in:
parent
f00d7c0288
commit
f576eec3c3
|
@ -10,7 +10,7 @@ storage:
|
||||||
basic-auth:
|
basic-auth:
|
||||||
username: USERNAME
|
username: USERNAME
|
||||||
# * NOTE: if you're having trouble with error "authentication required", you should maybe use a token access
|
# * 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
|
password: TOKEN
|
||||||
# * by default, if ssh dict is set with its keys filled, I'll try to clone with SSH
|
# * by default, if ssh dict is set with its keys filled, I'll try to clone with SSH
|
||||||
ssh:
|
ssh:
|
||||||
|
@ -19,7 +19,7 @@ storage:
|
||||||
passphrase: PASSPHRASE
|
passphrase: PASSPHRASE
|
||||||
|
|
||||||
# NOTE: the $LOCATION if refering to the "storage.location" path. It'll be replaced automatically
|
# 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:
|
files:
|
||||||
- darwin: "$LOCATION/macos/.zshrc:~/.zshrc"
|
- darwin: "$LOCATION/macos/.zshrc:~/.zshrc"
|
||||||
linux: "$LOCATION/linux/.zshrc:~/.zshrc"
|
linux: "$LOCATION/linux/.zshrc:~/.zshrc"
|
||||||
|
@ -29,7 +29,7 @@ folders:
|
||||||
linux: "$LOCATION/macos/.config:~/.config"
|
linux: "$LOCATION/macos/.config:~/.config"
|
||||||
|
|
||||||
package-managers:
|
package-managers:
|
||||||
installation-order: ["homebrew"]
|
installation-order: ["homebrew"] # available: brew, pip (pip check also for pip3), cargo, apt, npm, go
|
||||||
homebrew:
|
homebrew:
|
||||||
- bat
|
- bat
|
||||||
- hexyl
|
- hexyl
|
||||||
|
@ -46,5 +46,3 @@ package-managers:
|
||||||
- nmap
|
- nmap
|
||||||
- pinentry
|
- pinentry
|
||||||
- zsh
|
- 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.
|
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:
|
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
|
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:
|
template for your configuration:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
@ -122,8 +120,9 @@ folders:
|
||||||
linux: "$LOCATION/macos/.config:~/.config"
|
linux: "$LOCATION/macos/.config:~/.config"
|
||||||
|
|
||||||
package-managers:
|
package-managers:
|
||||||
installation-order: ["homebrew"]
|
installation-order:
|
||||||
homebrew:
|
- brew
|
||||||
|
brew:
|
||||||
- bat
|
- bat
|
||||||
- hexyl
|
- hexyl
|
||||||
- fd
|
- fd
|
||||||
|
@ -141,6 +140,10 @@ package-managers:
|
||||||
- zsh
|
- zsh
|
||||||
|
|
||||||
apt-get: []
|
apt-get: []
|
||||||
|
pip: []
|
||||||
|
cargo: []
|
||||||
|
pip: []
|
||||||
|
go: []
|
||||||
```
|
```
|
||||||
|
|
||||||
### Load your configuration onto the system
|
### 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(initCmd)
|
||||||
rootCmd.AddCommand(loadCmd)
|
rootCmd.AddCommand(loadCmd)
|
||||||
rootCmd.AddCommand(saveCmd)
|
rootCmd.AddCommand(saveCmd)
|
||||||
|
|
||||||
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "STDOUT will be more verbose")
|
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "STDOUT will be more verbose")
|
||||||
rootCmd.PersistentFlags().StringP("configuration-file", "c", "", "location of configuration file")
|
rootCmd.PersistentFlags().StringP("configuration-file", "c", "", "location of configuration file")
|
||||||
rootCmd.PersistentFlags().String("ssh-user", "", "SSH username to retrieve 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-files", false, "files will be ignored")
|
||||||
saveCmd.Flags().Bool("disable-folders", false, "folders 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().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().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")
|
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-files", saveCmd.Flags().Lookup("disable-files"))
|
||||||
viper.BindPFlag("save-disable-folders", saveCmd.Flags().Lookup("disable-folders"))
|
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("push", saveCmd.Flags().Lookup("push"))
|
||||||
viper.BindPFlag("disable-index-update", saveCmd.Flags().Lookup("disable-index"))
|
viper.BindPFlag("disable-index-update", saveCmd.Flags().Lookup("disable-index"))
|
||||||
viper.BindPFlag("message", saveCmd.Flags().Lookup("message"))
|
viper.BindPFlag("message", saveCmd.Flags().Lookup("message"))
|
||||||
|
@ -123,13 +122,6 @@ func save(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
el.Action("save")
|
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 {
|
if err := el.CleanUp(indexer.RemovedLines()); err != nil {
|
||||||
mapper.PrintError("failed to clean repository: %v\n", err)
|
mapper.PrintError("failed to clean repository: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -178,7 +170,7 @@ func load(cmd *cobra.Command, args []string) {
|
||||||
el.Action("load")
|
el.Action("load")
|
||||||
|
|
||||||
if viper.GetBool("load-enable-pkgs") {
|
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())
|
mapper.PrintError(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ type Ssh struct {
|
||||||
|
|
||||||
type PkgManagers struct {
|
type PkgManagers struct {
|
||||||
InstallationOrder []string `mapstructure:"installation-order" yaml:"installation-order"`
|
InstallationOrder []string `mapstructure:"installation-order" yaml:"installation-order"`
|
||||||
Homebrew []string `mapstructure:"homebrew" yaml:"homebrew"`
|
Brew []string `mapstructure:"brew" yaml:"brew"`
|
||||||
Aptitude []string `mapstructure:"apt-get" yaml:"apt-get"`
|
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
|
package mapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/datahearth/config-mapper/internal/configuration"
|
"github.com/datahearth/config-mapper/internal/configuration"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/gernest/wow"
|
"github.com/gernest/wow"
|
||||||
"github.com/gernest/wow/spin"
|
"github.com/gernest/wow/spin"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// InstallPackages install all packages from the configuration file by installation order
|
||||||
ErrFailedInstallation = errors.New("failed to install some packages. Please, checkout STDERR for more information")
|
func InstallPackages(c configuration.PkgManagers) error {
|
||||||
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 {
|
|
||||||
color.Blue("\n# Installing packages")
|
color.Blue("\n# Installing packages")
|
||||||
|
|
||||||
for _, pkg := range c.InstallationOrder {
|
for _, pkgManager := range c.InstallationOrder {
|
||||||
switch pkg {
|
var pkgs []string
|
||||||
case "homebrew":
|
switch pkgManager {
|
||||||
if err := installBrewPkgs(c.Homebrew); err != nil {
|
case "brew":
|
||||||
PrintError(err.Error())
|
pkgs = c.Brew
|
||||||
return ErrFailedInstallation
|
|
||||||
}
|
|
||||||
case "apt":
|
case "apt":
|
||||||
if err := installAptPkgs(c.Aptitude); err != nil {
|
pkgs = c.Apt
|
||||||
PrintError(err.Error())
|
case "cargo":
|
||||||
return ErrFailedInstallation
|
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
|
if len(pkgs) == 0 {
|
||||||
}
|
fmt.Printf("%s: nothing to do\n", 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!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
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