octopolo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/Guardfile +5 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +55 -0
- data/Rakefile +38 -0
- data/bash_completion.sh +13 -0
- data/bin/octopolo +21 -0
- data/bin/op +21 -0
- data/lib/octopolo.rb +15 -0
- data/lib/octopolo/changelog.rb +27 -0
- data/lib/octopolo/cli.rb +210 -0
- data/lib/octopolo/commands/accept_pull.rb +8 -0
- data/lib/octopolo/commands/compare_release.rb +9 -0
- data/lib/octopolo/commands/deployable.rb +8 -0
- data/lib/octopolo/commands/github_auth.rb +5 -0
- data/lib/octopolo/commands/new_branch.rb +9 -0
- data/lib/octopolo/commands/new_deployable.rb +8 -0
- data/lib/octopolo/commands/new_staging.rb +8 -0
- data/lib/octopolo/commands/octopolo_setup.rb +5 -0
- data/lib/octopolo/commands/pivotal_auth.rb +5 -0
- data/lib/octopolo/commands/pull_request.rb +13 -0
- data/lib/octopolo/commands/signoff.rb +10 -0
- data/lib/octopolo/commands/stage_up.rb +8 -0
- data/lib/octopolo/commands/stale_branches.rb +11 -0
- data/lib/octopolo/commands/sync_branch.rb +11 -0
- data/lib/octopolo/commands/tag_release.rb +13 -0
- data/lib/octopolo/config.rb +146 -0
- data/lib/octopolo/convenience_wrappers.rb +46 -0
- data/lib/octopolo/dated_branch_creator.rb +81 -0
- data/lib/octopolo/git.rb +262 -0
- data/lib/octopolo/github.rb +95 -0
- data/lib/octopolo/github/commit.rb +45 -0
- data/lib/octopolo/github/pull_request.rb +126 -0
- data/lib/octopolo/github/pull_request_creator.rb +127 -0
- data/lib/octopolo/github/user.rb +40 -0
- data/lib/octopolo/jira/story_commenter.rb +26 -0
- data/lib/octopolo/pivotal.rb +44 -0
- data/lib/octopolo/pivotal/story_commenter.rb +19 -0
- data/lib/octopolo/pull_request_merger.rb +99 -0
- data/lib/octopolo/renderer.rb +37 -0
- data/lib/octopolo/reports.rb +18 -0
- data/lib/octopolo/scripts.rb +23 -0
- data/lib/octopolo/scripts/accept_pull.rb +67 -0
- data/lib/octopolo/scripts/compare_release.rb +52 -0
- data/lib/octopolo/scripts/deployable.rb +27 -0
- data/lib/octopolo/scripts/github_auth.rb +87 -0
- data/lib/octopolo/scripts/new_branch.rb +34 -0
- data/lib/octopolo/scripts/new_deployable.rb +14 -0
- data/lib/octopolo/scripts/new_staging.rb +15 -0
- data/lib/octopolo/scripts/octopolo_setup.rb +55 -0
- data/lib/octopolo/scripts/pivotal_auth.rb +44 -0
- data/lib/octopolo/scripts/pull_request.rb +127 -0
- data/lib/octopolo/scripts/signoff.rb +85 -0
- data/lib/octopolo/scripts/stage_up.rb +26 -0
- data/lib/octopolo/scripts/stale_branches.rb +54 -0
- data/lib/octopolo/scripts/sync_branch.rb +37 -0
- data/lib/octopolo/scripts/tag_release.rb +70 -0
- data/lib/octopolo/templates/pull_request_body.erb +24 -0
- data/lib/octopolo/user_config.rb +112 -0
- data/lib/octopolo/version.rb +3 -0
- data/lib/octopolo/week.rb +130 -0
- data/octopolo.gemspec +31 -0
- data/spec/.DS_Store +0 -0
- data/spec/octopolo/cli_spec.rb +310 -0
- data/spec/octopolo/config_spec.rb +344 -0
- data/spec/octopolo/convenience_wrappers_spec.rb +80 -0
- data/spec/octopolo/dated_branch_creator_spec.rb +143 -0
- data/spec/octopolo/git_spec.rb +419 -0
- data/spec/octopolo/github/commit_spec.rb +59 -0
- data/spec/octopolo/github/pull_request_creator_spec.rb +174 -0
- data/spec/octopolo/github/pull_request_spec.rb +291 -0
- data/spec/octopolo/github/user_spec.rb +65 -0
- data/spec/octopolo/github_spec.rb +169 -0
- data/spec/octopolo/jira/stor_commenter_spec.rb +30 -0
- data/spec/octopolo/pivotal/story_commenter_spec.rb +34 -0
- data/spec/octopolo/pivotal_spec.rb +61 -0
- data/spec/octopolo/pull_request_merger_spec.rb +144 -0
- data/spec/octopolo/renderer_spec.rb +35 -0
- data/spec/octopolo/scripts/accept_pull_spec.rb +76 -0
- data/spec/octopolo/scripts/compare_release_spec.rb +115 -0
- data/spec/octopolo/scripts/deployable_spec.rb +52 -0
- data/spec/octopolo/scripts/github_auth_spec.rb +156 -0
- data/spec/octopolo/scripts/new_branch_spec.rb +41 -0
- data/spec/octopolo/scripts/new_deployable_spec.rb +18 -0
- data/spec/octopolo/scripts/new_staging_spec.rb +18 -0
- data/spec/octopolo/scripts/octopolo_setup_spec.rb +120 -0
- data/spec/octopolo/scripts/pivotal_auth_spec.rb +77 -0
- data/spec/octopolo/scripts/pull_request_spec.rb +217 -0
- data/spec/octopolo/scripts/signoff_spec.rb +139 -0
- data/spec/octopolo/scripts/stage_up_spec.rb +52 -0
- data/spec/octopolo/scripts/stale_branches_spec.rb +81 -0
- data/spec/octopolo/scripts/sync_branch_spec.rb +57 -0
- data/spec/octopolo/scripts/tag_release_spec.rb +108 -0
- data/spec/octopolo/user_config_spec.rb +167 -0
- data/spec/octopolo_spec.rb +7 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/engine_yard.cache +0 -0
- data/spec/support/sample_octopolo.yml +2 -0
- data/spec/support/sample_user.yml +2 -0
- data/templates/lib.erb +23 -0
- data/templates/script.erb +7 -0
- data/templates/spec.erb +29 -0
- metadata +344 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Y2E4MmFlMWM0MTc2YTdkODhhMDc2ODcwNTU0OGY1MzBlZmM4N2ViYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YjMwZWMyNmRjMWUxYmU1ZWJlMGU4MzExYjFiNzI3ZTdhZTAzYTgwMQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YzBhYzM4NjM1YzYyOWEzMWJlNmVjZWM3Nzk2NGE4MTU5ZTI5MjBiY2Y5NTk1
|
10
|
+
MjZlY2ZlOWVmZjMyZmVkZWQzMzkxNDBjMjMwZmU4NTU4MTQxNTUxYjdkZTFh
|
11
|
+
NzBhOTE3MWE3Yjk3YTVhMjgzNTI4NWY3MWMzODNhZWY0MmRkNjk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NjZkMTYyNGU1ZjNkMGRmZTk4YmExMmIyM2M3NzNkMGIxY2FkYjZkMDgwNTAy
|
14
|
+
NWIxMDE4ZWFjOGU5OGEyODIzOWFhMWE1Njg5NzAzODQ0OGU5MDQzY2RlMmQ4
|
15
|
+
YmU1ZGM4YzJlYmRlNjA0MmNlYTNiMjdhYmE1M2YzZGNkMTE1ZWI=
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
.automation.yml
|
2
|
+
.octopolo.yml
|
3
|
+
*.gem
|
4
|
+
*.rbc
|
5
|
+
.bundle
|
6
|
+
.config
|
7
|
+
coverage
|
8
|
+
InstalledFiles
|
9
|
+
lib/bundler/man
|
10
|
+
Gemfile.lock
|
11
|
+
pkg
|
12
|
+
rdoc
|
13
|
+
spec/reports
|
14
|
+
test/tmp
|
15
|
+
test/version_tmp
|
16
|
+
tmp
|
17
|
+
|
18
|
+
# YARD artifacts
|
19
|
+
.yardoc
|
20
|
+
_yardoc
|
21
|
+
doc/
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
octopolo
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p448
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Sport Ngin
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
Octopolo
|
2
|
+
========
|
3
|
+
|
4
|
+
[![Build Status][build_status_image]][build_status]
|
5
|
+
|
6
|
+
A set of Github workflow scripts.
|
7
|
+
|
8
|
+
|
9
|
+
### GitHub Octopolo
|
10
|
+
|
11
|
+
#### GitHub Setup
|
12
|
+
|
13
|
+
Interactively set up your local machine for GitHub octopolo, including
|
14
|
+
configuring your user-level setting and setting up a GitHub API token for our
|
15
|
+
scripts to use.
|
16
|
+
|
17
|
+
octopolo-setup
|
18
|
+
|
19
|
+
|
20
|
+
#### Create New Branch
|
21
|
+
|
22
|
+
Create a new branch from the master branch and push it out to GitHub.
|
23
|
+
|
24
|
+
new-branch bug-123-something
|
25
|
+
|
26
|
+
#### Create Pull Request for Current Branch
|
27
|
+
|
28
|
+
Create a pull-request against the project's deploy branch, associating with the
|
29
|
+
given GitHub issue, if one is provided.
|
30
|
+
|
31
|
+
pull-request
|
32
|
+
|
33
|
+
#### Deploy Current Branch to Staging
|
34
|
+
|
35
|
+
From within a bugfix branch, merge to the current staging branch.
|
36
|
+
|
37
|
+
stage-up
|
38
|
+
|
39
|
+
#### Merge Release Into Your Branch
|
40
|
+
|
41
|
+
From within a bugfix branch, merge the latest released code (or, optionally,
|
42
|
+
another named branch) into your current branch.
|
43
|
+
|
44
|
+
sync-branch
|
45
|
+
sync-branch some-other-branch
|
46
|
+
|
47
|
+
#### Review Changes In Releases
|
48
|
+
|
49
|
+
Select from recent release tags and generate a link to the GitHub compare view.
|
50
|
+
|
51
|
+
compare-releases
|
52
|
+
|
53
|
+
|
54
|
+
[build_status]: https://travis-ci.org/sportngin/octopolo
|
55
|
+
[build_status_image]: https://travis-ci.org/sportngin/octopolo.svg?branch=master
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
# TODO dogfood this rake task and wrap it into a script that is tested and whatnot
|
5
|
+
desc "Create new octopolo script"
|
6
|
+
task :new, [:scriptname] do |t, args|
|
7
|
+
require "erb"
|
8
|
+
scriptname = args[:scriptname]
|
9
|
+
|
10
|
+
if scriptname.nil? or scriptname.empty?
|
11
|
+
puts "Must provide a script name, e.g., rake new[do_something]"
|
12
|
+
else
|
13
|
+
# turn foo-bar into FooBar
|
14
|
+
class_file_name = scriptname.gsub(/[-]/, "_")
|
15
|
+
class_name = scriptname.split(/[_-]/).map(&:capitalize).join
|
16
|
+
|
17
|
+
puts "Creating a new script named #{scriptname} with a class named #{class_name}"
|
18
|
+
|
19
|
+
files = {
|
20
|
+
"templates/script.erb" => "bin/#{scriptname}",
|
21
|
+
"templates/lib.erb" => "lib/octopolo/scripts/#{class_file_name}.rb",
|
22
|
+
"templates/spec.erb" => "spec/octopolo/scripts/#{class_file_name}_spec.rb",
|
23
|
+
}
|
24
|
+
|
25
|
+
files.each do |template_path, output_path|
|
26
|
+
base_path = File.dirname(__FILE__)
|
27
|
+
template_file = File.expand_path(template_path, base_path)
|
28
|
+
output_file = File.expand_path(output_path, base_path)
|
29
|
+
perms = output_path.include?("bin/") ? 0755 : 0666
|
30
|
+
|
31
|
+
puts "writing to #{output_path}"
|
32
|
+
File.open(output_file, "w+", perms) do |f|
|
33
|
+
f.write(ERB.new(File.read(template_file)).result(binding))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/bash_completion.sh
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
_op() {
|
2
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
3
|
+
|
4
|
+
if [[ -z $OCTOPOLO_0_0_1_COMMANDS ]]; then
|
5
|
+
OCTOPOLO_0_0_1_COMMANDS=`op help -c`
|
6
|
+
fi
|
7
|
+
|
8
|
+
COMPREPLY=($(compgen -W "${OCTOPOLO_0_0_1_COMMANDS}" -- ${cur}))
|
9
|
+
return 0
|
10
|
+
}
|
11
|
+
|
12
|
+
complete -F _op op
|
13
|
+
complete -F _op octopolo
|
data/bin/octopolo
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'gli'
|
4
|
+
require_relative '../lib/octopolo'
|
5
|
+
|
6
|
+
include GLI::App
|
7
|
+
|
8
|
+
program_desc 'GitHub workflow scripts. From the Ngineers as SportNgin.'
|
9
|
+
version Octopolo::VERSION
|
10
|
+
|
11
|
+
wrap_help_text :verbatim
|
12
|
+
|
13
|
+
program_long_desc """
|
14
|
+
DOCUMENTATION
|
15
|
+
For documentation and help in setting up your configuration files,
|
16
|
+
see Octopolo's GitHub repo: https://github.com/sportngin/octopolo
|
17
|
+
"""
|
18
|
+
|
19
|
+
commands_from File.expand_path(File.dirname(__FILE__) + '/../lib/octopolo/commands')
|
20
|
+
|
21
|
+
exit run(ARGV)
|
data/bin/op
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'gli'
|
4
|
+
require_relative '../lib/octopolo'
|
5
|
+
|
6
|
+
include GLI::App
|
7
|
+
|
8
|
+
program_desc 'GitHub workflow scripts. From the Ngineers as SportNgin.'
|
9
|
+
version Octopolo::VERSION
|
10
|
+
|
11
|
+
wrap_help_text :verbatim
|
12
|
+
|
13
|
+
program_long_desc """
|
14
|
+
DOCUMENTATION
|
15
|
+
For documentation and help in setting up your configuration files,
|
16
|
+
see Octopolo's GitHub repo: https://github.com/sportngin/octopolo
|
17
|
+
"""
|
18
|
+
|
19
|
+
commands_from File.expand_path(File.dirname(__FILE__) + '/../lib/octopolo/commands')
|
20
|
+
|
21
|
+
exit run(ARGV)
|
data/lib/octopolo.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "readline"
|
2
|
+
require "octokit"
|
3
|
+
require "hashie"
|
4
|
+
require_relative "octopolo/cli"
|
5
|
+
require_relative "octopolo/config"
|
6
|
+
require_relative "octopolo/version"
|
7
|
+
require_relative "octopolo/convenience_wrappers"
|
8
|
+
|
9
|
+
module Octopolo
|
10
|
+
|
11
|
+
def self.config
|
12
|
+
@config ||= Octopolo::Config.parse
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Octopolo
|
4
|
+
class Changelog
|
5
|
+
attr_reader :filename
|
6
|
+
|
7
|
+
def initialize(filename="CHANGELOG.markdown")
|
8
|
+
@filename = filename
|
9
|
+
end
|
10
|
+
|
11
|
+
def readlines
|
12
|
+
File.readlines(@filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def open
|
16
|
+
FileUtils.touch(@filename) unless File.exists?(@filename)
|
17
|
+
File.copy_stream(@filename,'old_changelog')
|
18
|
+
File.open('old_changelog', 'r') do |old_changelog|
|
19
|
+
File.open(@filename, 'w') do |changelog|
|
20
|
+
yield changelog
|
21
|
+
old_changelog.each_line { |line| changelog.puts line }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
File.delete('old_changelog')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/octopolo/cli.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "highline"
|
3
|
+
|
4
|
+
module Octopolo
|
5
|
+
# Public: Class to perform cli-related tasks, like performing commands.
|
6
|
+
class CLI
|
7
|
+
# Public: Perform the given shell command.
|
8
|
+
#
|
9
|
+
# command - A String containing the command to perform.
|
10
|
+
# say_command - A Boolean determining whether to display the performed command to the screen. (default: true)
|
11
|
+
#
|
12
|
+
# Examples
|
13
|
+
#
|
14
|
+
# CLI.perform "git pull", false
|
15
|
+
# git pull
|
16
|
+
# Already up-to-date.
|
17
|
+
# # => "Already up-to-date."
|
18
|
+
#
|
19
|
+
# CLI.perform "git pull", false
|
20
|
+
# # => "Already up-to-date."
|
21
|
+
#
|
22
|
+
# Returns the output of the command as a String.
|
23
|
+
def self.perform(command, say_command = true)
|
24
|
+
# display the command
|
25
|
+
say command if say_command
|
26
|
+
# and then perform it
|
27
|
+
if Open3.respond_to?(:capture3)
|
28
|
+
output, error, status = Open3.capture3(command)
|
29
|
+
else
|
30
|
+
# Only necessary as long as we use 1.8.7, which doesn't have Open3.capture3
|
31
|
+
output = `#{command}`
|
32
|
+
end
|
33
|
+
|
34
|
+
# speak the output
|
35
|
+
say output if say_command
|
36
|
+
# return the output of the command
|
37
|
+
output
|
38
|
+
rescue => e
|
39
|
+
say "Unable to perform '#{command}': #{e.message}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Public: Perform the command, but do not print out the command
|
43
|
+
#
|
44
|
+
# command - A String containing the command to perform.
|
45
|
+
#
|
46
|
+
# Examples
|
47
|
+
#
|
48
|
+
# CLI.perform_quietly "git pull"
|
49
|
+
# Already up-to-date.
|
50
|
+
# # => "Already up-to-date."
|
51
|
+
def self.perform_quietly command
|
52
|
+
perform command, false
|
53
|
+
end
|
54
|
+
|
55
|
+
# Public: Replace the current process with the given shell command.
|
56
|
+
#
|
57
|
+
# command - A String containing the command to perform.
|
58
|
+
#
|
59
|
+
# Returns nothing and exits the current Ruby process.
|
60
|
+
def self.perform_and_exit(command)
|
61
|
+
say command
|
62
|
+
# Kernel#exec replaces the ruby process with the new bash process
|
63
|
+
# executing the command. This is useful for us mainly for things like
|
64
|
+
# calling `ssh` which will be interactive or `hub` which will open a text
|
65
|
+
# editor. Those commands don't play well with Kernel#` or Open3.capture3.
|
66
|
+
exec command
|
67
|
+
end
|
68
|
+
|
69
|
+
# Public: Display the given message.
|
70
|
+
#
|
71
|
+
# message - A String containig the message to display.
|
72
|
+
#
|
73
|
+
# Examples
|
74
|
+
#
|
75
|
+
# CLI.say "About to do something awesome"
|
76
|
+
#
|
77
|
+
# CLI.say "This may take a moment..."
|
78
|
+
#
|
79
|
+
# Returns nothing.
|
80
|
+
def self.say(message)
|
81
|
+
unless message.nil? || message.empty?
|
82
|
+
puts message
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Public: Display a blank line
|
87
|
+
def self.spacer_line
|
88
|
+
say " "
|
89
|
+
end
|
90
|
+
|
91
|
+
# Public: Perform a set of commands in the given directory.
|
92
|
+
#
|
93
|
+
# Yields nothing.
|
94
|
+
#
|
95
|
+
# dir - A String indicating the path to perform the commands in.
|
96
|
+
#
|
97
|
+
# Examples
|
98
|
+
#
|
99
|
+
# CLI.perform_in "~" do
|
100
|
+
# CLI.perform "rm -Rf"
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# CLI.perform_in "/tmp" do
|
104
|
+
# CLI.perform "ls"
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# Returns nothing.
|
108
|
+
def self.perform_in(dir)
|
109
|
+
say "Performing in #{dir}:"
|
110
|
+
Dir.chdir(dir) do
|
111
|
+
yield
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.ask(question, choices, skip_asking = false)
|
116
|
+
return choices.first if choices.size == 1
|
117
|
+
|
118
|
+
unless skip_asking
|
119
|
+
say question
|
120
|
+
choices.each_with_index do |choice, i|
|
121
|
+
say "#{i+1}) #{choice}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
selection = nil
|
126
|
+
while not choices.include?(selection)
|
127
|
+
selection = prompt
|
128
|
+
break if choices.include?(selection)
|
129
|
+
# if entering a 1-based index value
|
130
|
+
selection_index = selection.to_i - 1
|
131
|
+
selection = choices[selection_index] if selection_index >= 0
|
132
|
+
break if choices.include?(selection)
|
133
|
+
say "Not a valid choice."
|
134
|
+
end
|
135
|
+
|
136
|
+
selection
|
137
|
+
end
|
138
|
+
|
139
|
+
# Public: Ask a yes or no question
|
140
|
+
#
|
141
|
+
# question - The question to display to the user in the prompt
|
142
|
+
#
|
143
|
+
# Returns a Boolean
|
144
|
+
def self.ask_boolean(question)
|
145
|
+
answer = prompt("#{question} (y/n)")
|
146
|
+
# basically accept anything that starts with Y as a yes answer
|
147
|
+
answer =~ /^y/i
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.prompt prompt_text="> "
|
151
|
+
highline.ask prompt_text do |conf|
|
152
|
+
conf.readline = true
|
153
|
+
end.to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
# Public: Prompt user for multiple lines of input
|
157
|
+
#
|
158
|
+
# prompt_text - The text to display before the prompt
|
159
|
+
#
|
160
|
+
# Example:
|
161
|
+
#
|
162
|
+
# # Accept multiple lines of text, with the prompt "QA Plan:"
|
163
|
+
# plan = CLI.prompt_multiline "QA Plan:"
|
164
|
+
#
|
165
|
+
# Returns a String containing the value the user entered
|
166
|
+
def self.prompt_multiline prompt_text
|
167
|
+
highline.ask(prompt_text) do |conf|
|
168
|
+
# accept text until the first blank line (instead of stopping at the
|
169
|
+
# first newline), to allow multiple lines of input
|
170
|
+
conf.gather = ""
|
171
|
+
conf.readline = true
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Public: Prompt user for input, but do not display what they type
|
176
|
+
#
|
177
|
+
# prompt_text - The text to display before the prompt; e.g., "Password: "
|
178
|
+
#
|
179
|
+
# Returns a String containing the value the user entered
|
180
|
+
def self.prompt_secret prompt_text
|
181
|
+
highline.ask(prompt_text) do |conf|
|
182
|
+
# do not display the text input
|
183
|
+
conf.echo = false
|
184
|
+
conf.readline = true
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.copy_to_clipboard(input)
|
189
|
+
say "Putting '#{input}' on the clipboard."
|
190
|
+
# have to do this all roundy-abouty by passing to /bin/bash, because by default, ruby performs commands with /bin/sh, which doesn't respect the -n flag on echo
|
191
|
+
# http://stackoverflow.com/questions/5059039/ruby-execute-shell-command-echo-with-n-option
|
192
|
+
perform "/bin/bash -c 'echo -n #{input}' | pbcopy", false
|
193
|
+
end
|
194
|
+
|
195
|
+
# Public: Open the given path with Mac OS X's built-in `open` command
|
196
|
+
def self.open path
|
197
|
+
perform_and_exit "open '#{path}'"
|
198
|
+
end
|
199
|
+
|
200
|
+
# Public: Instantiate an instance of HighLine
|
201
|
+
#
|
202
|
+
# This is likely a temporary method until we replace a lot of CLI's guts
|
203
|
+
# with HighLine equivalents.
|
204
|
+
#
|
205
|
+
# Returns an instance of HighLine
|
206
|
+
def self.highline
|
207
|
+
HighLine.new
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|