crab 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. data/README.md +0 -1
  2. data/bin/crab +27 -14
  3. data/bin/crab-help +10 -2
  4. data/bin/crab-it +25 -11
  5. data/bin/crab-it-help +11 -2
  6. data/bin/crab-it-list +25 -15
  7. data/bin/crab-iteration +25 -11
  8. data/bin/crab-iteration-help +11 -2
  9. data/bin/crab-iteration-list +25 -15
  10. data/bin/crab-login +24 -13
  11. data/bin/crab-logout +22 -9
  12. data/bin/crab-project +42 -32
  13. data/bin/crab-rel +25 -11
  14. data/bin/crab-rel-help +12 -3
  15. data/bin/crab-rel-list +23 -15
  16. data/bin/crab-release +25 -11
  17. data/bin/crab-release-help +12 -3
  18. data/bin/crab-release-list +23 -15
  19. data/bin/crab-st +24 -11
  20. data/bin/crab-st-add +18 -10
  21. data/bin/crab-st-change +53 -39
  22. data/bin/crab-st-create +18 -10
  23. data/bin/crab-st-del +19 -11
  24. data/bin/crab-st-delete +19 -11
  25. data/bin/crab-st-find +32 -21
  26. data/bin/crab-st-help +11 -2
  27. data/bin/crab-st-list +32 -21
  28. data/bin/crab-st-ls +32 -21
  29. data/bin/crab-st-move +26 -14
  30. data/bin/crab-st-mv +26 -14
  31. data/bin/crab-st-new +18 -10
  32. data/bin/crab-st-pull +28 -20
  33. data/bin/crab-st-ren +26 -14
  34. data/bin/crab-st-rename +26 -14
  35. data/bin/crab-st-rm +19 -11
  36. data/bin/crab-st-show +19 -11
  37. data/bin/crab-st-up +53 -39
  38. data/bin/crab-st-update +53 -39
  39. data/bin/crab-story +24 -11
  40. data/bin/crab-story-add +18 -10
  41. data/bin/crab-story-change +53 -39
  42. data/bin/crab-story-create +18 -10
  43. data/bin/crab-story-del +19 -11
  44. data/bin/crab-story-delete +19 -11
  45. data/bin/crab-story-diff +54 -0
  46. data/bin/crab-story-find +32 -21
  47. data/bin/crab-story-help +11 -2
  48. data/bin/crab-story-list +32 -21
  49. data/bin/crab-story-ls +32 -21
  50. data/bin/crab-story-move +26 -14
  51. data/bin/crab-story-mv +26 -14
  52. data/bin/crab-story-new +18 -10
  53. data/bin/crab-story-pull +28 -20
  54. data/bin/crab-story-ren +26 -14
  55. data/bin/crab-story-rename +26 -14
  56. data/bin/crab-story-rm +19 -11
  57. data/bin/crab-story-show +19 -11
  58. data/bin/crab-story-up +53 -39
  59. data/bin/crab-story-update +53 -39
  60. data/bin/crab-tc +24 -11
  61. data/bin/crab-tc-add +32 -20
  62. data/bin/crab-tc-change +18 -8
  63. data/bin/crab-tc-create +32 -20
  64. data/bin/crab-tc-del +18 -10
  65. data/bin/crab-tc-delete +18 -10
  66. data/bin/crab-tc-find +32 -21
  67. data/bin/crab-tc-help +11 -2
  68. data/bin/crab-tc-list +32 -21
  69. data/bin/crab-tc-ls +32 -21
  70. data/bin/crab-tc-new +32 -20
  71. data/bin/crab-tc-rm +18 -10
  72. data/bin/crab-tc-show +28 -15
  73. data/bin/crab-tc-up +18 -8
  74. data/bin/crab-tc-update +18 -8
  75. data/bin/crab-testcase +24 -11
  76. data/bin/crab-testcase-add +32 -20
  77. data/bin/crab-testcase-change +18 -8
  78. data/bin/crab-testcase-create +32 -20
  79. data/bin/crab-testcase-del +18 -10
  80. data/bin/crab-testcase-delete +18 -10
  81. data/bin/crab-testcase-find +32 -21
  82. data/bin/crab-testcase-help +11 -2
  83. data/bin/crab-testcase-list +32 -21
  84. data/bin/crab-testcase-ls +32 -21
  85. data/bin/crab-testcase-new +32 -20
  86. data/bin/crab-testcase-rm +18 -10
  87. data/bin/crab-testcase-show +28 -15
  88. data/bin/crab-testcase-up +18 -8
  89. data/bin/crab-testcase-update +18 -8
  90. data/bin/crab-truncate +1 -0
  91. data/bin/crab-version +2 -1
  92. data/features/subcommand-help.feature +1 -0
  93. data/lib/crab.rb +2 -0
  94. data/lib/crab/cucumber_to_rally_adapter.rb +48 -0
  95. data/lib/crab/rally.rb +21 -1
  96. data/lib/crab/utilities.rb +10 -2
  97. data/lib/crab/version.rb +1 -1
  98. metadata +7 -4
@@ -1,18 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
2
  # vim: set ft=ruby:
3
+ require 'crab'
3
4
 
4
- cmd = ARGV.shift # get the subcommand
5
+ class Crab::StoryMain
5
6
 
6
- case cmd
7
- when "-h", "--help", NilClass
8
- system "crab-story-help"
9
- exit 0
10
- end
7
+ class << self
8
+
9
+ include Crab::Utilities
10
+
11
+ def run(args=ARGV)
12
+ cmd = args.shift # get the subcommand
11
13
 
12
- unless system("crab-story-#{cmd}", *ARGV)
13
- if $?.exitstatus == 127 # bash 'command not found'
14
- $stderr.puts "Unknown subcommand \"story #{cmd}\""
15
- system "crab-story-help"
16
- exit 127
14
+ case cmd
15
+ when "-h", "--help", NilClass
16
+ system "crab-story-help"
17
+ exit 0
18
+ end
19
+
20
+ unless system("crab-story-#{cmd}", *args)
21
+ if $?.exitstatus == 127 # bash 'command not found'
22
+ logger.error "Unknown subcommand \"story #{cmd}\""
23
+ system "crab-story-help"
24
+ exit 1
25
+ end
26
+ end
27
+ end
17
28
  end
18
29
  end
30
+
31
+ Crab::StoryMain.run
@@ -1,19 +1,27 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
2
3
  require 'crab'
3
4
 
4
- opts = Trollop::options do
5
- banner <<-BANNER
5
+ class Crab::StoryCreate
6
+
7
+ def self.run(args=ARGV)
8
+ opts = Trollop::options(args) do
9
+ banner <<-BANNER
6
10
  crab story create: create a new story in Rally
7
11
 
8
12
  Usage: crab story create <name> [options*]
9
- BANNER
10
- opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
11
- end
13
+ BANNER
14
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
15
+ end
12
16
 
13
- name = ARGV.join(" ")
14
- Trollop::die "Please specify a name for the story" if name.blank?
17
+ name = args.join(" ")
18
+ Trollop::die "Please specify a name for the story" if name.blank?
15
19
 
16
- Crab::Rally.new(opts[:dry]) do |rally|
17
- story = rally.create_story :name => name
18
- puts "#{story.formatted_id}: #{story.name} (#{story.state})"
20
+ Crab::Rally.new(opts[:dry]) do |rally|
21
+ story = rally.create_story :name => name
22
+ puts "#{story.formatted_id}: #{story.name} (#{story.state})"
23
+ end
24
+ end
19
25
  end
26
+
27
+ Crab::StoryCreate.run
@@ -1,59 +1,73 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
2
3
  require 'crab'
3
4
 
4
- include Crab::Utilities
5
+ class Crab::StoryUpdate
5
6
 
6
- cmd_opts = Trollop::options do
7
- banner <<-BANNER
7
+ class << self
8
+
9
+ include Crab::Utilities
10
+
11
+ def run(args=ARGV)
12
+
13
+ cmd_opts = Trollop::options(args) do
14
+ banner <<-BANNER
8
15
  crab story update: update a story in Rally
9
16
 
10
17
  Usage: crab story update <id> [options*]
11
- BANNER
12
- opt :name, "Name (title)", :type => String, :short => "-n"
13
- opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
14
- opt :estimate, "Estimate", :type => :int, :short => "-e"
15
- opt :iteration, "Iteration", :type => String, :short => "-i"
16
- opt :release, "Release", :type => String, :short => "-r"
17
- opt :blocked, "Blocked", :short => "-b"
18
- opt :unblocked, "Unblocked", :short => "-u"
19
- opt :parent, "Parent", :type => String, :short => "-p"
20
- opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
21
- end
18
+ BANNER
19
+ opt :name, "Name (title)", :type => String, :short => "-n"
20
+ opt :description, "Description", :type => String, :short => "-d"
21
+ opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
22
+ opt :estimate, "Estimate", :type => :int, :short => "-e"
23
+ opt :iteration, "Iteration", :type => String, :short => "-i"
24
+ opt :release, "Release", :type => String, :short => "-r"
25
+ opt :blocked, "Blocked", :short => "-b"
26
+ opt :unblocked, "Unblocked", :short => "-u"
27
+ opt :parent, "Parent", :type => String, :short => "-p"
28
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
29
+ end
22
30
 
23
- Trollop::die "No story given" if ARGV.empty?
24
- Trollop::die "Nothing to update. Please provide some options" unless cmd_opts.any? {|k, v| k.to_s =~ /_given$/ }
31
+ Trollop::die "No story given" if args.empty?
32
+ Trollop::die "Nothing to update. Please provide some options" unless cmd_opts.any? {|k, v| k.to_s =~ /_given$/ }
25
33
 
26
- opts = {}
27
- opts[:name] = cmd_opts[:name] if cmd_opts[:name_given]
28
- opts[:schedule_state] = state_from(cmd_opts[:state]) if cmd_opts[:state_given]
34
+ opts = {}
35
+ opts[:name] = cmd_opts[:name] if cmd_opts[:name_given]
36
+ opts[:description] = cmd_opts[:description] if cmd_opts[:description_given]
37
+ opts[:schedule_state] = state_from(cmd_opts[:state]) if cmd_opts[:state_given]
29
38
 
30
- if cmd_opts[:estimate_given]
31
- opts[:plan_estimate] = cmd_opts[:estimate] # nobody is going to remember "Plan Estimate", really
32
- end
39
+ if cmd_opts[:estimate_given]
40
+ opts[:plan_estimate] = cmd_opts[:estimate] # nobody is going to remember "Plan Estimate", really
41
+ end
33
42
 
34
- opts[:blocked] = cmd_opts[:blocked] if cmd_opts[:blocked_given]
35
- opts[:blocked] = !cmd_opts[:unblocked] if cmd_opts[:unblocked_given]
43
+ opts[:blocked] = cmd_opts[:blocked] if cmd_opts[:blocked_given]
44
+ opts[:blocked] = !cmd_opts[:unblocked] if cmd_opts[:unblocked_given]
36
45
 
37
- Crab::Rally.new(opts[:dry]) do |rally|
38
- rally.connect
46
+ Crab::Rally.new(opts[:dry]) do |rally|
39
47
 
40
- story = rally.find_story_with_id ARGV.first
48
+ story = rally.find_story_with_id args.first
41
49
 
42
- if cmd_opts[:iteration_given]
43
- opts[:iteration] = rally.find_iteration_by_name cmd_opts[:iteration], story.rally_object.project
44
- end
50
+ if cmd_opts[:iteration_given]
51
+ opts[:iteration] = rally.find_iteration_by_name cmd_opts[:iteration], story.rally_object.project
52
+ end
45
53
 
46
- if cmd_opts[:release_given]
47
- opts[:release] = rally.find_release_by_name cmd_opts[:release], story.rally_object.project
48
- end
54
+ if cmd_opts[:release_given]
55
+ opts[:release] = rally.find_release_by_name cmd_opts[:release], story.rally_object.project
56
+ end
49
57
 
50
- if cmd_opts[:parent_given]
51
- opts[:parent] = rally.find_story_with_id(cmd_opts[:parent]).rally_object
52
- end
58
+ if cmd_opts[:parent_given]
59
+ opts[:parent] = rally.find_story_with_id(cmd_opts[:parent]).rally_object
60
+ end
61
+
62
+ opts[:name] = story.name if opts[:name].blank?
53
63
 
54
- opts[:name] = story.name if opts[:name].blank?
64
+ story.update opts
55
65
 
56
- story.update opts
66
+ puts "#{story.formatted_id}: #{story.name} (#{story.state})"
67
+ end
57
68
 
58
- puts "#{story.formatted_id}: #{story.name} (#{story.state})"
69
+ end
70
+ end
59
71
  end
72
+
73
+ Crab::StoryUpdate.run
@@ -1,19 +1,27 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
2
3
  require 'crab'
3
4
 
4
- opts = Trollop::options do
5
- banner <<-BANNER
5
+ class Crab::StoryCreate
6
+
7
+ def self.run(args=ARGV)
8
+ opts = Trollop::options(args) do
9
+ banner <<-BANNER
6
10
  crab story create: create a new story in Rally
7
11
 
8
12
  Usage: crab story create <name> [options*]
9
- BANNER
10
- opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
11
- end
13
+ BANNER
14
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
15
+ end
12
16
 
13
- name = ARGV.join(" ")
14
- Trollop::die "Please specify a name for the story" if name.blank?
17
+ name = args.join(" ")
18
+ Trollop::die "Please specify a name for the story" if name.blank?
15
19
 
16
- Crab::Rally.new(opts[:dry]) do |rally|
17
- story = rally.create_story :name => name
18
- puts "#{story.formatted_id}: #{story.name} (#{story.state})"
20
+ Crab::Rally.new(opts[:dry]) do |rally|
21
+ story = rally.create_story :name => name
22
+ puts "#{story.formatted_id}: #{story.name} (#{story.state})"
23
+ end
24
+ end
19
25
  end
26
+
27
+ Crab::StoryCreate.run
@@ -1,21 +1,29 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
2
3
  require 'crab'
3
4
 
4
- opts = Trollop::options do
5
- banner <<-BANNER
5
+ class Crab::StoryDelete
6
+
7
+ def self.run(args=ARGV)
8
+ opts = Trollop::options(args) do
9
+ banner <<-BANNER
6
10
  crab story delete: delete an existing story in Rally
7
11
 
8
12
  Usage: crab story delete <id> [options*]
9
- BANNER
10
- opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
11
- end
13
+ BANNER
14
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
15
+ end
12
16
 
13
- id = ARGV.join(" ")
14
- Trollop::die "Story ID must be specified" if id.blank?
17
+ id = args.join(" ")
18
+ Trollop::die "Story ID must be specified" if id.blank?
15
19
 
16
- Crab::Rally.new(opts[:dry]) do |rally|
17
- story = rally.find_story_with_id id
18
- story.delete
20
+ Crab::Rally.new(opts[:dry]) do |rally|
21
+ story = rally.find_story_with_id id
22
+ story.delete
19
23
 
20
- puts "Story #{id} deleted."
24
+ puts "Story #{id} deleted."
25
+ end
26
+ end
21
27
  end
28
+
29
+ Crab::StoryDelete.run
@@ -1,21 +1,29 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
2
3
  require 'crab'
3
4
 
4
- opts = Trollop::options do
5
- banner <<-BANNER
5
+ class Crab::StoryDelete
6
+
7
+ def self.run(args=ARGV)
8
+ opts = Trollop::options(args) do
9
+ banner <<-BANNER
6
10
  crab story delete: delete an existing story in Rally
7
11
 
8
12
  Usage: crab story delete <id> [options*]
9
- BANNER
10
- opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
11
- end
13
+ BANNER
14
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
15
+ end
12
16
 
13
- id = ARGV.join(" ")
14
- Trollop::die "Story ID must be specified" if id.blank?
17
+ id = args.join(" ")
18
+ Trollop::die "Story ID must be specified" if id.blank?
15
19
 
16
- Crab::Rally.new(opts[:dry]) do |rally|
17
- story = rally.find_story_with_id id
18
- story.delete
20
+ Crab::Rally.new(opts[:dry]) do |rally|
21
+ story = rally.find_story_with_id id
22
+ story.delete
19
23
 
20
- puts "Story #{id} deleted."
24
+ puts "Story #{id} deleted."
25
+ end
26
+ end
21
27
  end
28
+
29
+ Crab::StoryDelete.run
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set ft=ruby :
3
+ require 'crab'
4
+
5
+ class Crab::StoryDiff
6
+
7
+ class << self
8
+
9
+ include Crab::Utilities
10
+
11
+ def run(args=ARGV)
12
+ opts = Trollop::options(args) do
13
+ banner <<-BANNER
14
+ crab story diff: compares Cucumber feature files with their Rally counterparts
15
+
16
+ Usage: crab story diff <file> [file*] [options*]
17
+ BANNER
18
+
19
+ opt :language, "Language to generate Cucumber features in (ISO code)", :default => "en", :short => "-l"
20
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
21
+ end
22
+
23
+ filenames = args.map do |filename|
24
+ Trollop::die "File does not exist: #{filename}" unless File.exists? filename
25
+ File.expand_path filename
26
+ end
27
+
28
+ Crab::Rally.new(opts[:dry]) do |rally|
29
+ filenames.each do |filename|
30
+
31
+ feature = parse_feature_in filename
32
+
33
+ show_args = "#{feature.story_id} #{"--language #{opts[:language]}" if opts[:language_given]} #{"--dry" if opts[:dry]}"
34
+ logger.info "About to invoke 'crab-story-show #{show_args}'"
35
+ rally_story_text = `crab-story-show #{show_args}`
36
+
37
+ Open3.popen3 "diff #{filename} -" do |stdin, stdout, stderr|
38
+ stdin.puts rally_story_text
39
+ stdin.close
40
+
41
+ puts stdout.read
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def parse_feature_in(filename)
48
+ logger.info "Parsing #{filename}"
49
+ Crab::CucumberToRallyAdapter.new File.read(filename), filename
50
+ end
51
+ end
52
+ end
53
+
54
+ Crab::StoryDiff.run
@@ -1,34 +1,45 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
2
3
  require 'crab'
3
4
 
4
- include Crab::Utilities
5
+ class Crab::StoryFind
5
6
 
6
- opts = Trollop::options do
7
- banner <<-BANNER
7
+ class << self
8
+
9
+ include Crab::Utilities
10
+
11
+ def run(args=ARGV)
12
+ opts = Trollop::options(args) do
13
+ banner <<-BANNER
8
14
  crab story find: find a story in Rally
9
15
 
10
16
  Usage: crab story find [options*] [text]
11
- BANNER
12
- opt :project, "Project to use (required unless set by 'crab project')", :short => "-p", :type => String
13
- opt :iteration, "Limit search to this iteration", :short => "-i", :type => String
14
- opt :release, "Limit search to this release", :short => "-r", :type => String
15
- opt :parent, "Limit search to children of this story", :short => "-P", :type => String
16
- opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
17
- end
17
+ BANNER
18
+ opt :project, "Project to use (required unless set by 'crab project')", :short => "-p", :type => String
19
+ opt :iteration, "Limit search to this iteration", :short => "-i", :type => String
20
+ opt :release, "Limit search to this release", :short => "-r", :type => String
21
+ opt :parent, "Limit search to children of this story", :short => "-P", :type => String
22
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
23
+ end
18
24
 
19
- pattern = ARGV.map(&:strip).reject(&:empty?)
20
- project_name = valid_project_name(opts)
25
+ pattern = args.map(&:strip).reject(&:empty?)
26
+ project_name = valid_project_name(opts)
21
27
 
22
- Crab::Rally.new(opts[:dry]) do |rally|
23
- project = rally.find_project(project_name)
24
- Trollop::die "Project #{opts[:project].inspect} not found" if project.nil?
28
+ Crab::Rally.new(opts[:dry]) do |rally|
29
+ project = rally.find_project(project_name)
30
+ Trollop::die "Project #{opts[:project].inspect} not found" if project.nil?
25
31
 
26
- find_opts = {}
27
- find_opts[:iteration] = rally.find_iteration_by_name opts[:iteration], project if opts[:iteration_given]
28
- find_opts[:release] = rally.find_release_by_name opts[:release], project if opts[:release_given]
29
- find_opts[:parent] = rally.find_story_with_id opts[:parent] if opts[:parent_given]
32
+ find_opts = {}
33
+ find_opts[:iteration] = rally.find_iteration_by_name opts[:iteration], project if opts[:iteration_given]
34
+ find_opts[:release] = rally.find_release_by_name opts[:release], project if opts[:release_given]
35
+ find_opts[:parent] = rally.find_story_with_id opts[:parent] if opts[:parent_given]
30
36
 
31
- rally.find_stories(project, pattern, find_opts).each do |story|
32
- puts "#{story.formatted_id}: #{story.name} (#{story.state})"
37
+ rally.find_stories(project, pattern, find_opts).each do |story|
38
+ puts "#{story.formatted_id}: #{story.name} (#{story.state})"
39
+ end
40
+ end
41
+ end
33
42
  end
34
43
  end
44
+
45
+ Crab::StoryFind.run
@@ -1,6 +1,11 @@
1
+ #!/usr/bin/env ruby
1
2
  # vim: set ft=ruby :
3
+ require 'crab'
2
4
 
3
- puts <<-HELP
5
+ class Crab::StoryHelp
6
+
7
+ def self.run
8
+ puts <<-HELP
4
9
  Usage: crab story <command> [options*]
5
10
 
6
11
  Available commands:
@@ -16,4 +21,8 @@ Usage: crab story <command> [options*]
16
21
  update Update stories
17
22
 
18
23
  --help, -h: Show this message
19
- HELP
24
+ HELP
25
+ end
26
+ end
27
+
28
+ Crab::StoryHelp.run