diff --git a/gitTag.byAge.go b/gitTag.byAge.go new file mode 100644 index 0000000..9d62acf --- /dev/null +++ b/gitTag.byAge.go @@ -0,0 +1,31 @@ +package gitpb + +// runs git, parses output +// types faster than you can + +import ( + "sort" + "time" +) + +func (all *GitTags) SortByAge() *GitTagIterator { + packs := all.selectAllGitTag() + + sort.Sort(GitTagAge(packs)) + + iterator := NewGitTagIterator(packs) + return iterator +} + +type GitTagAge []*GitTag + +func (a GitTagAge) Len() int { return len(a) } + +// sorts in ? order +func (a GitTagAge) Less(i, j int) bool { + if time.Since(a[i].Authordate.AsTime()) < time.Since(a[j].Authordate.AsTime()) { + return true + } + return false +} +func (a GitTagAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/gitTag.update.go b/gitTag.update.go index 8a7cea0..c8a35c3 100644 --- a/gitTag.update.go +++ b/gitTag.update.go @@ -1,6 +1,7 @@ package gitpb import ( + "path/filepath" "slices" "strings" "time" @@ -93,3 +94,46 @@ func (repo *Repo) NewestTag() *GitTag { } return nil } + +func (repo *Repo) LocalTagExists(findname string) bool { + loop := repo.Tags.SortByRefname() + for loop.Scan() { + ref := loop.Next() + // log.Info(repo.GoPath, ref.Refname) + if strings.HasPrefix(ref.Refname, "refs/remotes") { + continue + } + _, tagname := filepath.Split(ref.Refname) + // log.Info("tag:", path, tagname, "from", repo.GoPath) + if tagname == findname { + // log.Info("found tag:", path, tagname, "from", repo.GoPath) + return true + } + } + return false +} + +// returns true if 'taggy' is _ONLY_ a local tag +// this means you can not do a git pull or git push on it +func (repo *Repo) IsOnlyLocalTag(taggy string) bool { + // first make sure the tag is actually even local + if !repo.LocalTagExists(taggy) { + // this means it's not even local now. + return false + } + // okay, taggy exists, does it exist in a remote repo? + loop := repo.Tags.SortByRefname() + for loop.Scan() { + ref := loop.Next() + tagname := ref.Refname + if strings.HasPrefix(tagname, "refs/remotes") { + path, filename := filepath.Split(tagname) + if filename == taggy { + log.Log(GITPB, "found tag:", path, filename, "from", repo.GetGoPath()) + return false + } + } + } + // we couldn't find the local tag anywhere remote, so it's probably only local + return true +} diff --git a/rill.go b/rill.go index facc074..142b201 100644 --- a/rill.go +++ b/rill.go @@ -5,92 +5,100 @@ package gitpb import ( "errors" - "sort" "strings" - "time" + sync "sync" + "github.com/destel/rill" + "github.com/go-cmd/cmd" "go.wit.com/log" ) -func (all *GitTags) SortByAge() *GitTagIterator { - packs := all.selectAllGitTag() - - sort.Sort(GitTagAge(packs)) - - iterator := NewGitTagIterator(packs) - return iterator -} - -type GitTagAge []*GitTag - -func (a GitTagAge) Len() int { return len(a) } - -// sorts in ? order -func (a GitTagAge) Less(i, j int) bool { - if time.Since(a[i].Authordate.AsTime()) < time.Since(a[j].Authordate.AsTime()) { - return true - } - return false -} -func (a GitTagAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -// rill is awesome. long live rill -// attempt scan with rill -func (all *Repos) RillGitPull() error { - loop := all.SortByGoPath() - for loop.Scan() { - t := loop.Next() - log.Info("repo", t.GoPath) - } - /* - packs := all.SortByGoPath() - // Convert a slice of user IDs into a channel - ids := rill.FromSlice(packs, nil) - - // Read users from the API. - // Concurrency = 20 - dirs := rill.Map(ids, 20, func(id string) (*Repo, error) { - return packs[id], nil - }) - - // Activate users. - // Concurrency = 10 - err := rill.ForEach(dirs, 10, func(repo *Repo) error { - // could do something here - // fmt.Printf("Repo found : %s\n", repo.GoPath) - // repo.Run([]string{"git", "pull"}) - return nil - }) - */ - return nil -} - var ErrorMissingGitConfig error = errors.New("missing .git/config") var ErrorGitPullOnLocal error = errors.New("git pull on local only branch") +var ErrorGitPullOnDirty error = errors.New("cannot git pull on dirty repo") -// checks to see if you can do a 'git pull' -func (repo *Repo) IsOnlyLocalTag(currentName string) bool { - log.Warn("IsOnlyLocalTag(currentName string) not re-implemented yet") - return false -} - -func (repo *Repo) GitPull() (string, error) { +func (repo *Repo) GitPull() cmd.Status { currentName := repo.GetCurrentBranchName() if repo.IsOnlyLocalTag(currentName) { - return "", ErrorGitPullOnLocal + var result cmd.Status + result.Exit = 21 + result.Error = ErrorGitPullOnLocal + // log.Info("git pull skipped on local only branch", repo.GoPath) + return result } var cmd []string cmd = append(cmd, "git", "pull") r := repo.Run(cmd) - output := strings.Join(r.Stdout, "\n") + // output := strings.Join(r.Stdout, "\n") + /* notsure why I had this. I think from a long time ago if r.Error != nil { output = "git error_,,,_a_,,,_b_,,,c" } - if r.Error == nil { - log.Log(GITPBWARN, "git pull ran", repo.GetGoPath()) - log.Log(GITPBWARN, "git pull output", output) - } else { + */ + /* + if r.Error == nil { + if r.Exit == 0 { + log.Log(GITPBWARN, "git pull ran ", repo.GetGoPath()) + // log.Log(GITPBWARN, "git pull output", output) + return r + } else { + log.Log(GITPBWARN, "git pull error", repo.GetGoPath(), strings.Join(r.Stderr, "\n")) + return r + } + } log.Log(GITPBWARN, "git pull error", repo.GetGoPath(), r.Error) - } - return output, r.Error + */ + return r +} + +// rill is awesome. long live rill +// attempt scan with rill +func (all *Repos) RillGitPull(part1 int, part2 int) map[*Repo]cmd.Status { + var lock sync.Mutex + var allerr map[*Repo]cmd.Status + allerr = make(map[*Repo]cmd.Status) + + // Convert a slice of user IDs into a channel + ids := rill.FromSlice(all.Repos, nil) + + var counter int + // Read users from the API. + // Concurrency = 20 + dirs := rill.Map(ids, part1, func(id *Repo) (*Repo, error) { + return id, nil + }) + + rill.ForEach(dirs, part2, func(repo *Repo) error { + counter += 1 + if repo.CheckDirty() { + // log.Info("git pull skipped on dirty repo", repo.GoPath) + var result cmd.Status + result.Error = ErrorGitPullOnDirty + lock.Lock() + defer lock.Unlock() + allerr[repo] = result + } else { + // todo: sort out what the hell is wrong with my code + // something seems to be trampling things + /* + var dur time.Duration + dur = time.Duration((1+rand.Intn(50))*20) * time.Millisecond + time.Sleep(dur) + */ + var result cmd.Status + result = repo.GitPull() + log.Info("git pull", strings.Join(result.Stdout, " "), repo.GoPath) + lock.Lock() + defer lock.Unlock() + allerr[repo] = result + + } + return nil + }) + + // for r, err := range allerr { + // log.Info("git pull error:", r.GoPath, err) + // } + + return allerr }