|
|
|
@ -10,6 +10,7 @@ import ( |
|
|
|
|
"encoding/base64" |
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"sort" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"gopkg.in/src-d/go-git.v4" |
|
|
|
@ -22,7 +23,9 @@ import ( |
|
|
|
|
// different commit types.
|
|
|
|
|
type CommitInterface interface { |
|
|
|
|
// MessageHead returns the head of the commit message (i.e. the first line).
|
|
|
|
|
MessageHead() (string, error) |
|
|
|
|
// The CommitCommon of the outer Commit is passed in for added context, if
|
|
|
|
|
// necessary.
|
|
|
|
|
MessageHead(CommitCommon) (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
|
|
|
|
@ -36,15 +39,33 @@ type CommitInterface interface { |
|
|
|
|
GetHash() []byte |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// CommitCommon describes the fields common to all Commit objects.
|
|
|
|
|
type CommitCommon struct { |
|
|
|
|
// 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"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (cc CommitCommon) credAccountIDs() []string { |
|
|
|
|
m := map[string]struct{}{} |
|
|
|
|
for _, cred := range cc.Credentials { |
|
|
|
|
m[cred.AccountID] = struct{}{} |
|
|
|
|
} |
|
|
|
|
s := make([]string, 0, len(m)) |
|
|
|
|
for accountID := range m { |
|
|
|
|
s = append(s, accountID) |
|
|
|
|
} |
|
|
|
|
sort.Strings(s) |
|
|
|
|
return s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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"` |
|
|
|
|
Credential *CommitCredential `type:"credential"` |
|
|
|
|
|
|
|
|
|
// 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"` |
|
|
|
|
Common CommitCommon `yaml:",inline"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// MarshalYAML implements the yaml.Marshaler interface.
|
|
|
|
@ -84,7 +105,7 @@ func (c Commit) MarshalText() ([]byte, error) { |
|
|
|
|
return nil, fmt.Errorf("could not cast Commit %+v to interface : %w", c, err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
msgHead, err := commitInt.MessageHead() |
|
|
|
|
msgHead, err := commitInt.MessageHead(c.Common) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("error constructing message head: %w", err) |
|
|
|
|
} |
|
|
|
@ -133,7 +154,7 @@ func (r *Repo) AccreditCommit(commit Commit, sigInt sigcred.SignifierInterface) |
|
|
|
|
if err != nil { |
|
|
|
|
return commit, fmt.Errorf("could not accredit change commit: %w", err) |
|
|
|
|
} |
|
|
|
|
commit.Credentials = append(commit.Credentials, cred) |
|
|
|
|
commit.Common.Credentials = append(commit.Common.Credentials, cred) |
|
|
|
|
return commit, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -241,7 +262,7 @@ func (r *Repo) assertAccessControls( |
|
|
|
|
return accessctl.AssertCanCommit(acl, accessctl.CommitRequest{ |
|
|
|
|
Type: commitType, |
|
|
|
|
Branch: branch.Short(), |
|
|
|
|
Credentials: commit.Credentials, |
|
|
|
|
Credentials: commit.Common.Credentials, |
|
|
|
|
FilesChanged: pathsChanged, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
@ -318,7 +339,7 @@ func (r *Repo) verifyCommit(branch plumbing.ReferenceName, gitCommit GitCommit, |
|
|
|
|
base64.StdEncoding.EncodeToString(changeHash)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, cred := range gitCommit.Commit.Credentials { |
|
|
|
|
for _, cred := range gitCommit.Commit.Common.Credentials { |
|
|
|
|
sig, err := r.signifierForCredential(sigFS, cred) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("finding signifier for credential %+v: %w", cred, err) |
|
|
|
|