aboutsummaryrefslogtreecommitdiffstats
path: root/commands/input
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-07-12 12:44:46 +0200
committerMichael Muré <batolettre@gmail.com>2018-07-12 12:44:46 +0200
commitc498674718608a1171a4fcef6f26184df7d5fa7b (patch)
tree9cc53ea07b61d52b12cd5fa3367b25d04bebc150 /commands/input
parentd0443659123f912e9385e27efebe4b7da65aa2f6 (diff)
downloadgit-bug-c498674718608a1171a4fcef6f26184df7d5fa7b.tar.gz
add the new bug command with a very primitive bug datastructure
Diffstat (limited to 'commands/input')
-rw-r--r--commands/input/input.go104
1 files changed, 104 insertions, 0 deletions
diff --git a/commands/input/input.go b/commands/input/input.go
new file mode 100644
index 00000000..531a4386
--- /dev/null
+++ b/commands/input/input.go
@@ -0,0 +1,104 @@
+// Taken from the git-appraise project
+
+package input
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "github.com/MichaelMure/git-bug/repository"
+ "io/ioutil"
+ "os"
+ "os/exec"
+)
+
+// LaunchEditor launches the default editor configured for the given repo. This
+// method blocks until the editor command has returned.
+//
+// The specified filename should be a temporary file and provided as a relative path
+// from the repo (e.g. "FILENAME" will be converted to ".git/FILENAME"). This file
+// will be deleted after the editor is closed and its contents have been read.
+//
+// This method returns the text that was read from the temporary file, or
+// an error if any step in the process failed.
+func LaunchEditor(repo repository.Repo, fileName string) (string, error) {
+ editor, err := repo.GetCoreEditor()
+ if err != nil {
+ return "", fmt.Errorf("Unable to detect default git editor: %v\n", err)
+ }
+
+ path := fmt.Sprintf("%s/.git/%s", repo.GetPath(), fileName)
+
+ cmd, err := startInlineCommand(editor, path)
+ if err != nil {
+ // Running the editor directly did not work. This might mean that
+ // the editor string is not a path to an executable, but rather
+ // a shell command (e.g. "emacsclient --tty"). As such, we'll try
+ // to run the command through bash, and if that fails, try with sh
+ args := []string{"-c", fmt.Sprintf("%s %q", editor, path)}
+ cmd, err = startInlineCommand("bash", args...)
+ if err != nil {
+ cmd, err = startInlineCommand("sh", args...)
+ }
+ }
+ if err != nil {
+ return "", fmt.Errorf("Unable to start editor: %v\n", err)
+ }
+
+ if err := cmd.Wait(); err != nil {
+ return "", fmt.Errorf("Editing finished with error: %v\n", err)
+ }
+
+ output, err := ioutil.ReadFile(path)
+ if err != nil {
+ os.Remove(path)
+ return "", fmt.Errorf("Error reading edited file: %v\n", err)
+ }
+ os.Remove(path)
+ return string(output), err
+}
+
+// FromFile loads and returns the contents of a given file. If - is passed
+// through, much like git, it will read from stdin. This can be piped data,
+// unless there is a tty in which case the user will be prompted to enter a
+// message.
+func FromFile(fileName string) (string, error) {
+ if fileName == "-" {
+ stat, err := os.Stdin.Stat()
+ if err != nil {
+ return "", fmt.Errorf("Error reading from stdin: %v\n", err)
+ }
+ if (stat.Mode() & os.ModeCharDevice) == 0 {
+ // There is no tty. This will allow us to read piped data instead.
+ output, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ return "", fmt.Errorf("Error reading from stdin: %v\n", err)
+ }
+ return string(output), err
+ }
+
+ fmt.Printf("(reading comment from standard input)\n")
+ var output bytes.Buffer
+ s := bufio.NewScanner(os.Stdin)
+ for s.Scan() {
+ output.Write(s.Bytes())
+ output.WriteRune('\n')
+ }
+ return output.String(), nil
+ }
+
+ output, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return "", fmt.Errorf("Error reading file: %v\n", err)
+ }
+ return string(output), err
+}
+
+func startInlineCommand(command string, args ...string) (*exec.Cmd, error) {
+ cmd := exec.Command(command, args...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Start()
+ return cmd, err
+}