Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
simonjjones authored Aug 25, 2020
2 parents 1a41c23 + d7503fd commit bb2ff31
Show file tree
Hide file tree
Showing 11 changed files with 617 additions and 50 deletions.
3 changes: 2 additions & 1 deletion acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2321,7 +2321,8 @@ type logWriter struct {
}

func (l logWriter) Write(p []byte) (n int, err error) {
l.t.Log(string(p))
l.t.Helper()
l.t.Log(strings.TrimRight(string(p), "\n"))
return len(p), nil
}

Expand Down
3 changes: 2 additions & 1 deletion internal/registry/buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ func Validate(b Buildpack) error {
return nil
}

func ParseNamespaceName(id string) (string, string, error) {
// ParseNamespaceName parses a buildpack ID into Namespace and Name
func ParseNamespaceName(id string) (ns string, name string, err error) {
parts := strings.Split(id, "/")
if len(parts) < 2 {
return "", "", fmt.Errorf("invalid id %s does not contain a namespace", style.Symbol(id))
Expand Down
31 changes: 31 additions & 0 deletions internal/registry/git.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package registry

import (
"bytes"
"text/template"

"github.com/pkg/errors"
)

// GitCommit commits a Buildpack to a registry Cache.
func GitCommit(b Buildpack, username string, registryCache Cache) error {
if err := registryCache.Initialize(); err != nil {
return err
}

commitTemplate, err := template.New("buildpack").Parse(GitCommitTemplate)
if err != nil {
return err
}

var commit bytes.Buffer
if err := commitTemplate.Execute(&commit, b); err != nil {
return errors.Wrap(err, "creating template")
}

if err := registryCache.Commit(b, username, commit.String()); err != nil {
return err
}

return nil
}
105 changes: 105 additions & 0 deletions internal/registry/git_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package registry_test

import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/sclevine/spec"
"github.com/sclevine/spec/report"
"gopkg.in/src-d/go-git.v4"

ilogging "github.com/buildpacks/pack/internal/logging"
"github.com/buildpacks/pack/internal/registry"
"github.com/buildpacks/pack/logging"
h "github.com/buildpacks/pack/testhelpers"
)

func TestGit(t *testing.T) {
spec.Run(t, "Git", testGit, spec.Parallel(), spec.Report(report.Terminal{}))
}

func testGit(t *testing.T, when spec.G, it spec.S) {
var (
registryCache registry.Cache
tmpDir string
err error
registryFixture string
outBuf bytes.Buffer
logger logging.Logger
username string = "supra08"
)

it.Before(func() {
logger = ilogging.NewLogWithWriters(&outBuf, &outBuf)

tmpDir, err = ioutil.TempDir("", "registry")
h.AssertNil(t, err)

registryFixture = h.CreateRegistryFixture(t, tmpDir, filepath.Join("..", "..", "testdata", "registry"))
registryCache, err = registry.NewRegistryCache(logger, tmpDir, registryFixture)
h.AssertNil(t, err)
})

it.After(func() {
h.AssertNil(t, os.RemoveAll(tmpDir))
})

when("#GitCommit", func() {
when("ADD buildpack", func() {
it("commits addition", func() {
err := registry.GitCommit(registry.Buildpack{
Namespace: "example",
Name: "python",
Version: "1.0.0",
Yanked: false,
Address: "example.com",
}, username, registryCache)
h.AssertNil(t, err)

repo, err := git.PlainOpen(registryCache.Root)
h.AssertNil(t, err)

head, err := repo.Head()
h.AssertNil(t, err)

cIter, err := repo.Log(&git.LogOptions{From: head.Hash()})
h.AssertNil(t, err)

commit, err := cIter.Next()
h.AssertNil(t, err)

h.AssertEq(t, commit.Message, "ADD example/[email protected]")
})
})

when("YANK buildpack", func() {
it("commits yank", func() {
err := registry.GitCommit(registry.Buildpack{
Namespace: "example",
Name: "python",
Version: "1.0.0",
Yanked: true,
Address: "example.com",
}, username, registryCache)
h.AssertNil(t, err)

repo, err := git.PlainOpen(registryCache.Root)
h.AssertNil(t, err)

head, err := repo.Head()
h.AssertNil(t, err)

cIter, err := repo.Log(&git.LogOptions{From: head.Hash()})
h.AssertNil(t, err)

commit, err := cIter.Next()
h.AssertNil(t, err)

h.AssertEq(t, commit.Message, "YANK example/[email protected]")
})
})
})
}
57 changes: 57 additions & 0 deletions internal/registry/index.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package registry

import (
"fmt"
"path/filepath"
"regexp"

"github.com/pkg/errors"

"github.com/buildpacks/pack/internal/style"
)

var (
validCharsPattern = "[a-z0-9\\-.]+"
validCharsRegexp = regexp.MustCompile(fmt.Sprintf("^%s$", validCharsPattern))
)

// IndexPath resolves the path for a specific namespace and name of buildpack
func IndexPath(rootDir, ns, name string) (string, error) {
if err := validateField("namespace", ns); err != nil {
return "", err
}

if err := validateField("name", name); err != nil {
return "", err
}

var indexDir string
switch {
case len(name) == 1:
indexDir = "1"
case len(name) == 2:
indexDir = "2"
case len(name) == 3:
indexDir = filepath.Join("3", name[:2])
default:
indexDir = filepath.Join(name[:2], name[2:4])
}

return filepath.Join(rootDir, indexDir, fmt.Sprintf("%s_%s", ns, name)), nil
}

func validateField(field, value string) error {
length := len(value)
switch {
case length == 0:
return errors.Errorf("%s cannot be empty", style.Symbol(field))
case length > 253:
return errors.Errorf("%s too long (max 253 chars)", style.Symbol(field))
}

if !validCharsRegexp.MatchString(value) {
return errors.Errorf("%s contains illegal characters (must match %s)", style.Symbol(field), style.Symbol(validCharsPattern))
}

return nil
}
130 changes: 130 additions & 0 deletions internal/registry/index_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package registry_test

import (
"path/filepath"
"testing"

"github.com/heroku/color"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"

"github.com/buildpacks/pack/internal/registry"
h "github.com/buildpacks/pack/testhelpers"
)

func TestIndex(t *testing.T) {
color.Disable(true)
defer color.Disable(false)
spec.Run(t, "Index", testIndex, spec.Parallel(), spec.Report(report.Terminal{}))
}

func testIndex(t *testing.T, when spec.G, it spec.S) {
when("#IndexPath", func() {
when("valid", func() {
for _, scenario := range []struct {
desc,
root,
ns,
name,
expectation string
}{
{
desc: "1 char name",
root: "/tmp",
ns: "acme",
name: "a",
expectation: filepath.Join("/tmp", "1", "acme_a"),
},
{
desc: "2 char name",
root: "/tmp",
ns: "acme",
name: "ab",
expectation: filepath.Join("/tmp", "2", "acme_ab"),
},
{
desc: "3 char name",
root: "/tmp",
ns: "acme",
name: "abc",
expectation: filepath.Join("/tmp", "3", "ab", "acme_abc"),
},
{
desc: "4 char name",
root: "/tmp",
ns: "acme",
name: "abcd",
expectation: filepath.Join("/tmp", "ab", "cd", "acme_abcd"),
},
{
desc: "> 4 char name",
root: "/tmp",
ns: "acme",
name: "acmelang",
expectation: filepath.Join("/tmp", "ac", "me", "acme_acmelang"),
},
} {
scenario := scenario
it(scenario.desc, func() {
index, err := registry.IndexPath(scenario.root, scenario.ns, scenario.name)
h.AssertNil(t, err)
h.AssertEq(t, index, scenario.expectation)
})
}
})

when("invalid", func() {
for _, scenario := range []struct {
desc,
ns,
name,
error string
}{
{
desc: "ns is empty",
ns: "",
name: "a",
error: "'namespace' cannot be empty",
},
{
desc: "name is empty",
ns: "a",
name: "",
error: "'name' cannot be empty",
},
{
desc: "namespace has capital letters",
ns: "Acme",
name: "buildpack",
error: "'namespace' contains illegal characters (must match '[a-z0-9\\-.]+')",
},
{
desc: "name has capital letters",
ns: "acme",
name: "Buildpack",
error: "'name' contains illegal characters (must match '[a-z0-9\\-.]+')",
},
{
desc: "namespace is too long",
ns: h.RandString(254),
name: "buildpack",
error: "'namespace' too long (max 253 chars)",
},
{
desc: "name is too long",
ns: "acme",
name: h.RandString(254),
error: "'name' too long (max 253 chars)",
},
} {
scenario := scenario
when(scenario.desc, func() {
it("errors", func() {
_, err := registry.IndexPath("/tmp", scenario.ns, scenario.name)
h.AssertError(t, err, scenario.error)
})
})
}
})
})
}
Loading

0 comments on commit bb2ff31

Please sign in to comment.