forked from Plemya-x/ALR
add the ability to specify repository ref (#80)
closes #75 Reviewed-on: Plemya-x/ALR#80 Co-authored-by: Maxim Slipenko <no-reply@maxim.slipenko.com> Co-committed-by: Maxim Slipenko <no-reply@maxim.slipenko.com>
This commit is contained in:
@ -33,6 +33,7 @@ import (
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/go-git/go-git/v5"
|
||||
gitConfig "github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
@ -88,6 +89,14 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.FetchContext(ctx, &git.FetchOptions{
|
||||
Progress: os.Stderr,
|
||||
Force: true,
|
||||
})
|
||||
if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) {
|
||||
return err
|
||||
}
|
||||
|
||||
w, err := r.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -98,34 +107,41 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = w.PullContext(ctx, &git.PullOptions{Progress: os.Stderr})
|
||||
if errors.Is(err, git.NoErrAlreadyUpToDate) {
|
||||
revHash, err := resolveHash(r, repo.Ref)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving hash: %w", err)
|
||||
}
|
||||
|
||||
if old.Hash() == *revHash {
|
||||
slog.Info(gotext.Get("Repository up to date"), "name", repo.Name)
|
||||
} else if err != nil {
|
||||
}
|
||||
|
||||
err = w.Checkout(&git.CheckoutOptions{
|
||||
Hash: plumbing.NewHash(revHash.String()),
|
||||
Force: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoFS = w.Filesystem
|
||||
|
||||
// Make sure the DB is created even if the repo is up to date
|
||||
if !errors.Is(err, git.NoErrAlreadyUpToDate) || rs.db.IsEmpty(ctx) {
|
||||
new, err := r.Head()
|
||||
new, err := r.Head()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the DB was not present at startup, that means it's
|
||||
// empty. In this case, we need to update the DB fully
|
||||
// rather than just incrementally.
|
||||
if rs.db.IsEmpty(ctx) {
|
||||
err = rs.processRepoFull(ctx, repo, repoDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the DB was not present at startup, that means it's
|
||||
// empty. In this case, we need to update the DB fully
|
||||
// rather than just incrementally.
|
||||
if rs.db.IsEmpty(ctx) {
|
||||
err = rs.processRepoFull(ctx, repo, repoDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = rs.processRepoChanges(ctx, repo, r, w, old, new)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = rs.processRepoChanges(ctx, repo, r, w, old, new)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -139,9 +155,40 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = git.PlainCloneContext(ctx, repoDir, false, &git.CloneOptions{
|
||||
URL: repoURL.String(),
|
||||
r, err := git.PlainInit(repoDir, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.CreateRemote(&gitConfig.RemoteConfig{
|
||||
Name: git.DefaultRemoteName,
|
||||
URLs: []string{repoURL.String()},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.FetchContext(ctx, &git.FetchOptions{
|
||||
Progress: os.Stderr,
|
||||
Force: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, err := r.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
revHash, err := resolveHash(r, repo.Ref)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving hash: %w", err)
|
||||
}
|
||||
|
||||
err = w.Checkout(&git.CheckoutOptions{
|
||||
Hash: plumbing.NewHash(revHash.String()),
|
||||
Force: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@ -268,7 +315,8 @@ func (rs *Repos) processRepoChangesRunner(repoDir, scriptDir string) (*interp.Ru
|
||||
interp.StatHandler(handlers.RestrictedStat(repoDir)),
|
||||
interp.OpenHandler(handlers.RestrictedOpen(repoDir)),
|
||||
interp.StdIO(handlers.NopRWC{}, handlers.NopRWC{}, handlers.NopRWC{}),
|
||||
interp.Dir(scriptDir),
|
||||
// Use temp dir instead script dir because runner may be for deleted file
|
||||
interp.Dir(os.TempDir()),
|
||||
)
|
||||
}
|
||||
|
||||
@ -285,7 +333,7 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
|
||||
|
||||
patch, err := oldCommit.Patch(newCommit)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("error to create patch: %w", err)
|
||||
}
|
||||
|
||||
var actions []action
|
||||
@ -319,6 +367,7 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
|
||||
},
|
||||
)
|
||||
default:
|
||||
slog.Debug("unexpected, but I'll try to do")
|
||||
actions = append(actions, action{
|
||||
Type: actionUpdate,
|
||||
File: to.Path(),
|
||||
@ -332,7 +381,7 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
|
||||
for _, action := range actions {
|
||||
runner, err := rs.processRepoChangesRunner(repoDir, filepath.Dir(filepath.Join(repoDir, action.File)))
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("error creating process repo changes runner: %w", err)
|
||||
}
|
||||
|
||||
switch action.Type {
|
||||
@ -340,7 +389,6 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
|
||||
if filepath.Base(action.File) != "alr.sh" {
|
||||
continue
|
||||
}
|
||||
|
||||
scriptFl, err := oldCommit.File(action.File)
|
||||
if err != nil {
|
||||
return nil
|
||||
@ -378,7 +426,7 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
|
||||
|
||||
err = rs.updatePkg(ctx, repo, runner, r)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("error updatePkg: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,18 @@ package repos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/format/diff"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/client"
|
||||
|
||||
"mvdan.cc/sh/v3/interp"
|
||||
"mvdan.cc/sh/v3/syntax"
|
||||
|
||||
@ -137,3 +143,59 @@ func resolveOverrides(runner *interp.Runner, pkg *db.Package) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getHeadReference(r *git.Repository) (plumbing.ReferenceName, error) {
|
||||
remote, err := r.Remote(git.DefaultRemoteName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
endpoint, err := transport.NewEndpoint(remote.Config().URLs[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
gitClient, err := client.NewClient(endpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
session, err := gitClient.NewUploadPackSession(endpoint, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
info, err := session.AdvertisedReferences()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
refs, err := info.AllReferences()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return refs["HEAD"].Target(), nil
|
||||
}
|
||||
|
||||
func resolveHash(r *git.Repository, ref string) (*plumbing.Hash, error) {
|
||||
var err error
|
||||
|
||||
if ref == "" {
|
||||
reference, err := getHeadReference(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get head reference %w", err)
|
||||
}
|
||||
ref = reference.Short()
|
||||
}
|
||||
|
||||
hsh, err := r.ResolveRevision(git.DefaultRemoteName + "/" + plumbing.Revision(ref))
|
||||
if err != nil {
|
||||
hsh, err = r.ResolveRevision(plumbing.Revision(ref))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return hsh, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user