crab 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
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