Change all references to 'master' into 'trunk'

message: Change all references to 'master' into 'trunk'
change_hash: ABJwxLvHMmj63oJPIv/vNeRCIp1ZDZYuPLQT57x9K1lO
credentials:
- type: pgp_signature
  pub_key_id: 95C46FA6A41148AC
  body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl5Je88ACgkQlcRvpqQRSKyxyw/7B51/vvtlxLan9Z6q6rh7uyGcFf6WpWGiRDIccAJHqzegGP4eAb8V4Jzi9H4JJ82TnAc+EUegs8ewRiOcWj6YkU463b5CgUSwnzYKm86K6SyHGW1WH9OxFIDEMzCaVsktMEc9iLMl0dJNzakhPzu+qy74pU5xlypjCBzRLFeuqmnf4M1fq4FAq6fCs7ZVB3LccyC0mhCWsS2eiuCE/mVQ7WROVpxj5tplp71jlX6ZtWU7qsgvQS2V8ggtTVpCT2WE4u6bnu1oYOpSs9g+sxKKOAHKvZfjAMLG9qM3pOl1J+44W2Ms/mtON0VUX7G1Q5XVcmM0hPopXsiWLiAslSOAOuL+LE5iLq4nz1RyIbVh0QakYr+4NJL6Yt0L2I6lNVnUS4SgmMr86n8ZCcCjDAs6g5d7Zchqp3S3EF3bbJuLi0ICoOCxTD2gNkjo2BGverI8APLTUpujQl+9W/sGmT2aEdTpruGYjIcwsRaGo8VMDFECdZply5Ng1FbBoohv+j3vdO05fRyNkvRu3CBxP2tUe39jLxUmpu62igGF2VjZptsK0bLdzDpQ5Hv6jSZjn+mPyFJ5w+EX2JCRYpjn2eaYYtI/IyULGTaftzcEZeZibEhd/wQJnsEJNqXpCilDKgZajZyYhgy7BSeT9xDf2d8qyFoqWpvFhshHcesbUfG2O+Y=
  account: mediocregopher
main
mediocregopher 4 years ago
parent 181802ba0e
commit a5bee27892
  1. 2
      .gitignore
  2. 20
      SPEC.md
  3. 22
      cmd/dehub/main.go
  4. 1
      cmd/http-server/.gitignore
  5. 128
      commit.go
  6. 39
      commit_test.go
  7. 3
      repo.go
  8. 17
      repo_test.go
  9. 4
      sigcred/credential.go

2
.gitignore vendored

@ -1 +1 @@
dehub /dehub

@ -65,23 +65,23 @@ access_controls:
count: 1 count: 1
``` ```
# Master commit # Trunk Commit
All new commits being appended to the HEAD of the `master` branch are subject to All new commits being appended to the HEAD of the `trunk` branch are subject to
the following requirements: the following requirements:
* Must conform to all requirements defined by the `access_controls` section of * Must conform to all requirements defined by the `access_controls` section of
the `config.yml`, as found in the HEAD. If the commit is the initial commit of the `config.yml`, as found in the HEAD. If the commit is the initial commit of
the repo then it instead uses the `config.yml` found in itself. the branch then it instead uses the `config.yml` found in itself.
* Must not be a merge commit (this may be amended later, but at present it * Must not be a merge commit (this may be amended later, but at present it
simplifies implementation). simplifies implementation).
* The commit message must conform to the format and semantics defined below. * The commit message must conform to the format and semantics defined below.
## Master Commit Message ## Trunk Commit Message
The commit message for a commit being appended to the HEAD of the `master` The commit message for a commit being appended to the HEAD of the `trunk`
branch must conform to the following format: a single line (the message head) branch must conform to the following format: a single line (the message head)
giving a short description of the change, then two newlines, then a body which giving a short description of the change, then two newlines, then a body which
is a yaml formatted string: is a yaml formatted string:
@ -169,7 +169,7 @@ access control requirements. The message head of these are arbitrary, but the
body must be formatted as such: body must be formatted as such:
```yaml ```yaml
# This object matches the one found in the `credentials` section of the master # This object matches the one found in the `credentials` section of the trunk
# commit message. # commit message.
type: pgp_signature type: pgp_signature
account_id: some_user_id ``` account_id: some_user_id ```
@ -184,10 +184,10 @@ new signature commit, if they agree with the new changes.
## Merging MRs ## Merging MRs
When an MR has accumulated enough meta commits to fulfuill access control When an MR has accumulated enough meta commits to fulfill access control
requirements it may be coalesced into a single commit destined for the master requirements it may be coalesced into a single commit destined for the `trunk`
branch. See the Master Commit Message sub-section for details on how commits in branch. See the Trunk Commit Message sub-section for details on how commit
the master branch must be formatted. messages in the `trunk` branch must be formatted.
# TODO # TODO

@ -76,10 +76,16 @@ var subCmds = []subCmd{
return fmt.Errorf("could not cast %+v to SignifierInterface: %w", sig, err) return fmt.Errorf("could not cast %+v to SignifierInterface: %w", sig, err)
} }
_, hash, err := sctx.repo().CommitMaster(*msg, *accountID, sigInt) tc, err := sctx.repo().NewTrunkCommit(*msg, *accountID, sigInt)
if err != nil { if err != nil {
return err return fmt.Errorf("could not construct trunk commit: %w", err)
} }
hash, err := sctx.repo().Commit(tc, *accountID)
if err != nil {
return fmt.Errorf("could not commit trunk commit: %w", err)
}
fmt.Printf("changes committed to HEAD as %s\n", hash) fmt.Printf("changes committed to HEAD as %s\n", hash)
return nil return nil
}, },
@ -96,7 +102,7 @@ var subCmds = []subCmd{
return fmt.Errorf("could not resolve revision %q: %w", *rev, err) return fmt.Errorf("could not resolve revision %q: %w", *rev, err)
} }
if err := sctx.repo().VerifyMasterCommit(*h); err != nil { if err := sctx.repo().VerifyTrunkCommit(*h); err != nil {
return fmt.Errorf("could not verify commit at %q (%s): %w", *rev, *h, err) return fmt.Errorf("could not verify commit at %q (%s): %w", *rev, *h, err)
} }
@ -130,8 +136,8 @@ var subCmds = []subCmd{
return fmt.Errorf("malformed pre-receive hook stdin line %q", line) return fmt.Errorf("malformed pre-receive hook stdin line %q", line)
} }
if plumbing.ReferenceName(lineParts[2]) != plumbing.Master { if plumbing.ReferenceName(lineParts[2]) != dehub.Trunk {
return fmt.Errorf("only commits to the master branch are allowed at the moment (tried to push to %q)", lineParts[2]) return fmt.Errorf("only commits to the trunk branch are allowed at the moment (tried to push to %q)", lineParts[2])
} }
// the zeroRevision gets sent on the very first push // the zeroRevision gets sent on the very first push
@ -183,9 +189,9 @@ var subCmds = []subCmd{
for i := len(hashesToCheck) - 1; i >= 0; i-- { for i := len(hashesToCheck) - 1; i >= 0; i-- {
hash := hashesToCheck[i] hash := hashesToCheck[i]
fmt.Printf("Verifying master commit %q\n", hash) fmt.Printf("Verifying trunk commit %q\n", hash)
if err := sctx.repo().VerifyMasterCommit(hash); err != nil { if err := sctx.repo().VerifyTrunkCommit(hash); err != nil {
return fmt.Errorf("could not verify master commit %q", hash) return fmt.Errorf("could not verify trunk commit %q", hash)
} }
} }
fmt.Println("All pushed commits have been verified, well done.") fmt.Println("All pushed commits have been verified, well done.")

@ -0,0 +1 @@
dehub

@ -6,6 +6,7 @@ import (
"dehub/fs" "dehub/fs"
"dehub/sigcred" "dehub/sigcred"
"dehub/yamlutil" "dehub/yamlutil"
"encoding"
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
@ -18,16 +19,16 @@ import (
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
// MasterCommit describes the structure of the object encoded into the git // TrunkCommit describes the structure of the object encoded into the git
// message of a commit in the master branch. // message of a commit in the repo trunk.
type MasterCommit struct { type TrunkCommit struct {
Message string `yaml:"message"` Message string `yaml:"message"`
ChangeHash yamlutil.Blob `yaml:"change_hash"` ChangeHash yamlutil.Blob `yaml:"change_hash"`
Credentials []sigcred.Credential `yaml:"credentials"` Credentials []sigcred.Credential `yaml:"credentials"`
} }
type mcYAML struct { type tcYAML struct {
Val MasterCommit `yaml:",inline"` Val TrunkCommit `yaml:",inline"`
} }
func msgHead(msg string) string { func msgHead(msg string) string {
@ -39,55 +40,73 @@ func msgHead(msg string) string {
} }
// MarshalText implements the encoding.TextMarshaler interface by returning the // MarshalText implements the encoding.TextMarshaler interface by returning the
// form the MasterCommit object takes in the git commit message. // form the TrunkCommit object takes in the git commit message.
func (mc MasterCommit) MarshalText() ([]byte, error) { func (tc TrunkCommit) MarshalText() ([]byte, error) {
masterCommitEncoded, err := yaml.Marshal(mcYAML{mc}) trunkCommitEncoded, err := yaml.Marshal(tcYAML{tc})
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode MasterCommit message: %w", err) return nil, fmt.Errorf("failed to encode TrunkCommit message: %w", err)
} }
fullMsg := msgHead(mc.Message) + "\n\n" + string(masterCommitEncoded) fullMsg := msgHead(tc.Message) + "\n\n" + string(trunkCommitEncoded)
return []byte(fullMsg), nil return []byte(fullMsg), nil
} }
// UnmarshalText implements the encoding.TextUnmarshaler interface by decoding a // UnmarshalText implements the encoding.TextUnmarshaler interface by decoding a
// MasterCommit object which has been encoded into a git commit message. // TrunkCommit object which has been encoded into a git commit message.
func (mc *MasterCommit) UnmarshalText(msg []byte) error { func (tc *TrunkCommit) UnmarshalText(msg []byte) error {
i := bytes.Index(msg, []byte("\n")) i := bytes.Index(msg, []byte("\n"))
if i < 0 { if i < 0 {
return fmt.Errorf("commit message %q is malformed", msg) return fmt.Errorf("commit message %q is malformed", msg)
} }
msgHead, msg := msg[:i], msg[i:] msgHead, msg := msg[:i], msg[i:]
var mcy mcYAML var tcy tcYAML
if err := yaml.Unmarshal(msg, &mcy); err != nil { if err := yaml.Unmarshal(msg, &tcy); err != nil {
return fmt.Errorf("could not unmarshal MasterCommit message: %w", err) return fmt.Errorf("could not unmarshal TrunkCommit message: %w", err)
} }
*mc = mcy.Val *tc = tcy.Val
if !strings.HasPrefix(mc.Message, string(msgHead)) { if !strings.HasPrefix(tc.Message, string(msgHead)) {
return errors.New("encoded MasterCommit is malformed, it might not be an encoded MasterCommit") return errors.New("encoded TrunkCommit is malformed, it might not be an encoded TrunkCommit")
} }
return nil return nil
} }
// CommitMaster constructs a MasterCommit using the given SignifierInterface to // Commit uses the given TextMarshaler to create a git commit object (with the
// create a Credential for it. It returns the commit's hash after having set it // specified accountID as the author) and commits it to the current HEAD,
// to HEAD. // returning the hash of the commit.
// func (r *Repo) Commit(m encoding.TextMarshaler, accountID string) (plumbing.Hash, error) {
// TODO this method is a prototype and does not reflect the method's final form. msgB, err := m.MarshalText()
func (r *Repo) CommitMaster(msg, accountID string, sig sigcred.SignifierInterface) (MasterCommit, plumbing.Hash, error) { if err != nil {
return plumbing.ZeroHash, fmt.Errorf("error marshaling %T to string: %v", m, err)
}
w, err := r.GitRepo.Worktree()
if err != nil {
return plumbing.ZeroHash, fmt.Errorf("could not get git worktree: %w", err)
}
return w.Commit(string(msgB), &git.CommitOptions{
Author: &object.Signature{
Name: accountID,
When: time.Now(),
},
})
}
// NewTrunkCommit constructs a TrunkCommit using the given SignifierInterface to
// create a Credential for it.
func (r *Repo) NewTrunkCommit(msg, accountID string, sig sigcred.SignifierInterface) (TrunkCommit, error) {
_, headTree, err := r.head() _, headTree, err := r.head()
if errors.Is(err, plumbing.ErrReferenceNotFound) { if errors.Is(err, plumbing.ErrReferenceNotFound) {
headTree = &object.Tree{} headTree = &object.Tree{}
} else if err != nil { } else if err != nil {
return MasterCommit{}, plumbing.ZeroHash, err return TrunkCommit{}, err
} }
_, stagedTree, err := fs.FromStagedChangesTree(r.GitRepo) _, stagedTree, err := fs.FromStagedChangesTree(r.GitRepo)
if err != nil { if err != nil {
return MasterCommit{}, plumbing.ZeroHash, err return TrunkCommit{}, err
} }
// this is necessarily different than headTree for the case of there being // this is necessarily different than headTree for the case of there being
@ -97,18 +116,18 @@ func (r *Repo) CommitMaster(msg, accountID string, sig sigcred.SignifierInterfac
// data might be). // data might be).
sigFS, err := r.headOrRawFS() sigFS, err := r.headOrRawFS()
if err != nil { if err != nil {
return MasterCommit{}, plumbing.ZeroHash, err return TrunkCommit{}, err
} }
cfg, err := r.loadConfig(sigFS) cfg, err := r.loadConfig(sigFS)
if err != nil { if err != nil {
return MasterCommit{}, plumbing.ZeroHash, fmt.Errorf("could not load config: %w", err) return TrunkCommit{}, fmt.Errorf("could not load config: %w", err)
} }
changeHash := genChangeHash(nil, msg, headTree, stagedTree) changeHash := genChangeHash(nil, msg, headTree, stagedTree)
cred, err := sig.Sign(sigFS, changeHash) cred, err := sig.Sign(sigFS, changeHash)
if err != nil { if err != nil {
return MasterCommit{}, plumbing.ZeroHash, fmt.Errorf("failed to sign commit hash: %w", err) return TrunkCommit{}, fmt.Errorf("failed to sign commit hash: %w", err)
} }
cred.AccountID = accountID cred.AccountID = accountID
@ -120,37 +139,14 @@ func (r *Repo) CommitMaster(msg, accountID string, sig sigcred.SignifierInterfac
headTree, stagedTree, headTree, stagedTree,
) )
if err != nil { if err != nil {
return MasterCommit{}, plumbing.ZeroHash, fmt.Errorf("commit would not satisfy access controls: %w", err) return TrunkCommit{}, fmt.Errorf("commit would not satisfy access controls: %w", err)
} }
masterCommit := MasterCommit{ return TrunkCommit{
Message: msg, Message: msg,
ChangeHash: changeHash, ChangeHash: changeHash,
Credentials: []sigcred.Credential{cred}, Credentials: []sigcred.Credential{cred},
} }, nil
masterCommitB, err := masterCommit.MarshalText()
if err != nil {
return masterCommit, plumbing.ZeroHash, err
}
w, err := r.GitRepo.Worktree()
if err != nil {
return masterCommit, plumbing.ZeroHash, fmt.Errorf("could not get git worktree: %w", err)
}
hash, err := w.Commit(string(masterCommitB), &git.CommitOptions{
Author: &object.Signature{
Name: accountID,
When: time.Now(),
},
})
if err != nil {
return masterCommit, hash, fmt.Errorf("failed to commit changed: %w", err)
}
return masterCommit, hash, nil
} }
func (r *Repo) assertAccessControls( func (r *Repo) assertAccessControls(
@ -185,9 +181,9 @@ func (r *Repo) assertAccessControls(
return nil return nil
} }
// VerifyMasterCommit verifies that the commit at the given hash, which is // VerifyTrunkCommit verifies that the commit at the given hash, which is
// presumably on the master branch, is gucci. // presumably on the repo trunk, is gucci.
func (r *Repo) VerifyMasterCommit(h plumbing.Hash) error { func (r *Repo) VerifyTrunkCommit(h plumbing.Hash) error {
commit, err := r.GitRepo.CommitObject(h) commit, err := r.GitRepo.CommitObject(h)
if err != nil { if err != nil {
return fmt.Errorf("could not retrieve commit object: %w", err) return fmt.Errorf("could not retrieve commit object: %w", err)
@ -198,8 +194,8 @@ func (r *Repo) VerifyMasterCommit(h plumbing.Hash) error {
return fmt.Errorf("could not retrieve tree object: %w", err) return fmt.Errorf("could not retrieve tree object: %w", err)
} }
var masterCommit MasterCommit var trunkCommit TrunkCommit
if err := masterCommit.UnmarshalText([]byte(commit.Message)); err != nil { if err := trunkCommit.UnmarshalText([]byte(commit.Message)); err != nil {
return err return err
} }
@ -222,21 +218,21 @@ func (r *Repo) VerifyMasterCommit(h plumbing.Hash) error {
} }
err = r.assertAccessControls( err = r.assertAccessControls(
cfg.AccessControls, masterCommit.Credentials, cfg.AccessControls, trunkCommit.Credentials,
parentTree, commitTree, parentTree, commitTree,
) )
if err != nil { if err != nil {
return fmt.Errorf("failed to satisfy all access controls: %w", err) return fmt.Errorf("failed to satisfy all access controls: %w", err)
} }
expectedChangeHash := genChangeHash(nil, masterCommit.Message, parentTree, commitTree) expectedChangeHash := genChangeHash(nil, trunkCommit.Message, parentTree, commitTree)
if !bytes.Equal(masterCommit.ChangeHash, expectedChangeHash) { if !bytes.Equal(trunkCommit.ChangeHash, expectedChangeHash) {
return fmt.Errorf("malformed change_hash in commit body, is %s but should be %s", return fmt.Errorf("malformed change_hash in commit body, is %s but should be %s",
base64.StdEncoding.EncodeToString(expectedChangeHash), base64.StdEncoding.EncodeToString(expectedChangeHash),
base64.StdEncoding.EncodeToString(masterCommit.ChangeHash)) base64.StdEncoding.EncodeToString(trunkCommit.ChangeHash))
} }
for _, cred := range masterCommit.Credentials { for _, cred := range trunkCommit.Credentials {
sig, err := r.signifierForCredential(sigFS, cred) sig, err := r.signifierForCredential(sigFS, cred)
if err != nil { if err != nil {
return fmt.Errorf("error finding signifier for credential %+v: %w", cred, err) return fmt.Errorf("error finding signifier for credential %+v: %w", cred, err)
@ -245,7 +241,5 @@ func (r *Repo) VerifyMasterCommit(h plumbing.Hash) error {
} }
} }
// TODO access controls
return nil return nil
} }

@ -13,7 +13,7 @@ import (
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
func TestMasterCommitVerify(t *testing.T) { func TestTrunkCommitVerify(t *testing.T) {
type step struct { type step struct {
msg string msg string
msgHead string // defaults to msg msgHead string // defaults to msg
@ -81,10 +81,8 @@ func TestMasterCommitVerify(t *testing.T) {
h.stage(step.tree) h.stage(step.tree)
account := h.cfg.Accounts[0] account := h.cfg.Accounts[0]
masterCommit, hash, err := h.repo.CommitMaster(step.msg, account.ID, h.sig) trunkCommit, hash := h.trunkCommit(step.msg, account.ID, h.sig)
if err != nil { if err := h.repo.VerifyTrunkCommit(hash); err != nil {
t.Fatalf("failed to make MasterCommit: %v", err)
} else if err := h.repo.VerifyMasterCommit(hash); err != nil {
t.Fatalf("could not verify hash %v: %v", hash, err) t.Fatalf("could not verify hash %v: %v", hash, err)
} }
@ -99,12 +97,12 @@ func TestMasterCommitVerify(t *testing.T) {
t.Fatalf("commit message %q does not start with expected head %q", commit.Message, step.msgHead) t.Fatalf("commit message %q does not start with expected head %q", commit.Message, step.msgHead)
} }
var actualMasterCommit MasterCommit var actualTrunkCommit TrunkCommit
if err := actualMasterCommit.UnmarshalText([]byte(commit.Message)); err != nil { if err := actualTrunkCommit.UnmarshalText([]byte(commit.Message)); err != nil {
t.Fatalf("error unmarshaling commit body: %v", err) t.Fatalf("error unmarshaling commit body: %v", err)
} else if !reflect.DeepEqual(actualMasterCommit, masterCommit) { } else if !reflect.DeepEqual(actualTrunkCommit, trunkCommit) {
t.Fatalf("returned master commit:\n%s\ndoes not match actual one:\n%s", t.Fatalf("returned trunk commit:\n%s\ndoes not match actual one:\n%s",
spew.Sdump(masterCommit), spew.Sdump(actualMasterCommit)) spew.Sdump(trunkCommit), spew.Sdump(actualTrunkCommit))
} }
} }
}) })
@ -118,10 +116,7 @@ func TestConfigChange(t *testing.T) {
// commit the initial staged changes, which merely include the config and // commit the initial staged changes, which merely include the config and
// public key // public key
_, hash, err := h.repo.CommitMaster("commit configuration", h.cfg.Accounts[0].ID, h.sig) _, hash := h.trunkCommit("commit configuration", h.cfg.Accounts[0].ID, h.sig)
if err != nil {
t.Fatal(err)
}
hashes = append(hashes, hash) hashes = append(hashes, hash)
// create a new account and add it to the configuration. It should not be // create a new account and add it to the configuration. It should not be
@ -142,28 +137,22 @@ func TestConfigChange(t *testing.T) {
} }
h.stage(map[string]string{ConfigPath: string(cfgBody)}) h.stage(map[string]string{ConfigPath: string(cfgBody)})
_, _, err = h.repo.CommitMaster("add toot user", h.cfg.Accounts[1].ID, newSig) _, err = h.repo.NewTrunkCommit("add toot user", h.cfg.Accounts[1].ID, newSig)
if aclErr := (accessctl.ErrConditionSignatureUnsatisfied{}); !errors.As(err, &aclErr) { if aclErr := (accessctl.ErrConditionSignatureUnsatisfied{}); !errors.As(err, &aclErr) {
t.Fatalf("CommitMaster should have returned an ErrConditionSignatureUnsatisfied, but returned %v", err) t.Fatalf("NewTrunkCommit should have returned an ErrConditionSignatureUnsatisfied, but returned %v", err)
} }
// now add with the root user, this should work. // now add with the root user, this should work.
_, hash, err = h.repo.CommitMaster("add toot user", h.cfg.Accounts[0].ID, h.sig) _, hash = h.trunkCommit("add toot user", h.cfg.Accounts[0].ID, h.sig)
if err != nil {
t.Fatalf("got an unexpected error committing with root: %v", err)
}
hashes = append(hashes, hash) hashes = append(hashes, hash)
// _now_ the toot user should be able to do things. // _now_ the toot user should be able to do things.
h.stage(map[string]string{"foo/bar": "what a cool file"}) h.stage(map[string]string{"foo/bar": "what a cool file"})
_, hash, err = h.repo.CommitMaster("add a cool file", h.cfg.Accounts[1].ID, newSig) _, hash = h.trunkCommit("add a cool file", h.cfg.Accounts[1].ID, newSig)
if err != nil {
t.Fatalf("got an unexpected error committing with toot: %v", err)
}
hashes = append(hashes, hash) hashes = append(hashes, hash)
for i, hash := range hashes { for i, hash := range hashes {
if err := h.repo.VerifyMasterCommit(hash); err != nil { if err := h.repo.VerifyTrunkCommit(hash); err != nil {
t.Fatalf("commit %d (%v) should have been verified but wasn't: %v", i, hash, err) t.Fatalf("commit %d (%v) should have been verified but wasn't: %v", i, hash, err)
} }
} }

@ -24,6 +24,9 @@ const (
var ( var (
// ConfigPath defines the expected path to the Repo's configuration file. // ConfigPath defines the expected path to the Repo's configuration file.
ConfigPath = filepath.Join(DehubDir, "config.yml") ConfigPath = filepath.Join(DehubDir, "config.yml")
// Trunk defines the reference name of the trunk branch.
Trunk = plumbing.ReferenceName("refs/heads/trunk")
) )
type repoOpts struct { type repoOpts struct {

@ -9,9 +9,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
@ -102,17 +100,16 @@ func (h *harness) stage(tree map[string]string) {
} }
} }
func (h *harness) commit(msg string) plumbing.Hash { func (h *harness) trunkCommit(msg, accountID string, sig sigcred.SignifierInterface) (TrunkCommit, plumbing.Hash) {
w, err := h.repo.GitRepo.Worktree() tc, err := h.repo.NewTrunkCommit(msg, accountID, sig)
if err != nil { if err != nil {
h.t.Fatal(err) h.t.Fatalf("failed to make TrunkCommit: %v", err)
} }
hash, err := w.Commit(msg, &git.CommitOptions{
Author: &object.Signature{Name: "god"}, hash, err := h.repo.Commit(tc, accountID)
})
if err != nil { if err != nil {
h.t.Fatal(err) h.t.Fatalf("failed to commit TrunkCommit: %v", err)
} }
return hash return tc, hash
} }

@ -3,8 +3,8 @@ package sigcred
import "dehub/typeobj" import "dehub/typeobj"
// Credential represents a credential which has been attached to a commit which // Credential represents a credential which has been attached to a commit which
// hopefully will allow it to be included in the master branch. Exactly one // hopefully will allow it to be included in the trunk. Exactly one field tagged
// field tagged with "type" should be set. // with "type" should be set.
type Credential struct { type Credential struct {
PGPSignature *CredentialPGPSignature `type:"pgp_signature"` PGPSignature *CredentialPGPSignature `type:"pgp_signature"`

Loading…
Cancel
Save