Last active
March 27, 2020 11:24
-
-
Save rodkranz/f11b24b9c38ca46261a90587b54e99b9 to your computer and use it in GitHub Desktop.
Update all git repository in subfolders.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"os" | |
"os/exec" | |
"path" | |
"path/filepath" | |
"runtime" | |
"strings" | |
"sync" | |
"time" | |
log "github.com/sirupsen/logrus" | |
) | |
const ( | |
targetName = ".git" | |
version = "1.0" | |
) | |
var ( | |
verbose bool | |
debugMode bool | |
dir string | |
cpus int | |
ver bool | |
) | |
type Update struct { | |
Path string | |
File os.FileInfo | |
} | |
func init() { | |
flag.IntVar(&cpus, "cpus", runtime.NumCPU(), "Number of process running.") | |
flag.BoolVar(&verbose, "verbose", false, "Enable verbose mode.") | |
flag.BoolVar(&debugMode, "debug", false, "Enable debug mode.") | |
flag.StringVar(&dir, "dir", path.Dir(os.Args[0]), "Directory to search the '"+targetName+"' folder.") | |
flag.BoolVar(&ver, "v", false, "prints current roxy version") | |
flag.Parse() | |
runtime.GOMAXPROCS(cpus) | |
log.SetLevel(log.InfoLevel) | |
if debugMode { | |
log.SetLevel(log.DebugLevel) | |
} | |
} | |
func main() { | |
if ver { | |
log.Infof("current version of gitupdate is [%s].", version) | |
os.Exit(0) | |
} | |
log.Info("welcome to git update automatic.") | |
log.Infof("walking intro %s.", dir) | |
timeStart := time.Now() | |
var wg sync.WaitGroup | |
wg.Add(cpus) | |
stream := make(chan Update) | |
if err := filepath.Walk(dir, search(&wg, stream)); err != nil { | |
log.Errorf("error execute in dir: %s.", err.Error()) | |
} | |
close(stream) | |
wg.Wait() | |
timeEnd := time.Since(timeStart) | |
log.Infof("[took: %v] finished.", timeEnd) | |
} | |
func update(wg *sync.WaitGroup, in chan Update, i int) { | |
defer wg.Done() | |
for up := range in { | |
gitPath := path.Dir(up.Path) | |
if verbose { | |
log.Infof("[%d] updating [%s] at [%s].", i, up.File.Name(), gitPath) | |
} | |
cmdArgs := []string{"--work-tree=" + gitPath, "--git-dir=" + gitPath + "/" + up.File.Name(), "fetch", "--all"} // Git 1.7 | |
if debugMode { | |
log.Debugf("[%d] executing git command: [git %s].", i, strings.Join(cmdArgs, " ")) | |
} | |
timeStart := time.Now() | |
output, err := exec.Command("git", cmdArgs...).Output() | |
timeEnd := time.Since(timeStart) | |
if err != nil { | |
log.Errorf("[%d] could not update [%s] because: %s.", i, path.Base(gitPath), err) | |
log.Errorf("[%d] could not update [%s] output: %s.", i, path.Base(gitPath), output) | |
if verbose { | |
log.Errorf("[%d] [took: %v] [%s] has been NOT updated -> [path: %s].", i, timeEnd, path.Base(gitPath), gitPath) | |
} else { | |
log.Errorf("[%d] [took: %v] [%s] has been NOT updated.", i, timeEnd, path.Base(gitPath)) | |
} | |
continue | |
} | |
if verbose { | |
log.Infof("[%d] [took: %v] [%s] has been updated -> [path: %s].\n", i, timeEnd, path.Base(gitPath), gitPath) | |
} else { | |
log.Infof("[%d] [took: %v] [%s] has been updated.\n", i, timeEnd, path.Base(gitPath)) | |
} | |
} | |
} | |
func search(wg *sync.WaitGroup, stream chan Update) func(p string, f os.FileInfo, err error) error { | |
for i := 0; i < cpus; i++ { | |
go update(wg, stream, i) | |
} | |
return func(p string, f os.FileInfo, err error) error { | |
if err != nil { | |
return fmt.Errorf("search func failed: %s", err) | |
} | |
if !f.IsDir() { | |
if verbose { | |
log.Infof("[w] file ignored [%s].", p+f.Name()) | |
} | |
return nil | |
} | |
if !strings.EqualFold(f.Name(), targetName) { | |
if verbose { | |
log.Infof("[w] dir ignored [%s] at [%s].", f.Name(), p) | |
} | |
return nil | |
} | |
stream <- Update{ | |
Path: p, | |
File: f, | |
} | |
return nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment