2018-02-20 20:31:47 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"runtime"
|
|
|
|
|
|
|
|
"github.com/Luzifer/rconfig"
|
|
|
|
homedir "github.com/mitchellh/go-homedir"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
cfg = struct {
|
|
|
|
Config string `flag:"config,c" default:"~/.config/gotools.yml" description:"Configuration for update-gotools utility"`
|
|
|
|
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"`
|
|
|
|
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
|
|
|
|
}{}
|
|
|
|
|
|
|
|
version = "dev"
|
|
|
|
|
|
|
|
cfgFile *configFile
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2018-02-20 20:36:03 +00:00
|
|
|
if err := rconfig.Parse(&cfg); err != nil {
|
2018-02-20 20:31:47 +00:00
|
|
|
log.WithError(err).Fatal("Unable to parse commandline options")
|
|
|
|
}
|
|
|
|
|
|
|
|
if l, err := log.ParseLevel(cfg.LogLevel); err != nil {
|
|
|
|
log.WithError(err).Fatal("Unable to parse log level")
|
|
|
|
} else {
|
|
|
|
log.SetLevel(l)
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg.VersionAndExit {
|
|
|
|
fmt.Printf("update-gotools %s\n", version)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2018-02-20 20:36:03 +00:00
|
|
|
var err error
|
2018-02-20 20:31:47 +00:00
|
|
|
if cfg.Config, err = homedir.Expand(cfg.Config); err != nil {
|
|
|
|
log.WithError(err).Fatal("Unable to expand config path")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
cfgFile, err = defaultConfig()
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Fatal("Unable to create default config")
|
|
|
|
}
|
|
|
|
|
2018-04-06 09:39:03 +00:00
|
|
|
if err := cfgFile.LoadFromPath(cfg.Config); err != nil {
|
2018-02-20 20:31:47 +00:00
|
|
|
log.WithError(err).Fatal("Unable to parse config file")
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"version": version,
|
|
|
|
"num_cpu": runtime.NumCPU(),
|
|
|
|
}).Debugf("update-gotools started")
|
|
|
|
|
2018-02-21 09:35:45 +00:00
|
|
|
parallelRunners := runtime.NumCPU() - 1
|
|
|
|
if parallelRunners < 1 {
|
|
|
|
parallelRunners = 1
|
|
|
|
}
|
|
|
|
|
2018-02-20 20:31:47 +00:00
|
|
|
runPreCommands()
|
2018-02-21 09:35:45 +00:00
|
|
|
runPackageBuilds(parallelRunners, func(pkg pkgCfg) bool { return !pkg.Single })
|
2018-02-20 20:31:47 +00:00
|
|
|
runPackageBuilds(1, func(pkg pkgCfg) bool { return pkg.Single })
|
|
|
|
runPostCommands()
|
|
|
|
|
|
|
|
log.Info("Installation successful")
|
|
|
|
}
|
|
|
|
|
|
|
|
func runPreCommands() {
|
|
|
|
log.Info("Executing pre-commands")
|
|
|
|
if err := executeCommands(log.WithFields(log.Fields{
|
|
|
|
"step": "pre_commands",
|
|
|
|
}), cfgFile.PreCommands); err != nil {
|
|
|
|
log.WithError(err).Fatal("Pre-Command failed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func runPackageBuilds(n int, filter func(pkgCfg) bool) {
|
|
|
|
limit := newLimiter(n)
|
|
|
|
for _, pkg := range cfgFile.Packages {
|
|
|
|
if !filter(pkg) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
limit.Add()
|
|
|
|
go func(pkg pkgCfg) {
|
2018-02-20 21:45:45 +00:00
|
|
|
logVer, err := pkg.Version()
|
|
|
|
if err != nil {
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"pkg": pkg.Name,
|
|
|
|
}).WithError(err).Fatal("Unable to fetch version information")
|
|
|
|
}
|
|
|
|
|
2018-02-20 20:31:47 +00:00
|
|
|
if logVer == "" {
|
|
|
|
logVer = "HEAD"
|
|
|
|
}
|
|
|
|
|
|
|
|
pkgLog := log.WithFields(log.Fields{
|
|
|
|
"pkg": pkg.Name,
|
|
|
|
"ver": logVer,
|
|
|
|
})
|
|
|
|
|
|
|
|
if err := executePackage(pkg, pkgLog); err != nil {
|
|
|
|
pkgLog.WithError(err).Fatal("Failed to install package")
|
|
|
|
}
|
|
|
|
limit.Done()
|
|
|
|
}(pkg)
|
|
|
|
}
|
|
|
|
limit.Wait()
|
|
|
|
}
|
|
|
|
|
|
|
|
func runPostCommands() {
|
|
|
|
log.Info("Executing post-commands")
|
|
|
|
if err := executeCommands(log.WithFields(log.Fields{
|
|
|
|
"step": "post_commands",
|
|
|
|
}), cfgFile.PostCommands); err != nil {
|
|
|
|
log.WithError(err).Fatal("Post-Command failed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func defaultConfig() (*configFile, error) {
|
|
|
|
h, err := homedir.Dir()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &configFile{
|
|
|
|
Cwd: h,
|
|
|
|
Packages: []pkgCfg{},
|
|
|
|
PreCommands: [][]string{},
|
|
|
|
PostCommands: [][]string{},
|
|
|
|
}, nil
|
|
|
|
}
|