// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 package main import ( "fmt" "time" "go.wit.com/lib/gui/shell" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" ) func rillPull(repo *gitpb.Repo) error { if repo.IsDirty() { // never do dirty repos return nil } t, _ := repo.LastGitPull() if time.Since(t) < time.Minute*10 && !argv.Force { if argv.Verbose { log.Info(repo.GetFullPath(), "git pulled too recently", shell.FormatDuration(time.Since(t))) } return nil } cur := repo.GetCurrentBranchName() if !repo.IsBranchRemote(cur) { if argv.Verbose { log.Info(repo.GetFullPath(), "branch is not remote", cur) } return nil } var cmd []string cmd = append(cmd, "git", "pull") err := repo.RunVerbose(cmd) if err != nil { log.Info(repo.GetFullPath(), "git pull err:", err) } return nil } // is every repo on the devel branch? func doGitPullNew() error { if argv.Pull == nil { return fmt.Errorf("not really 'fetch pull'") } if argv.Force { now := time.Now() pullcount := me.forge.RillFuncError(rillPull) count := me.forge.RillReload() if count != 0 { me.forge.ConfigSave() } total, count, nope, _ := IsEverythingOnMaster() log.Printf("Master branch check. %d total repos. (%d git pulled) (%d not on master branch) (%s) git pull total=%d\n", total, count, nope, shell.FormatDuration(time.Since(now)), pullcount) return nil } check := gitpb.NewRepos() if argv.Pull.Dirty != nil { check = findDirty() } if argv.Pull.Patches != nil { check = findReposWithPatches() } if check.Len() == 0 { // check = doFind() check = findAll() // check = find50() // check = findMine() } me.forge.PrintHumanTableFull(check) found, err := me.forge.LookupPB(check) if err != nil { log.Info("LookupPB() failed", err, "len(check)=", check.Len()) return err } // me.forge.PrintHumanTableFull(found) // check to see if the repos need to be updated update := gitpb.NewRepos() for repo := range found.IterAll() { a := repo.GetLocalHash(repo.GetMasterBranchName()) ns := repo.GetNamespace() repo2 := me.forge.Repos.FindByNamespace(ns) if repo2 == nil { log.Info("repo namespace does not exist", a, repo.Namespace) continue } b := repo2.GetLocalHash(repo2.GetMasterBranchName()) if b == a { continue } log.Info(a, "!=", b, repo.Namespace) update.AppendByNamespace(repo2) } if update.Len() == 0 { // nothing to update return nil } if _, err := me.forge.UpdatePB(update); err != nil { log.Info("UpdatePB() failed", err, "len(check)=", update.Len()) return err } return nil } /* func doGitPull() { allerr := me.found.RillGitPull(40, 5) all := me.found.SortByFullPath() for all.Scan() { repo := all.Next() result := allerr[repo] if result.Error == gitpb.ErrorGitPullOnDirty { log.Info("skip git pull. repo is dirty", repo.GetGoPath()) continue } if result.Error == gitpb.ErrorGitPullOnLocal { log.Info("skip git pull. local branch ", repo.GetGoPath()) continue } if result.Exit == 0 { continue } log.Info("git pull error:", repo.GetGoPath(), result.Error) log.Info("git pull error:", repo.GetGoPath(), result.Stdout) } } */ // git fetch origin master:master func rillFetchMaster(repo *gitpb.Repo) error { if repo.GetCurrentBranchName() != repo.GetUserBranchName() { // only fetch when branch is on the user branch return nil } branch := repo.GetMasterBranchName() cmd := []string{"git", "fetch", "origin", branch + ":" + branch} err := repo.RunVerbose(cmd) return err } func doGitFetch() { me.forge.RillFuncError(rillFetchMaster) count := me.forge.RillReload() if count != 0 { me.forge.ConfigSave() } } func doMergeDevel() (*gitpb.Repos, error) { var err error done := gitpb.NewRepos() found := findMergeToDevel() for repo := range found.IterAll() { if repo.CheckDirty() { log.Info("repo is dirty", repo.GetGoPath()) continue } log.Info("Starting merge on", repo.GetGoPath()) if repo.CheckoutDevel() { log.Info("checkout devel failed", repo.GetGoPath()) err = fmt.Errorf("checkout devel failed") break } if _, err := repo.MergeToDevel(); err != nil { log.Info("merge from user failed", repo.GetGoPath(), err) err = fmt.Errorf("merge from user failed") // log.Info(strings.Join(r.Stdout, "\n")) // log.Info(strings.Join(r.Stderr, "\n")) break } done.Append(repo) /* if repo.CheckoutMaster() { log.Info("checkout master failed", repo.GetGoPath()) return } if _, err := repo.MergeToMaster(); err != nil { log.Info("merge from devel failed", repo.GetGoPath(), err) return } */ } return done, err } func doMergeMaster() (*gitpb.Repos, error) { var err error done := gitpb.NewRepos() found := findMergeToMaster() for repo := range found.IterAll() { if repo.CheckDirty() { log.Info("repo is dirty", repo.GetGoPath()) continue } log.Info("Starting merge on", repo.GetGoPath()) if repo.CheckoutMaster() { log.Info("checkout devel failed", repo.GetGoPath()) err = fmt.Errorf("checkout devel failed") break } if _, err := repo.MergeToMaster(); err != nil { log.Info("merge from user failed", repo.GetGoPath(), err) err = fmt.Errorf("merge from user failed") // log.Info(strings.Join(r.Stdout, "\n")) // log.Info(strings.Join(r.Stderr, "\n")) break } done.Append(repo) } return done, err }