Skip to content

Commit

Permalink
fix(aur): allow to have multiple AUR configs pointing to the same repo (
Browse files Browse the repository at this point in the history
#4712)

- using the sha256 of the git url as repo name so we avoid race
conditions
- actually made the git client have a global lock so it doesn't step
over itself

closes #4679

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
caarlos0 committed Mar 20, 2024
1 parent 6e0f426 commit 08851dc
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 35 deletions.
48 changes: 14 additions & 34 deletions internal/client/git.go
Expand Up @@ -19,14 +19,11 @@ import (
"golang.org/x/crypto/ssh"
)

var gil sync.Mutex

// DefaulGitSSHCommand used for git over SSH.
const DefaulGitSSHCommand = `ssh -i "{{ .KeyPath }}" -o StrictHostKeyChecking=accept-new -F /dev/null`

var cloneLock = cloneGlobalLock{
l: sync.Mutex{},
repos: map[string]bool{},
}

type gitClient struct {
branch string
}
Expand All @@ -46,6 +43,9 @@ func (g *gitClient) CreateFiles(
message string,
files []RepoFile,
) (err error) {
gil.Lock()
defer gil.Unlock()

url, err := tmpl.New(ctx).Apply(repo.GitURL)
if err != nil {
return fmt.Errorf("git: failed to template git url: %w", err)
Expand Down Expand Up @@ -79,7 +79,8 @@ func (g *gitClient) CreateFiles(
cwd := filepath.Join(parent, name)
env := []string{fmt.Sprintf("GIT_SSH_COMMAND=%s", sshcmd)}

if err := cloneLock.clone(url, func() error {
if _, err := os.Stat(cwd); errors.Is(err, os.ErrNotExist) {
log.Infof("cloning %s %s", name, cwd)
if err := os.MkdirAll(parent, 0o755); err != nil {
return fmt.Errorf("git: failed to create parent: %w", err)
}
Expand All @@ -98,21 +99,17 @@ func (g *gitClient) CreateFiles(
}); err != nil {
return fmt.Errorf("git: failed to setup local repository: %w", err)
}
if g.branch == "" {
return nil
}
if err := runGitCmds(ctx, cwd, env, [][]string{
{"checkout", g.branch},
}); err != nil {
if g.branch != "" {
if err := runGitCmds(ctx, cwd, env, [][]string{
{"checkout", "-b", g.branch},
{"checkout", g.branch},
}); err != nil {
return fmt.Errorf("git: could not checkout branch %s: %w", g.branch, err)
if err := runGitCmds(ctx, cwd, env, [][]string{
{"checkout", "-b", g.branch},
}); err != nil {
return fmt.Errorf("git: could not checkout branch %s: %w", g.branch, err)
}
}
}
return nil
}); err != nil {
return err
}

for _, file := range files {
Expand Down Expand Up @@ -216,20 +213,3 @@ func runGitCmds(ctx *context.Context, cwd string, env []string, cmds [][]string)
func nameFromURL(url string) string {
return strings.TrimSuffix(url[strings.LastIndex(url, "/")+1:], ".git")
}

type cloneGlobalLock struct {
l sync.Mutex
repos map[string]bool
}

func (c *cloneGlobalLock) clone(url string, fn func() error) error {
c.l.Lock()
defer c.l.Unlock()

if c.repos[url] {
return nil
}

c.repos[url] = true
return fn()
}
3 changes: 2 additions & 1 deletion internal/pipe/aur/aur.go
Expand Up @@ -3,6 +3,7 @@ package aur
import (
"bufio"
"bytes"
"crypto/sha256"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -385,7 +386,7 @@ func doPublish(ctx *context.Context, pkgs []*artifact.Artifact) error {
URL: cfg.GitURL,
SSHCommand: cfg.GitSSHCommand,
},
Name: cfg.Name,
Name: fmt.Sprintf("%x", sha256.Sum256([]byte(cfg.GitURL))),
})

files := make([]client.RepoFile, 0, len(pkgs))
Expand Down
82 changes: 82 additions & 0 deletions internal/pipe/aur/aur_test.go
Expand Up @@ -482,6 +482,88 @@ func TestRunPipe(t *testing.T) {
requireEqualRepoFiles(t, folder, ".", "foo", url)
}

func TestRunPipeMultipleConfigurations(t *testing.T) {
url := testlib.GitMakeBareRepository(t)
key := testlib.MakeNewSSHKey(t, "")

folder := t.TempDir()
ctx := testctx.NewWithCfg(
config.Project{
Dist: folder,
ProjectName: "foo",
AURs: []config.AUR{
{
Name: "foo",
IDs: []string{"foo"},
PrivateKey: key,
License: "MIT",
GitURL: url,
Description: "The foo aur",
Directory: "foo",
},
{
Name: "bar",
IDs: []string{"bar"},
PrivateKey: key,
License: "MIT",
GitURL: url,
Description: "The bar aur",
Directory: "bar",
},
},
},
testctx.WithCurrentTag("v1.0.1-foo"),
testctx.WithSemver(1, 0, 1, "foo"),
testctx.WithVersion("1.0.1-foo"),
)

path := filepath.Join(folder, "bin.tar.gz")
ctx.Artifacts.Add(&artifact.Artifact{
Name: "bar_bin.tar.gz",
Path: path,
Goos: "linux",
Goarch: "amd64",
Goamd64: "v1",
Type: artifact.UploadableArchive,
Extra: map[string]interface{}{
artifact.ExtraID: "bar",
artifact.ExtraFormat: "tar.gz",
artifact.ExtraBinaries: []string{"bar"},
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "bin.tar.gz",
Path: path,
Goos: "linux",
Goarch: "amd64",
Goamd64: "v1",
Type: artifact.UploadableArchive,
Extra: map[string]interface{}{
artifact.ExtraID: "foo",
artifact.ExtraFormat: "tar.gz",
artifact.ExtraBinaries: []string{"name"},
},
})

f, err := os.Create(path)
require.NoError(t, err)
require.NoError(t, f.Close())
client := client.NewMock()

require.NoError(t, Pipe{}.Default(ctx))
require.NoError(t, runAll(ctx, client))
require.NoError(t, Pipe{}.Publish(ctx))

dir := t.TempDir()
_, err = git.Run(testctx.New(), "-C", dir, "clone", url, "repo")
require.NoError(t, err)

require.FileExists(t, filepath.Join(dir, "repo", "foo", ".SRCINFO"))
require.FileExists(t, filepath.Join(dir, "repo", "foo", "PKGBUILD"))
require.FileExists(t, filepath.Join(dir, "repo", "bar", ".SRCINFO"))
require.FileExists(t, filepath.Join(dir, "repo", "bar", "PKGBUILD"))
}

func TestRunPipeNoBuilds(t *testing.T) {
ctx := testctx.NewWithCfg(config.Project{
ProjectName: "foo",
Expand Down

0 comments on commit 08851dc

Please sign in to comment.