From f5b034095a74ae88410bf3383c39b1e99c0f36a0 Mon Sep 17 00:00:00 2001
From: Junegunn Choi <junegunn.c@gmail.com>
Date: Wed, 18 Feb 2015 00:51:44 +0900
Subject: [PATCH] Fix race condition in asynchronous -1 and -0

---
 src/core.go     |  6 +++---
 src/matcher.go  |  6 ++++--
 src/merger.go   |  2 ++
 test/test_go.rb | 10 ++++++++++
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/core.go b/src/core.go
index 71e3aa96..ea97b4e6 100644
--- a/src/core.go
+++ b/src/core.go
@@ -149,11 +149,11 @@ func Run(options *Options) {
 					reading = reading && evt == EvtReadNew
 					snapshot, count := chunkList.Snapshot()
 					terminal.UpdateCount(count, !reading)
-					matcher.Reset(snapshot, terminal.Input(), false)
+					matcher.Reset(snapshot, terminal.Input(), false, !reading)
 
 				case EvtSearchNew:
 					snapshot, _ := chunkList.Snapshot()
-					matcher.Reset(snapshot, terminal.Input(), true)
+					matcher.Reset(snapshot, terminal.Input(), true, !reading)
 					delay = false
 
 				case EvtSearchProgress:
@@ -170,7 +170,7 @@ func Run(options *Options) {
 							if opts.Select1 && count > 1 || opts.Exit0 && !opts.Select1 && count > 0 {
 								deferred = false
 								terminal.startChan <- true
-							} else if !reading {
+							} else if val.final {
 								if opts.Exit0 && count == 0 || opts.Select1 && count == 1 {
 									if opts.PrintQuery {
 										fmt.Println(opts.Query)
diff --git a/src/matcher.go b/src/matcher.go
index 84130b23..bfe9d287 100644
--- a/src/matcher.go
+++ b/src/matcher.go
@@ -14,6 +14,7 @@ import (
 type MatchRequest struct {
 	chunks  []*Chunk
 	pattern *Pattern
+	final   bool
 }
 
 // Matcher is responsible for performing search
@@ -91,6 +92,7 @@ func (m *Matcher) Loop() {
 
 		if !cancelled {
 			m.mergerCache[patternString] = merger
+			merger.final = request.final
 			m.eventBox.Set(EvtSearchFin, merger)
 		}
 	}
@@ -197,7 +199,7 @@ func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
 }
 
 // Reset is called to interrupt/signal the ongoing search
-func (m *Matcher) Reset(chunks []*Chunk, patternRunes []rune, cancel bool) {
+func (m *Matcher) Reset(chunks []*Chunk, patternRunes []rune, cancel bool, final bool) {
 	pattern := m.patternBuilder(patternRunes)
 
 	var event util.EventType
@@ -206,5 +208,5 @@ func (m *Matcher) Reset(chunks []*Chunk, patternRunes []rune, cancel bool) {
 	} else {
 		event = reqRetry
 	}
-	m.reqBox.Set(event, MatchRequest{chunks, pattern})
+	m.reqBox.Set(event, MatchRequest{chunks, pattern, final})
 }
diff --git a/src/merger.go b/src/merger.go
index bd2158d1..5bfc81d5 100644
--- a/src/merger.go
+++ b/src/merger.go
@@ -12,6 +12,7 @@ type Merger struct {
 	merged  []*Item
 	cursors []int
 	sorted  bool
+	final   bool
 	count   int
 }
 
@@ -22,6 +23,7 @@ func NewMerger(lists [][]*Item, sorted bool) *Merger {
 		merged:  []*Item{},
 		cursors: make([]int, len(lists)),
 		sorted:  sorted,
+		final:   false,
 		count:   0}
 
 	for _, list := range mg.lists {
diff --git a/test/test_go.rb b/test/test_go.rb
index 70e531f2..27c7b332 100644
--- a/test/test_go.rb
+++ b/test/test_go.rb
@@ -290,6 +290,16 @@ class TestGoFZF < MiniTest::Unit::TestCase
     assert_equal ['555555'], readonce.split($/)
   end
 
+  def test_select_1_exit_0_fail
+    [:'0', :'1', [:'1', :'0']].each do |opt|
+      tmux.send_keys "seq 1 100 | #{fzf :print_query, :multi, :q, 5, *opt}", :Enter
+      tmux.until { |lines| lines.last =~ /^> 5/ }
+      tmux.send_keys :BTab, :BTab, :BTab, :Enter
+      tmux.until { |lines| lines[-1].include?(FIN) }
+      assert_equal ['5', '5', '15', '25'], readonce.split($/)
+    end
+  end
+
   def test_query_unicode
     tmux.send_keys "(echo abc; echo 臧€雮橂嫟) | #{fzf :query, '臧€雼�'}", :Enter
     tmux.until { |lines| lines.last.start_with? '>' }
-- 
GitLab