Have the dehub command check if there are any staged changes before committing

message: |-
  Have the dehub command check if there are any staged changes before committing

  The check happens before msg is filled by EDITOR, to save frustration for the
  user. I'm not super convinced the logic here is correct, as the Status returned
  by worktree is somewhat complex. But it's the best I can do at the moment, and
  the tests pass, so it's gonna get shipped.
change_hash: AIqqhJwt4URaUOxePbgXWOdLwrG6dtuh+CL9T4CFWQ3M
credentials:
- type: pgp_signature
  pub_key_id: 95C46FA6A41148AC
  body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl5Qd7kACgkQlcRvpqQRSKyeKw//WAQEn99jYyfFSVQeozuczha3wgnIMU59Pa+NIz2hz6BCF9O2L8iuHn+4zBr5GCywTmf2gRfLkl5ZC0yPVy1JgXobtnWFmLxkUyZV9JZiSHVeJmTsA3kO2VUtR9W4HrFBRUk+tUF3VhY4rbVslRACPmF3iEgmhqQ+H3yuogvfUewu7UIcczEP8+lorTqfV/8IC2yRCU2/wiBwbTDiKBF1M95Yms3K63ZOuCRKnkreB0o2KAHCGJ7QSHp2GwzeqXrB4dTYEOJmy0m1a1cWEd5703kqJ/dVdLGfOkn4MBrj22UOnFW7Y/i6NtNsWN1ILDncieykgIgec9sXxA2NILVGMnasmj6qW2wovukxz8xJzfS6dpke/wRu5J5qHfVx9bHJVIFOySNe25qCfm+lchCmsCRiRGg++J+bw/Ubsy8Tlq8SjTlQVm5ACqQCd4C0RsuR5DwzXHIDMnXsgwVWa19pQ4KM5EhMnn0WU+qRJpg3qLYWDMjj0pMuPxxSkXCc3YSf6nLeplCotXDnM8maoukJMvYqr4zEQ5SHrSkLaDNXdBVifuMEiGow1DDXJw+iYZKXNT/LNWCrafzI9IdI1suQgJUqwiJPMBKLzcgi/b5PKNXpBtiADCTvJelQQEOsVqCjsgO4bdemnecztdb9DezJfMEibhd8RoPcXj9W+X7OYZU=
  account: mediocregopher
This commit is contained in:
mediocregopher 2020-02-21 17:37:19 -07:00
parent 98d8aed08a
commit 2add3a2501
3 changed files with 61 additions and 1 deletions

View File

@ -102,10 +102,19 @@ var subCmds = []subCmd{
name: "commit",
descr: "commits staged changes to the head of the current branch",
body: func(sctx subCmdCtx) error {
msg := sctx.flag.String("msg", "", "Commit message to use")
msg := sctx.flag.String("msg", "", "Commit message")
accountID := sctx.flag.String("account-id", "", "Account to sign commit as")
sctx.flagParse()
// Don't bother checking any of the parameters, especially commit
// message, if there's no staged changes,
hasStaged, err := sctx.repo().HasStagedChanges()
if err != nil {
return fmt.Errorf("error determining if any changes have been staged: %w", err)
} else if !hasStaged {
return errors.New("no changes have been staged for commit")
}
if *accountID == "" {
flag.PrintDefaults()
return errors.New("-account-id is required")

View File

@ -93,6 +93,29 @@ func (r *Repo) Commit(m encoding.TextMarshaler, accountID string) (plumbing.Hash
})
}
// HasStagedChanges returns true if there are file changes which have been
// staged (e.g. via "git add").
func (r *Repo) HasStagedChanges() (bool, error) {
w, err := r.GitRepo.Worktree()
if err != nil {
return false, fmt.Errorf("error retrieving worktree: %w", err)
}
status, err := w.Status()
if err != nil {
return false, fmt.Errorf("error retrieving worktree status: %w", err)
}
var any bool
for _, fileStatus := range status {
if fileStatus.Staging != git.Unmodified {
any = true
break
}
}
return any, nil
}
// NewChangeCommit constructs a ChangeCommit using the given SignifierInterface
// to create a Credential for it.
func (r *Repo) NewChangeCommit(msg, accountID string, sig sigcred.SignifierInterface) (ChangeCommit, error) {

View File

@ -7,6 +7,7 @@ import (
"io"
"math/rand"
"path/filepath"
"runtime/debug"
"testing"
"gopkg.in/src-d/go-git.v4/plumbing"
@ -113,3 +114,30 @@ func (h *harness) changeCommit(msg, accountID string, sig sigcred.SignifierInter
return tc, hash
}
func TestHasStagedChanges(t *testing.T) {
harness := newHarness(t)
assertHasStaged := func(expHasStaged bool) {
hasStaged, err := harness.repo.HasStagedChanges()
if err != nil {
debug.PrintStack()
t.Fatalf("error calling HasStagedChanges: %v", err)
} else if hasStaged != expHasStaged {
debug.PrintStack()
t.Fatalf("expected HasStagedChanges to return %v", expHasStaged)
}
}
// the harness starts with some staged changes
assertHasStaged(true)
harness.stage(map[string]string{"foo": "bar"})
assertHasStaged(true)
harness.changeCommit("first commit", "root", harness.sig)
assertHasStaged(false)
harness.stage(map[string]string{"foo": ""}) // delete foo
assertHasStaged(true)
harness.changeCommit("second commit", "root", harness.sig)
assertHasStaged(false)
}