Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

Commit

Permalink
Add basic Lock implementation (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
sdboyer committed Oct 18, 2016
2 parents 095637b + f569990 commit 2f506ee
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 0 deletions.
84 changes: 84 additions & 0 deletions lock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"encoding/hex"
"encoding/json"
"fmt"
"io"

"github.com/sdboyer/gps"
)

type Lock struct {
Memo []byte
P []gps.LockedProject
}

type rawLock struct {
Memo string `json:"memo"`
P []lockedDep `json:"projects"`
}

type lockedDep struct {
Name string `json:"name"`
Version string `json:"version,omitempty"`
Branch string `json:"branch,omitempty"`
Revision string `json:"revision"`
Repository string `json:"repo,omitempty"`
Packages []string `json:"packages"`
}

func ReadLock(r io.Reader) (*Lock, error) {
rl := rawLock{}
err := json.NewDecoder(r).Decode(&rl)
if err != nil {
return nil, err
}

b, err := hex.DecodeString(rl.Memo)
if err != nil {
return nil, fmt.Errorf("invalid hash digest in lock's memo field")
}
l := &Lock{
Memo: b,
P: make([]gps.LockedProject, len(rl.P)),
}

for i, ld := range rl.P {
r := gps.Revision(ld.Revision)

var v gps.Version
if ld.Version != "" {
if ld.Branch != "" {
return nil, fmt.Errorf("lock file specified both a branch (%s) and version (%s) for %s", ld.Branch, ld.Version, ld.Name)
}
v = gps.NewVersion(ld.Version).Is(r)
} else if ld.Branch != "" {
v = gps.NewBranch(ld.Branch).Is(r)
} else if r == "" {
return nil, fmt.Errorf("lock file has entry for %s, but specifies no version", ld.Name)
} else {
v = r
}

id := gps.ProjectIdentifier{
ProjectRoot: gps.ProjectRoot(ld.Name),
NetworkName: ld.Repository,
}
l.P[i] = gps.NewLockedProject(id, v, ld.Packages)
}

return l, nil
}

func (l *Lock) InputHash() []byte {
return l.Memo
}

func (l *Lock) Projects() []gps.LockedProject {
return l.P
}
68 changes: 68 additions & 0 deletions lock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"encoding/hex"
"reflect"
"strings"
"testing"

"github.com/sdboyer/gps"
)

func TestReadLock(t *testing.T) {
const le = `{
"memo": "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e",
"projects": [
{
"name": "github.com/sdboyer/gps",
"branch": "master",
"version": "v0.12.0",
"revision": "d05d5aca9f895d19e9265839bffeadd74a2d2ecb",
"packages": ["."]
}
]
}`
const lg = `{
"memo": "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e",
"projects": [
{
"name": "github.com/sdboyer/gps",
"branch": "master",
"revision": "d05d5aca9f895d19e9265839bffeadd74a2d2ecb",
"packages": ["."]
}
]
}`

_, err := ReadLock(strings.NewReader(le))
if err == nil {
t.Error("Reading lock with invalid props should have caused error, but did not")
} else if !strings.Contains(err.Error(), "both a branch") {
t.Errorf("Unexpected error %q; expected multiple version error", err)
}

l, err := ReadLock(strings.NewReader(lg))
if err != nil {
t.Fatalf("Should have read Lock correctly, but got err %q", err)
}

b, _ := hex.DecodeString("2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e")
l2 := &Lock{
Memo: b,
P: []gps.LockedProject{
gps.NewLockedProject(
gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/gps")},
gps.NewBranch("master").Is(gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb")),
[]string{"."},
),
},
}

if !reflect.DeepEqual(l, l2) {
t.Error("Valid lock did not parse as expected")
}
}

0 comments on commit 2f506ee

Please sign in to comment.