-
Notifications
You must be signed in to change notification settings - Fork 127
/
Copy pathrepo_stash.go
122 lines (105 loc) · 3.09 KB
/
repo_stash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package git
import (
"bytes"
"io"
"regexp"
"strconv"
"strings"
)
// Stash represents a stash in the repository.
type Stash struct {
// Index is the index of the stash.
Index int
// Message is the message of the stash.
Message string
// Files is the list of files in the stash.
Files []string
}
// StashListOptions describes the options for the StashList function.
type StashListOptions struct {
// CommandOptions describes the options for the command.
CommandOptions
}
var stashLineRegexp = regexp.MustCompile(`^stash@\{(\d+)\}: (.*)$`)
// StashList returns a list of stashes in the repository.
// This must be run in a work tree.
func (r *Repository) StashList(opts ...StashListOptions) ([]*Stash, error) {
var opt StashListOptions
if len(opts) > 0 {
opt = opts[0]
}
stashes := make([]*Stash, 0)
cmd := NewCommand("stash", "list", "--name-only").AddOptions(opt.CommandOptions)
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
if err := cmd.RunInDirPipeline(stdout, stderr, r.path); err != nil {
return nil, concatenateError(err, stderr.String())
}
var stash *Stash
lines := strings.Split(stdout.String(), "\n")
for i := 0; i < len(lines); i++ {
line := strings.TrimSpace(lines[i])
// Init entry
if match := stashLineRegexp.FindStringSubmatch(line); len(match) == 3 {
// Append the previous stash
if stash != nil {
stashes = append(stashes, stash)
}
idx, err := strconv.Atoi(match[1])
if err != nil {
idx = -1
}
stash = &Stash{
Index: idx,
Message: match[2],
Files: make([]string, 0),
}
} else if stash != nil && line != "" {
stash.Files = append(stash.Files, line)
}
}
// Append the last stash
if stash != nil {
stashes = append(stashes, stash)
}
return stashes, nil
}
// StashDiff returns a parsed diff object for the given stash index.
// This must be run in a work tree.
func (r *Repository) StashDiff(index int, maxFiles, maxFileLines, maxLineChars int, opts ...DiffOptions) (*Diff, error) {
var opt DiffOptions
if len(opts) > 0 {
opt = opts[0]
}
cmd := NewCommand("stash", "show", "-p", "--full-index", "-M", strconv.Itoa(index)).AddOptions(opt.CommandOptions)
stdout, w := io.Pipe()
done := make(chan SteamParseDiffResult)
go StreamParseDiff(stdout, done, maxFiles, maxFileLines, maxLineChars)
stderr := new(bytes.Buffer)
err := cmd.RunInDirPipeline(w, stderr, r.path)
_ = w.Close() // Close writer to exit parsing goroutine
if err != nil {
return nil, concatenateError(err, stderr.String())
}
result := <-done
return result.Diff, result.Err
}
// StashPushOptions describes the options for the StashPush function.
type StashPushOptions struct {
// CommandOptions describes the options for the command.
CommandOptions
}
// StashPush pushes the current worktree to the stash.
// This must be run in a work tree.
func (r *Repository) StashPush(msg string, opts ...StashPushOptions) error {
var opt StashPushOptions
if len(opts) > 0 {
opt = opts[0]
}
cmd := NewCommand("stash", "push")
if msg != "" {
cmd.AddArgs("-m", msg)
}
cmd.AddOptions(opt.CommandOptions)
_, err := cmd.RunInDir(r.path)
return err
}