pgit 0.0.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.agignore +3 -0
- data/.travis.yml +1 -0
- data/README.markdown +32 -9
- data/Rakefile +12 -0
- data/bin/pgit +167 -25
- data/lib/pgit.rb +40 -10
- data/lib/pgit/bilateral/handle_back.rb +22 -0
- data/lib/pgit/bilateral/handle_choose_story.rb +31 -0
- data/lib/pgit/bilateral/story.rb +44 -0
- data/lib/pgit/command.rb +83 -0
- data/lib/pgit/command/add.rb +36 -0
- data/lib/pgit/command/application.rb +21 -0
- data/lib/pgit/command/edit.rb +36 -0
- data/lib/pgit/command/remove.rb +36 -0
- data/lib/pgit/command/run.rb +32 -0
- data/lib/pgit/command/show.rb +53 -0
- data/lib/pgit/configuration.rb +27 -3
- data/lib/pgit/current_project.rb +9 -45
- data/lib/pgit/current_project/validator.rb +2 -1
- data/lib/pgit/error/external.rb +11 -0
- data/lib/pgit/error/user.rb +12 -0
- data/lib/pgit/helpers/heredoc.rb +17 -0
- data/lib/pgit/helpers/query_methods.rb +63 -0
- data/lib/pgit/helpers/string_extensions.rb +29 -0
- data/lib/pgit/installer/bash_auto_completion.rb +57 -0
- data/lib/pgit/pivotal/collection_request.rb +21 -0
- data/lib/pgit/pivotal/individual_request.rb +47 -0
- data/lib/pgit/pivotal/iteration.rb +6 -0
- data/lib/pgit/pivotal/iterations.rb +15 -0
- data/lib/pgit/pivotal/project.rb +6 -0
- data/lib/pgit/pivotal/projects.rb +20 -0
- data/lib/pgit/pivotal/query.rb +8 -0
- data/lib/pgit/pivotal/request.rb +33 -0
- data/lib/pgit/pivotal/request/query.rb +25 -0
- data/lib/pgit/pivotal/story.rb +38 -0
- data/lib/pgit/pivotal_request_validator.rb +1 -1
- data/lib/pgit/project.rb +78 -0
- data/lib/pgit/project/add.rb +28 -0
- data/lib/pgit/project/application.rb +21 -0
- data/lib/pgit/project/interactive_adder.rb +41 -0
- data/lib/pgit/project/remove.rb +41 -0
- data/lib/pgit/project/reuse_api_token_adder.rb +48 -0
- data/lib/pgit/response_handler.rb +16 -0
- data/lib/pgit/root.rb +5 -0
- data/lib/pgit/status.rb +16 -0
- data/lib/pgit/story_branch/application.rb +3 -3
- data/lib/pgit/{name_parser.rb → story_branch/name_parser.rb} +0 -0
- data/lib/pgit/story_branch/story_id_parser.rb +11 -0
- data/lib/pgit/validators/project_validator.rb +20 -0
- data/lib/pgit/version.rb +1 -1
- data/lib/pivotal +0 -0
- data/pgit.gemspec +5 -0
- data/spec/fixtures/iterations +1 -0
- data/spec/pgit/bilateral/handle_back_spec.rb +29 -0
- data/spec/pgit/bilateral/handle_choose_story_spec.rb +17 -0
- data/spec/pgit/bilateral/story_spec.rb +178 -0
- data/spec/pgit/command/add_spec.rb +68 -0
- data/spec/pgit/command/application_spec.rb +110 -0
- data/spec/pgit/command/edit_spec.rb +61 -0
- data/spec/pgit/command/remove_spec.rb +76 -0
- data/spec/pgit/command/run_spec.rb +49 -0
- data/spec/pgit/command/show_spec.rb +95 -0
- data/spec/pgit/command_spec.rb +299 -0
- data/spec/pgit/configuration_spec.rb +121 -18
- data/spec/pgit/current_project/validator_spec.rb +2 -1
- data/spec/pgit/current_project_spec.rb +20 -71
- data/spec/pgit/{external_error_spec.rb → error/external_spec.rb} +3 -3
- data/spec/pgit/error/user_spec.rb +17 -0
- data/spec/pgit/helpers/heredoc_spec.rb +33 -0
- data/spec/pgit/helpers/query_methods_spec.rb +24 -0
- data/spec/pgit/helpers/string_extensions_spec.rb +49 -0
- data/spec/pgit/installer/bash_auto_completion_spec.rb +134 -0
- data/spec/pgit/pivotal/individual_request_spec.rb +32 -0
- data/spec/pgit/pivotal/iteration_spec.rb +19 -0
- data/spec/pgit/pivotal/iterations_spec.rb +37 -0
- data/spec/pgit/pivotal/project_spec.rb +9 -0
- data/spec/pgit/pivotal/projects_spec.rb +48 -0
- data/spec/pgit/pivotal/request/query_spec.rb +24 -0
- data/spec/pgit/pivotal/story_spec.rb +113 -0
- data/spec/pgit/pivotal_request_validator_spec.rb +3 -3
- data/spec/pgit/project/add_spec.rb +52 -0
- data/spec/pgit/project/application_spec.rb +69 -0
- data/spec/pgit/project/interactive_adder_spec.rb +45 -0
- data/spec/pgit/project/remove_spec.rb +86 -0
- data/spec/pgit/project/reuse_api_token_adder_spec.rb +41 -0
- data/spec/pgit/project_spec.rb +513 -0
- data/spec/pgit/status_spec.rb +40 -0
- data/spec/pgit/story_branch/application_spec.rb +5 -8
- data/spec/pgit/story_branch/name_parser_spec.rb +3 -3
- data/spec/pgit/story_branch/story_id_parser_spec.rb +17 -0
- data/spec/pgit/validators/project_validator_spec.rb +39 -0
- metadata +146 -21
- data/lib/pgit/configuration/layout_error.rb +0 -9
- data/lib/pgit/configuration/missing_attributes_error.rb +0 -10
- data/lib/pgit/configuration/not_found_error.rb +0 -10
- data/lib/pgit/configuration/project_missing_error.rb +0 -10
- data/lib/pgit/configuration/validator.rb +0 -41
- data/lib/pgit/current_project/no_paths_match_working_dir_error.rb +0 -10
- data/lib/pgit/external_error.rb +0 -9
- data/lib/pgit/installer/configuration.rb +0 -34
- data/lib/pgit/story.rb +0 -44
- data/spec/pgit/configuration/missing_attributes_error_spec.rb +0 -30
- data/spec/pgit/configuration/not_found_error_spec.rb +0 -17
- data/spec/pgit/configuration/project_missing_error_spec.rb +0 -30
- data/spec/pgit/configuration/validator_spec.rb +0 -79
- data/spec/pgit/current_project/no_paths_match_working_dir_error_spec.rb +0 -17
- data/spec/pgit/installer/configuration_spec.rb +0 -162
- data/spec/pgit/story_spec.rb +0 -35
data/lib/pgit/project.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'pgit'
|
2
|
+
|
3
|
+
module PGit
|
4
|
+
class Project < PGit::Pivotal::IndividualRequest
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include PGit::Helpers::QueryMethods
|
7
|
+
extend PGit::Helpers::QueryMethods
|
8
|
+
|
9
|
+
validates_with PGit::Validators::ProjectValidator
|
10
|
+
|
11
|
+
attr_writer :api_token, :id, :path
|
12
|
+
attr_reader :path, :api_token, :id, :configuration, :kind
|
13
|
+
attr_query :id, :path, :api_token
|
14
|
+
|
15
|
+
def initialize(configuration=:no_config_given,
|
16
|
+
proj={},
|
17
|
+
&block)
|
18
|
+
yield self if block_given?
|
19
|
+
@query_hash = proj
|
20
|
+
@configuration = configuration
|
21
|
+
@cmds = proj.fetch('commands') { Array.new }
|
22
|
+
set_default_queries
|
23
|
+
end
|
24
|
+
|
25
|
+
def commands=(some_commands)
|
26
|
+
@cmds = some_commands
|
27
|
+
end
|
28
|
+
|
29
|
+
def commands
|
30
|
+
build_commands(@cmds)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_hash
|
34
|
+
{
|
35
|
+
"path" => path,
|
36
|
+
"api_token" => api_token,
|
37
|
+
"id" => id,
|
38
|
+
"commands" => commands.map {|cmd| cmd.to_hash}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def save!
|
43
|
+
ensure_given_queries
|
44
|
+
raise PGit::Error::User, errors.full_messages.first unless valid?
|
45
|
+
|
46
|
+
remove_old_copy { configuration.projects = configuration.projects << self }
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove!
|
50
|
+
remove_old_copy
|
51
|
+
end
|
52
|
+
|
53
|
+
def exists?
|
54
|
+
configuration.projects.find {|p| p.path == path}
|
55
|
+
end
|
56
|
+
|
57
|
+
def sublink
|
58
|
+
"projects/#{id}"
|
59
|
+
end
|
60
|
+
private
|
61
|
+
|
62
|
+
def remove_old_copy
|
63
|
+
configuration.projects = configuration.projects.reject {|p| p.path == path}
|
64
|
+
yield if block_given?
|
65
|
+
configuration.save!
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_commands(cmds)
|
69
|
+
cmds.map do |cmd|
|
70
|
+
if cmd.respond_to?(:name) && cmd.respond_to?(:steps)
|
71
|
+
cmd
|
72
|
+
else
|
73
|
+
cmd.map { |k,v| PGit::Command.new(k, v, self) }.first
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pgit'
|
2
|
+
|
3
|
+
#TODO: Find a way to make execute! just be a call on children tasks
|
4
|
+
module PGit
|
5
|
+
class Project
|
6
|
+
class Add
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_reader :adder
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
raise PGit::Error::User, 'Project path already exists. See `pgit proj update --help.`' if app.exists?
|
13
|
+
|
14
|
+
@reuse_adder = PGit::Project::ReuseApiTokenAdder.new(app.project, app.projects)
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute!
|
18
|
+
@reuse_adder.execute!
|
19
|
+
@adder = PGit::Project::InteractiveAdder.new(@reuse_adder.project)
|
20
|
+
|
21
|
+
adder.execute!
|
22
|
+
adder.save!
|
23
|
+
|
24
|
+
puts "Successfully added the project!"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module PGit
|
4
|
+
class Project
|
5
|
+
class Application
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@project, :exists?, :save!
|
8
|
+
def_delegators :@config, :projects
|
9
|
+
attr_reader :project
|
10
|
+
|
11
|
+
def initialize(global_opts, opts, args)
|
12
|
+
@config = PGit::Configuration.new
|
13
|
+
@project = PGit::Project.new(@config) do |p|
|
14
|
+
p.path = opts["path"]
|
15
|
+
p.api_token = opts["api_token"]
|
16
|
+
p.id = opts["id"]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'pgit'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module PGit
|
5
|
+
class Project
|
6
|
+
class InteractiveAdder
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@project, :save!
|
10
|
+
attr_reader :project
|
11
|
+
|
12
|
+
def initialize(project)
|
13
|
+
@project = project
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute!
|
17
|
+
if project.api_token == :no_api_token_given
|
18
|
+
puts "What's the project api_token?"
|
19
|
+
project.api_token = STDIN.gets.chomp
|
20
|
+
end
|
21
|
+
|
22
|
+
get_projects
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_projects
|
26
|
+
projects = PGit::Pivotal::Projects.new(api_token: project.api_token).get!
|
27
|
+
question = Interactive::Question.new do |q|
|
28
|
+
q.question = "Which project do you want to associate with the working directory?"
|
29
|
+
q.options = [projects]
|
30
|
+
q.columns = [:index, :name]
|
31
|
+
end
|
32
|
+
|
33
|
+
question.ask do |response|
|
34
|
+
if response.whole_number?
|
35
|
+
project.id = projects[response.to_i].id
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'interactive'
|
2
|
+
module PGit
|
3
|
+
class Project
|
4
|
+
class Remove
|
5
|
+
include Interactive
|
6
|
+
|
7
|
+
attr_reader :project, :projects
|
8
|
+
def initialize(app)
|
9
|
+
@project = app.project
|
10
|
+
@projects = app.projects
|
11
|
+
|
12
|
+
raise PGit::Error::User, "#{@project.path} is not in the configuration file." unless @project.exists?
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute!
|
16
|
+
confirm.ask_and_wait_for_valid_response do |confirm_response|
|
17
|
+
if confirm_response.yes?
|
18
|
+
puts "Removing #{path} from the configuration file..."
|
19
|
+
project.remove!
|
20
|
+
puts "Removed."
|
21
|
+
elsif confirm_response.no?
|
22
|
+
puts "Cancelling..."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def confirm
|
30
|
+
Question.new do |c|
|
31
|
+
c.question = "Are you sure you want to remove #{path} from the configuration file?"
|
32
|
+
c.options = [:yes, :no]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def path
|
37
|
+
@project.path
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'pgit'
|
2
|
+
|
3
|
+
module PGit
|
4
|
+
class Project
|
5
|
+
class ReuseApiTokenAdder
|
6
|
+
include Interactive
|
7
|
+
|
8
|
+
attr_reader :projects, :project
|
9
|
+
def initialize(project_to_add_to, projects_in_config)
|
10
|
+
@project = project_to_add_to
|
11
|
+
@projects = projects_in_config
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute!
|
15
|
+
return false if @projects.empty?
|
16
|
+
|
17
|
+
reuse_question.ask_and_wait_for_valid_response do |reuse_response|
|
18
|
+
if reuse_response.yes?
|
19
|
+
which_to_reuse_question.ask_and_wait_for_valid_response do |which_response|
|
20
|
+
if which_response.whole_number?
|
21
|
+
project.api_token = projects[which_response.to_i].api_token
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def reuse_question
|
31
|
+
Question.new do |q|
|
32
|
+
q.question = "Do you want to reuse an api token?"
|
33
|
+
q.options = [:yes, :no]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def which_to_reuse_question
|
38
|
+
Question.new do |q|
|
39
|
+
q.question = "Which one?"
|
40
|
+
q.options = [projects.map do |proj|
|
41
|
+
OpenStruct.new(api_token: proj.api_token, path: proj.path)
|
42
|
+
end, :cancel]
|
43
|
+
q.columns = [:index, :api_token, :path]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PGit
|
2
|
+
class ResponseHandler
|
3
|
+
attr_reader :question
|
4
|
+
def execute!
|
5
|
+
if response_can_be_handled?
|
6
|
+
@question.ask do |response|
|
7
|
+
@response_handlers.each {|handler| handler.new(options(response)).execute! }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def response_can_be_handled?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/pgit/root.rb
ADDED
data/lib/pgit/status.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class PGit::Status
|
2
|
+
def initialize(global_options, options, args)
|
3
|
+
end
|
4
|
+
|
5
|
+
def execute!
|
6
|
+
current_branch = PGit::CurrentBranch.new
|
7
|
+
raise PGit::Error::User, 'The current branch is not associated with a story. Does not have a story id.' unless current_branch.story_id
|
8
|
+
story = PGit::Pivotal::Story.new(current_branch.story_id)
|
9
|
+
story_hash = story.get!
|
10
|
+
table = Terminal::Table.new do |t|
|
11
|
+
t.rows = story_hash.to_a
|
12
|
+
end
|
13
|
+
|
14
|
+
puts table
|
15
|
+
end
|
16
|
+
end
|
@@ -3,9 +3,9 @@ module PGit
|
|
3
3
|
class Application
|
4
4
|
def initialize(global_options, options, arguments)
|
5
5
|
if story_id = options[:start]
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
story = PGit::Pivotal::Story.new(story_id)
|
7
|
+
story.get!
|
8
|
+
|
9
9
|
name_parser = PGit::StoryBranch::NameParser.new(story)
|
10
10
|
story_branch = PGit::StoryBranch.new(name_parser)
|
11
11
|
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class PGit::StoryBranch::StoryIdParser
|
2
|
+
def initialize(branch_name)
|
3
|
+
@branch_name = branch_name
|
4
|
+
end
|
5
|
+
|
6
|
+
def parse
|
7
|
+
raise PGit::Error::User, "The current branch is not associated with a story. Does not have a story id." unless @branch_name.match(/\d+$/)
|
8
|
+
|
9
|
+
@branch_name.match(/\d+$/)[0]
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'pgit'
|
2
|
+
|
3
|
+
module PGit
|
4
|
+
module Validators
|
5
|
+
class ProjectValidator < ActiveModel::Validator
|
6
|
+
def validate(project)
|
7
|
+
project.get!
|
8
|
+
|
9
|
+
unless project.respond_to?(:kind)
|
10
|
+
project.errors[:curl] << "is not able to do the request. Please check your internet connection."
|
11
|
+
end
|
12
|
+
#
|
13
|
+
if project.respond_to?(:kind) && project.kind == 'error'
|
14
|
+
project.errors[:base] << "Project api_token or id is not valid."
|
15
|
+
puts project.errors.full_messages
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/pgit/version.rb
CHANGED
data/lib/pivotal
ADDED
File without changes
|
data/pgit.gemspec
CHANGED
@@ -20,7 +20,12 @@ spec = Gem::Specification.new do |s|
|
|
20
20
|
s.add_development_dependency('rspec', '~> 3.1')
|
21
21
|
s.add_development_dependency('coveralls', '~> 0.7')
|
22
22
|
s.add_development_dependency('simplecov', '~> 0.9')
|
23
|
+
s.add_development_dependency('pry-byebug', '~> 3.0.1')
|
24
|
+
s.add_development_dependency('byebug', '~> 3.5.1')
|
23
25
|
s.add_runtime_dependency('gli','2.12.2')
|
26
|
+
s.add_runtime_dependency('activemodel','~> 4.2.0')
|
27
|
+
s.add_runtime_dependency('rainbow', '~> 2.0.0')
|
28
|
+
s.add_runtime_dependency('interactive', '~> 0.6.0')
|
24
29
|
s.license = 'MIT'
|
25
30
|
s.requirements << 'At least one project that uses Pivotal Tracker and Git'
|
26
31
|
s.requirements << 'cURL, at least 7.35.0'
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"kind":"iteration","number":15,"project_id":1228944,"team_strength":1,"stories":[{"kind":"story","id":90501214,"project_id":1228944,"name":"fix bug where calling project.get! defines methods on ALL projects. Use define_singleton_method.","story_type":"bug","current_state":"accepted","accepted_at":"2015-03-17T22:08:23Z","requested_by_id":1121520,"owned_by_id":1121520,"owner_ids":[1121520],"labels":[],"created_at":"2015-03-17T13:02:11Z","updated_at":"2015-03-17T22:12:28Z","url":"https://www.pivotaltracker.com/story/show/90501214"},{"kind":"story","id":90285028,"project_id":1228944,"name":"pgit proj asks if you want to reuse an api_token","description":"`Do you want to reuse an api_token? [y/n]`\n - y\n - `Which one? (1/2/c)\n - 1. /some/path: token\n - 2. /some/other/path: another_token\n ","story_type":"feature","current_state":"accepted","estimate":1,"accepted_at":"2015-03-18T01:11:47Z","requested_by_id":1121520,"owner_ids":[],"labels":[{"kind":"label","id":10378716,"project_id":1228944,"name":"project","created_at":"2015-01-05T11:42:35Z","updated_at":"2015-01-05T11:42:35Z"}],"created_at":"2015-03-13T14:29:42Z","updated_at":"2015-03-18T02:18:32Z","url":"https://www.pivotaltracker.com/story/show/90285028"},{"kind":"story","id":90566322,"project_id":1228944,"name":"pgit install no longer attempts to save an example config file in favor of using pgit proj add","story_type":"chore","current_state":"accepted","accepted_at":"2015-03-18T01:11:48Z","requested_by_id":1121520,"owned_by_id":1121520,"owner_ids":[1121520],"labels":[{"kind":"label","id":10378716,"project_id":1228944,"name":"project","created_at":"2015-01-05T11:42:35Z","updated_at":"2015-01-05T11:42:35Z"}],"created_at":"2015-03-18T01:07:29Z","updated_at":"2015-03-18T02:18:41Z","url":"https://www.pivotaltracker.com/story/show/90566322"},{"kind":"story","id":85418516,"project_id":1228944,"name":"pgit project rm","description":"Which project do you want to remove? [0/1/q]\n0 -- /Developer/blah\n1 -- /Developer/blah/blah\nq -- quit\n\nAre you sure you want to remove \"/Developer/blah\"? [y/c/q]\n\nIf user answers yes, proceed, \"Removing /Developer/blah as a PGit project.\"\nif user answers cancel, go back to first question\nIf user answers quit, then say you're quitting and quit.","story_type":"feature","current_state":"accepted","estimate":1,"accepted_at":"2015-03-20T00:22:35Z","requested_by_id":1121520,"owned_by_id":1121520,"owner_ids":[1121520],"labels":[{"kind":"label","id":10378716,"project_id":1228944,"name":"project","created_at":"2015-01-05T11:42:35Z","updated_at":"2015-01-05T11:42:35Z"}],"created_at":"2015-01-05T11:26:32Z","updated_at":"2015-03-20T00:22:34Z","url":"https://www.pivotaltracker.com/story/show/85418516"},{"kind":"story","id":90748872,"project_id":1228944,"name":"pgit story should display list of stories for the current and backlog iterations.","description":"`pgit story`, by default, will display a list of stories for the current iteration. It will ask, which story are you interested in? [0/1/2/3/4/5/c]\n 0 -- [feature-type] [points] [title] [assignment]\n 1 -- [feature-type] [points] [title] [assignment]\nIt should display information about the story, color coded.\n\n\n","story_type":"feature","current_state":"started","estimate":2,"requested_by_id":1121520,"owned_by_id":1121520,"owner_ids":[1121520],"labels":[{"kind":"label","id":10420512,"project_id":1228944,"name":"story","created_at":"2015-01-08T12:25:39Z","updated_at":"2015-01-08T12:25:39Z"}],"created_at":"2015-03-20T00:56:29Z","updated_at":"2015-03-22T12:35:20Z","url":"https://www.pivotaltracker.com/story/show/90748872"}],"start":"2015-03-16T04:00:00Z","finish":"2015-03-23T04:00:00Z"},{"kind":"iteration","number":16,"project_id":1228944,"team_strength":1,"stories":[],"start":"2015-03-23T04:00:00Z","finish":"2015-03-30T04:00:00Z"},{"kind":"iteration","number":17,"project_id":1228944,"team_strength":1,"stories":[{"kind":"story","id":90833342,"project_id":1228944,"name":"make getting project ids easier when adding a project","description":"```{\"kind\":\"me\",\"id\":1121520,\"name\":\"Edderic\",\"initials\":\"ED\",\"username\":\"edderic\",\"time_zone\":{\"kind\":\"time_zone\",\"olson_name\":\"America/Los_Angeles\",\"offset\":\"-07:00\"},\"api_token\":\"302ebab4f92dcc77dbee9d18bf09e576\",\"has_google_identity\":true,\"projects\":[{\"kind\":\"membership_summary\",\"id\":3492008,\"project_id\":915432,\"project_name\":\"ideabind\",\"project_color\":\"155f8b\",\"role\":\"owner\",\"last_viewed_at\":\"2015-02-10T01:26:35Z\"},{\"kind\":\"membership_summary\",\"id\":3570108,\"project_id\":932970,\"project_name\":\"palace\",\"project_color\":\"ee61f0\",\"role\":\"owner\",\"last_viewed_at\":\"2013-12-04T19:48:46Z\"},{\"kind\":\"membership_summary\",\"id\":3593330,\"project_id\":938010,\"project_name\":\"Ojibss\",\"project_color\":\"b800bb\",\"role\":\"owner\",\"last_viewed_at\":\"2013-10-28T15:25:44Z\"},{\"kind\":\"membership_summary\",\"id\":3662734,\"project_id\":953934,\"project_name\":\"QuidPlays\",\"project_color\":\"00a3d6\",\"role\":\"owner\",\"last_viewed_at\":\"2013-11-11T10:14:36Z\"},{\"kind\":\"membership_summary\",\"id\":3699234,\"project_id\":961764,\"project_name\":\"Granuvolver\",\"project_color\":\"d82b00\",\"role\":\"owner\",\"last_viewed_at\":\"2014-01-15T19:37:38Z\"},{\"kind\":\"membership_summary\",\"id\":3801016,\"project_id\":985420,\"project_name\":\"Adjust Brightness Script\",\"project_color\":\"ffc100\",\"role\":\"owner\",\"last_viewed_at\":\"2014-01-05T02:54:46Z\"},{\"kind\":\"membership_summary\",\"id\":4064208,\"project_id\":1041282,\"project_name\":\"Training\",\"project_color\":\"818182\",\"role\":\"owner\",\"last_viewed_at\":\"2014-03-20T00:57:48Z\"},{\"kind\":\"membership_summary\",\"id\":4434754,\"project_id\":1120660,\"project_name\":\"Cooking Assistant\",\"project_color\":\"e46642\",\"role\":\"owner\",\"last_viewed_at\":\"2014-11-13T00:34:00Z\"},{\"kind\":\"membership_summary\",\"id\":4948554,\"project_id\":1228944,\"project_name\":\"PGit\",\"project_color\":\"8100ea\",\"role\":\"owner\",\"last_viewed_at\":\"2015-03-21T14:25:10Z\"},{\"kind\":\"membership_summary\",\"id\":5271772,\"project_id\":1300676,\"project_name\":\"Interactive\",\"project_color\":\"555555\",\"role\":\"owner\",\"last_viewed_at\":\"2015-03-21T13:15:55Z\"}],\"email\":\"edderic@gmail.com\",\"receives_in_app_notifications\":true,\"created_at\":\"2013-09-18T19:08:50Z\",\"updated_at\":\"2015-03-21T15:04:26Z\"}```","story_type":"feature","current_state":"unstarted","estimate":2,"requested_by_id":1121520,"owner_ids":[],"labels":[{"kind":"label","id":10378716,"project_id":1228944,"name":"project","created_at":"2015-01-05T11:42:35Z","updated_at":"2015-01-05T11:42:35Z"}],"created_at":"2015-03-21T15:34:55Z","updated_at":"2015-03-21T15:42:18Z","url":"https://www.pivotaltracker.com/story/show/90833342"}],"start":"2015-03-30T04:00:00Z","finish":"2015-04-06T04:00:00Z"},{"kind":"iteration","number":18,"project_id":1228944,"team_strength":1,"stories":[{"kind":"story","id":86168300,"project_id":1228944,"name":"pgit project mv --src=source_path --dest=destination_path","story_type":"feature","current_state":"unstarted","estimate":1,"requested_by_id":1121520,"owner_ids":[],"labels":[{"kind":"label","id":10378716,"project_id":1228944,"name":"project","created_at":"2015-01-05T11:42:35Z","updated_at":"2015-01-05T11:42:35Z"}],"created_at":"2015-01-15T00:18:57Z","updated_at":"2015-01-15T00:24:26Z","url":"https://www.pivotaltracker.com/story/show/86168300"}],"start":"2015-04-06T04:00:00Z","finish":"2015-04-13T04:00:00Z"},{"kind":"iteration","number":19,"project_id":1228944,"team_strength":1,"stories":[{"kind":"story","id":86169384,"project_id":1228944,"name":"pgit project show","story_type":"feature","current_state":"unstarted","estimate":1,"requested_by_id":1121520,"owner_ids":[],"labels":[],"created_at":"2015-01-15T00:29:39Z","updated_at":"2015-01-15T00:30:39Z","url":"https://www.pivotaltracker.com/story/show/86169384"},{"kind":"story","id":86366000,"project_id":1228944,"name":"Move models into their own folder","story_type":"chore","current_state":"unstarted","requested_by_id":1121520,"owner_ids":[],"labels":[],"created_at":"2015-01-17T14:11:49Z","updated_at":"2015-02-01T22:57:23Z","url":"https://www.pivotaltracker.com/story/show/86366000"},{"kind":"story","id":86365990,"project_id":1228944,"name":"Move Command-Line classes to their own folder","story_type":"chore","current_state":"unstarted","requested_by_id":1121520,"owner_ids":[],"labels":[],"created_at":"2015-01-17T14:10:57Z","updated_at":"2015-02-01T22:57:25Z","url":"https://www.pivotaltracker.com/story/show/86365990"}],"start":"2015-04-13T04:00:00Z","finish":"2015-04-20T04:00:00Z"}]
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PGit::Bilateral::HandleBack do
|
4
|
+
describe '#execute!' do
|
5
|
+
it 'should call #reask on the parent_question' do
|
6
|
+
stories = double('stories')
|
7
|
+
question = instance_double('Interactive::Question', reask!: nil)
|
8
|
+
response = instance_double('Interactive::Response', back?: true)
|
9
|
+
options = {response: response, parent_question: question, stories: stories}
|
10
|
+
|
11
|
+
back_handler = PGit::Bilateral::HandleBack.new(options)
|
12
|
+
back_handler.execute!
|
13
|
+
|
14
|
+
expect(question).to have_received(:reask!)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should not call #reask on the parent question if response is not back' do
|
18
|
+
stories = double('stories')
|
19
|
+
question = instance_double('Interactive::Question', reask!: nil)
|
20
|
+
response = instance_double('Interactive::Response', back?: false)
|
21
|
+
options = {response: response, parent_question: question, stories: stories}
|
22
|
+
|
23
|
+
back_handler = PGit::Bilateral::HandleBack.new(options)
|
24
|
+
back_handler.execute!
|
25
|
+
|
26
|
+
expect(question).not_to have_received(:reask!)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PGit::Bilateral::HandleChooseStory do
|
4
|
+
it 'should create the branch' do
|
5
|
+
some_story = double('PGit::Story')
|
6
|
+
chosen_story = double('PGit::Story')
|
7
|
+
options = {response: '1', stories: [some_story, chosen_story]}
|
8
|
+
story_branch = double('PGit::StoryBranch', start: true)
|
9
|
+
|
10
|
+
name_parser = double('PGit::StoryBranch::NameParser')
|
11
|
+
allow(PGit::StoryBranch::NameParser).to receive(:new).with(chosen_story).and_return(name_parser)
|
12
|
+
allow(PGit::StoryBranch).to receive(:new).with(name_parser).and_return(story_branch)
|
13
|
+
handle_choose_story = PGit::Bilateral::HandleChooseStory.new(options)
|
14
|
+
|
15
|
+
expect(story_branch).to have_received(:start)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PGit::Bilateral::Story do
|
4
|
+
describe 'scope is bad scope' do
|
5
|
+
it 'should raise an error' do
|
6
|
+
project = instance_double('PGit::Project', id: 12345, api_token: 'someapitoken')
|
7
|
+
options = { scope: 'blah' }
|
8
|
+
query = {scope: :current}
|
9
|
+
story_1 = instance_double('PGit::Story',
|
10
|
+
story_type: 'chore',
|
11
|
+
estimate: 2,
|
12
|
+
name: 'some story',
|
13
|
+
current_state: 'unstarted')
|
14
|
+
story_2 = instance_double('PGit::Story',
|
15
|
+
story_type: 'feature',
|
16
|
+
estimate: 3,
|
17
|
+
name: 'some other story',
|
18
|
+
current_state: 'unstarted')
|
19
|
+
stories = [story_1, story_2]
|
20
|
+
iteration_1 = double('PGit::Pivotal::Iteration', stories: stories)
|
21
|
+
iterations = [iteration_1]
|
22
|
+
iterations_obj = double('PGit::Pivotal::Iterations', get!: iterations)
|
23
|
+
allow(PGit::Pivotal::Iterations).
|
24
|
+
to receive(:new).with(query).and_return(iterations_obj)
|
25
|
+
config = double('config', :question= => nil, :options= => nil, :columns= => nil)
|
26
|
+
question = instance_double('Interactive::Question', ask: nil)
|
27
|
+
allow(Interactive::Question).to receive(:new).and_yield(config).and_return(question)
|
28
|
+
expect{ PGit::Bilateral::Story.new(options) }.to raise_error(PGit::Error::User, 'Invalid options. See `pgit iteration -h` for valid options.')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#execute!' do
|
33
|
+
describe 'scope is done' do
|
34
|
+
it 'should show the done ones' do
|
35
|
+
project = instance_double('PGit::Project', id: 12345, api_token: 'someapitoken')
|
36
|
+
options = { scope: :done }
|
37
|
+
query = {scope: :done}
|
38
|
+
story_1 = instance_double('PGit::Story',
|
39
|
+
story_type: 'chore',
|
40
|
+
estimate: 2,
|
41
|
+
name: 'some story',
|
42
|
+
current_state: 'accepted')
|
43
|
+
story_2 = instance_double('PGit::Story',
|
44
|
+
story_type: 'feature',
|
45
|
+
estimate: 3,
|
46
|
+
name: 'some other story',
|
47
|
+
current_state: 'accepted')
|
48
|
+
stories = [story_1, story_2]
|
49
|
+
iteration_1 = double('PGit::Pivotal::Iteration', stories: stories)
|
50
|
+
iterations = [iteration_1]
|
51
|
+
iterations_obj = double('PGit::Pivotal::Iterations', get!: iterations)
|
52
|
+
allow(PGit::Pivotal::Iterations).
|
53
|
+
to receive(:new).with(query).and_return(iterations_obj)
|
54
|
+
config = double('config', :question= => nil, :options= => nil, :columns= => nil)
|
55
|
+
question = instance_double('Interactive::Question', ask: nil)
|
56
|
+
allow(Interactive::Question).to receive(:new).and_yield(config).and_return(question)
|
57
|
+
interactive_story = PGit::Bilateral::Story.new(options)
|
58
|
+
interactive_story.execute!
|
59
|
+
|
60
|
+
expect(config).to have_received(:question=).with("Which story do you want to branch-ify?")
|
61
|
+
expect(config).to have_received(:options=).with([stories, :back])
|
62
|
+
expect(config).to have_received(:columns=).with([:index, :story_type, :estimate, :name, :current_state])
|
63
|
+
expect(question).to have_received(:ask)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'scope is backlog' do
|
68
|
+
it 'should show the backlog stories' do
|
69
|
+
project = instance_double('PGit::Project', id: 12345, api_token: 'someapitoken')
|
70
|
+
options = { scope: :backlog }
|
71
|
+
query = {scope: :backlog}
|
72
|
+
story_1 = instance_double('PGit::Story',
|
73
|
+
story_type: 'chore',
|
74
|
+
estimate: 2,
|
75
|
+
name: 'some story',
|
76
|
+
current_state: 'unstarted')
|
77
|
+
story_2 = instance_double('PGit::Story',
|
78
|
+
story_type: 'feature',
|
79
|
+
estimate: 3,
|
80
|
+
name: 'some other story',
|
81
|
+
current_state: 'unstarted')
|
82
|
+
stories = [story_1, story_2]
|
83
|
+
iteration_1 = double('PGit::Pivotal::Iteration', stories: stories)
|
84
|
+
iterations = [iteration_1]
|
85
|
+
iterations_obj = double('PGit::Pivotal::Iterations', get!: iterations)
|
86
|
+
allow(PGit::Pivotal::Iterations).
|
87
|
+
to receive(:new).with(query).and_return(iterations_obj)
|
88
|
+
config = double('config', :question= => nil, :options= => nil, :columns= => nil)
|
89
|
+
question = instance_double('Interactive::Question', ask: nil)
|
90
|
+
response = instance_double('Interactive::Response', valid?: true)
|
91
|
+
allow(question).to receive(:ask).and_yield(response)
|
92
|
+
allow(Interactive::Question).to receive(:new).and_yield(config).and_return(question)
|
93
|
+
handle_choose_story = instance_double('PGit::Bilateral::HandleChooseStory',
|
94
|
+
execute!: nil)
|
95
|
+
interactive_story = PGit::Bilateral::Story.new(options)
|
96
|
+
response_options = {response: response, stories: stories, parent_question: interactive_story.question}
|
97
|
+
allow(PGit::Bilateral::HandleChooseStory).to receive(:new).with(response_options).
|
98
|
+
and_return(handle_choose_story)
|
99
|
+
interactive_story.execute!
|
100
|
+
|
101
|
+
expect(config).to have_received(:question=).with("Which story do you want to branch-ify?")
|
102
|
+
expect(config).to have_received(:options=).with([stories, :back])
|
103
|
+
expect(config).to have_received(:columns=).with([:index, :story_type, :estimate, :name, :current_state])
|
104
|
+
expect(question).to have_received(:ask)
|
105
|
+
expect(handle_choose_story).to have_received(:execute!)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'scope is current' do
|
110
|
+
it 'should show a list of stories for the current iteration' do
|
111
|
+
project = instance_double('PGit::Project', id: 12345, api_token: 'someapitoken')
|
112
|
+
options = { scope: :current }
|
113
|
+
query = {scope: :current}
|
114
|
+
story_1 = instance_double('PGit::Story',
|
115
|
+
story_type: 'chore',
|
116
|
+
estimate: 2,
|
117
|
+
name: 'some story',
|
118
|
+
current_state: 'unstarted')
|
119
|
+
story_2 = instance_double('PGit::Story',
|
120
|
+
story_type: 'feature',
|
121
|
+
estimate: 3,
|
122
|
+
name: 'some other story',
|
123
|
+
current_state: 'unstarted')
|
124
|
+
stories = [story_1, story_2]
|
125
|
+
iteration_1 = double('PGit::Pivotal::Iteration', stories: stories)
|
126
|
+
iterations = [iteration_1]
|
127
|
+
iterations_obj = double('PGit::Pivotal::Iterations', get!: iterations)
|
128
|
+
allow(PGit::Pivotal::Iterations).
|
129
|
+
to receive(:new).with(query).and_return(iterations_obj)
|
130
|
+
config = double('config', :question= => nil, :options= => nil, :columns= => nil)
|
131
|
+
question = instance_double('Interactive::Question', ask: nil)
|
132
|
+
allow(Interactive::Question).to receive(:new).and_yield(config).and_return(question)
|
133
|
+
interactive_story = PGit::Bilateral::Story.new(options)
|
134
|
+
interactive_story.execute!
|
135
|
+
|
136
|
+
expect(config).to have_received(:question=).with("Which story do you want to branch-ify?")
|
137
|
+
expect(config).to have_received(:options=).with([stories, :back])
|
138
|
+
expect(config).to have_received(:columns=).with([:index, :story_type, :estimate, :name, :current_state])
|
139
|
+
expect(question).to have_received(:ask)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'scope is current_backlog' do
|
144
|
+
it 'show a list of stories for the current and backlog iteration' do
|
145
|
+
project = instance_double('PGit::Project', id: 12345, api_token: 'someapitoken')
|
146
|
+
|
147
|
+
options = { scope: :current_backlog }
|
148
|
+
query = {scope: :current_backlog}
|
149
|
+
story_1 = instance_double('PGit::Story',
|
150
|
+
story_type: 'chore',
|
151
|
+
estimate: 2,
|
152
|
+
name: 'some story',
|
153
|
+
current_state: 'unstarted')
|
154
|
+
story_2 = instance_double('PGit::Story',
|
155
|
+
story_type: 'feature',
|
156
|
+
estimate: 3,
|
157
|
+
name: 'some other story',
|
158
|
+
current_state: 'unstarted')
|
159
|
+
stories = [story_1, story_2]
|
160
|
+
iteration_1 = double('PGit::Pivotal::Iteration', stories: stories)
|
161
|
+
iterations = [iteration_1]
|
162
|
+
iterations_obj = double('PGit::Pivotal::Iterations', get!: iterations)
|
163
|
+
allow(PGit::Pivotal::Iterations).
|
164
|
+
to receive(:new).with(query).and_return(iterations_obj)
|
165
|
+
config = double('config', :question= => nil, :options= => nil, :columns= => nil)
|
166
|
+
question = instance_double('Interactive::Question', ask: nil)
|
167
|
+
allow(Interactive::Question).to receive(:new).and_yield(config).and_return(question)
|
168
|
+
interactive_story = PGit::Bilateral::Story.new(options)
|
169
|
+
interactive_story.execute!
|
170
|
+
|
171
|
+
expect(config).to have_received(:question=).with("Which story do you want to branch-ify?")
|
172
|
+
expect(config).to have_received(:options=).with([stories, :back])
|
173
|
+
expect(config).to have_received(:columns=).with([:index, :story_type, :estimate, :name, :current_state])
|
174
|
+
expect(question).to have_received(:ask)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|