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
This commit is contained in:
parent
181802ba0e
commit
a5bee27892
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
dehub
|
||||
/dehub
|
||||
|
20
SPEC.md
20
SPEC.md
@ -65,23 +65,23 @@ access_controls:
|
||||
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:
|
||||
|
||||
* 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 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
|
||||
simplifies implementation).
|
||||
|
||||
* 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)
|
||||
giving a short description of the change, then two newlines, then a body which
|
||||
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:
|
||||
|
||||
```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.
|
||||
type: pgp_signature
|
||||
account_id: some_user_id ```
|
||||
@ -184,10 +184,10 @@ new signature commit, if they agree with the new changes.
|
||||
|
||||
## Merging MRs
|
||||
|
||||
When an MR has accumulated enough meta commits to fulfuill access control
|
||||
requirements it may be coalesced into a single commit destined for the master
|
||||
branch. See the Master Commit Message sub-section for details on how commits in
|
||||
the master branch must be formatted.
|
||||
When an MR has accumulated enough meta commits to fulfill access control
|
||||
requirements it may be coalesced into a single commit destined for the `trunk`
|
||||
branch. See the Trunk Commit Message sub-section for details on how commit
|
||||
messages in the `trunk` branch must be formatted.
|
||||
|
||||
# TODO
|
||||
|
||||
|
@ -76,10 +76,16 @@ var subCmds = []subCmd{
|
||||
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 {
|
||||
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)
|
||||
return nil
|
||||
},
|
||||
@ -96,7 +102,7 @@ var subCmds = []subCmd{
|
||||
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)
|
||||
}
|
||||
|
||||
@ -130,8 +136,8 @@ var subCmds = []subCmd{
|
||||
return fmt.Errorf("malformed pre-receive hook stdin line %q", line)
|
||||
}
|
||||
|
||||
if plumbing.ReferenceName(lineParts[2]) != plumbing.Master {
|
||||
return fmt.Errorf("only commits to the master branch are allowed at the moment (tried to push to %q)", lineParts[2])
|
||||
if plumbing.ReferenceName(lineParts[2]) != dehub.Trunk {
|
||||
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
|
||||
@ -183,9 +189,9 @@ var subCmds = []subCmd{
|
||||
|
||||
for i := len(hashesToCheck) - 1; i >= 0; i-- {
|
||||
hash := hashesToCheck[i]
|
||||
fmt.Printf("Verifying master commit %q\n", hash)
|
||||
if err := sctx.repo().VerifyMasterCommit(hash); err != nil {
|
||||
return fmt.Errorf("could not verify master commit %q", hash)
|
||||
fmt.Printf("Verifying trunk commit %q\n", hash)
|
||||
if err := sctx.repo().VerifyTrunkCommit(hash); err != nil {
|
||||
return fmt.Errorf("could not verify trunk commit %q", hash)
|
||||
}
|
||||
}
|
||||
fmt.Println("All pushed commits have been verified, well done.")
|
||||
|
1
cmd/http-server/.gitignore
vendored
Normal file
1
cmd/http-server/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dehub
|
128
commit.go
128
commit.go
@ -6,6 +6,7 @@ import (
|
||||
"dehub/fs"
|
||||
"dehub/sigcred"
|
||||
"dehub/yamlutil"
|
||||
"encoding"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -18,16 +19,16 @@ import (
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// MasterCommit describes the structure of the object encoded into the git
|
||||
// message of a commit in the master branch.
|
||||
type MasterCommit struct {
|
||||
// TrunkCommit describes the structure of the object encoded into the git
|
||||
// message of a commit in the repo trunk.
|
||||
type TrunkCommit struct {
|
||||
Message string `yaml:"message"`
|
||||
ChangeHash yamlutil.Blob `yaml:"change_hash"`
|
||||
Credentials []sigcred.Credential `yaml:"credentials"`
|
||||
}
|
||||
|
||||
type mcYAML struct {
|
||||
Val MasterCommit `yaml:",inline"`
|
||||
type tcYAML struct {
|
||||
Val TrunkCommit `yaml:",inline"`
|
||||
}
|
||||
|
||||
func msgHead(msg string) string {
|
||||
@ -39,55 +40,73 @@ func msgHead(msg string) string {
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface by returning the
|
||||
// form the MasterCommit object takes in the git commit message.
|
||||
func (mc MasterCommit) MarshalText() ([]byte, error) {
|
||||
masterCommitEncoded, err := yaml.Marshal(mcYAML{mc})
|
||||
// form the TrunkCommit object takes in the git commit message.
|
||||
func (tc TrunkCommit) MarshalText() ([]byte, error) {
|
||||
trunkCommitEncoded, err := yaml.Marshal(tcYAML{tc})
|
||||
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
|
||||
}
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface by decoding a
|
||||
// MasterCommit object which has been encoded into a git commit message.
|
||||
func (mc *MasterCommit) UnmarshalText(msg []byte) error {
|
||||
// TrunkCommit object which has been encoded into a git commit message.
|
||||
func (tc *TrunkCommit) UnmarshalText(msg []byte) error {
|
||||
i := bytes.Index(msg, []byte("\n"))
|
||||
if i < 0 {
|
||||
return fmt.Errorf("commit message %q is malformed", msg)
|
||||
}
|
||||
msgHead, msg := msg[:i], msg[i:]
|
||||
|
||||
var mcy mcYAML
|
||||
if err := yaml.Unmarshal(msg, &mcy); err != nil {
|
||||
return fmt.Errorf("could not unmarshal MasterCommit message: %w", err)
|
||||
var tcy tcYAML
|
||||
if err := yaml.Unmarshal(msg, &tcy); err != nil {
|
||||
return fmt.Errorf("could not unmarshal TrunkCommit message: %w", err)
|
||||
}
|
||||
|
||||
*mc = mcy.Val
|
||||
if !strings.HasPrefix(mc.Message, string(msgHead)) {
|
||||
return errors.New("encoded MasterCommit is malformed, it might not be an encoded MasterCommit")
|
||||
*tc = tcy.Val
|
||||
if !strings.HasPrefix(tc.Message, string(msgHead)) {
|
||||
return errors.New("encoded TrunkCommit is malformed, it might not be an encoded TrunkCommit")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommitMaster constructs a MasterCommit using the given SignifierInterface to
|
||||
// create a Credential for it. It returns the commit's hash after having set it
|
||||
// to HEAD.
|
||||
//
|
||||
// TODO this method is a prototype and does not reflect the method's final form.
|
||||
func (r *Repo) CommitMaster(msg, accountID string, sig sigcred.SignifierInterface) (MasterCommit, plumbing.Hash, error) {
|
||||
// Commit uses the given TextMarshaler to create a git commit object (with the
|
||||
// specified accountID as the author) and commits it to the current HEAD,
|
||||
// returning the hash of the commit.
|
||||
func (r *Repo) Commit(m encoding.TextMarshaler, accountID string) (plumbing.Hash, error) {
|
||||
msgB, err := m.MarshalText()
|
||||
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()
|
||||
if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
||||
headTree = &object.Tree{}
|
||||
} else if err != nil {
|
||||
return MasterCommit{}, plumbing.ZeroHash, err
|
||||
return TrunkCommit{}, err
|
||||
}
|
||||
|
||||
_, stagedTree, err := fs.FromStagedChangesTree(r.GitRepo)
|
||||
if err != nil {
|
||||
return MasterCommit{}, plumbing.ZeroHash, err
|
||||
return TrunkCommit{}, err
|
||||
}
|
||||
|
||||
// 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).
|
||||
sigFS, err := r.headOrRawFS()
|
||||
if err != nil {
|
||||
return MasterCommit{}, plumbing.ZeroHash, err
|
||||
return TrunkCommit{}, err
|
||||
}
|
||||
|
||||
cfg, err := r.loadConfig(sigFS)
|
||||
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)
|
||||
cred, err := sig.Sign(sigFS, changeHash)
|
||||
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
|
||||
|
||||
@ -120,37 +139,14 @@ func (r *Repo) CommitMaster(msg, accountID string, sig sigcred.SignifierInterfac
|
||||
headTree, stagedTree,
|
||||
)
|
||||
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,
|
||||
ChangeHash: changeHash,
|
||||
Credentials: []sigcred.Credential{cred},
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repo) assertAccessControls(
|
||||
@ -185,9 +181,9 @@ func (r *Repo) assertAccessControls(
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyMasterCommit verifies that the commit at the given hash, which is
|
||||
// presumably on the master branch, is gucci.
|
||||
func (r *Repo) VerifyMasterCommit(h plumbing.Hash) error {
|
||||
// VerifyTrunkCommit verifies that the commit at the given hash, which is
|
||||
// presumably on the repo trunk, is gucci.
|
||||
func (r *Repo) VerifyTrunkCommit(h plumbing.Hash) error {
|
||||
commit, err := r.GitRepo.CommitObject(h)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
var masterCommit MasterCommit
|
||||
if err := masterCommit.UnmarshalText([]byte(commit.Message)); err != nil {
|
||||
var trunkCommit TrunkCommit
|
||||
if err := trunkCommit.UnmarshalText([]byte(commit.Message)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -222,21 +218,21 @@ func (r *Repo) VerifyMasterCommit(h plumbing.Hash) error {
|
||||
}
|
||||
|
||||
err = r.assertAccessControls(
|
||||
cfg.AccessControls, masterCommit.Credentials,
|
||||
cfg.AccessControls, trunkCommit.Credentials,
|
||||
parentTree, commitTree,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to satisfy all access controls: %w", err)
|
||||
}
|
||||
|
||||
expectedChangeHash := genChangeHash(nil, masterCommit.Message, parentTree, commitTree)
|
||||
if !bytes.Equal(masterCommit.ChangeHash, expectedChangeHash) {
|
||||
expectedChangeHash := genChangeHash(nil, trunkCommit.Message, parentTree, commitTree)
|
||||
if !bytes.Equal(trunkCommit.ChangeHash, expectedChangeHash) {
|
||||
return fmt.Errorf("malformed change_hash in commit body, is %s but should be %s",
|
||||
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)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestMasterCommitVerify(t *testing.T) {
|
||||
func TestTrunkCommitVerify(t *testing.T) {
|
||||
type step struct {
|
||||
msg string
|
||||
msgHead string // defaults to msg
|
||||
@ -81,10 +81,8 @@ func TestMasterCommitVerify(t *testing.T) {
|
||||
h.stage(step.tree)
|
||||
account := h.cfg.Accounts[0]
|
||||
|
||||
masterCommit, hash, err := h.repo.CommitMaster(step.msg, account.ID, h.sig)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to make MasterCommit: %v", err)
|
||||
} else if err := h.repo.VerifyMasterCommit(hash); err != nil {
|
||||
trunkCommit, hash := h.trunkCommit(step.msg, account.ID, h.sig)
|
||||
if err := h.repo.VerifyTrunkCommit(hash); err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
var actualMasterCommit MasterCommit
|
||||
if err := actualMasterCommit.UnmarshalText([]byte(commit.Message)); err != nil {
|
||||
var actualTrunkCommit TrunkCommit
|
||||
if err := actualTrunkCommit.UnmarshalText([]byte(commit.Message)); err != nil {
|
||||
t.Fatalf("error unmarshaling commit body: %v", err)
|
||||
} else if !reflect.DeepEqual(actualMasterCommit, masterCommit) {
|
||||
t.Fatalf("returned master commit:\n%s\ndoes not match actual one:\n%s",
|
||||
spew.Sdump(masterCommit), spew.Sdump(actualMasterCommit))
|
||||
} else if !reflect.DeepEqual(actualTrunkCommit, trunkCommit) {
|
||||
t.Fatalf("returned trunk commit:\n%s\ndoes not match actual one:\n%s",
|
||||
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
|
||||
// public key
|
||||
_, hash, err := h.repo.CommitMaster("commit configuration", h.cfg.Accounts[0].ID, h.sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, hash := h.trunkCommit("commit configuration", h.cfg.Accounts[0].ID, h.sig)
|
||||
hashes = append(hashes, hash)
|
||||
|
||||
// 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)})
|
||||
|
||||
_, _, 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) {
|
||||
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.
|
||||
_, hash, err = h.repo.CommitMaster("add toot user", h.cfg.Accounts[0].ID, h.sig)
|
||||
if err != nil {
|
||||
t.Fatalf("got an unexpected error committing with root: %v", err)
|
||||
}
|
||||
_, hash = h.trunkCommit("add toot user", h.cfg.Accounts[0].ID, h.sig)
|
||||
hashes = append(hashes, hash)
|
||||
|
||||
// _now_ the toot user should be able to do things.
|
||||
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)
|
||||
if err != nil {
|
||||
t.Fatalf("got an unexpected error committing with toot: %v", err)
|
||||
}
|
||||
_, hash = h.trunkCommit("add a cool file", h.cfg.Accounts[1].ID, newSig)
|
||||
hashes = append(hashes, hash)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
3
repo.go
3
repo.go
@ -24,6 +24,9 @@ const (
|
||||
var (
|
||||
// ConfigPath defines the expected path to the Repo's configuration file.
|
||||
ConfigPath = filepath.Join(DehubDir, "config.yml")
|
||||
|
||||
// Trunk defines the reference name of the trunk branch.
|
||||
Trunk = plumbing.ReferenceName("refs/heads/trunk")
|
||||
)
|
||||
|
||||
type repoOpts struct {
|
||||
|
21
repo_test.go
21
repo_test.go
@ -9,9 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/object"
|
||||
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 {
|
||||
w, err := h.repo.GitRepo.Worktree()
|
||||
func (h *harness) trunkCommit(msg, accountID string, sig sigcred.SignifierInterface) (TrunkCommit, plumbing.Hash) {
|
||||
tc, err := h.repo.NewTrunkCommit(msg, accountID, sig)
|
||||
if err != nil {
|
||||
h.t.Fatal(err)
|
||||
}
|
||||
hash, err := w.Commit(msg, &git.CommitOptions{
|
||||
Author: &object.Signature{Name: "god"},
|
||||
})
|
||||
if err != nil {
|
||||
h.t.Fatal(err)
|
||||
h.t.Fatalf("failed to make TrunkCommit: %v", err)
|
||||
}
|
||||
|
||||
return hash
|
||||
hash, err := h.repo.Commit(tc, accountID)
|
||||
if err != nil {
|
||||
h.t.Fatalf("failed to commit TrunkCommit: %v", err)
|
||||
}
|
||||
|
||||
return tc, hash
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package sigcred
|
||||
import "dehub/typeobj"
|
||||
|
||||
// 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
|
||||
// field tagged with "type" should be set.
|
||||
// hopefully will allow it to be included in the trunk. Exactly one field tagged
|
||||
// with "type" should be set.
|
||||
type Credential struct {
|
||||
PGPSignature *CredentialPGPSignature `type:"pgp_signature"`
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user