-
Notifications
You must be signed in to change notification settings - Fork 136
/
backlog.go
108 lines (97 loc) · 2.38 KB
/
backlog.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
package main
// A Backlog represents a queue of file paths that may be received while we're
// still running a command. There are a couple of different policies for how to
// handle this. If there are no {} (substitution sequences) in the command, then
// we only need to preserve one of the paths. If there is a {}, then we need to
// preserve each unique path in the backlog.
type Backlog interface {
// Add a path to the backlog.
Add(path string)
// Show what path should be processed next.
Next() string
// Remove the next path from the backlog and return whether
// the backlog is now empty.
RemoveOne() (empty bool)
}
// A UnifiedBacklog only remembers one backlog item at a time.
type UnifiedBacklog struct {
s string
empty bool
}
func NewUnifiedBacklog() *UnifiedBacklog {
return &UnifiedBacklog{empty: true}
}
// Add adds path to b if there is not a path there currently.
// Otherwise it discards it.
func (b *UnifiedBacklog) Add(path string) {
if b.empty {
b.s = path
b.empty = false
}
}
// Next returns the path in b.
func (b *UnifiedBacklog) Next() string {
if b.empty {
panic("Next() called on empty backlog")
}
return b.s
}
// RemoveOne removes the path in b.
func (b *UnifiedBacklog) RemoveOne() bool {
if b.empty {
panic("RemoveOne() called on empty backlog")
}
b.empty = true
b.s = ""
return true
}
// A UniqueFilesBacklog keeps a set of the paths it has received.
type UniqueFilesBacklog struct {
empty bool
next string
rest map[string]struct{}
}
func NewUniqueFilesBacklog() *UniqueFilesBacklog {
return &UniqueFilesBacklog{
empty: true,
next: "",
rest: make(map[string]struct{}),
}
}
// Add adds path to the set of files in b.
func (b *UniqueFilesBacklog) Add(path string) {
defer func() { b.empty = false }()
if b.empty {
b.next = path
return
}
if path == b.next {
return
}
b.rest[path] = struct{}{}
}
// Next returns one of the paths in b.
func (b *UniqueFilesBacklog) Next() string {
if b.empty {
panic("Next() called on empty backlog")
}
return b.next
}
// RemoveOne removes one of the paths from b (the same path that was returned by
// a preceding call to Next).
func (b *UniqueFilesBacklog) RemoveOne() bool {
if b.empty {
panic("RemoveOne() called on empty backlog")
}
if len(b.rest) == 0 {
b.next = ""
b.empty = true
return true
}
for next := range b.rest {
b.next = next
break
}
delete(b.rest, b.next)
return false
}