package main import ( "bufio" "bytes" "errors" "fmt" "io" "io/ioutil" "os" "os/exec" "strings" ) const defaultCommitFileMsgTpl = `%s # Please enter the description for your commit(s). Lines starting with '#' will # be ignored, and an empty message aborts the commit.` func tmpFileMsg(tpl string, args ...interface{}) (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("", "dehub.*.txt") if err != nil { return "", fmt.Errorf("could not open temp file: %w", err) } tmpfName := tmpf.Name() defer os.Remove(tmpfName) tmpBody := bytes.NewBufferString(fmt.Sprintf(tpl, args...)) _, 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 }