+36
git/git.go
+36
git/git.go
···
4
4
"bufio"
5
5
"fmt"
6
6
"net/url"
7
+
"os"
7
8
"os/exec"
9
+
"path"
10
+
"sort"
8
11
"strings"
9
12
)
10
13
···
96
99
}
97
100
98
101
return string(output), nil
102
+
}
103
+
104
+
func FormatPatchToTmp(revRange string) ([]string, error) {
105
+
tmpDir, err := os.MkdirTemp("", "knit-patches-")
106
+
if err != nil {
107
+
return nil, err
108
+
}
109
+
110
+
cmd := exec.Command(
111
+
"git",
112
+
"format-patch",
113
+
"--output-directory",
114
+
tmpDir,
115
+
revRange,
116
+
)
117
+
if err := cmd.Run(); err != nil {
118
+
return nil, err
119
+
}
120
+
121
+
entries, err := os.ReadDir(tmpDir)
122
+
if err != nil {
123
+
return nil, err
124
+
}
125
+
126
+
var paths []string
127
+
for _, entry := range entries {
128
+
if entry.IsDir() {
129
+
continue
130
+
}
131
+
paths = append(paths, path.Join(tmpDir, entry.Name()))
132
+
}
133
+
sort.Strings(paths)
134
+
return paths, nil
99
135
}
100
136
101
137
func RemoteBranches(remote string) ([]string, error) {
+23
-1
knit.go
+23
-1
knit.go
···
1
1
package knit
2
2
3
-
import "errors"
3
+
import (
4
+
"errors"
5
+
"os"
6
+
"os/exec"
7
+
)
4
8
5
9
// DefaultHost is the default host for tangled.sh services
6
10
const DefaultHost = "tangled.sh"
···
11
15
// ErrRequiresAuth is returned when a command requires authentication but the
12
16
// user has not authenticated with the host
13
17
var ErrRequiresAuth = errors.New("authentication required")
18
+
19
+
func Editor() string {
20
+
e := os.Getenv("EDITOR")
21
+
if e != "" {
22
+
return e
23
+
}
24
+
25
+
options := []string{"nvim", "vim", "nano"}
26
+
for _, opt := range options {
27
+
_, err := exec.LookPath(opt)
28
+
if err != nil {
29
+
continue
30
+
}
31
+
return opt
32
+
}
33
+
34
+
return "vi"
35
+
}
+26
-6
pr/create.go
+26
-6
pr/create.go
···
6
6
"fmt"
7
7
"net/http"
8
8
"net/url"
9
+
"os"
10
+
"os/exec"
9
11
"path"
10
12
"strings"
11
13
"sync"
···
36
38
}
37
39
_ = client
38
40
41
+
paths, err := git.FormatPatchToTmp(args[0])
42
+
if err != nil {
43
+
return err
44
+
}
45
+
46
+
editor := exec.Command(knit.Editor(), paths...)
47
+
editor.Stdout = os.Stdout
48
+
editor.Stderr = os.Stderr
49
+
editor.Stdin = os.Stdin
50
+
if err := editor.Run(); err != nil {
51
+
return err
52
+
}
53
+
54
+
// Combine the result into a single slice
55
+
var patch []byte
56
+
for _, p := range paths {
57
+
b, err := os.ReadFile(p)
58
+
if err != nil {
59
+
return err
60
+
}
61
+
patch = append(patch, b...)
62
+
}
63
+
39
64
// Get available remotes
40
65
remotes, err := git.Remotes()
41
66
if err != nil {
···
58
83
Value(&remote).
59
84
Options(options...).
60
85
Run()
61
-
}
62
-
63
-
patch, err := git.FormatPatch(args[0])
64
-
if err != nil {
65
-
return err
66
86
}
67
87
68
88
branches, err := git.RemoteBranches(remote.Name)
···
118
138
form.Add("title", title)
119
139
form.Add("body", description)
120
140
form.Add("targetBranch", targetBranch)
121
-
form.Add("patch", patch)
141
+
form.Add("patch", string(patch))
122
142
123
143
p := remote.Path
124
144
if !strings.HasPrefix(p, "@") {