summaryrefslogtreecommitdiffstats
path: root/vendor
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-07-09 21:09:52 +1000
committerJesse Duffield <jessedduffield@gmail.com>2023-07-10 17:12:21 +1000
commit6b9390409eb533fe87648be55e9db7d36b1d9ee3 (patch)
tree43e35b86a17dbee8aac245cc93c2645727b61148 /vendor
parent8964cedf27cbdb81f59e2400cfc89684d7458605 (diff)
Use an interface for tasks instead of a concrete struct
By using an interface for tasks we can use a fake implementation in tests with extra methods
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/jesseduffield/gocui/gui.go93
-rw-r--r--vendor/github.com/jesseduffield/gocui/task.go94
-rw-r--r--vendor/github.com/jesseduffield/gocui/task_manager.go67
-rw-r--r--vendor/modules.txt2
4 files changed, 168 insertions, 88 deletions
diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go
index 006761293..47590f959 100644
--- a/vendor/github.com/jesseduffield/gocui/gui.go
+++ b/vendor/github.com/jesseduffield/gocui/gui.go
@@ -177,87 +177,6 @@ type Gui struct {
taskManager *TaskManager
}
-type TaskManager struct {
- // Tracks whether the program is busy (i.e. either something is happening on
- // the main goroutine or a worker goroutine). Used by integration tests
- // to wait until the program is idle before progressing.
- idleListeners []chan struct{}
- tasks map[int]*Task
- newTaskId int
- tasksMutex sync.Mutex
-}
-
-func newTaskManager() *TaskManager {
- return &TaskManager{
- tasks: make(map[int]*Task),
- idleListeners: []chan struct{}{},
- }
-}
-
-func (self *TaskManager) NewTask() *Task {
- self.tasksMutex.Lock()
- defer self.tasksMutex.Unlock()
-
- self.newTaskId++
- taskId := self.newTaskId
-
- withMutex := func(f func()) {
- self.tasksMutex.Lock()
- defer self.tasksMutex.Unlock()
-
- f()
-
- // Check if all tasks are done
- for _, task := range self.tasks {
- if task.isBusy {
- return
- }
- }
-
- // If we get here, all tasks are done, so
- // notify listeners that the program is idle
- for _, listener := range self.idleListeners {
- listener <- struct{}{}
- }
- }
- onDone := func() {
- withMutex(func() {
- delete(self.tasks, taskId)
- })
- }
- task := &Task{id: taskId, isBusy: true, onDone: onDone, withMutex: withMutex}
- self.tasks[taskId] = task
-
- return task
-}
-
-func (self *TaskManager) AddIdleListener(c chan struct{}) {
- self.idleListeners = append(self.idleListeners, c)
-}
-
-type Task struct {
- id int
- isBusy bool
- onDone func()
- withMutex func(func())
-}
-
-func (self *Task) Done() {
- self.onDone()
-}
-
-func (self *Task) Pause() {
- self.withMutex(func() {
- self.isBusy = false
- })
-}
-
-func (self *Task) Continue() {
- self.withMutex(func() {
- self.isBusy = true
- })
-}
-
// NewGui returns a new Gui object with a given output mode.
func NewGui(mode OutputMode, supportOverlaps bool, playRecording bool, headless bool, runeReplacements map[rune]string) (*Gui, error) {
g := &Gui{}
@@ -314,7 +233,7 @@ func NewGui(mode OutputMode, supportOverlaps bool, playRecording bool, headless
return g, nil
}
-func (g *Gui) NewTask() *Task {
+func (g *Gui) NewTask() *TaskImpl {
return g.taskManager.NewTask()
}
@@ -322,7 +241,7 @@ func (g *Gui) NewTask() *Task {
// integration tests which can wait for the program to be idle before taking
// the next step in the test.
func (g *Gui) AddIdleListener(c chan struct{}) {
- g.taskManager.AddIdleListener(c)
+ g.taskManager.addIdleListener(c)
}
// Close finalizes the library. It should be called after a successful
@@ -689,7 +608,7 @@ func getKey(key interface{}) (Key, rune, error) {
// userEvent represents an event triggered by the user.
type userEvent struct {
f func(*Gui) error
- task *Task
+ task Task
}
// Update executes the passed function. This method can be called safely from a
@@ -712,7 +631,7 @@ func (g *Gui) UpdateAsync(f func(*Gui) error) {
g.updateAsyncAux(f, task)
}
-func (g *Gui) updateAsyncAux(f func(*Gui) error, task *Task) {
+func (g *Gui) updateAsyncAux(f func(*Gui) error, task Task) {
g.userEvents <- userEvent{f: f, task: task}
}
@@ -722,7 +641,7 @@ func (g *Gui) updateAsyncAux(f func(*Gui) error, task *Task) {
// consider itself 'busy` as it runs the code. Don't use for long-running
// background goroutines where you wouldn't want lazygit to be considered busy
// (i.e. when you wouldn't want a loader to be shown to the user)
-func (g *Gui) OnWorker(f func(*Task)) {
+func (g *Gui) OnWorker(f func(Task)) {
task := g.NewTask()
go func() {
g.onWorkerAux(f, task)
@@ -730,7 +649,7 @@ func (g *Gui) OnWorker(f func(*Task)) {
}()
}
-func (g *Gui) onWorkerAux(f func(*Task), task *Task) {
+func (g *Gui) onWorkerAux(f func(Task), task Task) {
panicking := true
defer func() {
if panicking && Screen != nil {
diff --git a/vendor/github.com/jesseduffield/gocui/task.go b/vendor/github.com/jesseduffield/gocui/task.go
new file mode 100644
index 000000000..ace72f4a8
--- /dev/null
+++ b/vendor/github.com/jesseduffield/gocui/task.go
@@ -0,0 +1,94 @@
+package gocui
+
+// A task represents the fact that the program is busy doing something, which
+// is useful for integration tests which only want to proceed when the program
+// is idle.
+
+type Task interface {
+ Done()
+ Pause()
+ Continue()
+ // not exporting because we don't need to
+ isBusy() bool
+}
+
+type TaskImpl struct {
+ id int
+ busy bool
+ onDone func()
+ withMutex func(func())
+}
+
+func (self *TaskImpl) Done() {
+ self.onDone()
+}
+
+func (self *TaskImpl) Pause() {
+ self.withMutex(func() {
+ self.busy = false
+ })
+}
+
+func (self *TaskImpl) Continue() {
+ self.withMutex(func() {
+ self.busy = true
+ })
+}
+
+func (self *TaskImpl) isBusy() bool {
+ return self.busy
+}
+
+type TaskStatus int
+
+const (
+ TaskStatusBusy TaskStatus = iota
+ TaskStatusPaused
+ TaskStatusDone
+)
+
+type FakeTask struct {
+ status TaskStatus
+}
+
+func NewFakeTask() *FakeTask {
+ return &FakeTask{
+ status: TaskStatusBusy,
+ }
+}
+
+func (self *FakeTask) Done() {
+ self.status = TaskStatusDone
+}
+
+func (self *FakeTask) Pause() {
+ self.status = TaskStatusPaused
+}
+
+func (self *FakeTask) Continue() {
+ self.status = TaskStatusBusy
+}
+
+func (self *FakeTask) isBusy() bool {
+ return self.status == TaskStatusBusy
+}
+
+func (self *FakeTask) Status() TaskStatus {
+ return self.status
+}
+
+func (self *FakeTask) FormatStatus() string {
+ return formatTaskStatus(self.status)
+}
+
+func formatTaskStatus(status TaskStatus) string {
+ switch status {
+ case TaskStatusBusy:
+ return "busy"
+ case TaskStatusPaused:
+ return "paused"
+ case TaskStatusDone:
+ return "done"
+ }
+ return "unknown"
+}
diff --git a/vendor/github.com/jesseduffield/gocui/task_manager.go b/vendor/github.com/jesseduffield/gocui/task_manager.go
new file mode 100644
index 000000000..e3c82b4d4
--- /dev/null
+++ b/vendor/github.com/jesseduffield/gocui/task_manager.go
@@ -0,0 +1,67 @@
+package gocui
+
+import "sync"
+
+// Tracks whether the program is busy (i.e. either something is happening on
+// the main goroutine or a worker goroutine). Used by integration tests
+// to wait until the program is idle before progressing.
+type TaskManager struct {
+ // each of these listeners will be notified when the program goes from busy to idle
+ idleListeners []chan struct{}
+ tasks map[int]Task
+ // auto-incrementing id for new tasks
+ nextId int
+
+ mutex sync.Mutex
+}
+
+func newTaskManager() *TaskManager {
+ return &TaskManager{
+ tasks: make(map[int]Task),
+ idleListeners: []chan struct{}{},
+ }
+}
+
+func (self *TaskManager) NewTask() *TaskImpl {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+
+ self.nextId++
+ taskId := self.nextId
+
+ onDone := func() { self.delete(taskId) }
+ task := &TaskImpl{id: taskId, busy: true, onDone: onDone, withMutex: self.withMutex}
+ self.tasks[taskId] = task
+
+ return task
+}
+
+func (self *TaskManager) addIdleListener(c chan struct{}) {
+ self.idleListeners = append(self.idleListeners, c)
+}
+
+func (self *TaskManager) withMutex(f func()) {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+
+ f()
+
+ // Check if all tasks are done
+ for _, task := range self.tasks {
+ if task.isBusy() {
+ return
+ }
+ }
+
+ // If we get here, all tasks are done, so
+ // notify listeners that the program is idle
+ for _, listener := range self.idleListeners {
+ listener <- struct{}{}
+ }
+}
+
+func (self *TaskManager) delete(taskId int) {
+ self.withMutex(func() {
+ delete(self.tasks, taskId)
+ })
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 4c89cd64e..88f05f458 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -172,7 +172,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem
github.com/jesseduffield/go-git/v5/utils/merkletrie/index
github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame
github.com/jesseduffield/go-git/v5/utils/merkletrie/noder
-# github.com/jesseduffield/gocui v0.3.1-0.20230709105400-44d9f78b4b52
+# github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b
## explicit; go 1.12
github.com/jesseduffield/gocui
# github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10