Refactor commit type and logic to account for future commit types

---
type: change
message: |-
  Refactor commit type and logic to account for future commit types

  This commit introduces a CommitInterface which CommitChange (previously
  ChangeCommit) now implements. Additionally, now all commit messages will include
  a type field and a "---" separator. The code is written to still accept all the
  old commit messages used in this repo. Other than those changes, most of this is
  just rearranging existing code.
change_hash: AHjWAUxCjXgOL0Sb+oQZc6TmuVgVHJn08zpGreYyChwx
credentials:
- type: pgp_signature
  pub_key_id: 95C46FA6A41148AC
  body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl5gOuoACgkQlcRvpqQRSKxapA//bODd2IwX2D7nFBkEEd00ol1l4vaw7pgwCjqyQtyskeCZ5IH6H6PkYOSmU9DIBde+cGo35Oi5ynChmfnSatvUZ1dLRJqm8FfOGDw/IsccyYDd1iptj16Ckr6Bsht1XgFJNN10hufuAg77fRIwbGi003WCQdnrJZ1Xbtgex6a4rUqVFW+sjXAB1msmo5B5nabfm/ta0epptxhlINIY2qP5Vb+ftdb2lRUNQwkIEr5GErfAgN3sxYEfqQvLzr/007tEeVznyhdgww47awWsBaTEd6njycbWpphnNA8PbcgUGKDYsj3qLz/bCR1VQOdWgod8PLEru2O+uC2+72ssfT9NDn8HB/WrBKG4W4oykJIhXJ5um18/B9ZSxPMlTQv2Yr4nF7w+Sx3UynEdUTducbIOUq2K+JnI+Ln3gHe0yRw5UEfrzymR4f2Nfe1I13rJk2W7SVRDmOYidr0MwBlLs8tmnJFMWmWZtd1hpPOpyOyUF1jKgvMuR9ferb5niuc3Lk4trqDiaF+tjy/NmAv/7c+qiVmKKpVJVVqvT60TqBR9DTHjRGktcPFD50sc811Th+Xd9RdhzpIYM+0DT790FTf8E0hY6wm/NKTGplfqwBSNZk87SeIiFTu7sZWVpAaPz1vTmVGduC1oj3/Zlv6TzNrUAp3VwBepROBhZlHCHUr9tKg=
  account: mediocregopher
main
mediocregopher 4 years ago
parent 9bfd012221
commit cf05b3a072
  1. 3
      ROADMAP.md
  2. 13
      cmd/dehub/main.go
  3. 202
      commit.go
  4. 64
      commit_change.go
  5. 105
      commit_change_test.go
  6. 103
      commit_test.go
  7. 2
      config.go
  8. 6
      repo.go
  9. 22
      repo_test.go

@ -20,6 +20,9 @@ set, only a sequence of milestones and the requirements to hit them.
## Milestone: Enough polish to show off the project
* Maybe coalesce the `accessctl`, `fs`, and `sigcred` packages back into the
root "dehub" package.
* Polish commands
- New flag system, some kind of interactivity support (e.g. user doesn't
specify required argument, give them a prompt on the CLI to input it

@ -155,12 +155,17 @@ var subCmds = []subCmd{
return fmt.Errorf("could not cast %+v to SignifierInterface: %w", sig, err)
}
tc, err := sctx.repo().NewChangeCommit(*msg, *accountID, sigInt)
commit, err := sctx.repo().NewCommitChange(*msg)
if err != nil {
return fmt.Errorf("could not construct change commit: %w", err)
}
hash, err := sctx.repo().Commit(tc, *accountID)
commit, err = sctx.repo().AccreditCommit(commit, *accountID, sigInt)
if err != nil {
return fmt.Errorf("could not accredit commit: %w", err)
}
hash, err := sctx.repo().Commit(commit, *accountID)
if err != nil {
return fmt.Errorf("could not commit change commit: %w", err)
}
@ -191,7 +196,7 @@ var subCmds = []subCmd{
branchName = plumbing.NewBranchReferenceName(*branch)
}
if err := sctx.repo().VerifyChangeCommit(branchName, *h); err != nil {
if err := sctx.repo().VerifyCommit(branchName, *h); err != nil {
return fmt.Errorf("could not verify commit at %q (%s): %w", *rev, *h, err)
}
@ -278,7 +283,7 @@ var subCmds = []subCmd{
for i := len(hashesToCheck) - 1; i >= 0; i-- {
hash := hashesToCheck[i]
fmt.Printf("Verifying change commit %q\n", hash)
if err := sctx.repo().VerifyChangeCommit(branchName, hash); err != nil {
if err := sctx.repo().VerifyCommit(branchName, hash); err != nil {
return fmt.Errorf("could not verify change commit %q: %w", hash, err)
}
}

@ -5,10 +5,9 @@ import (
"dehub/accessctl"
"dehub/fs"
"dehub/sigcred"
"dehub/yamlutil"
"dehub/typeobj"
"encoding"
"encoding/base64"
"errors"
"fmt"
"strings"
"time"
@ -19,57 +18,114 @@ import (
yaml "gopkg.in/yaml.v2"
)
// ChangeCommit describes the structure of a change commit message.
type ChangeCommit struct {
Message string `yaml:"message"`
ChangeHash yamlutil.Blob `yaml:"change_hash"`
// CommitInterface describes the methods which must be implemented by the
// different commit types.
type CommitInterface interface {
// MessageHead returns the head of the commit message (i.e. the first line).
MessageHead() (string, error)
// Hash returns the raw hash which Signifiers can sign to accredit this
// commit. The tree objects given describe the filesystem state of the
// parent commit, and the filesystem state of this commit.
//
// This method should _not_ change any fields on the commit.
Hash(parent, this *object.Tree) ([]byte, error)
// GetHash returns the signable Hash embedded in the commit, which should
// hopefully correspond to the Commit's Credentials.
GetHash() []byte
}
// Commit represents a single Commit which is being added to a branch. Only one
// field should be set on a Commit, unless otherwise noted.
type Commit struct {
Change *CommitChange `type:"change,default"`
// Credentials represent all created Credentials for this commit, and can be
// set on all Commit objects regardless of other fields being set.
Credentials []sigcred.Credential `yaml:"credentials"`
}
type ccYAML struct {
Val ChangeCommit `yaml:",inline"`
// MarshalYAML implements the yaml.Marshaler interface.
func (c Commit) MarshalYAML() (interface{}, error) {
return typeobj.MarshalYAML(c)
}
func msgHead(msg string) string {
i := strings.Index(msg, "\n")
if i > 0 {
return msg[:i]
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *Commit) UnmarshalYAML(unmarshal func(interface{}) error) error {
return typeobj.UnmarshalYAML(c, unmarshal)
}
// Interface returns the CommitInterface instance encapsulated by this Commit
// object.
func (c Commit) Interface() (CommitInterface, error) {
el, _, err := typeobj.Element(c)
if err != nil {
return nil, err
}
return msg
return el.(CommitInterface), nil
}
// MarshalText implements the encoding.TextMarshaler interface by returning the
// form the ChangeCommit object takes in the git commit message.
func (cc ChangeCommit) MarshalText() ([]byte, error) {
changeCommitEncoded, err := yaml.Marshal(ccYAML{cc})
// form the Commit object takes in the git commit message.
func (c Commit) MarshalText() ([]byte, error) {
commitInt, err := c.Interface()
if err != nil {
return nil, fmt.Errorf("could not cast Commit %+v to interface : %w", c, err)
}
msgHead, err := commitInt.MessageHead()
if err != nil {
return nil, fmt.Errorf("error constructing message head: %w", err)
}
msgBodyB, err := yaml.Marshal(c)
if err != nil {
return nil, fmt.Errorf("failed to encode ChangeCommit message: %w", err)
return nil, fmt.Errorf("error marshaling commit %+v as yaml: %w", c, err)
}
fullMsg := msgHead(cc.Message) + "\n\n" + string(changeCommitEncoded)
return []byte(fullMsg), nil
w := new(bytes.Buffer)
w.WriteString(msgHead)
w.WriteString("\n\n---\n")
w.Write(msgBodyB)
return w.Bytes(), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface by decoding a
// ChangeCommit object which has been encoded into a git commit message.
func (cc *ChangeCommit) UnmarshalText(msg []byte) error {
// Commit object which has been encoded into a git commit message.
func (c *Commit) UnmarshalText(msg []byte) error {
i := bytes.Index(msg, []byte("\n"))
if i < 0 {
return fmt.Errorf("commit message %q is malformed", msg)
return fmt.Errorf("commit message %q is malformed, it has no body", msg)
}
msgHead, msg := msg[:i], msg[i:]
msgBody := msg[i:]
var ccy ccYAML
if err := yaml.Unmarshal(msg, &ccy); err != nil {
return fmt.Errorf("could not unmarshal ChangeCommit message: %w", err)
if err := yaml.Unmarshal(msgBody, c); err != nil {
return fmt.Errorf("could not unmarshal Commit message from yaml: %w", err)
}
return nil
}
*cc = ccy.Val
if !strings.HasPrefix(cc.Message, string(msgHead)) {
return errors.New("encoded ChangeCommit is malformed, it might not be an encoded ChangeCommit")
// AccreditCommit returns the given Commit with an appended Credential provided
// by the given account and its Signifier.
func (r *Repo) AccreditCommit(commit Commit, accountID string, sigInt sigcred.SignifierInterface) (Commit, error) {
commitInt, err := commit.Interface()
if err != nil {
return commit, fmt.Errorf("could not cast commit %+v to interface: %w", commit, err)
}
return nil
headFS, err := r.HeadFS()
if err != nil {
return commit, fmt.Errorf("could not grab snapshot of HEAD fs: %w", err)
}
cred, err := sigInt.Sign(headFS, commitInt.GetHash())
if err != nil {
return commit, fmt.Errorf("could not accreddit change commit: %w", err)
}
cred.AccountID = accountID
commit.Credentials = append(commit.Credentials, cred)
return commit, nil
}
// Commit uses the given TextMarshaler to create a git commit object (with the
@ -116,50 +172,6 @@ func (r *Repo) HasStagedChanges() (bool, error) {
return any, nil
}
// NewChangeCommit constructs a ChangeCommit. If sig is given then it is used to
// create a Credential for the ChangeCommit.
func (r *Repo) NewChangeCommit(msg, accountID string, sig sigcred.SignifierInterface) (ChangeCommit, error) {
_, headTree, err := r.head()
if errors.Is(err, plumbing.ErrReferenceNotFound) {
headTree = &object.Tree{}
} else if err != nil {
return ChangeCommit{}, err
}
_, stagedTree, err := fs.FromStagedChangesTree(r.GitRepo)
if err != nil {
return ChangeCommit{}, err
}
changeHash := genChangeHash(nil, msg, headTree, stagedTree)
var creds []sigcred.Credential
if sig != nil {
// this is necessarily different than headTree for the case of there
// being no HEAD (ie it's the first commit). In that case we want
// headTree to be empty (because it's being used to generate the change
// hash), but we want the signifier to use the raw fs (because that's
// where the signifier's data might be).
sigFS, err := r.headOrRawFS()
if err != nil {
return ChangeCommit{}, err
}
cred, err := sig.Sign(sigFS, changeHash)
if err != nil {
return ChangeCommit{}, fmt.Errorf("failed to sign commit hash: %w", err)
}
cred.AccountID = accountID
creds = append(creds, cred)
}
return ChangeCommit{
Message: msg,
ChangeHash: changeHash,
Credentials: creds,
}, nil
}
func (r *Repo) assertAccessControls(
accessCtls []accessctl.BranchAccessControl, creds []sigcred.Credential,
branch plumbing.ReferenceName, from, to *object.Tree,
@ -197,28 +209,23 @@ func (r *Repo) assertAccessControls(
return nil
}
// VerifyChangeCommit verifies that the change commit at the given hash, which
// is presumably on the given branch, is gucci.
func (r *Repo) VerifyChangeCommit(branch plumbing.ReferenceName, h plumbing.Hash) error {
commit, err := r.GitRepo.CommitObject(h)
// VerifyCommit verifies that the commit at the given hash, which is presumably
// on the given branch, is gucci.
func (r *Repo) VerifyCommit(branch plumbing.ReferenceName, h plumbing.Hash) error {
commitObj, err := r.GitRepo.CommitObject(h)
if err != nil {
return fmt.Errorf("could not retrieve commit object: %w", err)
}
commitTree, err := r.GitRepo.TreeObject(commit.TreeHash)
commitTree, err := r.GitRepo.TreeObject(commitObj.TreeHash)
if err != nil {
return fmt.Errorf("could not retrieve tree object: %w", err)
}
var changeCommit ChangeCommit
if err := changeCommit.UnmarshalText([]byte(commit.Message)); err != nil {
return err
}
sigTree := commitTree // only for root commit
parentTree := &object.Tree{}
if commit.NumParents() > 0 {
parent, err := commit.Parent(0)
if commitObj.NumParents() > 0 {
parent, err := commitObj.Parent(0)
if err != nil {
return fmt.Errorf("could not retrieve parent of commit: %w", err)
} else if parentTree, err = r.GitRepo.TreeObject(parent.TreeHash); err != nil {
@ -228,27 +235,40 @@ func (r *Repo) VerifyChangeCommit(branch plumbing.ReferenceName, h plumbing.Hash
}
sigFS := fs.FromTree(sigTree)
var commit Commit
if err := commit.UnmarshalText([]byte(commitObj.Message)); err != nil {
return err
}
cfg, err := r.loadConfig(sigFS)
if err != nil {
return fmt.Errorf("error loading config: %w", err)
}
err = r.assertAccessControls(
cfg.AccessControls, changeCommit.Credentials,
cfg.AccessControls, commit.Credentials,
branch, parentTree, commitTree,
)
if err != nil {
return fmt.Errorf("failed to satisfy all access controls: %w", err)
}
expectedChangeHash := genChangeHash(nil, changeCommit.Message, parentTree, commitTree)
if !bytes.Equal(changeCommit.ChangeHash, expectedChangeHash) {
commitInt, err := commit.Interface()
if err != nil {
return fmt.Errorf("could not cast commit %+v to interface: %w", commit, err)
}
changeHash := commitInt.GetHash()
expectedChangeHash, err := commitInt.Hash(parentTree, commitTree)
if err != nil {
return fmt.Errorf("error calculating expected change hash: %w", err)
} else if !bytes.Equal(changeHash, expectedChangeHash) {
return fmt.Errorf("malformed change_hash in commit body, is %s but should be %s",
base64.StdEncoding.EncodeToString(expectedChangeHash),
base64.StdEncoding.EncodeToString(changeCommit.ChangeHash))
base64.StdEncoding.EncodeToString(changeHash))
}
for _, cred := range changeCommit.Credentials {
for _, cred := range commit.Credentials {
sig, err := r.signifierForCredential(sigFS, cred)
if err != nil {
return fmt.Errorf("error finding signifier for credential %+v: %w", cred, err)

@ -0,0 +1,64 @@
package dehub
import (
"dehub/fs"
"dehub/yamlutil"
"errors"
"strings"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
)
// CommitChange describes the structure of a change commit message.
type CommitChange struct {
Message string `yaml:"message"`
ChangeHash yamlutil.Blob `yaml:"change_hash"`
}
var _ CommitInterface = CommitChange{}
// NewCommitChange constructs a Commit populated with a CommitChange
// encompassing the currently staged file changes. The Credentials of the
// returned Commit will _not_ be filled in.
func (r *Repo) NewCommitChange(msg string) (Commit, error) {
_, headTree, err := r.head()
if errors.Is(err, plumbing.ErrReferenceNotFound) {
headTree = &object.Tree{}
} else if err != nil {
return Commit{}, err
}
_, stagedTree, err := fs.FromStagedChangesTree(r.GitRepo)
if err != nil {
return Commit{}, err
}
cc := CommitChange{Message: msg}
if cc.ChangeHash, err = cc.Hash(headTree, stagedTree); err != nil {
return Commit{}, err
}
return Commit{
Change: &cc,
}, nil
}
// MessageHead implements the method for the CommitInterface interface.
func (cc CommitChange) MessageHead() (string, error) {
i := strings.Index(cc.Message, "\n")
if i > 0 {
return cc.Message[:i], nil
}
return cc.Message, nil
}
// Hash implements the method for the CommitInterface interface.
func (cc CommitChange) Hash(parent, this *object.Tree) ([]byte, error) {
return genChangeHash(nil, cc.Message, parent, this), nil
}
// GetHash implements the method for the CommitInterface interface.
func (cc CommitChange) GetHash() []byte {
return cc.ChangeHash
}

@ -0,0 +1,105 @@
package dehub
import (
"reflect"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
)
func TestChangeCommitVerify(t *testing.T) {
type step struct {
msg string
msgHead string // defaults to msg
tree map[string]string
}
testCases := []struct {
descr string
steps []step
}{
{
descr: "single commit",
steps: []step{
{
msg: "first commit",
tree: map[string]string{"a": "0", "b": "1"},
},
},
},
{
descr: "multiple commits",
steps: []step{
{
msg: "first commit",
tree: map[string]string{"a": "0", "b": "1"},
},
{
msg: "second commit, changing a",
tree: map[string]string{"a": "1"},
},
{
msg: "third commit, empty",
},
{
msg: "fourth commit, adding c, removing b",
tree: map[string]string{"b": "", "c": "2"},
},
},
},
{
descr: "big body commits",
steps: []step{
{
msg: "first commit, single line but with newline\n",
},
{
msg: "second commit, single line but with two newlines\n\n",
msgHead: "second commit, single line but with two newlines\n\n",
},
{
msg: "third commit, multi-line with one newline\nanother line!",
msgHead: "third commit, multi-line with one newline\n\n",
},
{
msg: "fourth commit, multi-line with two newlines\n\nanother line!",
msgHead: "fourth commit, multi-line with two newlines\n\n",
},
},
},
}
for _, test := range testCases {
t.Run(test.descr, func(t *testing.T) {
h := newHarness(t)
for _, step := range test.steps {
h.stage(step.tree)
account := h.cfg.Accounts[0]
commit, hash := h.changeCommit(step.msg, account.ID, h.sig)
if err := h.repo.VerifyCommit(MainRefName, hash); err != nil {
t.Fatalf("could not verify hash %v: %v", hash, err)
}
commitObj, err := h.repo.GitRepo.CommitObject(hash)
if err != nil {
t.Fatalf("failed to retrieve commit %v: %v", hash, err)
} else if step.msgHead == "" {
step.msgHead = strings.TrimSpace(step.msg) + "\n\n"
}
if !strings.HasPrefix(commitObj.Message, step.msgHead) {
t.Fatalf("commit message %q does not start with expected head %q", commitObj.Message, step.msgHead)
}
var actualCommit Commit
if err := actualCommit.UnmarshalText([]byte(commitObj.Message)); err != nil {
t.Fatalf("error unmarshaling commit body: %v", err)
} else if !reflect.DeepEqual(actualCommit, commit) {
t.Fatalf("returned change commit:\n%s\ndoes not match actual one:\n%s",
spew.Sdump(commit), spew.Sdump(actualCommit))
}
}
})
}
}

@ -2,112 +2,13 @@ package dehub
import (
"dehub/sigcred"
"reflect"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
yaml "gopkg.in/yaml.v2"
)
func TestChangeCommitVerify(t *testing.T) {
type step struct {
msg string
msgHead string // defaults to msg
tree map[string]string
}
testCases := []struct {
descr string
steps []step
}{
{
descr: "single commit",
steps: []step{
{
msg: "first commit",
tree: map[string]string{"a": "0", "b": "1"},
},
},
},
{
descr: "multiple commits",
steps: []step{
{
msg: "first commit",
tree: map[string]string{"a": "0", "b": "1"},
},
{
msg: "second commit, changing a",
tree: map[string]string{"a": "1"},
},
{
msg: "third commit, empty",
},
{
msg: "fourth commit, adding c, removing b",
tree: map[string]string{"b": "", "c": "2"},
},
},
},
{
descr: "big body commits",
steps: []step{
{
msg: "first commit, single line but with newline\n",
},
{
msg: "second commit, single line but with two newlines\n\n",
msgHead: "second commit, single line but with two newlines\n\n",
},
{
msg: "third commit, multi-line with one newline\nanother line!",
msgHead: "third commit, multi-line with one newline\n\n",
},
{
msg: "fourth commit, multi-line with two newlines\n\nanother line!",
msgHead: "fourth commit, multi-line with two newlines\n\n",
},
},
},
}
for _, test := range testCases {
t.Run(test.descr, func(t *testing.T) {
h := newHarness(t)
for _, step := range test.steps {
h.stage(step.tree)
account := h.cfg.Accounts[0]
changeCommit, hash := h.changeCommit(step.msg, account.ID, h.sig)
if err := h.repo.VerifyChangeCommit(MainRefName, hash); err != nil {
t.Fatalf("could not verify hash %v: %v", hash, err)
}
commit, err := h.repo.GitRepo.CommitObject(hash)
if err != nil {
t.Fatalf("failed to retrieve commit %v: %v", hash, err)
} else if step.msgHead == "" {
step.msgHead = strings.TrimSpace(step.msg) + "\n\n"
}
if !strings.HasPrefix(commit.Message, step.msgHead) {
t.Fatalf("commit message %q does not start with expected head %q", commit.Message, step.msgHead)
}
var actualChangeCommit ChangeCommit
if err := actualChangeCommit.UnmarshalText([]byte(commit.Message)); err != nil {
t.Fatalf("error unmarshaling commit body: %v", err)
} else if !reflect.DeepEqual(actualChangeCommit, changeCommit) {
t.Fatalf("returned change commit:\n%s\ndoes not match actual one:\n%s",
spew.Sdump(changeCommit), spew.Sdump(actualChangeCommit))
}
}
})
}
}
func TestConfigChange(t *testing.T) {
h := newHarness(t)
@ -137,7 +38,7 @@ func TestConfigChange(t *testing.T) {
h.stage(map[string]string{ConfigPath: string(cfgBody)})
_, badHash := h.changeCommit("add toot user", h.cfg.Accounts[1].ID, newSig)
if err := h.repo.VerifyChangeCommit(MainRefName, badHash); err == nil {
if err := h.repo.VerifyCommit(MainRefName, badHash); err == nil {
t.Fatal("toot user shouldn't be able to add itself to config")
}
h.reset(hash, git.HardReset)
@ -153,7 +54,7 @@ func TestConfigChange(t *testing.T) {
hashes = append(hashes, hash)
for i, hash := range hashes {
if err := h.repo.VerifyChangeCommit(MainRefName, hash); err != nil {
if err := h.repo.VerifyCommit(MainRefName, hash); err != nil {
t.Fatalf("commit %d (%v) should have been verified but wasn't: %v", i, hash, err)
}
}

@ -44,7 +44,7 @@ func (r *Repo) loadConfig(fs fs.FS) (Config, error) {
// LoadConfig loads the Config object from the HEAD of the repo, or directly
// from the filesystem if there is no HEAD yet.
func (r *Repo) LoadConfig() (Config, error) {
headFS, err := r.headOrRawFS()
headFS, err := r.HeadFS()
if err != nil {
return Config{}, fmt.Errorf("error retrieving repo HEAD: %w", err)
}

@ -158,9 +158,9 @@ func (r *Repo) head() (*object.Commit, *object.Tree, error) {
return headCommit, headTree, nil
}
// headOrRawFS returns an FS based on the HEAD commit, or if there is no HEAD
// commit (it's an empty repo) an FS based on the raw filesystem.
func (r *Repo) headOrRawFS() (fs.FS, error) {
// HeadFS returns an FS based on the HEAD commit, or if there is no HEAD commit
// (it's an empty repo) an FS based on the raw filesystem.
func (r *Repo) HeadFS() (fs.FS, error) {
_, headTree, err := r.head()
if errors.Is(err, plumbing.ErrReferenceNotFound) {
bfs, err := r.billyFilesystem()

@ -107,18 +107,24 @@ func (h *harness) stage(tree map[string]string) {
}
}
func (h *harness) changeCommit(msg, accountID string, sig sigcred.SignifierInterface) (ChangeCommit, plumbing.Hash) {
tc, err := h.repo.NewChangeCommit(msg, accountID, sig)
func (h *harness) changeCommit(msg, accountID string, sig sigcred.SignifierInterface) (Commit, plumbing.Hash) {
commit, err := h.repo.NewCommitChange(msg)
if err != nil {
h.t.Fatalf("failed to make ChangeCommit: %v", err)
h.t.Fatalf("failed to create CommitChange: %v", err)
}
hash, err := h.repo.Commit(tc, accountID)
if sig != nil {
if commit, err = h.repo.AccreditCommit(commit, accountID, sig); err != nil {
h.t.Fatalf("failed to accredit commit: %v", err)
}
}
hash, err := h.repo.Commit(commit, accountID)
if err != nil {
h.t.Fatalf("failed to commit ChangeCommit: %v", err)
}
return tc, hash
return commit, hash
}
func (h *harness) reset(to plumbing.Hash, mode git.ResetMode) {
@ -193,9 +199,9 @@ access_controls:
_, hash1 := harness.changeCommit("ain't no laws", "toot", nil)
// verifying the first should work, but not the second.
if err := harness.repo.VerifyChangeCommit(MainRefName, hash0); err != nil {
if err := harness.repo.VerifyCommit(MainRefName, hash0); err != nil {
t.Fatalf("first commit %q should be verifiable, but got: %v", hash0, err)
} else if err := harness.repo.VerifyChangeCommit(MainRefName, hash1); err == nil {
} else if err := harness.repo.VerifyCommit(MainRefName, hash1); err == nil {
t.Fatalf("second commit %q should not have been verified", hash1)
}
@ -212,7 +218,7 @@ accounts:
path: ".dehub/root.asc"
`})
_, hash2 := harness.changeCommit("Fix the config!", "root", harness.sig)
if err := harness.repo.VerifyChangeCommit(MainRefName, hash2); err != nil {
if err := harness.repo.VerifyCommit(MainRefName, hash2); err != nil {
t.Fatalf("config fix commit %q should be verifiable, but got: %v", hash2, err)
}
}

Loading…
Cancel
Save