Class: Rerun::Runner

Inherits:
Object
  • Object
show all
Includes:
System
Defined in:
lib/rerun/runner.rb

Instance Method Summary collapse

Methods included from System

#app_name, #growl, #growl?, #growlcmd, #icon, #linux?, #mac?, #osx_foundation?, #windows?

Constructor Details

#initialize(run_command, options = {}) ⇒ Runner

Returns a new instance of Runner.



6
7
8
9
# File 'lib/rerun/runner.rb', line 6

def initialize(run_command, options = {})
  @run_command, @options = run_command, options
  @run_command = "ruby #{@run_command}" if @run_command.split(' ').first =~ /\.rb$/
end

Instance Method Details

#clear?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/rerun/runner.rb', line 26

def clear?
  @options[:clear]
end

#dirObject



18
19
20
# File 'lib/rerun/runner.rb', line 18

def dir
  @options[:dir] || "."
end

#exit?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/rerun/runner.rb', line 30

def exit?
  @options[:exit]
end

#git_head_changed?Boolean

Returns:

  • (Boolean)


136
137
138
139
140
# File 'lib/rerun/runner.rb', line 136

def git_head_changed?
  old_git_head = @git_head
  read_git_head
  @git_head and old_git_head and @git_head != old_git_head
end

#joinObject



112
113
114
# File 'lib/rerun/runner.rb', line 112

def join
  @watcher.join
end

#notify(title, body) ⇒ Object



147
148
149
150
151
# File 'lib/rerun/runner.rb', line 147

def notify(title, body)
  growl title, body
  puts
  say "#{app_name} #{title}"
end

#patternObject



22
23
24
# File 'lib/rerun/runner.rb', line 22

def pattern
  @options[:pattern] || DEFAULT_PATTERN
end

#read_git_headObject



142
143
144
145
# File 'lib/rerun/runner.rb', line 142

def read_git_head
  git_head_file = File.join(dir, '.git', 'HEAD')
  @git_head = File.exists?(git_head_file) && File.read(git_head_file)
end

#restartObject



11
12
13
14
15
16
# File 'lib/rerun/runner.rb', line 11

def restart
  @restarting = true
  stop
  start
  @restarting = false
end

#running?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/rerun/runner.rb', line 116

def running?
  signal(0)
end

#say(msg) ⇒ Object



153
154
155
# File 'lib/rerun/runner.rb', line 153

def say msg
  puts "#{Time.now.strftime("%T")} - #{msg}"
end

#signal(signal) ⇒ Object



120
121
122
123
124
125
# File 'lib/rerun/runner.rb', line 120

def signal(signal)
  Process.kill(signal, @pid)
  true
rescue
  false
end

#startObject



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
# File 'lib/rerun/runner.rb', line 34

def start
  if windows?
    raise "Sorry, Rerun does not work on Windows."
  end

  if (!@already_running)
    taglines = [
      "To infinity... and beyond!",
      "Charge!",
    ]
    notify "launched", taglines[rand(taglines.size)]
    @already_running = true
  else
    taglines = [
      "Here we go again!",
      "Keep on trucking.",
      "Once more unto the breach, dear friends, once more!",
      "The road goes ever on and on, down from the door where it began.",
    ]
    notify "restarted", taglines[rand(taglines.size)]
  end

  print "\033[H\033[2J" if clear?  # see http://ascii-table.com/ansi-escape-sequences-vt-100.php

  @pid = Kernel.fork do
    begin
      # Signal.trap("INT") { exit }
      exec(@run_command)
    rescue => e
      puts e
      exit
    end
  end
  status_thread = Process.detach(@pid) # so if the child exits, it dies

  Signal.trap("INT") do  # INT = control-C
    stop # first stop the child
    exit
  end

  begin
    sleep 2
  rescue Interrupt => e
    # in case someone hits control-C immediately
    stop
    exit
  end

  if exit?
    status = status_thread.value
    if status.success?
      notify "succeeded", ""
    else
      notify "failed", "Exit status #{status.exitstatus}"
    end
  else
    if !running?
      notify "Launch Failed", "See console for error output"
      @already_running = false
    end
  end

  unless @watcher
    watcher_class = osx_foundation? ? OSXWatcher : FSWatcher
    # watcher_class = FSWatcher

    watcher = watcher_class.new do
      restart unless @restarting
    end
    say "Watching #{dir}/#{pattern}"
    watcher.add_directory(dir, pattern)
    watcher.sleep_time = 1
    watcher.start
    @watcher = watcher
  end

end

#stopObject



127
128
129
130
131
132
133
134
# File 'lib/rerun/runner.rb', line 127

def stop
  if @pid && (@pid != 0)
    notify "stopped", "All good things must come to an end." unless @restarting
    signal("KILL") && Process.wait(@pid)
  end
rescue => e
  false
end