crab 0.2.12 → 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set ft=ruby:
3
+ require 'crab'
4
+
5
+ class Crab::DefectMain
6
+
7
+ class << self
8
+
9
+ include Crab::Utilities
10
+
11
+ def run(args=ARGV)
12
+ cmd = args.shift # get the subcommand
13
+
14
+ case cmd
15
+ when "-h", "--help", NilClass
16
+ system "crab-defect-help"
17
+ exit 0
18
+ end
19
+
20
+ unless system("crab-defect-#{cmd}", *args)
21
+ if $?.exitstatus == 127 # bash 'command not found'
22
+ logger.error "Unknown subcommand \"defect #{cmd}\""
23
+ system "crab-defect-help"
24
+ exit 1
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Crab::DefectMain.run
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set ft=ruby :
3
+ require 'crab'
4
+
5
+ class Crab::DefectDelete
6
+
7
+ def self.run(args=ARGV)
8
+ opts = Trollop::options(args) do
9
+ banner <<-BANNER
10
+ crab defect delete: delete an existing defect in Rally
11
+
12
+ Usage: crab defect delete <id> [options*]
13
+ BANNER
14
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
15
+ end
16
+
17
+ id = args.join(" ")
18
+ Trollop::die "Defect ID must be specified" if id.blank?
19
+
20
+ Crab::Rally.new(opts[:dry]) do |rally|
21
+ defect = rally.find_defect_with_id id
22
+ defect.delete
23
+
24
+ puts "Defect #{id} deleted."
25
+ end
26
+ end
27
+ end
28
+
29
+ Crab::DefectDelete.run
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set ft=ruby :
3
+ require 'crab'
4
+
5
+ class Crab::DefectFind
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 defect find: find a defect in Rally
15
+
16
+ Usage: crab defect find [options*] [text]
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 defect", :short => "-P", :type => String
22
+ opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
23
+ end
24
+
25
+ pattern = args.map(&:strip).reject(&:empty?)
26
+ project_name = valid_project_name(opts)
27
+
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?
31
+
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_defect_with_id opts[:parent] if opts[:parent_given]
36
+
37
+ rally.find_defects(project, pattern, find_opts).each do |defect|
38
+ puts "#{defect.formatted_id}: #{defect.name} (#{defect.state})"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ Crab::DefectFind.run
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set ft=ruby :
3
+ require 'crab'
4
+
5
+ class Crab::DefectHelp
6
+
7
+ def self.run
8
+ puts <<-HELP
9
+ Usage: crab defect <command> [options*]
10
+
11
+ Available commands:
12
+
13
+ create Create a new defect in a story
14
+ delete Delete an existing defect
15
+ find Find defects
16
+ help Show this help text
17
+ list List defects
18
+ show Show a defect (and its steps) as a Cucumber scenario
19
+ update Update a defect
20
+
21
+ --help, -h: Show this message
22
+ HELP
23
+ end
24
+ end
25
+
26
+ Crab::DefectHelp.run
@@ -13,10 +13,12 @@ crab version #{Crab::VERSION}: A Cucumber-Rally bridge
13
13
  Available commands:
14
14
 
15
15
  help Show this help text
16
- iteration Manipulate iterations
17
16
  login Persistently authenticate user with Rally
18
17
  logout Remove stored Rally credentials
19
18
  project Persistently select project to work with in Rally
19
+
20
+ defect Manipulate defects
21
+ iteration Manipulate iterations
20
22
  release Manipulate releases
21
23
  story Manipulate stories
22
24
  testcase Manipulate test cases
@@ -13,16 +13,26 @@ class Crab::Login
13
13
  banner <<-BANNER
14
14
  Usage: crab login [options*]
15
15
 
16
- Log into Rally. Your credentials will be written to ~/.crab/credentials.
16
+ Log into Rally. Your credentials will be written to ~/.crab/credentials unless --project is specified.
17
17
  BANNER
18
18
 
19
19
  opt :username, "Username", :type => String, :short => "-u"
20
20
  opt :password, "Password", :type => String, :short => "-p"
21
+ opt :project, "Store credentials into current folder", :short => "-P", :default => false
21
22
  end
22
23
 
23
24
  username = opts[:username_given] ? opts[:username] : ask("Username: ")
24
25
  password = opts[:password_given] ? opts[:password] : ask("Password: ") {|q| q.echo = false }
25
26
 
27
+ crab_dir = if opts[:project]
28
+ File.expand_path "./.crab"
29
+ else
30
+ File.expand_path "~/.crab"
31
+ end
32
+
33
+ FileUtils.mkdir_p crab_dir
34
+ credentials_file = "#{crab_dir}/credentials"
35
+
26
36
  File.open(credentials_file, 'w') do |file|
27
37
  file.puts username
28
38
  file.puts password
@@ -14,15 +14,16 @@ class Crab::Logout
14
14
  banner <<-BANNER
15
15
  Usage: crab logout [options*]
16
16
 
17
- Log out of Rally. Your credentials will be removed from ~/.crab/credentials.
17
+ Log out of Rally. Your credentials will be removed from current project directory or home folder (~/.crab/credentials).
18
18
  BANNER
19
19
  opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
20
20
  end
21
21
 
22
22
  fileutils_opts = opts[:dry] ? {:noop => true, :verbose => true} : {}
23
- FileUtils.rm_rf(credentials_file, fileutils_opts)
23
+ file = credentials_file
24
+ FileUtils.rm_rf(file, fileutils_opts)
24
25
 
25
- puts "Credentials removed for #{username}"
26
+ puts "Credentials removed from #{file}"
26
27
 
27
28
  end
28
29
  end
@@ -15,14 +15,21 @@ crab project: show or persistently select project to work with in Rally
15
15
 
16
16
  Usage: crab project [name] [options*]
17
17
  BANNER
18
+ opt :clear, "Remove a previous project selection", :short => "-c", :default => false
18
19
  opt :dry, "Dry-run (don't change anything)", :short => "-D", :default => false
19
20
  end
20
21
 
21
22
  name = args.join(" ").strip
23
+ is_dry_run = opts[:dry] ? { :noop => true, :verbose => true } : {}
22
24
 
23
25
  if name.empty?
24
26
  if current_project_name.present?
25
- puts current_project_name
27
+ if opts[:clear]
28
+ FileUtils.rm_rf dotcrab_file("project"), is_dry_run
29
+ puts "Project selection removed."
30
+ else
31
+ puts current_project_name
32
+ end
26
33
  else
27
34
  puts "No project currently selected."
28
35
  end
@@ -33,7 +40,7 @@ Usage: crab project [name] [options*]
33
40
  project = rally.find_project name
34
41
  Trollop::die "#{name.inspect} is not a valid project" if project.nil?
35
42
 
36
- FileUtils.mkdir_p ".crab", opts[:dry] ? { :noop => true, :verbose => true } : {}
43
+ FileUtils.mkdir_p ".crab", is_dry_run
37
44
  file = ".crab/project"
38
45
  output = project.name
39
46
 
@@ -12,7 +12,7 @@ class Crab::TestCaseCreate
12
12
  opts = add_or_update_options <<-BANNER, args
13
13
  crab testcase create: add a test case to a story in Rally
14
14
 
15
- Usage: crab testcase create <story> <name> [options*]
15
+ Usage: crab testcase create <story> --name <name> [options*]
16
16
  BANNER
17
17
 
18
18
  story_id = args.shift
@@ -24,7 +24,6 @@ Usage: crab testcase create <story> <name> [options*]
24
24
 
25
25
  unless opts[:name_given]
26
26
  logger.error "Error: Test case name not provided."
27
- system "crab-testcase-help"
28
27
  exit 1
29
28
  end
30
29
 
@@ -32,7 +31,6 @@ Usage: crab testcase create <story> <name> [options*]
32
31
  tc = rally.create_test_case(story_id, name, sanitize_options(opts))
33
32
  puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -12,7 +12,7 @@ class Crab::TestCaseCreate
12
12
  opts = add_or_update_options <<-BANNER, args
13
13
  crab testcase create: add a test case to a story in Rally
14
14
 
15
- Usage: crab testcase create <story> <name> [options*]
15
+ Usage: crab testcase create <story> --name <name> [options*]
16
16
  BANNER
17
17
 
18
18
  story_id = args.shift
@@ -24,7 +24,6 @@ Usage: crab testcase create <story> <name> [options*]
24
24
 
25
25
  unless opts[:name_given]
26
26
  logger.error "Error: Test case name not provided."
27
- system "crab-testcase-help"
28
27
  exit 1
29
28
  end
30
29
 
@@ -32,7 +31,6 @@ Usage: crab testcase create <story> <name> [options*]
32
31
  tc = rally.create_test_case(story_id, name, sanitize_options(opts))
33
32
  puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -12,7 +12,7 @@ class Crab::TestCaseCreate
12
12
  opts = add_or_update_options <<-BANNER, args
13
13
  crab testcase create: add a test case to a story in Rally
14
14
 
15
- Usage: crab testcase create <story> <name> [options*]
15
+ Usage: crab testcase create <story> --name <name> [options*]
16
16
  BANNER
17
17
 
18
18
  story_id = args.shift
@@ -24,7 +24,6 @@ Usage: crab testcase create <story> <name> [options*]
24
24
 
25
25
  unless opts[:name_given]
26
26
  logger.error "Error: Test case name not provided."
27
- system "crab-testcase-help"
28
27
  exit 1
29
28
  end
30
29
 
@@ -32,7 +31,6 @@ Usage: crab testcase create <story> <name> [options*]
32
31
  tc = rally.create_test_case(story_id, name, sanitize_options(opts))
33
32
  puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -12,7 +12,7 @@ class Crab::TestCaseCreate
12
12
  opts = add_or_update_options <<-BANNER, args
13
13
  crab testcase create: add a test case to a story in Rally
14
14
 
15
- Usage: crab testcase create <story> <name> [options*]
15
+ Usage: crab testcase create <story> --name <name> [options*]
16
16
  BANNER
17
17
 
18
18
  story_id = args.shift
@@ -24,7 +24,6 @@ Usage: crab testcase create <story> <name> [options*]
24
24
 
25
25
  unless opts[:name_given]
26
26
  logger.error "Error: Test case name not provided."
27
- system "crab-testcase-help"
28
27
  exit 1
29
28
  end
30
29
 
@@ -32,7 +31,6 @@ Usage: crab testcase create <story> <name> [options*]
32
31
  tc = rally.create_test_case(story_id, name, sanitize_options(opts))
33
32
  puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -12,7 +12,7 @@ class Crab::TestCaseCreate
12
12
  opts = add_or_update_options <<-BANNER, args
13
13
  crab testcase create: add a test case to a story in Rally
14
14
 
15
- Usage: crab testcase create <story> <name> [options*]
15
+ Usage: crab testcase create <story> --name <name> [options*]
16
16
  BANNER
17
17
 
18
18
  story_id = args.shift
@@ -24,7 +24,6 @@ Usage: crab testcase create <story> <name> [options*]
24
24
 
25
25
  unless opts[:name_given]
26
26
  logger.error "Error: Test case name not provided."
27
- system "crab-testcase-help"
28
27
  exit 1
29
28
  end
30
29
 
@@ -32,7 +31,6 @@ Usage: crab testcase create <story> <name> [options*]
32
31
  tc = rally.create_test_case(story_id, name, sanitize_options(opts))
33
32
  puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -12,7 +12,7 @@ class Crab::TestCaseCreate
12
12
  opts = add_or_update_options <<-BANNER, args
13
13
  crab testcase create: add a test case to a story in Rally
14
14
 
15
- Usage: crab testcase create <story> <name> [options*]
15
+ Usage: crab testcase create <story> --name <name> [options*]
16
16
  BANNER
17
17
 
18
18
  story_id = args.shift
@@ -24,7 +24,6 @@ Usage: crab testcase create <story> <name> [options*]
24
24
 
25
25
  unless opts[:name_given]
26
26
  logger.error "Error: Test case name not provided."
27
- system "crab-testcase-help"
28
27
  exit 1
29
28
  end
30
29
 
@@ -32,7 +31,6 @@ Usage: crab testcase create <story> <name> [options*]
32
31
  tc = rally.create_test_case(story_id, name, sanitize_options(opts))
33
32
  puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -11,3 +11,11 @@ Feature: Log In and Out of Rally
11
11
  Then the exit status should be 0
12
12
  And the user's home directory should have a file named ".crab/credentials"
13
13
 
14
+ Scenario: Logged Out, Logging In project specific
15
+ Given a directory named "my-project"
16
+ And I cd to "my-project"
17
+ When I run `crab login -P` interactively
18
+ And I type my username
19
+ And I type my password
20
+ Then the exit status should be 0
21
+ And a file named ".crab/credentials" should exist
@@ -1,18 +1,24 @@
1
1
  Feature: Project Selection
2
-
2
+
3
3
  In order to work with the find, list etc commands more effectively
4
4
  A lazy developer
5
5
  Wants to set the project persistently across all commands
6
6
 
7
- Background:
7
+ Background:
8
8
  Given I am logged in
9
9
 
10
- Scenario: Selecting a Project
11
- Given no project is selected
10
+ Scenario: Selecting and Clearing Projects
11
+ Given I select my test project
12
+
13
+ When I run `crab project --clear`
14
+ Then the output should contain "Project selection removed."
15
+
12
16
  When I run `crab project`
13
17
  Then the output should contain "No project currently selected."
18
+
14
19
  When I select my test project
15
20
  Then the exit status should be 0
21
+
16
22
  When I run `crab project`
17
23
  Then the output should be the name of my test project
18
24
 
@@ -0,0 +1,31 @@
1
+ Feature: Recursively looks for .crab folder
2
+
3
+ In order to easily work with multiple projects and avoid having to cd back into project's root
4
+ A lazy developer
5
+ Wants to run crab from any project's subfolder
6
+
7
+ Background:
8
+ Given a directory named "crab-project/subfolder/othersubfolder"
9
+
10
+ Scenario: Uses Parent Folder Project Settings From Any Subfolder
11
+ Given I am logged in
12
+ And no project is selected
13
+ And I cd to "crab-project"
14
+ And I have selected my test project
15
+ When I cd to "subfolder"
16
+ And I run `crab project`
17
+ Then the output should be the name of my test project
18
+ When I cd to "othersubfolder"
19
+ And I run `crab project`
20
+ Then the output should be the name of my test project
21
+
22
+ Scenario: Uses Parent Folder Credentials From Subfolder
23
+ Given I run `crab logout`
24
+ And I cd to "crab-project"
25
+ When I run `crab login -P` interactively
26
+ And I type my username
27
+ And I type my password
28
+ Then a file named ".crab/credentials" should exist
29
+ When I cd to "subfolder"
30
+ And I run `crab logout`
31
+ Then a file named "../.crab/credentials" should not exist
@@ -21,17 +21,10 @@ def get_story(story_id)
21
21
  end
22
22
 
23
23
  def get_project
24
- if File.exists? ".crab/tests/project"
25
- File.read(".crab/tests/project").strip
24
+ project_file = File.expand_path("~/.crab/tests/project")
25
+ if File.exists? project_file
26
+ File.read(project_file).strip
26
27
  else
27
- raise "Please run rake cucumber:setup first"
28
- end
29
- end
30
-
31
- def get_test_project
32
- begin
33
- test_project = File.read(File.expand_path("~/.crab/tests/project"))
34
- rescue
35
28
  raise "Looks like your test project isn't set up. Please run 'rake cucumber:setup'"
36
29
  end
37
30
  end
@@ -45,10 +38,12 @@ crab version #{Crab::VERSION}: A Cucumber-Rally bridge
45
38
  Available commands:
46
39
 
47
40
  help Show this help text
48
- iteration Manipulate iterations
49
41
  login Persistently authenticate user with Rally
50
42
  logout Remove stored Rally credentials
51
43
  project Persistently select project to work with in Rally
44
+
45
+ defect Manipulate defects
46
+ iteration Manipulate iterations
52
47
  release Manipulate releases
53
48
  story Manipulate stories
54
49
  testcase Manipulate test cases
@@ -110,6 +105,7 @@ end
110
105
 
111
106
  Given /^no project is selected$/ do
112
107
  Given 'I run `rm -rf ".crab/project"`'
108
+ Then 'the exit status should be 0'
113
109
  end
114
110
 
115
111
  Given /^I have selected the project "([^"]*)"$/ do |project|
@@ -122,13 +118,15 @@ Given /^I have selected the project "([^"]*)"$/ do |project|
122
118
  end
123
119
 
124
120
  Given /^I have selected my test project$/ do
125
- When %Q{I run `crab project "#{get_test_project}"`}
121
+ When %{I run `crab project "#{get_project}"`}
122
+ Then %{the exit status should be 0}
126
123
  end
127
124
 
128
125
  When /^I select my test project$/ do
129
- When %Q{I run `crab project "#{get_test_project}"`}
126
+ When %{I run `crab project "#{get_project}"`}
127
+ Then %{the exit status should be 0}
130
128
  end
131
129
 
132
130
  Then /^the output should be the name of my test project$/ do
133
- Then %Q{the output should contain "#{get_test_project}"}
131
+ Then %Q{the output should contain "#{get_project}"}
134
132
  end
@@ -38,7 +38,7 @@ Feature: Subcommand Help
38
38
  | story show | Usage: crab story show <id> [options*] |
39
39
  | story help | Usage: crab story <command> [options*] |
40
40
 
41
- | testcase create | Usage: crab testcase create <story> <name> [options*] |
41
+ | testcase create | Usage: crab testcase create <story> --name <name> [options*] |
42
42
  | testcase update | Usage: crab testcase update <id> [options*] |
43
43
  | testcase delete | Usage: crab testcase delete <id> [options*] |
44
44
  | testcase find | Usage: crab testcase find [options*] [text] |
@@ -0,0 +1,51 @@
1
+ class Crab::Defect
2
+
3
+ def initialize(rally_defect)
4
+ @rally_defect = rally_defect
5
+ end
6
+
7
+ def formatted_id
8
+ @rally_defect.formatted_i_d
9
+ end
10
+
11
+ def name
12
+ @rally_defect.name
13
+ end
14
+
15
+ def description
16
+ @rally_defect.description
17
+ end
18
+
19
+ def environment
20
+ @rally_defect.environment
21
+ end
22
+
23
+ def browser
24
+ @rally_defect.navegador
25
+ end
26
+
27
+ def statte
28
+ @rally_defect.schedule_state
29
+ end
30
+
31
+ def severity
32
+ @rally_defect.severity
33
+ end
34
+
35
+ def target_date
36
+ @rally_defect.target_date
37
+ end
38
+
39
+ def task_status
40
+ @rally_defect.task_status
41
+ end
42
+
43
+ def test_case_status
44
+ @rally_defect.test_case_status
45
+ end
46
+
47
+ def delete
48
+ @rally_defect.delete
49
+ end
50
+
51
+ end
@@ -15,7 +15,13 @@ module Crab
15
15
  def connect
16
16
  get_credentials
17
17
  logger.info "Connecting to Rally as #{@username}..."
18
- @rally = ::RallyRestAPI.new :username => @username, :password => @password
18
+
19
+ rally_logger = Logger.new(STDERR)
20
+ rally_logger.formatter = Logger::Formatter.new
21
+ rally_logger.progname = 'rally'
22
+ rally_logger.level = ENV['CRAB_LOG_LEVEL'].present? ? ENV['CRAB_LOG_LEVEL'].to_i : Logger::WARN
23
+
24
+ @rally = ::RallyRestAPI.new :username => @username, :password => @password, :logger => rally_logger
19
25
  end
20
26
 
21
27
  def get_credentials
@@ -30,6 +36,13 @@ module Crab
30
36
  Crab::Story.new(story, @dry_run)
31
37
  end
32
38
 
39
+ def find_defect_with_id defect_id
40
+ logger.info "Looking up defect with ID #{defect_id}"
41
+ defect = @rally.find(:defect) { equal :formatted_i_d, defect_id }.first
42
+ Trollop::die "Defect with ID #{defect_id.inspect} not found" if defect.nil?
43
+ Crab::Defect.new(defect, @dry_run)
44
+ end
45
+
33
46
  def find_testcases(project, pattern, opts)
34
47
  logger.info "Looking for testcases matching #{pattern.inspect} with options #{opts.keys.inspect} in #{project.name.inspect}"
35
48
 
@@ -52,6 +65,25 @@ module Crab
52
65
  end
53
66
  end
54
67
 
68
+ def find_defects(project, pattern, opts)
69
+ logger.info "Looking for defects matching #{pattern.inspect} with options #{opts.keys.inspect} in #{project.name.inspect}"
70
+ if pattern.join.empty? && opts.empty?
71
+ return @rally.find_all(:defect, :fetch => true, :project => project).map {|s| Crab::Defect.new(s, @dry_run) }
72
+ end
73
+
74
+ rally_stories = @rally.find(:defect, :fetch => true, :project => project) do
75
+ Crab::Rally.search_for_words_in pattern, self
76
+
77
+ equal :iteration, opts[:iteration] if opts[:iteration]
78
+ equal :release, opts[:release] if opts[:release]
79
+ equal :parent, opts[:parent].rally_object if opts[:parent]
80
+ end
81
+
82
+ rally_stories.map {|defect| Crab::Defect.new(defect, @dry_run) }.tap do |defects|
83
+ logger.info "Found #{defects.size} defects"
84
+ end
85
+ end
86
+
55
87
  def find_stories(project, pattern, opts)
56
88
  logger.info "Looking for stories matching #{pattern.inspect} with options #{opts.keys.inspect} in #{project.name.inspect}"
57
89
  if pattern.join.empty? && opts.empty?
@@ -4,8 +4,7 @@ module Crab
4
4
  include Logging
5
5
 
6
6
  def credentials_file
7
- FileUtils.mkdir_p File.expand_path("~/.crab")
8
- File.expand_path("~/.crab/credentials")
7
+ dotcrab_file 'credentials'
9
8
  end
10
9
 
11
10
  def valid_credentials_file
@@ -20,9 +19,8 @@ module Crab
20
19
  end
21
20
 
22
21
  def current_project_name
23
- if File.exists? ".crab/project"
24
- File.read(".crab/project").strip
25
- end
22
+ project_file = dotcrab_file('project')
23
+ File.read(project_file).strip if File.exists?(project_file)
26
24
  end
27
25
 
28
26
  def state_from(option)
@@ -77,5 +75,21 @@ module Crab
77
75
  def sanitize(source)
78
76
  Sanitize.clean source, :remove_contents => %w{style}
79
77
  end
78
+
79
+ def dotcrab_file(file)
80
+ current_folder = File.expand_path '.'
81
+
82
+ while current_folder != '/'
83
+
84
+ dotcrab = "#{current_folder}/.crab"
85
+ if File.exists? "#{dotcrab}/#{file}"
86
+ return "#{dotcrab}/#{file}"
87
+ end
88
+ current_folder = File.expand_path "#{current_folder}/.."
89
+
90
+ end
91
+
92
+ File.expand_path "~/.crab/#{file}"
93
+ end
80
94
  end
81
95
  end
@@ -1,3 +1,3 @@
1
1
  module Crab
2
- VERSION = "0.2.12"
2
+ VERSION = "0.2.13"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crab
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 12
10
- version: 0.2.12
9
+ - 13
10
+ version: 0.2.13
11
11
  platform: ruby
12
12
  authors:
13
13
  - Carlos Villela
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-05 00:00:00 -03:00
18
+ date: 2011-10-06 00:00:00 -03:00
19
19
  default_executable: crab
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -149,6 +149,10 @@ email:
149
149
  - cvillela@thoughtworks.com
150
150
  executables:
151
151
  - crab
152
+ - crab-defect
153
+ - crab-defect-delete
154
+ - crab-defect-find
155
+ - crab-defect-help
152
156
  - crab-help
153
157
  - crab-it
154
158
  - crab-it-help
@@ -249,6 +253,10 @@ files:
249
253
  - README.md
250
254
  - Rakefile
251
255
  - bin/crab
256
+ - bin/crab-defect
257
+ - bin/crab-defect-delete
258
+ - bin/crab-defect-find
259
+ - bin/crab-defect-help
252
260
  - bin/crab-help
253
261
  - bin/crab-it
254
262
  - bin/crab-it-help
@@ -345,6 +353,7 @@ files:
345
353
  - features/move-in-rally.feature
346
354
  - features/project-selection.feature
347
355
  - features/pull-from-rally-into-cucumber.feature
356
+ - features/recursively-look-for-dotcrab-folder.feature
348
357
  - features/show-from-rally.feature
349
358
  - features/steps/rally_steps.rb
350
359
  - features/subcommand-help.feature
@@ -354,6 +363,7 @@ files:
354
363
  - lib/crab/cucumber_feature.rb
355
364
  - lib/crab/cucumber_scenario.rb
356
365
  - lib/crab/cucumber_to_rally_adapter.rb
366
+ - lib/crab/defect.rb
357
367
  - lib/crab/logging.rb
358
368
  - lib/crab/rally.rb
359
369
  - lib/crab/rally_to_cucumber_adapter.rb