Add support for using EDITOR to construct commit messages.

message: |-
  Add support for using EDITOR to construct commit messages.

  I feel like I can breathe again! The code is more functional than aesthetic, but
  it works damnit!
change_hash: AP+JESJn2+CP1FCDvwJqaXUM354rpoK5oU6Me4uByxaf
credentials:
- type: pgp_signature
  pub_key_id: 95C46FA6A41148AC
  body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl5QaUwACgkQlcRvpqQRSKxY4g/9E6D6CdR3h9JuCHVhVQTeU5NzEPoJTQdGZgOTr8t9lEAceNfzBlxVExKf3KFRDQhDjXOu/tbqgsCAu6n6xdSGc+7nnFRhA+nYrg6c9PMenjbH43eB8s+MxrrXoWYWEKr1inlHEBMoV6GQQpXMuSCPDJ/HwfWqzjG7bHM9Fi1nDQwlh5cBY6KxQwKWWBrCeG5FDdT9AKKZY6Y7WPC9HEPnk1TdkaJNXsZ65IxycggaLc25qWx6EyjQjHONrzpV3R7b6LJQkxrp5tyA60IauGdeAivKmghLDvBK7ItjA8TGu81PUuvthyBQTRfs+3vrYIAtXUzo/LODRjTJumEPCiJ7zUfbhVNqYDR/EdXC9E8eBSPhK37twzdDvdHAfyXWuH9wAZ0B8oqv7ChwGyHlKkCbMksu8OTAllAdYOUpFpVQfNdTrSY/fUO/oWeTG7cHuTCN7AYphkHDjVgUh3A0b1QDwZnH7j4C6oRvExb7rUfgFw/9EIG1hSMMdb4imbJmjkEVWhchHGF9ipkMPYANswQSuDpbtOEyGf3OK0PlFFeqn3k5RyecmmuQd4pKKE7ASNKZwOd//UVxjz8Aa3NsZoZU3tbQJ8dnE6vit0Iggz7d4jbIxaQCd0gGbHRPtCppU6kTa52Lx+Zg01F+KGvr+/E6jXB/6pGoOqK0XObQtMKGSJ0=
  account: mediocregopher
This commit is contained in:
mediocregopher 2020-02-21 16:35:53 -07:00
parent 3344b8372d
commit 98d8aed08a

View File

@ -2,12 +2,15 @@ package main
import (
"bufio"
"bytes"
"dehub"
"errors"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"strings"
"gopkg.in/src-d/go-git.v4/plumbing"
@ -20,6 +23,63 @@ func exitErr(err error) {
os.Exit(1)
}
func tmpFileMsg() (string, error) {
editor := os.Getenv("EDITOR")
if editor == "" {
return "", errors.New("EDITOR not set, please set it or use -msg in order to create your commit message")
} else if _, err := os.Stat(editor); err != nil {
return "", fmt.Errorf("could not stat EDITOR %q: %w", editor, err)
}
tmpf, err := ioutil.TempFile("", "")
if err != nil {
return "", fmt.Errorf("could not open temp file: %w", err)
}
tmpfName := tmpf.Name()
defer os.Remove(tmpfName)
tmpBody := bytes.NewBufferString(`
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.`)
_, err = io.Copy(tmpf, tmpBody)
tmpf.Close()
if err != nil {
return "", fmt.Errorf("could not write helper message to temp file %q: %w", tmpfName, err)
}
cmd := exec.Command(editor, tmpfName)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("error running '%s %q': %w", editor, tmpfName, err)
}
body, err := ioutil.ReadFile(tmpfName)
if err != nil {
return "", fmt.Errorf("error retrieving message body from %q: %w", tmpfName, err)
}
bodyFiltered := new(bytes.Buffer)
bodyBR := bufio.NewReader(bytes.NewBuffer(body))
for {
line, err := bodyBR.ReadString('\n')
if errors.Is(err, io.EOF) {
break
} else if err != nil {
return "", fmt.Errorf("error reading from buffered body: %w", err)
}
if !strings.HasPrefix(strings.TrimSpace(line), "#") {
bodyFiltered.WriteString(line)
}
}
return strings.TrimSpace(bodyFiltered.String()), nil
}
type subCmdCtx struct {
repo func() *dehub.Repo
flag *flag.FlagSet
@ -46,9 +106,19 @@ var subCmds = []subCmd{
accountID := sctx.flag.String("account-id", "", "Account to sign commit as")
sctx.flagParse()
if *msg == "" || *accountID == "" {
if *accountID == "" {
flag.PrintDefaults()
return errors.New("-msg and -account-id are both required")
return errors.New("-account-id is required")
}
if *msg == "" {
var err error
if *msg, err = tmpFileMsg(); err != nil {
return fmt.Errorf("error collecting commit message from user: %w", err)
} else if *msg == "" {
return errors.New("empty commit message, not doing anything")
}
}
cfg, err := sctx.repo().LoadConfig()