Skip to content

Commit

Permalink
Fix history generation for monorepo
Browse files Browse the repository at this point in the history
This fixes history generation for the monorepo by calling `git` directly to generate the history.
  • Loading branch information
silkeh committed Sep 20, 2023
1 parent fd62ab2 commit 4cd877b
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 82 deletions.
151 changes: 71 additions & 80 deletions builder/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
package builder

import (
"bytes"
"encoding/xml"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
"strings"
"time"

git "github.com/libgit2/git2go/v34"
Expand Down Expand Up @@ -156,81 +159,29 @@ func GetFileContents(repo *git.Repository, tag, path string) ([]byte, error) {
//
// The repository path will be taken as the directory name of the pkgfile that
// is given to this function.
func NewPackageHistory(pkgfile string) (*PackageHistory, error) {
// Repodir
path := filepath.Dir(pkgfile)
func NewPackageHistory(repo *git.Repository, pkgfile string) (*PackageHistory, error) {
repoDir := abs(filepath.Dir(strings.TrimSuffix(repo.Path(), "/")))
pkgDir := abs(filepath.Dir(pkgfile))

repo, err := git.OpenRepository(path)
if err != nil {
return nil, err
}
// Get all the tags
var tags []string

tags, err = repo.Tags.List()
refs, err := gitLog(pkgDir)
if err != nil {
return nil, err
}

updates := make(map[string]*PackageUpdate)

// Iterate all of the tags
err = repo.Tags.Foreach(func(name string, id *git.Oid) error {
if name == "" || id == nil {
return nil
}

var commit *git.Commit

obj, rErr := repo.Lookup(id)
if rErr != nil {
return rErr
}

switch obj.Type() {
// Unannotated tag
case git.ObjectCommit:
commit, rErr = obj.AsCommit()
if rErr != nil {
return rErr
}

tags = append(tags, name)
// Annotated tag with commit target
case git.ObjectTag:
tag, tErr := obj.AsTag()
if tErr != nil {
return tErr
}

commit, tErr = repo.LookupCommit(tag.TargetId())
if tErr != nil {
return tErr
}

tags = append(tags, name)
default:
return fmt.Errorf("Internal git error, found %s", obj.Type().String())
}

if commit == nil {
return nil
for _, ref := range refs {
oid, _ := git.NewOid(ref)
commit, err := repo.LookupCommit(oid)
if err != nil {
return nil, fmt.Errorf("unable to resolve commit %q: %w", ref, err)
}

commitObj := NewPackageUpdate(name, commit, id.String())
updates[name] = commitObj

return nil
})
// Foreach went bork
if err != nil {
return nil, err
updates[ref] = NewPackageUpdate(ref, commit, ref)
}
// Sort the tags by -refname
sort.Sort(sort.Reverse(sort.StringSlice(tags)))

ret := &PackageHistory{pkgfile: pkgfile}
ret.scanUpdates(repo, updates, tags)
ret := &PackageHistory{pkgfile: rel(repoDir, pkgfile)}
ret.scanUpdates(repo, updates, refs)
updates = nil

if len(ret.Updates) < 1 {
Expand All @@ -241,6 +192,40 @@ func NewPackageHistory(pkgfile string) (*PackageHistory, error) {
return ret, nil
}

func execGit(args ...string) (string, error) {
var buf bytes.Buffer

cmd := exec.Command("git", args...)
cmd.Stdout = &buf

if err := cmd.Run(); err != nil {
return "", fmt.Errorf("error running Git: %w", err)
}

return buf.String(), nil
}

func gitLog(path string) ([]string, error) {
out, err := execGit("-C", path, "log", "--pretty=format:%H", path)
if err != nil {
return nil, fmt.Errorf("unable to get Git history: %w", err)
}

return strings.Split(out, "\n"), nil
}

func rel(base, target string) string {
s, _ := filepath.Rel(abs(base), abs(target))

return s
}

func abs(path string) string {
s, _ := filepath.Abs(path)

return s
}

// SortUpdatesByRelease is a simple wrapper to allowing sorting history.
type SortUpdatesByRelease []*PackageUpdate

Expand All @@ -253,24 +238,20 @@ func (a SortUpdatesByRelease) Swap(i, j int) {
}

func (a SortUpdatesByRelease) Less(i, j int) bool {
if a[i].Package.Release == a[j].Package.Release {
return a[i].Time.Before(a[j].Time)
}

return a[i].Package.Release < a[j].Package.Release
}

// scanUpdates will go back through the collected, "ok" tags, and analyze
// them to be more useful.
func (p *PackageHistory) scanUpdates(repo *git.Repository, updates map[string]*PackageUpdate, tags []string) {
// basename of file
fname := filepath.Base(p.pkgfile)

updateSet := make([]*PackageUpdate, 0, len(tags))

// Iterate the commit set in order
for _, tagID := range tags {
update := updates[tagID]
if update == nil {
continue
}
fname := p.pkgfile
updateSet := make(map[int]*PackageUpdate, len(updates))

for _, update := range updates {
b, err := GetFileContents(repo, update.ObjectID, fname)
if err != nil {
continue
Expand All @@ -282,16 +263,26 @@ func (p *PackageHistory) scanUpdates(repo *git.Repository, updates map[string]*P
continue
}

if u, ok := updateSet[pkg.Release]; ok && u.Time.Before(update.Time) {
continue
}

update.Package = pkg
updateSet = append(updateSet, update)
updateSet[pkg.Release] = update
}

updateList := make(SortUpdatesByRelease, 0, len(updates))

for _, update := range updateSet {
updateList = append(updateList, update)
}

sort.Sort(sort.Reverse(SortUpdatesByRelease(updateSet)))
sort.Sort(sort.Reverse(updateList))

if len(updateSet) >= MaxChangelogEntries {
p.Updates = updateSet[:MaxChangelogEntries]
if len(updateList) >= MaxChangelogEntries {
p.Updates = updateList[:MaxChangelogEntries]
} else {
p.Updates = updateSet
p.Updates = updateList
}
}

Expand Down
7 changes: 5 additions & 2 deletions builder/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

log "github.com/DataDrake/waterlog"
"github.com/getsolus/libosdev/disk"
git "github.com/libgit2/git2go/v34"
)

var (
Expand Down Expand Up @@ -184,8 +185,10 @@ func (m *Manager) SetPackage(pkg *Package) error {
// Obtain package history for git builds
if pkg.Type == PackageTypeYpkg {
repoDir := filepath.Dir(pkg.Path)
if PathExists(filepath.Join(repoDir, ".git")) {
if history, err := NewPackageHistory(pkg.Path); err == nil {
repo, err := git.OpenRepositoryExtended(repoDir, 0, "/")

if err == nil {
if history, err := NewPackageHistory(repo, pkg.Path); err == nil {
log.Debugln("Obtained package history")

m.history = history
Expand Down

0 comments on commit 4cd877b

Please sign in to comment.