gitnesse 0.12.6 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +6 -0
  3. data/Rakefile +6 -11
  4. data/bin/.keep +0 -0
  5. data/bin/gitnesse +2 -32
  6. data/config/gitnesse.rb.example +2 -4
  7. data/gitnesse.gemspec +22 -21
  8. data/lib/gitnesse/cli/helpers/config_helpers.rb +13 -0
  9. data/lib/gitnesse/cli/helpers/feature_helpers.rb +26 -0
  10. data/lib/gitnesse/cli/helpers/wiki_helpers.rb +53 -0
  11. data/lib/gitnesse/cli/task/help.rb +42 -0
  12. data/lib/gitnesse/cli/task/info.rb +29 -0
  13. data/lib/gitnesse/cli/task/pull.rb +26 -0
  14. data/lib/gitnesse/cli/task/push.rb +101 -0
  15. data/lib/gitnesse/cli/task/run.rb +85 -0
  16. data/lib/gitnesse/cli/task.rb +67 -0
  17. data/lib/gitnesse/cli.rb +55 -0
  18. data/lib/gitnesse/config.rb +68 -0
  19. data/lib/gitnesse/config_loader.rb +36 -0
  20. data/lib/gitnesse/dependency_checker.rb +86 -0
  21. data/lib/gitnesse/dir_manager.rb +37 -0
  22. data/lib/gitnesse/feature.rb +63 -0
  23. data/lib/gitnesse/feature_extractor.rb +29 -0
  24. data/lib/gitnesse/feature_transform.rb +30 -0
  25. data/lib/gitnesse/hooks/gitnesse.rb +5 -0
  26. data/lib/gitnesse/hooks.rb +30 -33
  27. data/lib/gitnesse/railtie.rb +3 -1
  28. data/lib/gitnesse/rake/tasks.rake +11 -0
  29. data/lib/gitnesse/tasks.rb +7 -4
  30. data/lib/gitnesse/version.rb +1 -1
  31. data/lib/gitnesse/wiki/page.rb +103 -0
  32. data/lib/gitnesse/wiki.rb +80 -143
  33. data/lib/gitnesse.rb +10 -102
  34. data/spec/lib/cli/task/help_spec.rb +34 -0
  35. data/spec/lib/cli/task/info_spec.rb +22 -0
  36. data/spec/lib/cli/task/pull_spec.rb +24 -0
  37. data/spec/lib/cli/task/push_spec.rb +24 -0
  38. data/spec/lib/cli_spec.rb +13 -0
  39. data/spec/lib/config_loader_spec.rb +46 -0
  40. data/spec/lib/config_spec.rb +61 -0
  41. data/spec/lib/dependency_checker_spec.rb +193 -0
  42. data/spec/lib/dir_manager_spec.rb +46 -0
  43. data/spec/lib/feature_extractor_spec.rb +30 -0
  44. data/spec/lib/feature_spec.rb +53 -0
  45. data/spec/lib/feature_transform_spec.rb +25 -0
  46. data/spec/lib/hooks_spec.rb +40 -0
  47. data/spec/lib/version_spec.rb +9 -0
  48. data/spec/lib/wiki/page_spec.rb +68 -0
  49. data/spec/lib/wiki_spec.rb +34 -0
  50. data/spec/spec_helper.rb +4 -0
  51. data/spec/support/cli.rb +20 -0
  52. data/spec/support/example_config/gitnesse.rb +4 -0
  53. data/{test/test_helper.rb → spec/support/example_features/addition.feature} +0 -16
  54. data/spec/support/example_features/division.feature +10 -0
  55. data/spec/support/example_wiki_pages/developer_can_sync_features_to_code.md +29 -0
  56. data/spec/support_helper.rb +79 -0
  57. metadata +103 -109
  58. data/README.md +0 -85
  59. data/features/step_definitions/gitnesse_steps.rb +0 -54
  60. data/features/support/env.rb +0 -65
  61. data/features/sync_wiki_features_to_code.feature +0 -29
  62. data/lib/gitnesse/configuration.rb +0 -54
  63. data/lib/gitnesse/dependencies.rb +0 -39
  64. data/lib/gitnesse/features.rb +0 -38
  65. data/lib/gitnesse/git_config.rb +0 -39
  66. data/lib/gitnesse/support/hook.rb +0 -11
  67. data/lib/gitnesse/tasks.rake +0 -34
  68. data/test/lib/gitnesse/build_page_content_test.rb +0 -89
  69. data/test/lib/gitnesse/commit_info_test.rb +0 -16
  70. data/test/lib/gitnesse/configuration_defaults_test.rb +0 -11
  71. data/test/lib/gitnesse/configuration_to_hash_test.rb +0 -25
  72. data/test/lib/gitnesse/custom_branch_test.rb +0 -24
  73. data/test/lib/gitnesse/dependencies_check_test.rb +0 -73
  74. data/test/lib/gitnesse/extract_features_test.rb +0 -44
  75. data/test/lib/gitnesse/gather_test.rb +0 -30
  76. data/test/lib/gitnesse/load_feature_files_into_wiki_test.rb +0 -34
  77. data/test/lib/gitnesse/read_git_config_test.rb +0 -33
  78. data/test/lib/gitnesse/strip_results_test.rb +0 -52
  79. data/test/lib/gitnesse/version_test.rb +0 -7
  80. data/test/lib/gitnesse/wiki_append_results_test.rb +0 -50
  81. data/test/lib/gitnesse/write_file_test.rb +0 -18
  82. data/test/wiki_test_helper.rb +0 -11
@@ -0,0 +1,68 @@
1
+ require 'singleton'
2
+
3
+ module Gitnesse
4
+ class Config
5
+ include Singleton
6
+
7
+ ConfigStruct = Struct.new :repository_url, :features_dir, :branch,
8
+ :annotate_results, :identifier
9
+
10
+ # Config Options:
11
+ #
12
+ # repository_url - URl to remote git-based wiki.
13
+ # features_dir - directory for local features. Defaults to "features"
14
+ # branch - git branch of remote git-based wiki to use. Defaults to
15
+ # 'master'
16
+ # annotate_results - boolean, determines if Gitnesse will annotate cucumber
17
+ # results to wiki pages. Defaults to false
18
+ # identifier - if annotate_results is checked, an identifier to use
19
+ # to indicate who ran the cukes.
20
+ # e.g. "Uncle Bob's MacBook Air"
21
+
22
+ @@config = ConfigStruct.new
23
+
24
+ # default config options
25
+ @@config.annotate_results = false
26
+ @@config.branch = 'master'
27
+ @@config.features_dir = 'features'
28
+
29
+ # Allows external configuration of the ConfigStruct using a block.
30
+ #
31
+ # Accepts a block for config options
32
+ #
33
+ # Returns the current configuration
34
+ #
35
+ # Example:
36
+ # @config = Gitnesse::Config.instance
37
+ #
38
+ # Gitnesse::Config.config do |config|
39
+ # config.annotate_results = true
40
+ # end
41
+ #
42
+ # @config.annotate_results #=> true
43
+ def self.config
44
+ yield @@config if block_given?
45
+ Hash[@@config.each_pair.to_a]
46
+ end
47
+
48
+ # Converts the current configuration option to a hash
49
+ #
50
+ # Returns a hash
51
+ def to_h
52
+ Hash[@@config.each_pair.to_a]
53
+ end
54
+
55
+ # Method_missing used to make it easier to access ConfigStruct values
56
+ #
57
+ # Example:
58
+ # @config = Gitnesse::Config.instance
59
+ # @config.annotate_results #=> false
60
+ def method_missing(method, *args, &block)
61
+ if @@config.respond_to?(method)
62
+ @@config.send(method, *args, &block)
63
+ else
64
+ raise NoMethodError
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ module Gitnesse
2
+ class ConfigLoader
3
+ class ConfigFileError < StandardError ; end
4
+
5
+ def self.find_and_load
6
+ files = Dir.glob(File.join("**", "gitnesse.rb"))
7
+
8
+ files = reject_irrelevant_files files
9
+
10
+ files_with_config = files.select do |file_name|
11
+ file_content = File.read(file_name)
12
+ file_content.match("Gitnesse::Config.config do")
13
+ end
14
+
15
+ case files_with_config.length
16
+ when 0
17
+ raise_error "Can't find a gitnesse.rb file with Gitnesse configuration."
18
+ when 1
19
+ load(File.absolute_path(files_with_config.first))
20
+ else
21
+ raise_error "Multiple configuration files found:", files_with_config
22
+ end
23
+ end
24
+
25
+ private
26
+ def self.reject_irrelevant_files(files)
27
+ files.reject { |f| !!(File.absolute_path(f) =~ /.*(spec|vendor).*/) }
28
+ end
29
+
30
+ def self.raise_error(message, files = nil)
31
+ puts message
32
+ files.each { |f| puts f } if files
33
+ exit 1
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,86 @@
1
+ module Gitnesse
2
+ class DependencyChecker
3
+ attr_reader :errors
4
+
5
+ def initialize
6
+ @errors = []
7
+ end
8
+
9
+ def check
10
+ check_git
11
+ check_cucumber
12
+ check_repository_url
13
+ check_identifier
14
+ check_features_dir_exists
15
+
16
+ display_errors if @errors.any?
17
+ end
18
+
19
+ def display_errors
20
+ puts "Configuration errors were found!"
21
+
22
+ @errors.each do |error|
23
+ puts " - #{error}"
24
+ end
25
+
26
+ exit
27
+ end
28
+
29
+ # Checks that Git is installed on the system.
30
+ #
31
+ # Returns true or raises DependencyNotMetError if git is broken
32
+ def check_git
33
+ if system("git --version &> /dev/null")
34
+ true
35
+ else
36
+ @errors << "Git not found or not working"
37
+ end
38
+ end
39
+
40
+ # Checks that Cucumber is installed on the system.
41
+ #
42
+ # Returns true or raises DependencyNotMetError if Cucumber is broken
43
+ def check_cucumber
44
+ if system("cucumber --version &> /dev/null")
45
+ true
46
+ else
47
+ @errors << "Cucumber not found or not working"
48
+ end
49
+ end
50
+
51
+ # Checks that repository_url is set in Gitnesse::Config.
52
+ #
53
+ # Returns true or raises DependencyNotMetError if repository_url isn't set
54
+ def check_repository_url
55
+ url = Gitnesse::Config.instance.repository_url
56
+ if url.nil? || url.empty?
57
+ @errors << "You must specify a repository_url to run Gitnesse"
58
+ else
59
+ true
60
+ end
61
+ end
62
+
63
+ # Checks that identifier is set in Gitnesse::Config, if annotate_results is
64
+ # set.
65
+ #
66
+ # Returns true or raises DependencyNotMetError if identifier isn't set
67
+ def check_identifier
68
+ return true unless Gitnesse::Config.instance.annotate_results
69
+ identifier = Gitnesse::Config.instance.identifier
70
+ if identifier.nil? || identifier.empty?
71
+ @errors << "You must specify identifier to use the annotate_results option"
72
+ else
73
+ true
74
+ end
75
+ end
76
+
77
+ def check_features_dir_exists
78
+ dir = Gitnesse::Config.instance.features_dir
79
+ if File.directory?(dir)
80
+ true
81
+ else
82
+ @errors << "The features directory './#{dir}' does not exist."
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,37 @@
1
+ require 'fileutils'
2
+
3
+ module Gitnesse
4
+ class DirManager
5
+ # Public: Checks/Creates ~/.gitnesse/{{project_name}} dir.
6
+ # The project name is derived from the folder gitnesse is run in.
7
+ #
8
+ # Returns the path to the created project dir
9
+ def self.make_project_dir
10
+ FileUtils.mkdir_p project_dir
11
+ project_dir
12
+ end
13
+
14
+ # Public: Removes project dir, but not ~/.gitnesse dir
15
+ #
16
+ # Returns nothing
17
+ def self.remove_project_dir
18
+ FileUtils.rm_rf project_dir
19
+ end
20
+
21
+ # Public: Checks that project directory is present
22
+ #
23
+ # Returns a boolean indicating if the dir exists or not
24
+ def self.project_dir_present?
25
+ File.directory? project_dir
26
+ end
27
+
28
+ private
29
+ # Private: Constructs project dir path in ~/.gitnesse folder
30
+ #
31
+ # Returns a string path
32
+ def self.project_dir
33
+ project_name = File.basename Dir.pwd
34
+ "#{Dir.home}/.gitnesse/#{project_name}"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,63 @@
1
+ module Gitnesse
2
+ class Feature
3
+ attr_accessor :filename
4
+
5
+ def initialize(filename)
6
+ if filename =~ /^\.\/features\/(.+)/
7
+ @filename = filename.scan(/^\.?\/?features\/(.+)/).flatten.first
8
+ else
9
+ @filename = filename
10
+ end
11
+
12
+ @config = Gitnesse::Config.instance
13
+ end
14
+
15
+ # Public: Converts feature filename into the filename used on the remote
16
+ # git-based wiki
17
+ #
18
+ # Returns the converted filename
19
+ def wiki_filename
20
+ "features/#{@filename}.md".gsub('/', ' > ')
21
+ end
22
+
23
+ # Public: Reads the feature's contents. Caches result so only reads from FS
24
+ # first time it's called.
25
+ #
26
+ # Returns a string
27
+ def read
28
+ @content ||= File.read("#{@config.features_dir}/#{@filename}")
29
+ end
30
+
31
+ # Public: Writes updated content to the feature, or creates a new feature if
32
+ # it doesn't exist.
33
+ #
34
+ # content - The new/updated content to write to the file
35
+ #
36
+ # Returns the passed content
37
+ def write(content)
38
+ File.open("#{@config.features_dir}/#{@filename}", 'w') do |f|
39
+ f.write content
40
+ end
41
+
42
+ @content = nil
43
+
44
+ content
45
+ end
46
+
47
+ # Public: Generates the path to the index page the feature would appear on.
48
+ # Used to group Features for creating index pages.
49
+ #
50
+ # Returns a string indicating the index page.
51
+ def index_page
52
+ p = wiki_filename.scan(/^(features\ \>\ .+) >/).flatten[0] || 'features'
53
+ p + ".md"
54
+ end
55
+
56
+ # Public: Generates relative link for wiki index pages.
57
+ #
58
+ # Returns a string containing the relative link as markdown
59
+ def relative_link
60
+ "[[#{wiki_filename.gsub('.md', '')}]]"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ module Gitnesse
2
+ class FeatureExtractor
3
+
4
+ # Extracts Cucumber features from a Markdown-formatted string
5
+ #
6
+ # string - Markdown-formatted string to find Cucumber features in
7
+ #
8
+ # Returns an array of matches
9
+ def self.extract!(string)
10
+ matches = string.scan(/\u0060{3}gherkin\s*(.+?)\u0060{3}/im).flatten
11
+
12
+ if matches.any?
13
+ # Remove newline characters from beginning/end of each feature
14
+ matches.map { |m| m.lstrip! ; m.chomp! }
15
+ else
16
+ []
17
+ end
18
+ end
19
+
20
+ # Checks if a string contains a Cucumber feature
21
+ #
22
+ # string - Markdown-formatted string to check for Cucumber features in
23
+ #
24
+ # Returns true if there are features, false otherwise
25
+ def self.contains_features?(string)
26
+ string.scan(/\u0060{3}gherkin\s*(.+?)\u0060{3}/im).flatten.any?
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ module Gitnesse
2
+ class FeatureTransform
3
+
4
+ # Converts a Cucumber feature into a Markdown string compatible with
5
+ # Github's Wiki system
6
+ #
7
+ # feature - Cucumber feature to convert to Markdown
8
+ #
9
+ # Returns a string
10
+ def self.convert(feature)
11
+ unless feature.scan(/^\s*?Feature\:(.+?)\n/).flatten.any?
12
+ return <<-EOS.chomp
13
+ # Undefined Feature
14
+
15
+ This feature hasn't been added yet.
16
+ EOS
17
+ end
18
+
19
+ title = feature.scan(/^\s*?Feature\:(.+?)\n/).flatten.first.lstrip.chomp
20
+
21
+ <<-EOS.chomp
22
+ # #{title}
23
+
24
+ ```gherkin
25
+ #{feature.chomp}
26
+ ```
27
+ EOS
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ require 'gitnesse'
2
+
3
+ After do |scenario|
4
+ Gitnesse::Hooks.append_results(scenario)
5
+ end
@@ -1,52 +1,49 @@
1
1
  module Gitnesse
2
2
  class Hooks
3
- @dir = File.join(Dir.home, ".gitnesse")
3
+ @config = Gitnesse::Config.instance
4
4
 
5
- # Public: Sets up ~/.gitnesse for appending scenario results
5
+ DIR = File.expand_path("./#{@config.features_dir}/support")
6
+ PATH = File.expand_path("./#{@config.features_dir}/support/gitnesse.rb")
7
+
8
+ # Public: Copies Gitnesse Cucumber hooks to Cucumber's support dir.
6
9
  #
7
10
  # Returns nothing
8
- def self.setup
9
- Gitnesse::Configuration.load_using_search
10
- FileUtils.rm_rf(@dir) if File.directory?(@dir)
11
- Dir.mkdir(@dir)
12
- `git clone #{Gitnesse.configuration.repository_url} #{@dir} &> /dev/null`
13
- Wiki.new(@dir).remove_past_results
11
+ def self.create!
12
+ FileUtils.mkdir_p DIR unless File.directory?(DIR)
13
+
14
+ file = File.expand_path("#{File.dirname(__FILE__)}/hooks/gitnesse.rb")
15
+ FileUtils.cp file, PATH
14
16
  end
15
17
 
16
- # Public: Removes ~/.gitnesse after all cukes are run
18
+ # Public: Removes existing Gitnesse hooks in Cucumber's support dir
17
19
  #
18
20
  # Returns nothing
19
- def self.teardown
20
- puts " Pushing Cucumber results to wiki."
21
- Dir.chdir(@dir) do
22
- `git push origin master &> /dev/null`
23
- end
24
-
25
- FileUtils.rm_rf(@dir)
26
- FileUtils.rm(File.absolute_path("#{Gitnesse.configuration.target_directory}/support/gitnesse_hooks.rb"))
27
- puts " Done."
21
+ def self.destroy!
22
+ FileUtils.rm PATH, force: true
28
23
  end
29
24
 
30
- # Public: Adds hooks into Cucumber
25
+ # Public: Used by Gitnesse hook to append results to wiki page for feature
26
+ #
27
+ # scenario - Cucumber scenario passed by post-scenario hook
31
28
  #
32
29
  # Returns nothing
33
- def self.create
34
- hook_file = File.join(File.dirname(__FILE__), "support/hook.rb")
35
- support_dir = File.absolute_path("#{Gitnesse.configuration.target_directory}/support")
36
- target_file = File.join(support_dir, "gitnesse_hooks.rb")
30
+ def self.append_results(scenario)
31
+ Gitnesse::ConfigLoader.find_and_load
32
+ dir = Gitnesse::DirManager.project_dir
37
33
 
38
- Dir.mkdir(support_dir) unless File.directory?(support_dir)
34
+ file = scenario.file.gsub(/^#{@config.features_dir}\//, '')
39
35
 
40
- File.write(target_file, File.read(hook_file))
41
- end
36
+ page = file.gsub("/", " > ")
37
+ name = scenario.name
38
+ status = scenario.status
42
39
 
43
- # Public: Appends scenario results to relevant page in wiki
44
- #
45
- # scenario - the scenario results from Cucumber
46
- #
47
- # Returns nothing
48
- def self.append_to_wiki(scenario)
49
- Wiki.new(@dir).append_results(scenario)
40
+ @wiki = Gitnesse::Wiki.new(@config.repository_url, dir, clone: false)
41
+ page = @wiki.pages.find { |f| f.wiki_path.include?(page) }
42
+
43
+ return unless page
44
+
45
+ page.append_result name, status
46
+ @wiki.repo.add(page.wiki_path)
50
47
  end
51
48
  end
52
49
  end
@@ -1,4 +1,6 @@
1
1
  require 'gitnesse'
2
+ require 'gitnesse/cli/task'
3
+
2
4
  require 'rails'
3
5
 
4
6
  module Gitnesse
@@ -6,7 +8,7 @@ module Gitnesse
6
8
  railtie_name :gitnesse
7
9
 
8
10
  rake_tasks do
9
- load File.dirname(__FILE__) + '/tasks.rake'
11
+ load File.dirname(__FILE__) + '/rake/tasks.rake'
10
12
  end
11
13
  end
12
14
  end
@@ -0,0 +1,11 @@
1
+ namespace :gitnesse do
2
+ task :environment do
3
+ end
4
+
5
+ Gitnesse::Cli.tasks.values.each do |task|
6
+ desc(task.desc) if task.desc
7
+ task task.name.to_sym => :environment do
8
+ task.new(STDOUT).perform
9
+ end
10
+ end
11
+ end
@@ -1,8 +1,11 @@
1
- require "rake"
2
- require "rake/tasklib"
1
+ require 'gitnesse'
2
+ require 'gitnesse/cli/task'
3
+
4
+ require 'rake'
5
+ require 'rake/tasklib'
3
6
 
4
7
  module Gitnesse
5
8
  class Tasks < ::Rake::TaskLib
6
- load File.dirname(__FILE__) + '/tasks.rake'
9
+ load File.dirname(__FILE__) + "/rake/tasks.rake"
7
10
  end
8
- end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module Gitnesse
2
- VERSION = "0.12.6"
2
+ VERSION = "1.0.0.beta2"
3
3
  end
@@ -0,0 +1,103 @@
1
+ module Gitnesse
2
+ class Wiki
3
+ class Page
4
+ attr_reader :wiki_path, :path, :filename, :relative_path
5
+
6
+ # Public: Creates a new Wiki Page object. Contains references to the page
7
+ # and an easy way to access/update relevant page data.
8
+ #
9
+ # path - full path to the file
10
+ #
11
+ # Returns a Wiki::Page object
12
+ def initialize(path)
13
+ @wiki_path = path
14
+ @relative_path = get_relative_path
15
+ @filename = get_filename
16
+ @path = "#{@relative_path}/#{@filename}"
17
+ end
18
+
19
+ # Public: Reads the file's contents. Caches result so only reads from FS
20
+ # first time it's called per page.
21
+ #
22
+ # Returns a string
23
+ def read
24
+ @content ||= File.read(@wiki_path)
25
+ end
26
+
27
+ # Public: Writes content to the file.
28
+ #
29
+ # Returns the passed content
30
+ def write(content)
31
+ File.open(@wiki_path, 'w+') do |f|
32
+ f.write content
33
+ end
34
+
35
+ @content = nil
36
+
37
+ content
38
+ end
39
+
40
+ # Public: Removes existing results from the feature page.
41
+ #
42
+ # Returns nothing
43
+ def remove_results
44
+ write(read.gsub(/(\s+\!\[\].*)/, ''))
45
+ end
46
+
47
+ # Public: Appends the result of a Cucumber scenario to the feature's wiki
48
+ # page.
49
+ #
50
+ # scenario - feature scenario that was run
51
+ # status - return status of the scenario, e.g. :passed, :undefined,
52
+ # :failing
53
+ #
54
+ # Returns nothing
55
+ def append_result(scenario, status)
56
+ status = status.to_s
57
+ image = "![](https://s3.amazonaws.com/gitnesse/github/#{status}.png)"
58
+ string = "\n\n#{image} \`"
59
+ string << "Last Result For Scenario '#{scenario}': "
60
+ string << status.upcase
61
+ string << " (#{Time.now.strftime("%b %d, %Y, %-l:%M %p")} - "
62
+ string << "#{Gitnesse::Config.instance.identifier})\`"
63
+
64
+ write(read + string)
65
+ end
66
+
67
+ protected
68
+ # Protected: Converts wiki-formatted filename into directories containing
69
+ # the page.
70
+ #
71
+ # Wiki filenames are formatted to accomodate nested directories, so for
72
+ # example the local feature "features/thing/thing.feature" would be given
73
+ # the filename "features > thing > thing.feature" in the wiki.
74
+ #
75
+ # path - path to convert
76
+ #
77
+ # Returns a string dir path
78
+ #
79
+ # Examples:
80
+ # @wiki_path = "features > thing > thing.feature.md"
81
+ # get_relative_path #=> "./features/thing"
82
+ #
83
+ # @wiki_path = "thing.feature"
84
+ # get_relative_path #=> "./features"
85
+ def get_relative_path
86
+ dirs = File.basename(@wiki_path).scan(/(\w+)\ \>/).flatten
87
+ dirs.shift if dirs.first == "features"
88
+ "./#{Gitnesse::Config.instance.features_dir}/#{dirs.join("/")}"
89
+ end
90
+
91
+ # Protected: Extracts the local filename for the wiki page
92
+ #
93
+ # Returns a string containing the filename
94
+ #
95
+ # Examples:
96
+ # @wiki_path = "features > thing > thing.feature.md"
97
+ # get_filename #=> "thing.feature"
98
+ def get_filename
99
+ File.basename(@wiki_path, '.md').scan(/(\w+\.feature)$/).flatten.first
100
+ end
101
+ end
102
+ end
103
+ end