geordi 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YThiMjA2MGUwNzA4OWJiMGMyZGRlOWEzNThlM2ZlZjFiYTQ2YmU0Ng==
5
- data.tar.gz: !binary |-
6
- ZDIyN2Y2MTIzODZjZjhiZmUzMWRmNDVjODczYzFhNGZlYzM1MWI5NA==
2
+ SHA1:
3
+ metadata.gz: ac4e04e376ff1dbe4d61f1f461ec3babc7336878
4
+ data.tar.gz: d116626e960d6917d0966555c9605595eff3901b
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MWU0ZjMxNjVmMGI0MGUxZmM0OTA5N2ZkMDMyZTg1OGE1M2Y4NDgyZTNjOWJk
10
- YTU2MWI1MGYxZjg4Mjc3NDBjM2YwMmY5YWNiNDBkOTc5M2Y5ZGY0ODAyZjAx
11
- NzgyZDQzNTcyZjM4ZTU0OTY2MzllMzM5YjA3YmVhMDY3MDJhODE=
12
- data.tar.gz: !binary |-
13
- NGNjNmUxOGU5MzIyNmM0NWZlN2U0MGUzYmNlNDlmNzM2MjAxOTgzMzE1MmMw
14
- MDIyNDZmOTZiMDIxOTBiM2Y4ZjI0YWE2ZTg2MDM5ZmMxNmIzMjA1YzYzOGY0
15
- YzhiNmMyOTgwYTY3NDBlNzI1NjhjMTQ0NjRiMzc2MzVhNmQ0YTY=
6
+ metadata.gz: 99be3db5c23f4f7a162af265279052da96728c4e855e3bf2bf3a661a57245fda9b0cff74d0314e6d6391175f1064be3ffe7637249b1b3e0f91728243f1ce7b2f
7
+ data.tar.gz: 632c0ffe2b237905b1b0c0fe8c1dfbea9eb83678e3905eb26a51538d6219a5b75c1ee399fe20c985570999e5acf9574df59730d7acca45b80ce6b06984390f05
@@ -1,171 +1,7 @@
1
1
  desc 'commit', 'Commit using a story title from Pivotal Tracker'
2
2
  def commit
3
+ require 'geordi/gitpt'
4
+
3
5
  Gitpt.new.run
4
6
  end
5
7
 
6
- class Gitpt
7
- include Geordi::Interaction
8
- require 'yaml'
9
- require 'highline'
10
- require 'pivotal-tracker'
11
-
12
- attr_reader :token, :initials, :settings_file, :deprecated_token_file,
13
- :highline, :applicable_stories, :memberships
14
-
15
- def initialize
16
- @highline = HighLine.new
17
- @settings_file = File.join(ENV['HOME'], '.gitpt')
18
- @deprecated_token_file = File.join(ENV['HOME'], '.pt_token')
19
- load_settings
20
- settings_were_invalid = (not settings_valid?)
21
-
22
- hello unless settings_valid?
23
- request_settings while not settings_valid?
24
- stored if settings_were_invalid
25
-
26
- PivotalTracker::Client.use_ssl = true
27
- PivotalTracker::Client.token = token
28
- end
29
-
30
- def settings_valid?
31
- token and token.size > 10
32
- end
33
-
34
- def bold(string)
35
- HighLine::BOLD + string + HighLine::RESET
36
- end
37
-
38
- def highlight(string)
39
- bold HighLine::BLUE + string
40
- end
41
-
42
- def hello
43
- highline.say HighLine::RESET
44
- highline.say "Welcome to #{bold 'gitpt'}.\n\n"
45
- end
46
-
47
- def loading(message, &block)
48
- print message
49
- STDOUT.flush
50
- yield
51
- print "\r" + ' ' * message.size + "\r" # Remove loading message
52
- STDOUT.flush
53
- end
54
-
55
- def stored
56
- highline.say left(<<-MESSAGE)
57
- Thank you. Your settings have been stored at #{highlight @settings_file}
58
- You may remove that file for the wizard to reappear.
59
-
60
- ----------------------------------------------------
61
-
62
- MESSAGE
63
- end
64
-
65
- def request_settings
66
- highline.say highlight('Your settings are missing or invalid.')
67
- highline.say "Please configure your Pivotal Tracker access.\n\n"
68
- token = highline.ask bold("Your API key:") + " "
69
- initials = highline.ask bold("Your PT initials") + " (optional, used for highlighting your stories): "
70
- highline.say "\n"
71
-
72
- settings = { :token => token, :initials => initials }
73
- File.open settings_file, 'w' do |file|
74
- file.write settings.to_yaml
75
- end
76
- load_settings
77
- end
78
-
79
- def load_settings
80
- if File.exists? settings_file
81
- settings = YAML.load(File.read settings_file)
82
- @initials = settings[:initials]
83
- @token = settings[:token]
84
- else
85
- if File.exists?(deprecated_token_file)
86
- highline.say left(<<-MESSAGE)
87
- #{HighLine::YELLOW}You are still using #{highlight(deprecated_token_file) + HighLine::YELLOW} which will be deprecated in a future version.
88
- Please migrate your settings to ~/.gitpt or remove #{deprecated_token_file} for the wizard to cast magic.
89
- MESSAGE
90
- @token = File.read(deprecated_token_file)
91
- end
92
- end
93
- end
94
-
95
- def load_projects
96
- project_id_filename = '.pt_project_id'
97
- if File.exists?(project_id_filename)
98
- project_ids = File.read('.pt_project_id').split(/[\s]+/).map(&:to_i)
99
- end
100
-
101
- unless project_ids and project_ids.size > 0
102
- highline.say left(<<-MESSAGE)
103
- Sorry, I could not find a project ID in #{highlight project_id_filename} :(
104
-
105
- Please put at least one Pivotal Tracker project id into #{project_id_filename} in this directory.
106
- You may add multiple IDs, separated using white space.
107
- MESSAGE
108
- exit 1
109
- end
110
-
111
- loading 'Connecting to Pivotal Tracker...' do
112
- projects = project_ids.collect do |project_id|
113
- PivotalTracker::Project.find(project_id)
114
- end
115
-
116
- @memberships = projects.collect(&:memberships).map(&:all).flatten
117
-
118
- @applicable_stories = projects.collect do |project|
119
- project.stories.all(:state => 'started,finished,rejected')
120
- end.flatten
121
- end
122
- end
123
-
124
- def choose_story
125
- selected_story = nil
126
-
127
- highline.choose do |menu|
128
- menu.header = "Choose a story"
129
- applicable_stories.each do |story|
130
- owner_name = story.owned_by
131
- owner = if owner_name
132
- owners = memberships.select{|member| member.name == owner_name}
133
- owners.first ? owners.first.initials : '?'
134
- else
135
- '?'
136
- end
137
-
138
- state = story.current_state
139
- if state == 'started'
140
- state = HighLine::GREEN + state + HighLine::RESET
141
- elsif state != 'finished'
142
- state = HighLine::RED + state + HighLine::RESET
143
- end
144
- state += HighLine::BOLD if owner == initials
145
-
146
- label = "(#{owner}, #{state}) #{story.name}"
147
- label = bold(label) if owner == initials
148
- menu.choice(label) { selected_story = story }
149
- end
150
- menu.hidden ''
151
- end
152
-
153
- if selected_story
154
- message = highline.ask("\nAdd an optional message")
155
- highline.say message
156
-
157
- commit_message = "[##{selected_story.id}] #{selected_story.name}"
158
- if message.strip != ''
159
- commit_message << ' - '<< message.strip
160
- end
161
-
162
- exec('git', 'commit', '-m', commit_message)
163
- end
164
- end
165
-
166
- def run
167
- load_projects
168
- choose_story
169
- end
170
-
171
- end
@@ -2,14 +2,13 @@ desc 'deploy', 'Guided deployment'
2
2
  def deploy
3
3
  ENV['PAGER'] = 'cat'
4
4
 
5
- master_branch = prompt('master branch', 'master')
6
- production_branch = prompt('production branch', 'production')
7
- production_stage = prompt('production capistrano stage', 'production')
5
+ master_branch = prompt 'master branch:', 'master'
6
+ production_branch = prompt 'production branch:', 'production'
7
+ production_stage = prompt 'production capistrano stage:', 'production'
8
8
 
9
9
  announce "Checking if your #{master_branch} is up to date"
10
-
11
- diff_size = call_or_fail("git fetch && git diff #{master_branch} origin/#{master_branch} | wc -l", true)
12
- changes_size = call_or_fail('git status -s | wc -l', true)
10
+ diff_size = `git fetch && git diff #{master_branch} origin/#{master_branch} | wc -l`.strip
11
+ changes_size = `git status -s | wc -l`.strip
13
12
 
14
13
  if diff_size == '0' and changes_size == '0'
15
14
  note 'All good.'
@@ -18,48 +17,23 @@ def deploy
18
17
  end
19
18
 
20
19
  announce "Checking what's on #{production_stage} right now..."
21
-
22
- call_or_fail "git checkout #{production_branch} && git pull"
20
+ Util.system! "git checkout #{production_branch} && git pull"
23
21
 
24
22
  announce "You are about to deploy the following commits from #{master_branch} to #{production_branch}:"
23
+ Util.system! "git log #{production_branch}..#{master_branch} --oneline"
25
24
 
26
- call_or_fail "git log #{production_branch}..#{master_branch} --oneline"
27
-
28
- if prompt('Go ahead with the deployment?', 'n').downcase == 'y'
29
- puts
25
+ if prompt('Go ahead with the deployment?', 'n', /y|yes/)
30
26
  capistrano_call = "cap #{production_stage} deploy:migrations"
31
27
  if file_containing?('Gemfile', /capistrano/)
32
28
  capistrano_call = "bundle exec #{capistrano_call}"
33
29
  end
34
- call_or_fail("git merge #{master_branch} && git push && #{capistrano_call}")
35
- success 'Deployment complete.'
36
- else
37
- fail 'Deployment cancelled.'
38
- end
39
30
 
40
- end
41
-
42
- private
31
+ puts
32
+ Util.system! "git merge #{master_branch} && git push && #{capistrano_call}"
43
33
 
44
- def call_or_fail(command, return_output = false)
45
- note_cmd command
46
- if return_output
47
- result = `#{command}`.to_s.strip
48
- $?.success? or fail "Error while calling #{command}: #{$?}"
34
+ success 'Deployment complete.'
49
35
  else
50
- result = system(command) or fail "Error while calling #{command}: #{$?}"
51
- puts
36
+ fail 'Deployment cancelled.'
52
37
  end
53
- result
54
- end
55
38
 
56
- def prompt(message, default)
57
- print "#{message}"
58
- print " [#{default}]" if default
59
- print ": "
60
- input = $stdin.gets.strip
61
- if input.empty? && default
62
- input = default
63
- end
64
- input
65
39
  end
@@ -13,11 +13,9 @@ def security_update(step='prepare')
13
13
  when 'prepare'
14
14
  announce 'Preparing for security update'
15
15
  warn 'Please read https://makandracards.com/makandra/1587 before applying security updates!'
16
- note 'About to: pull master and production branches, checkout production'
17
- wait 'Continue?'
16
+ note 'About to checkout production and pull'
17
+ prompt('Continue?', 'y', /y|yes/) or fail 'Cancelled.'
18
18
 
19
- Util.system! 'git checkout master', :show_cmd => true
20
- Util.system! 'git pull', :show_cmd => true
21
19
  Util.system! 'git checkout production', :show_cmd => true
22
20
  Util.system! 'git pull', :show_cmd => true
23
21
 
@@ -34,11 +32,10 @@ def security_update(step='prepare')
34
32
  `git status --porcelain`.empty? or fail('There are uncommitted changes.')
35
33
  note 'Working directory clean.'
36
34
 
37
- print 'Have you successfully run all tests? [yN] '
38
- exit unless $stdin.gets =~ /[yes]+/
35
+ prompt('Have you successfully run all tests?', 'n', /y|yes/) or fail 'Please run tests first.'
39
36
 
40
37
  note 'About to: push production, checkout & pull master, merge production, push master, deploy all stages'
41
- wait 'Continue?'
38
+ prompt('Continue?', 'n', /y|yes/) or fail 'Cancelled.'
42
39
 
43
40
  Util.system! 'git push', :show_cmd => true
44
41
  Util.system! 'git checkout master', :show_cmd => true
@@ -1,84 +1,66 @@
1
- class ::String
2
- def colorize(color_code)
3
- "\e[#{color_code}m#{self}\e[0m"
4
- end
5
-
6
- def red() colorize(31) end
7
- def pink() colorize(35) end
8
- def green() colorize(32) end
9
- end
10
-
11
1
  desc 'setup-vnc', 'Setup VNC for running Selenium tests there'
12
2
  def setup_vnc
13
3
  `clear`
14
4
 
15
- instruct <<-TEXT
16
- This script will help you install a VNC server and a VNC viewer.
17
-
5
+ note 'This script will help you install a VNC server and a VNC viewer.'
6
+ puts
7
+ puts strip_heredoc <<-TEXT
18
8
  With those you will be able to use our cucumber script without being
19
- disturbed by focus-stealing selenium windows. Instead, they will open
20
- inside a VNC session. You can still inspect everything with #{"geordi
21
- vnc_show".pink}.
9
+ disturbed by focus-stealing Selenium windows. Instead, they will open
10
+ inside a VNC session.
22
11
 
23
- Please open a second shell to execute instructions.
12
+ You can still inspect everything with:
24
13
  TEXT
14
+ note_cmd 'geordi vnc-show'
15
+ puts
16
+ note 'Please open a second shell to execute instructions.'
17
+ prompt 'Continue ...'
25
18
 
26
19
  announce 'Setup VNC server'
27
20
 
28
- if installed?('vncserver')
21
+ vnc_server_installed = system('which vncserver > /dev/null 2>&1')
22
+ if vnc_server_installed
29
23
  success 'It appears you already have a VNC server installed. Good job!'
30
24
  else
31
- instruct <<-TEXT
32
- Please run #{'sudo apt-get install vnc4server'.pink}.
33
- TEXT
34
-
35
- instruct <<-TEXT
36
- We will now set a password for your VNC server.
25
+ puts 'Please run:'
26
+ note_cmd 'sudo apt-get install vnc4server'
27
+ prompt 'Continue ...'
37
28
 
29
+ puts
30
+ note 'We will now set a password for your VNC server.'
31
+ puts strip_heredoc <<-TEXT
38
32
  When running our cucumber script, you will not actually need this
39
33
  password, and there is no security risk. However, if you start a vncserver
40
34
  without our cucumber script, a user with your password can connect to
41
35
  your machine.
42
36
 
43
- Please run #{'vncserver :20'.pink} and #{'enter a secure password'.red}.
44
- TEXT
45
-
46
- instruct <<-TEXT
47
- Now stop the server again.
48
- Please run #{'vncserver -kill :20'.pink}.
49
37
  TEXT
38
+ puts 'Please run:'
39
+ note_cmd 'vncserver :20'
40
+ warn 'Enter a secure password!'
41
+ prompt 'Continue ...'
42
+
43
+ puts 'Now stop the server again. Please run:'
44
+ note_cmd 'vncserver -kill :20'
45
+ prompt 'Continue ...'
50
46
  end
51
47
 
52
48
  announce 'Setup VNC viewer'
53
49
 
54
- if installed?('vncviewer')
50
+ vnc_viewer_installed = system('which vncviewer > /dev/null 2>&1')
51
+ if vnc_viewer_installed
55
52
  success 'It appears you already have a VNC viewer installed. Good job!'
56
53
  else
57
- instruct <<-TEXT
58
- Please run #{'sudo apt-get install xtightvncviewer'.pink}.
59
- TEXT
54
+ puts 'Please run:'
55
+ note_cmd 'sudo apt-get install xtightvncviewer'
56
+ prompt 'Continue ...'
60
57
  end
61
58
 
62
- instruct <<-TEXT, false
59
+ puts
60
+ puts strip_heredoc <<-TEXT
63
61
  All done. Our cucumber script will now automatically run Selenium features
64
62
  in VNC.
65
- #{"Happy cuking!".green}
66
63
  TEXT
67
64
 
68
- end
69
-
70
- private
71
-
72
- def instruct(text, wait = true)
73
- text =~ /^( *)./
74
- level = $1 ? $1.size : 0
75
- text.gsub!(/^ {#{level}}/, '')
76
- puts text
77
-
78
- wait('[ENTER]') if wait
79
- end
80
-
81
- def installed?(app)
82
- `which #{app}`
83
- $?.success?
65
+ success 'Happy cuking!'
84
66
  end
@@ -70,7 +70,7 @@ module Geordi
70
70
  unless FirefoxForSelenium.binary(@version).exist?
71
71
  note "Firefox #{@version} not found."
72
72
 
73
- puts left(<<-INSTRUCTIONS)
73
+ puts strip_heredoc(<<-INSTRUCTIONS)
74
74
  Install it with
75
75
  geordi setup_firefox_for_selenium #{@version}
76
76
 
@@ -137,7 +137,7 @@ module Geordi
137
137
  def say_hello
138
138
  execute_command('clear')
139
139
 
140
- puts left(<<-HELLO)
140
+ puts strip_heredoc(<<-HELLO)
141
141
  Whenever Firefox updates, Selenium breaks. This is annoying. This
142
142
  script will help you create an unchanging version of Firefox for your
143
143
  Selenium tests.
@@ -154,30 +154,27 @@ module Geordi
154
154
  - It will automatically be used for your Selenium scenarios if you run
155
155
  your Cucumber using the cuc binary from the geordi gem.
156
156
  - It will live in #{path}
157
-
158
157
  HELLO
159
158
 
160
- wait "Press ENTER when you're ready to begin."
159
+ prompt "Press ENTER when you're ready to begin."
161
160
  end
162
161
 
163
162
  def check_if_run_before
164
163
  if original_binary.exist?
165
164
  note 'This version seems to be already installed.'
166
- puts
167
- wait 'Press ENTER to continue anyway or press CTRL+C to abort.'
165
+ prompt 'Press ENTER to continue anyway or press CTRL+C to abort.'
168
166
  end
169
167
  end
170
168
 
171
169
  def download_firefox
172
170
  path.mkpath
173
171
 
174
- puts left(<<-INSTRUCTION)
172
+ puts strip_heredoc(<<-INSTRUCTION)
175
173
  Please download an old version of Firefox from: #{download_url}
176
174
  Unpack it with: tar xvjf firefox-#{@version}.tar.bz2 -C #{path} --strip-components=1
177
175
  Now #{path.join('firefox')} should be the firefox binary, not a directory.
178
-
179
176
  INSTRUCTION
180
- wait "Press ENTER when you're done."
177
+ prompt "Press ENTER when you're done."
181
178
 
182
179
  File.file?(binary) or raise "Could not find #{binary}"
183
180
  end
@@ -195,7 +192,7 @@ module Geordi
195
192
  execute_command("mv #{binary} #{original_binary}")
196
193
  execute_command("mv #{binary}-bin #{original_binary}-bin")
197
194
  patched_binary = Tempfile.new('firefox')
198
- patched_binary.write left(<<-PATCH)
195
+ patched_binary.write strip_heredoc(<<-PATCH)
199
196
  #!/usr/bin/env ruby
200
197
  exec('#{original_binary}', '-no-remote', '-P', '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}', *ARGV)
201
198
  PATCH
@@ -206,7 +203,7 @@ module Geordi
206
203
  end
207
204
 
208
205
  def configure_old_firefox
209
- puts left(<<-INSTRUCTION)
206
+ puts strip_heredoc(<<-INSTRUCTION)
210
207
  You will now have to do some manual configuration.
211
208
 
212
209
  This script will open the patched copy of Firefox when you press ENTER.
@@ -218,18 +215,17 @@ module Geordi
218
215
  Firefox profile
219
216
  - Disable all automatic updates under Edit / Preferences / Advanced /
220
217
  Update (do this quickly or Firefox will already have updated)
221
-
222
218
  INSTRUCTION
223
219
 
224
- wait 'Open the patched copy of Firefox with ENTER.'
220
+ prompt 'Open the patched copy of Firefox with ENTER.'
225
221
  run_firefox_for_selenium
226
222
  end
227
223
 
228
224
  def kkthxbb
229
225
  success "Congratulations, you're done!"
230
226
 
231
- puts left(<<-INSTRUCTION)
232
-
227
+ puts
228
+ puts strip_heredoc(<<-INSTRUCTION)
233
229
  Your patched copy of Firefox will be used when you run Cucumber using
234
230
  the cucumber script that comes with the geordi gem. If you prefer to run
235
231
  Cucumber on your own, you must call it like this:
@@ -0,0 +1,165 @@
1
+ class Gitpt
2
+ include Geordi::Interaction
3
+ require 'yaml'
4
+ require 'highline'
5
+ require 'pivotal-tracker'
6
+
7
+ attr_reader :token, :initials, :settings_file, :deprecated_token_file,
8
+ :highline, :applicable_stories, :memberships
9
+
10
+ def initialize
11
+ @highline = HighLine.new
12
+ @settings_file = File.join(ENV['HOME'], '.gitpt')
13
+ @deprecated_token_file = File.join(ENV['HOME'], '.pt_token')
14
+ load_settings
15
+ settings_were_invalid = (not settings_valid?)
16
+
17
+ hello unless settings_valid?
18
+ request_settings while not settings_valid?
19
+ stored if settings_were_invalid
20
+
21
+ PivotalTracker::Client.use_ssl = true
22
+ PivotalTracker::Client.token = token
23
+ end
24
+
25
+ def settings_valid?
26
+ token and token.size > 10
27
+ end
28
+
29
+ def bold(string)
30
+ HighLine::BOLD + string + HighLine::RESET
31
+ end
32
+
33
+ def highlight(string)
34
+ bold HighLine::BLUE + string
35
+ end
36
+
37
+ def hello
38
+ highline.say HighLine::RESET
39
+ highline.say "Welcome to #{bold 'gitpt'}.\n\n"
40
+ end
41
+
42
+ def loading(message, &block)
43
+ print message
44
+ STDOUT.flush
45
+ yield
46
+ print "\r" + ' ' * message.size + "\r" # Remove loading message
47
+ STDOUT.flush
48
+ end
49
+
50
+ def stored
51
+ highline.say strip_heredoc(<<-MESSAGE)
52
+ Thank you. Your settings have been stored at #{highlight @settings_file}
53
+ You may remove that file for the wizard to reappear.
54
+
55
+ ----------------------------------------------------
56
+
57
+ MESSAGE
58
+ end
59
+
60
+ def request_settings
61
+ highline.say highlight('Your settings are missing or invalid.')
62
+ highline.say "Please configure your Pivotal Tracker access.\n\n"
63
+ token = highline.ask bold("Your API key:") + " "
64
+ initials = highline.ask bold("Your PT initials") + " (optional, used for highlighting your stories): "
65
+ highline.say "\n"
66
+
67
+ settings = { :token => token, :initials => initials }
68
+ File.open settings_file, 'w' do |file|
69
+ file.write settings.to_yaml
70
+ end
71
+ load_settings
72
+ end
73
+
74
+ def load_settings
75
+ if File.exists? settings_file
76
+ settings = YAML.load(File.read settings_file)
77
+ @initials = settings[:initials]
78
+ @token = settings[:token]
79
+ else
80
+ if File.exists?(deprecated_token_file)
81
+ highline.say strip_heredoc(<<-MESSAGE)
82
+ #{HighLine::YELLOW}You are still using #{highlight(deprecated_token_file) + HighLine::YELLOW} which will be deprecated in a future version.
83
+ Please migrate your settings to ~/.gitpt or remove #{deprecated_token_file} for the wizard to cast magic.
84
+ MESSAGE
85
+ @token = File.read(deprecated_token_file)
86
+ end
87
+ end
88
+ end
89
+
90
+ def load_projects
91
+ project_id_filename = '.pt_project_id'
92
+ if File.exists?(project_id_filename)
93
+ project_ids = File.read('.pt_project_id').split(/[\s]+/).map(&:to_i)
94
+ end
95
+
96
+ unless project_ids and project_ids.size > 0
97
+ warn "Sorry, I could not find a project ID in #{project_id_filename} :("
98
+ puts
99
+
100
+ puts "Please put at least one Pivotal Tracker project id into #{project_id_filename} in this directory."
101
+ puts 'You may add multiple IDs, separated using white space.'
102
+ exit 1
103
+ end
104
+
105
+ loading 'Connecting to Pivotal Tracker...' do
106
+ projects = project_ids.collect do |project_id|
107
+ PivotalTracker::Project.find(project_id)
108
+ end
109
+
110
+ @memberships = projects.collect(&:memberships).map(&:all).flatten
111
+
112
+ @applicable_stories = projects.collect do |project|
113
+ project.stories.all(:state => 'started,finished,rejected')
114
+ end.flatten
115
+ end
116
+ end
117
+
118
+ def choose_story
119
+ selected_story = nil
120
+
121
+ highline.choose do |menu|
122
+ menu.header = "Choose a story"
123
+ applicable_stories.each do |story|
124
+ owner_name = story.owned_by
125
+ owner = if owner_name
126
+ owners = memberships.select{|member| member.name == owner_name}
127
+ owners.first ? owners.first.initials : '?'
128
+ else
129
+ '?'
130
+ end
131
+
132
+ state = story.current_state
133
+ if state == 'started'
134
+ state = HighLine::GREEN + state + HighLine::RESET
135
+ elsif state != 'finished'
136
+ state = HighLine::RED + state + HighLine::RESET
137
+ end
138
+ state += HighLine::BOLD if owner == initials
139
+
140
+ label = "(#{owner}, #{state}) #{story.name}"
141
+ label = bold(label) if owner == initials
142
+ menu.choice(label) { selected_story = story }
143
+ end
144
+ menu.hidden ''
145
+ end
146
+
147
+ if selected_story
148
+ message = highline.ask("\nAdd an optional message")
149
+ highline.say message
150
+
151
+ commit_message = "[##{selected_story.id}] #{selected_story.name}"
152
+ if message.strip != ''
153
+ commit_message << ' - '<< message.strip
154
+ end
155
+
156
+ exec('git', 'commit', '-m', commit_message)
157
+ end
158
+ end
159
+
160
+ def run
161
+ load_projects
162
+ choose_story
163
+ end
164
+
165
+ end
@@ -31,17 +31,25 @@ module Geordi
31
31
  puts "\e[32m#{message}\e[0m" # green
32
32
  end
33
33
 
34
- def wait(text)
35
- message = "#{text}"
36
- puts "\e[36m#{message}\e[0m" # cyan
37
- $stdin.gets
38
- end
39
-
40
- def left(string)
34
+ def strip_heredoc(string)
41
35
  leading_whitespace = (string.match(/\A( +)[^ ]+/) || [])[1]
42
36
  string.gsub! /^#{leading_whitespace}/, '' if leading_whitespace
43
37
  string
44
38
  end
45
39
 
40
+ # Returns the user's input.
41
+ # If agreement_regex is given, returns whether the input matches the regex.
42
+ def prompt(text, default = nil, agreement_regex = nil)
43
+ message = "#{text} "
44
+ message << "[#{default}] " if default
45
+
46
+ puts
47
+ print "\e[36m#{message}\e[0m" # cyan
48
+ input = $stdin.gets.strip
49
+ input = default if input.empty? && default
50
+
51
+ agreement_regex ? !!(input =~ agreement_regex) : input
52
+ end
53
+
46
54
  end
47
55
  end
data/lib/geordi/util.rb CHANGED
@@ -11,18 +11,21 @@ module Geordi
11
11
  # Thus, we have this handy method here.
12
12
  def installing_missing_gems(&block)
13
13
  yield
14
- rescue LoadError => e
15
- gem_name = e.message.split('--').last.strip
14
+ rescue LoadError => error
15
+ error.message =~ /-- (\S+)\Z/
16
+ $1 or raise # could not extract a gem name from the error message, re-raise the error
17
+
18
+ gem_name = $1.strip
16
19
  install_command = 'gem install ' + gem_name
17
20
 
18
21
  # install missing gem
19
22
  warn 'Probably missing gem: ' + gem_name
20
- wait 'Auto-install it?'
23
+ prompt('Install it now?', 'y', /y|yes/) or fail 'Missing Gems.'
21
24
  system! install_command, :show_cmd => true
22
25
 
23
26
  # retry
24
27
  Gem.clear_paths
25
- note 'Trying again ...'
28
+ note 'Retrying ...'
26
29
  require gem_name
27
30
  retry
28
31
  end
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.3'
3
3
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geordi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-28 00:00:00.000000000 Z
11
+ date: 2015-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.18.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.18.0
27
27
  description: Collection of command line tools we use in our daily work with Ruby,
@@ -56,8 +56,8 @@ executables:
56
56
  extensions: []
57
57
  extra_rdoc_files: []
58
58
  files:
59
- - .gitignore
60
- - .ruby-version
59
+ - ".gitignore"
60
+ - ".ruby-version"
61
61
  - Gemfile
62
62
  - LICENSE
63
63
  - README.md
@@ -124,6 +124,7 @@ files:
124
124
  - lib/geordi/cucumber.rb
125
125
  - lib/geordi/dump_loader.rb
126
126
  - lib/geordi/firefox_for_selenium.rb
127
+ - lib/geordi/gitpt.rb
127
128
  - lib/geordi/interaction.rb
128
129
  - lib/geordi/remote.rb
129
130
  - lib/geordi/run_tests.rb
@@ -133,7 +134,7 @@ homepage: http://makandra.com
133
134
  licenses:
134
135
  - MIT
135
136
  metadata: {}
136
- post_install_message: ! "\n ********************************************\n\n geordi
137
+ post_install_message: "\n ********************************************\n\n geordi
137
138
  1.0 moves most of the scripts to\n the `geordi` binary. Run `geordi` and\n `geordi
138
139
  help <cmd>` for further information.\n\n Tip: Create an alias for geordi for
139
140
  quick \n access. Add this to your ~/.bashrc:\n\n alias g=\"geordi\"\n\n
@@ -143,17 +144,17 @@ require_paths:
143
144
  - lib
144
145
  required_ruby_version: !ruby/object:Gem::Requirement
145
146
  requirements:
146
- - - ! '>='
147
+ - - ">="
147
148
  - !ruby/object:Gem::Version
148
149
  version: '0'
149
150
  required_rubygems_version: !ruby/object:Gem::Requirement
150
151
  requirements:
151
- - - ! '>='
152
+ - - ">="
152
153
  - !ruby/object:Gem::Version
153
154
  version: '0'
154
155
  requirements: []
155
156
  rubyforge_project: geordi
156
- rubygems_version: 2.2.2
157
+ rubygems_version: 2.4.3
157
158
  signing_key:
158
159
  specification_version: 4
159
160
  summary: Collection of command line tools we use in our daily work with Ruby, Rails