diff --git a/commit.go b/commit.go index f518bde..8b6611f 100644 --- a/commit.go +++ b/commit.go @@ -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) diff --git a/commit_change.go b/commit_change.go index 61628ee..7608184 100644 --- a/commit_change.go +++ b/commit_change.go @@ -45,7 +45,7 @@ func (r *Repo) NewCommitChange(msg string) (Commit, error) { } // MessageHead implements the method for the CommitInterface interface. -func (cc CommitChange) MessageHead() (string, error) { +func (cc CommitChange) MessageHead(CommitCommon) (string, error) { i := strings.Index(cc.Message, "\n") if i > 0 { return cc.Message[:i], nil diff --git a/commit_credential.go b/commit_credential.go index 3d79b07..ea7acb4 100644 --- a/commit_credential.go +++ b/commit_credential.go @@ -4,6 +4,7 @@ import ( "dehub/yamlutil" "encoding/base64" "fmt" + "strings" "gopkg.in/src-d/go-git.v4/plumbing/object" ) @@ -27,12 +28,14 @@ func (r *Repo) NewCommitCredential(hash []byte) (Commit, error) { } // MessageHead implements the method for the CommitInterface interface. -func (cc CommitCredential) MessageHead() (string, error) { +func (cc CommitCredential) MessageHead(common CommitCommon) (string, error) { hash64 := base64.StdEncoding.EncodeToString(cc.CredentialedHash) if len(hash64) > 6 { hash64 = hash64[:6] + "..." } - return fmt.Sprintf("Credential of hash %s", hash64), nil + + credAccounts := strings.Join(common.credAccountIDs(), ", ") + return fmt.Sprintf("Credential of hash %s by %s", hash64, credAccounts), nil } // Hash implements the method for the CommitInterface.