2add3a2501
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
144 lines
3.2 KiB
Go
144 lines
3.2 KiB
Go
package dehub
|
|
|
|
import (
|
|
"bytes"
|
|
"dehub/accessctl"
|
|
"dehub/sigcred"
|
|
"io"
|
|
"math/rand"
|
|
"path/filepath"
|
|
"runtime/debug"
|
|
"testing"
|
|
|
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
|
yaml "gopkg.in/yaml.v2"
|
|
)
|
|
|
|
type harness struct {
|
|
t *testing.T
|
|
rand *rand.Rand
|
|
repo *Repo
|
|
cfg *Config
|
|
sig sigcred.SignifierInterface
|
|
}
|
|
|
|
func newHarness(t *testing.T) *harness {
|
|
rand := rand.New(rand.NewSource(0xb4eadb01))
|
|
sig, pubKeyBody := sigcred.SignifierPGPTmp(rand)
|
|
pubKeyPath := filepath.Join(DehubDir, "root.asc")
|
|
|
|
cfg := &Config{
|
|
Accounts: []Account{{
|
|
ID: "root",
|
|
Signifiers: []sigcred.Signifier{{PGPPublicKeyFile: &sigcred.SignifierPGPFile{
|
|
Path: pubKeyPath,
|
|
}}},
|
|
}},
|
|
AccessControls: []accessctl.AccessControl{
|
|
{
|
|
Pattern: "**",
|
|
Condition: accessctl.Condition{
|
|
Signature: &accessctl.ConditionSignature{
|
|
AccountIDs: []string{"root"},
|
|
Count: "100%",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
cfgBody, err := yaml.Marshal(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
h := &harness{
|
|
t: t,
|
|
rand: rand,
|
|
repo: InitMemRepo(),
|
|
cfg: cfg,
|
|
sig: sig,
|
|
}
|
|
h.stage(map[string]string{
|
|
ConfigPath: string(cfgBody),
|
|
pubKeyPath: string(pubKeyBody),
|
|
})
|
|
|
|
return h
|
|
}
|
|
|
|
func (h *harness) stage(tree map[string]string) {
|
|
w, err := h.repo.GitRepo.Worktree()
|
|
if err != nil {
|
|
h.t.Fatal(err)
|
|
}
|
|
fs := w.Filesystem
|
|
for path, content := range tree {
|
|
if content == "" {
|
|
if _, err := w.Remove(path); err != nil {
|
|
h.t.Fatalf("error removing %q: %v", path, err)
|
|
}
|
|
continue
|
|
}
|
|
|
|
dir := filepath.Dir(path)
|
|
if err := fs.MkdirAll(dir, 0666); err != nil {
|
|
h.t.Fatalf("error making directory %q: %v", dir, err)
|
|
}
|
|
|
|
f, err := fs.Create(path)
|
|
if err != nil {
|
|
h.t.Fatalf("error creating file %q: %v", path, err)
|
|
|
|
} else if _, err := io.Copy(f, bytes.NewBufferString(content)); err != nil {
|
|
h.t.Fatalf("error writing to file %q: %v", path, err)
|
|
|
|
} else if err := f.Close(); err != nil {
|
|
h.t.Fatalf("error closing file %q: %v", path, err)
|
|
|
|
} else if _, err := w.Add(path); err != nil {
|
|
h.t.Fatalf("error adding file %q to index: %v", path, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (h *harness) changeCommit(msg, accountID string, sig sigcred.SignifierInterface) (ChangeCommit, plumbing.Hash) {
|
|
tc, err := h.repo.NewChangeCommit(msg, accountID, sig)
|
|
if err != nil {
|
|
h.t.Fatalf("failed to make ChangeCommit: %v", err)
|
|
}
|
|
|
|
hash, err := h.repo.Commit(tc, accountID)
|
|
if err != nil {
|
|
h.t.Fatalf("failed to commit ChangeCommit: %v", err)
|
|
}
|
|
|
|
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)
|
|
}
|