add ability to credential range of change commits
--- type: change message: |- add ability to credential range of change commits previously it wasn't possible to generate a credential for the changes of a range of commits, which was not super helpful. Now it is! change_hash: AG8eGxGH30bZYieD7uYtiUtpQL7u357SKPE0rvbk8LpR credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl55QyAACgkQlcRvpqQRSKxU6g/+Lu4zVh8dz7ziZCYyOEwn7jrQ+L0UXMUmaHx6sL6eOd6P3m583etkl3EQbSCoTUvEGTcuxKm1bSb1hcd6NNjRaol6IpTaQtm71NQTbfUo7jZi8aq3P9o+tXr2UPqcht1nxcAXQEoOoK7MO2mVj6weWRQ40gFo5xwI/eO8KygZc3uXKSlWswvgs9jTDx9zyTDCMI9JX9S6Ino24K1RIRuZIAfOhUIRLq3vi8JmymhpjMAeyOj/gvBNfwkbUL0zGrikPr4VJbHtZDHsDZUnOB0kM7xZngq1jUe2yuiF+m2XG9eIXIGmP1hY1QTS+JllffZKtK781IsPs3Ncc2szwhqwEMpqYFLvNu6YFOvMaI6+gki/aqM3dzK74kopWBMnqgI18Z2mcgm0EwENnKVWyanMZ8UdfSHqORf+t6pO/fNkt7a0Dra9S/izmJEaalswj3EZmtJ4Z/qi9GW1ab7SUnccZyLTK22YoymgQ4VauYoa0WjmIDKpdnmU0/R7OMJtUJYoMy8aTGnVeNlu7IcaPh7yfGCGvA07h8l6wow0HsFiNoTCO7HW4O0HKLEtu+mcNnQsH2qFTSLcl3EJh7qhiMSCROHC78UIndgNweTKSxQcNynxfBmcZfJyW451RsuTHfwgoTWB2m8ZKVl24QM8tsOa68gSrOYk4IO43AL7I7w7Gas= account: mediocregopher
This commit is contained in:
parent
f3226d6171
commit
aa1a4969f3
@ -102,23 +102,38 @@ func cmdCommit(ctx context.Context, cmd *dcmd.Cmd) {
|
|||||||
cmd.SubCmd("credential", "Commit credential of a different commit",
|
cmd.SubCmd("credential", "Commit credential of a different commit",
|
||||||
func(ctx context.Context, cmd *dcmd.Cmd) {
|
func(ctx context.Context, cmd *dcmd.Cmd) {
|
||||||
flag := cmd.FlagSet()
|
flag := cmd.FlagSet()
|
||||||
rev := flag.String("rev", "", "Revision of commit to accredit")
|
startRev := flag.String("start", "", "Revision of the starting commit to accredit (when accrediting a range of changes)")
|
||||||
|
endRev := flag.String("end", "HEAD", "Revision of the ending commit to accredit (when accrediting a range of changes)")
|
||||||
|
rev := flag.String("rev", "", "Revision of commit to accredit (when accrediting a single commit)")
|
||||||
cmd.Run(func() (context.Context, error) {
|
cmd.Run(func() (context.Context, error) {
|
||||||
if *rev == "" {
|
if *rev == "" && *startRev == "" {
|
||||||
return nil, errors.New("-rev is required")
|
return nil, errors.New("-rev or -start is required")
|
||||||
} else if hasStaged {
|
} else if hasStaged {
|
||||||
return nil, errors.New("credential commit cannot have any files changed")
|
return nil, errors.New("credential commit cannot have any files changed")
|
||||||
}
|
}
|
||||||
|
|
||||||
gitCommit, err := repo.GetGitRevision(plumbing.Revision(*rev))
|
var credCommit dehub.Commit
|
||||||
if err != nil {
|
if *rev != "" {
|
||||||
return nil, fmt.Errorf("resolving revision %q: %w", *rev, err)
|
gitCommit, err := repo.GetGitRevision(plumbing.Revision(*rev))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("resolving revision %q: %w", *rev, err)
|
||||||
|
} else if credCommit, err = repo.NewCommitCredential(gitCommit.Interface.GetHash()); err != nil {
|
||||||
|
return nil, fmt.Errorf("constructing credential commit: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gitCommits, err := repo.GetGitRevisionRange(
|
||||||
|
plumbing.Revision(*startRev),
|
||||||
|
plumbing.Revision(*endRev),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("resolving revisions %q to %q: %w",
|
||||||
|
*startRev, *endRev, err)
|
||||||
|
} else if credCommit, err = repo.NewCommitCredentialFromChanges(gitCommits); err != nil {
|
||||||
|
return nil, fmt.Errorf("constructing credential commit: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
credCommit, err := repo.NewCommitCredential(gitCommit.Interface.GetHash())
|
if err := accreditAndCommit(credCommit); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("constructing credential commit: %w", err)
|
|
||||||
} else if err := accreditAndCommit(credCommit); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
43
commit.go
43
commit.go
@ -439,3 +439,46 @@ func (r *Repo) verifyCommit(branch plumbing.ReferenceName, gitCommit GitCommit,
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type changeRangeInfo struct {
|
||||||
|
lastChangeCommit GitCommit
|
||||||
|
authors map[string]struct{}
|
||||||
|
msg string
|
||||||
|
startTree, endTree *object.Tree
|
||||||
|
changeHash []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// changeRangeInfo returns various pieces of information about a range of
|
||||||
|
// commits' changes.
|
||||||
|
func (r *Repo) changeRangeInfo(commits []GitCommit) (changeRangeInfo, error) {
|
||||||
|
info := changeRangeInfo{
|
||||||
|
authors: map[string]struct{}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastChangeCommitOk bool
|
||||||
|
for _, commit := range commits {
|
||||||
|
if _, ok := commit.Interface.(*CommitChange); ok {
|
||||||
|
info.lastChangeCommit = commit
|
||||||
|
lastChangeCommitOk = true
|
||||||
|
for _, cred := range commit.Commit.Common.Credentials {
|
||||||
|
info.authors[cred.AccountID] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !lastChangeCommitOk {
|
||||||
|
return changeRangeInfo{}, errors.New("no change commits found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// startTree has to be the tree of the parent of the first commit, which
|
||||||
|
// isn't included in commits. Determine it the hard way.
|
||||||
|
var err error
|
||||||
|
if info.startTree, err = r.parentTree(commits[0].GitCommit); err != nil {
|
||||||
|
return changeRangeInfo{}, fmt.Errorf("getting tree of parent of %q: %w",
|
||||||
|
commits[0].GitCommit.Hash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info.msg = info.lastChangeCommit.Commit.Change.Message
|
||||||
|
info.endTree = info.lastChangeCommit.GitTree
|
||||||
|
info.changeHash = genChangeHash(nil, info.msg, info.startTree, info.endTree)
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
@ -74,40 +74,17 @@ func (cc CommitChange) GetHash() []byte {
|
|||||||
// start/end will be different than the one which needs to be accredited in
|
// start/end will be different than the one which needs to be accredited in
|
||||||
// onto/end.
|
// onto/end.
|
||||||
func (r *Repo) CombineCommitChanges(commits []GitCommit, onto plumbing.ReferenceName) (GitCommit, error) {
|
func (r *Repo) CombineCommitChanges(commits []GitCommit, onto plumbing.ReferenceName) (GitCommit, error) {
|
||||||
authorsSet := map[string]struct{}{}
|
info, err := r.changeRangeInfo(commits)
|
||||||
var lastChangeCommit GitCommit
|
if err != nil {
|
||||||
var lastChangeCommitOk bool
|
return GitCommit{}, err
|
||||||
for _, commit := range commits {
|
|
||||||
if _, ok := commit.Interface.(*CommitChange); ok {
|
|
||||||
lastChangeCommit = commit
|
|
||||||
lastChangeCommitOk = true
|
|
||||||
for _, cred := range commit.Commit.Common.Credentials {
|
|
||||||
authorsSet[cred.AccountID] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !lastChangeCommitOk {
|
|
||||||
return GitCommit{}, errors.New("no change commits in range")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authors := make([]string, 0, len(authorsSet))
|
authors := make([]string, 0, len(info.authors))
|
||||||
for author := range authorsSet {
|
for author := range info.authors {
|
||||||
authors = append(authors, author)
|
authors = append(authors, author)
|
||||||
}
|
}
|
||||||
sort.Strings(authors)
|
sort.Strings(authors)
|
||||||
|
|
||||||
// startTree has to be the tree of startRev, which isn't included in
|
|
||||||
// commits. Determine it the hard way.
|
|
||||||
startTree, err := r.parentTree(commits[0].GitCommit)
|
|
||||||
if err != nil {
|
|
||||||
return GitCommit{}, fmt.Errorf("getting tree of parent of %q: %w",
|
|
||||||
commits[0].GitCommit.Hash, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := lastChangeCommit.Commit.Change.Message
|
|
||||||
endTree := lastChangeCommit.GitTree
|
|
||||||
changeHash := genChangeHash(nil, msg, startTree, endTree)
|
|
||||||
|
|
||||||
ontoBranchName, err := r.ReferenceToBranchName(onto)
|
ontoBranchName, err := r.ReferenceToBranchName(onto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitCommit{}, fmt.Errorf("resolving %q into a branch name: %w", onto, err)
|
return GitCommit{}, fmt.Errorf("resolving %q into a branch name: %w", onto, err)
|
||||||
@ -120,8 +97,8 @@ func (r *Repo) CombineCommitChanges(commits []GitCommit, onto plumbing.Reference
|
|||||||
return GitCommit{}, fmt.Errorf("resolving revision %q: %w", onto, err)
|
return GitCommit{}, fmt.Errorf("resolving revision %q: %w", onto, err)
|
||||||
}
|
}
|
||||||
ontoTree := ontoCommit.GitTree
|
ontoTree := ontoCommit.GitTree
|
||||||
ontoEndChangeHash := genChangeHash(nil, msg, ontoTree, endTree)
|
ontoEndChangeHash := genChangeHash(nil, info.msg, ontoTree, info.endTree)
|
||||||
if !bytes.Equal(ontoEndChangeHash, changeHash) {
|
if !bytes.Equal(ontoEndChangeHash, info.changeHash) {
|
||||||
// TODO figure out what files to show as being the "problem files" in
|
// TODO figure out what files to show as being the "problem files" in
|
||||||
// the error message
|
// the error message
|
||||||
return GitCommit{}, fmt.Errorf("rebasing onto %q would cause the change hash to change, aborting combine", onto)
|
return GitCommit{}, fmt.Errorf("rebasing onto %q would cause the change hash to change, aborting combine", onto)
|
||||||
@ -129,7 +106,7 @@ func (r *Repo) CombineCommitChanges(commits []GitCommit, onto plumbing.Reference
|
|||||||
|
|
||||||
var creds []sigcred.Credential
|
var creds []sigcred.Credential
|
||||||
for _, commit := range commits {
|
for _, commit := range commits {
|
||||||
if bytes.Equal(commit.Interface.GetHash(), changeHash) {
|
if bytes.Equal(commit.Interface.GetHash(), info.changeHash) {
|
||||||
creds = append(creds, commit.Commit.Common.Credentials...)
|
creds = append(creds, commit.Commit.Common.Credentials...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,8 +118,8 @@ func (r *Repo) CombineCommitChanges(commits []GitCommit, onto plumbing.Reference
|
|||||||
|
|
||||||
commit := Commit{
|
commit := Commit{
|
||||||
Change: &CommitChange{
|
Change: &CommitChange{
|
||||||
Message: msg,
|
Message: info.msg,
|
||||||
ChangeHash: changeHash,
|
ChangeHash: info.changeHash,
|
||||||
},
|
},
|
||||||
Common: CommitCommon{Credentials: creds},
|
Common: CommitCommon{Credentials: creds},
|
||||||
}
|
}
|
||||||
@ -151,7 +128,7 @@ func (r *Repo) CombineCommitChanges(commits []GitCommit, onto plumbing.Reference
|
|||||||
Commit: commit,
|
Commit: commit,
|
||||||
Author: strings.Join(authors, ","),
|
Author: strings.Join(authors, ","),
|
||||||
ParentHash: ontoCommit.GitCommit.Hash,
|
ParentHash: ontoCommit.GitCommit.Hash,
|
||||||
GitTree: endTree,
|
GitTree: info.endTree,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitCommit{}, fmt.Errorf("storing commit: %w", err)
|
return GitCommit{}, fmt.Errorf("storing commit: %w", err)
|
||||||
|
@ -27,6 +27,18 @@ func (r *Repo) NewCommitCredential(hash []byte) (Commit, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCommitCredentialFromChanges constructs and returns a Comit populated with
|
||||||
|
// a CommitCredential for all changes in the given range of GitCommits. The
|
||||||
|
// message of the last change commit in the range is used when generating the
|
||||||
|
// hash.
|
||||||
|
func (r *Repo) NewCommitCredentialFromChanges(commits []GitCommit) (Commit, error) {
|
||||||
|
info, err := r.changeRangeInfo(commits)
|
||||||
|
if err != nil {
|
||||||
|
return Commit{}, err
|
||||||
|
}
|
||||||
|
return r.NewCommitCredential(info.changeHash)
|
||||||
|
}
|
||||||
|
|
||||||
// MessageHead implements the method for the CommitInterface interface.
|
// MessageHead implements the method for the CommitInterface interface.
|
||||||
func (cc CommitCredential) MessageHead(common CommitCommon) (string, error) {
|
func (cc CommitCredential) MessageHead(common CommitCommon) (string, error) {
|
||||||
hash64 := base64.StdEncoding.EncodeToString(cc.CredentialedHash)
|
hash64 := base64.StdEncoding.EncodeToString(cc.CredentialedHash)
|
||||||
|
Loading…
Reference in New Issue
Block a user