+36
git/git.go
+36
git/git.go
···
4
"bufio"
5
"fmt"
6
"net/url"
7
+
"os"
8
"os/exec"
9
+
"path"
10
+
"sort"
11
"strings"
12
)
13
···
99
}
100
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
135
}
136
137
func RemoteBranches(remote string) ([]string, error) {
+23
-1
knit.go
+23
-1
knit.go
···
1
package knit
2
3
-
import "errors"
4
5
// DefaultHost is the default host for tangled.sh services
6
const DefaultHost = "tangled.sh"
···
11
// ErrRequiresAuth is returned when a command requires authentication but the
12
// user has not authenticated with the host
13
var ErrRequiresAuth = errors.New("authentication required")
···
1
package knit
2
3
+
import (
4
+
"errors"
5
+
"os"
6
+
"os/exec"
7
+
)
8
9
// DefaultHost is the default host for tangled.sh services
10
const DefaultHost = "tangled.sh"
···
15
// ErrRequiresAuth is returned when a command requires authentication but the
16
// user has not authenticated with the host
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
"fmt"
7
"net/http"
8
"net/url"
9
"path"
10
"strings"
11
"sync"
···
36
}
37
_ = client
38
39
// Get available remotes
40
remotes, err := git.Remotes()
41
if err != nil {
···
58
Value(&remote).
59
Options(options...).
60
Run()
61
-
}
62
-
63
-
patch, err := git.FormatPatch(args[0])
64
-
if err != nil {
65
-
return err
66
}
67
68
branches, err := git.RemoteBranches(remote.Name)
···
118
form.Add("title", title)
119
form.Add("body", description)
120
form.Add("targetBranch", targetBranch)
121
-
form.Add("patch", patch)
122
123
p := remote.Path
124
if !strings.HasPrefix(p, "@") {
···
6
"fmt"
7
"net/http"
8
"net/url"
9
+
"os"
10
+
"os/exec"
11
"path"
12
"strings"
13
"sync"
···
38
}
39
_ = client
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
+
64
// Get available remotes
65
remotes, err := git.Remotes()
66
if err != nil {
···
83
Value(&remote).
84
Options(options...).
85
Run()
86
}
87
88
branches, err := git.RemoteBranches(remote.Name)
···
138
form.Add("title", title)
139
form.Add("body", description)
140
form.Add("targetBranch", targetBranch)
141
+
form.Add("patch", string(patch))
142
143
p := remote.Path
144
if !strings.HasPrefix(p, "@") {