mergit 1.0.0 → 1.1.0

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.
data/README.md CHANGED
@@ -27,7 +27,7 @@ Mergit uses simple text processing, therefore it can be tripped up. Some known
27
27
 
28
28
  Add this line to your application's Gemfile:
29
29
 
30
- gem 'mergit', '~> 1.0'
30
+ gem 'mergit', '~> 1.1'
31
31
 
32
32
  And then execute:
33
33
 
@@ -13,6 +13,10 @@ class Mergit
13
13
  # @return {Hash} A frozen hash with the rules for replacements.
14
14
  attr_reader :replacements
15
15
 
16
+ # All `require`d files will have 'MERGIT' start and end comments around them showing what file was included.
17
+ #
18
+ # The initial `:filename` or `:string` will not have 'MERGIT' comments.
19
+ #
16
20
  # @param [Array<Pathname, String>] search_path The list of directories to search.
17
21
  # @param [Hash] replacements A list of keywords to replace.
18
22
  # @param [Hash] options Either `:filename` or `:string` should be set.
@@ -24,7 +28,7 @@ class Mergit
24
28
  @output = StringIO.new
25
29
  begin
26
30
  if options.key?(:filename)
27
- scan_file(Pathname.new(options[:filename]).realpath)
31
+ Pathname.new(options[:filename]).open('r') { |fp| scan(fp.read) }
28
32
  elsif options.key?(:string)
29
33
  scan(options[:string])
30
34
  end
@@ -35,32 +39,17 @@ class Mergit
35
39
 
36
40
  # Finds a library using the {#search_path}
37
41
  #
38
- # @param [String] lib_name The name of the library to look for.
42
+ # @param [String, Pathname] filename The name of the library to look for.
39
43
  # @return [Nil, Pathname] Returns `nil` if it isn't found or a {http://rubydoc.info/stdlib/pathname/frames Pathname} if it is found.
40
- def find_requirement lib_name
44
+ def find_requirement filename
45
+ filename = Pathname.new filename
41
46
  @search_path.each do |directory|
42
- possible_path = directory + "#{lib_name}.rb"
47
+ possible_path = directory + filename.dirname + "#{filename.basename('.rb')}.rb"
43
48
  return possible_path.realpath if possible_path.file?
44
49
  end
45
50
  nil
46
51
  end
47
52
 
48
-
49
- # Finds a library using the {#search_path}
50
- #
51
- # This is identical to {#find_requirement} except it raises {Mergit::RequirementNotFound} if
52
- # it fails to find the library.
53
- #
54
- # @raise [Mergit::RequirementNotFound] if it can't find the library.
55
- # @param (see #find_requirement)
56
- # @return [Pathname] Returns the {http://rubydoc.info/stdlib/pathname/frames Pathname} of the library.
57
- # @see #find_requirement
58
- def find_requirement! lib_name
59
- find_requirement(lib_name).tap do |retval|
60
- raise Mergit::RequirementNotFound.new("Unabled to find require'd file: #{lib_name}") if retval.nil?
61
- end
62
- end
63
-
64
53
  ## Scans a single line of the file.
65
54
  #
66
55
  # It looks for things that need to be changed, and {#emit}s the resulting
@@ -72,13 +61,8 @@ class Mergit
72
61
  line.chomp!
73
62
  if line =~ /#\s*MERGIT:\s*skip\s*$/
74
63
  nil # do nothing
75
- elsif line =~ /^\s*require\s+'([^']+)'\s*$/ or line =~ /^\s*require\s+"([^"]+)"\s*$/
76
- requirement = find_requirement($1)
77
- if requirement.nil?
78
- emit line
79
- else
80
- scan_file requirement
81
- end
64
+ elsif line =~ /^\s*require\s+'([^']+)'/ or line =~ /^\s*require\s+"([^"]+)"/
65
+ scan_file($1) or emit(line)
82
66
  else
83
67
  replacements.each_key do |string_to_replace|
84
68
  line.gsub!(string_to_replace, replacements[string_to_replace])
@@ -91,27 +75,27 @@ class Mergit
91
75
  #
92
76
  # It passes each line of the file to {#scan_line} for parsing.
93
77
  #
78
+ # If the `filename` was already scanned, it'll do nothing and return `true`.
79
+ #
80
+ # If the `filename` doesn't exist in the {#search_path}, then it'll return `false`.
81
+ #
94
82
  # @param [Pathname] filename The file to scan.
95
- # @return [Nil]
83
+ # @return [FalseClass, TrueClass] Returns true if the file was emitted. Returns false if it cannot find the file in {#search_path}
96
84
  def scan_file filename
97
- relative_filename = if filename.relative?
98
- filename
99
- else
100
- filename.relative_path_from(Pathname.pwd)
101
- end
102
- if @visited_files.include? relative_filename
103
- return
104
- else
105
- @visited_files << relative_filename
106
- end
107
- emit "### MERGIT: Start of '#{relative_filename}'"
108
- filename.readlines.each { |line| scan_line line }
109
- emit "### MERGIT: End of '#{relative_filename}'"
85
+ filename_path = find_requirement(filename)
86
+ return false if filename_path.nil?
87
+ return true if @visited_files.include? filename_path
88
+
89
+ @visited_files << filename_path
90
+ emit "### MERGIT: Start of '#{filename}'"
91
+ filename_path.readlines.each { |line| scan_line line }
92
+ emit "### MERGIT: End of '#{filename}'"
93
+ return true
110
94
  end
111
95
 
112
96
  ## Scans a string
113
97
  #
114
- # It splits a string up into individual line via {#string_split} and
98
+ # It splits a string up into individual lines via {#string_split} and
115
99
  # passes them to {#scan_line}.
116
100
  #
117
101
  # @param [String] string The string to parse.
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
  class Mergit
3
3
  # The version of the Mergit Library.
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
@@ -0,0 +1,5 @@
1
+ puts "I'm requiring the no require file."
2
+
3
+ require 'no_requires'
4
+
5
+ puts "See!"
@@ -0,0 +1,3 @@
1
+ puts "Hi! I have no require lines."
2
+ puts "But I have lots to say!"
3
+ puts "Like 'supercalifragilisticexpialidocious'."
@@ -0,0 +1,2 @@
1
+ puts "I'm a ruby file that has a parent directory."
2
+ puts "I'm useful for testing relative paths."
@@ -2,87 +2,139 @@ require 'spec_helper'
2
2
  require 'mergit/processor'
3
3
 
4
4
  describe Mergit::Processor do
5
- let(:search_path) { [LIB_PATH] }
5
+ let(:search_path) { [EXAMPLE_DIR] }
6
6
  let(:replacements) { {} }
7
+ let(:do_not_close) { false } # Setting this to true prevents the @output being closed (and preventing further calls of scan_*())
8
+ let(:mergit_options) { { :string => '', :do_not_close => do_not_close } }
9
+ subject { Mergit::Processor.new(search_path, replacements, mergit_options) }
10
+
11
+ let(:no_requires_file) { EXAMPLE_DIR + 'no_requires.rb' }
12
+ let(:has_requires_file) { EXAMPLE_DIR + 'has_requires.rb' }
13
+ let(:relative_path_file) { EXAMPLE_DIR + 'relative' + 'path.rb' }
14
+
15
+ describe "#new" do
16
+ context "when passed a filename" do
17
+ after { Mergit::Processor.new(search_path, replacements, :filename => no_requires_file) }
18
+
19
+ it "should not add MERGIT comments" do
20
+ Mergit::Processor.any_instance.should_not_receive(:emit).with(/MERGIT/)
21
+ end
22
+ end
23
+ end
7
24
 
8
25
  describe "find_requirement" do
9
- subject { Mergit::Processor.new(search_path, replacements, :string => '') }
26
+ let(:expected_filename) { has_requires_file }
10
27
 
11
- context "with a known lib-file" do
12
- let(:lib_file) { Pathname.new File.expand_path('../../../lib/mergit.rb', __FILE__) }
13
- let(:lib_name) { lib_file.basename '.rb' }
28
+ shared_examples "find requirement" do
29
+ it "should return an absolute path" do
30
+ subject.find_requirement(filename).should be_absolute
31
+ end
14
32
 
15
- it "should find mergit.rb" do
16
- subject.find_requirement(lib_name).should eq(lib_file)
33
+ it "should return the expected Pathname" do
34
+ subject.find_requirement(filename).should eq(expected_filename)
17
35
  end
18
36
  end
19
37
 
38
+ context "with relative string filename" do
39
+ let(:filename) { expected_filename.basename('.rb').to_s }
40
+ it_behaves_like "find requirement"
41
+ end
42
+
43
+ context "with absolute string filename" do
44
+ let(:filename) { expected_filename.to_s }
45
+ it_behaves_like "find requirement"
46
+ end
47
+
48
+ context "with relative Pathname filename" do
49
+ let(:filename) { expected_filename.basename('.rb') }
50
+ it_behaves_like "find requirement"
51
+ end
52
+
53
+ context "with absolute Pathname filename" do
54
+ let(:filename) { expected_filename }
55
+ it_behaves_like "find requirement"
56
+ end
57
+
20
58
  it "should return nil if it doesn't exist" do
21
59
  subject.find_requirement('does-not-exist').should be_nil
22
60
  end
23
61
  end
24
62
 
25
- describe "find_requirement!" do
26
- subject { Mergit::Processor.new(search_path, replacements, :string => '') }
63
+ describe "scan_file" do
64
+ let(:do_not_close) { true }
27
65
 
28
- context "with a known lib-file" do
29
- let(:lib_file) { Pathname.new File.expand_path('../../../lib/mergit.rb', __FILE__) }
30
- let(:lib_name) { lib_file.basename '.rb' }
66
+ shared_examples "it emits a string that" do
67
+ before { subject.scan_file(path) }
31
68
 
32
- it "should find mergit.rb" do
33
- subject.find_requirement!(lib_name).should eq(lib_file)
69
+ it "should start with a MERGIT comment" do
70
+ subject.output.should =~ /\A### MERGIT: Start of '#{path}'$/
71
+ end
72
+
73
+ it "should end with a MERGIT comment" do
74
+ subject.output.should =~ /^### MERGIT: End of '#{path}'\Z/
34
75
  end
35
76
  end
36
77
 
37
- it "should raise an exception when it doesn't exist" do
38
- expect { subject.find_requirement!('does-not-exist') }.
39
- to raise_error(Mergit::RequirementNotFound)
78
+ context "with an absolute path" do
79
+ let(:path) { no_requires_file }
80
+ it_behaves_like "it emits a string that"
40
81
  end
41
- end
42
82
 
43
- describe "scan_file" do
44
- subject { Mergit::Processor.new(search_path, replacements, :string => '', :do_not_close => true) }
83
+ context "with a relative path" do
84
+ let(:path) { 'relative/path' }
85
+ it_behaves_like "it emits a string that"
86
+ end
45
87
 
46
88
  context "of an existing lib_file" do
47
- let(:lib_file) { Pathname.new('../../../lib/mergit/version.rb').expand_path(__FILE__) }
48
- let(:relative_lib_file) { 'lib/mergit/version.rb' }
49
- let(:lib_name) { lib_file.basename '.rb' }
89
+ let(:lib_file) { no_requires_file }
50
90
 
51
91
  it "should call .scan_line multiple times" do
52
- subject.should_receive(:scan_line).at_least(3).times
92
+ subject.should_receive(:scan_line).exactly(3).times
53
93
  subject.scan_file(lib_file)
54
94
  end
55
95
 
56
- context "then the output" do
57
- before { subject.scan_file(lib_file) }
58
- it "should start with the merget header" do
59
- subject.output.should =~ /\A### MERGIT: Start of '#{relative_lib_file}'$/
60
- end
61
-
62
- it "should end with the merget header" do
63
- subject.output.should =~ /^### MERGIT: End of '#{relative_lib_file}'\Z/
64
- end
96
+ it "should return true" do
97
+ subject.scan_file(lib_file).should be_true
98
+ end
65
99
 
66
- it "contain the contents of lib_file" do
67
- subject.output.should include(lib_file.read)
68
- end
100
+ it "contain the contents of lib_file" do
101
+ subject.scan_file(lib_file)
102
+ subject.output.should include(lib_file.read)
69
103
  end
70
104
  end
71
105
 
72
- context "with a lib_file that has a requires" do
73
- let(:required_content) { Pathname.new('../../../lib/mergit/version.rb').expand_path(__FILE__).read }
74
- let(:lib_file) { Pathname.new('../../../lib/mergit.rb').expand_path(__FILE__) }
75
- subject { Mergit::Processor.new(search_path, replacements, :string => '', :do_not_close => true) }
76
- before { subject.scan_file(lib_file) }
106
+ it "should call .find_requirement with the filename" do
107
+ subject.should_receive(:find_requirement).with('some_file_name')
108
+ subject.scan_file('some_file_name')
109
+ end
110
+
111
+ context "with a filename that contains a requires" do
112
+ let(:filename) { has_requires_file }
113
+ let(:required_file) { no_requires_file }
114
+ before { subject.scan_file(filename) }
77
115
 
78
116
  it "should contain the required file" do
79
- subject.output.should include(required_content)
117
+ subject.output.should include(required_file.read)
118
+ end
119
+ end
120
+
121
+ context "called a second time with the same filename" do
122
+ before { subject.scan_file(no_requires_file) }
123
+
124
+ it "should return true" do
125
+ subject.scan_file(no_requires_file).should be_true
126
+ end
127
+ end
128
+
129
+ context "with a filename that doesn't exist" do
130
+ it "should return false" do
131
+ subject.scan_file('file-does-not-exist').should be_false
80
132
  end
81
133
  end
82
134
  end
83
135
 
84
136
  describe "scan" do
85
- subject { Mergit::Processor.new(search_path, replacements, :string => '', :do_not_close => true) }
137
+ let(:do_not_close) { true }
86
138
 
87
139
  context "with a string" do
88
140
  let(:ruby_string) { "puts 'hello'\nrequire 'pathname'\n\nputs 'goodbye'\n" }
@@ -112,14 +164,22 @@ describe Mergit::Processor do
112
164
  end
113
165
 
114
166
  describe "scan_line" do
115
- subject { Mergit::Processor.new(search_path, replacements, :string => '', :do_not_close => true) }
167
+ let(:do_not_close) { true }
116
168
 
117
169
  context "given a single requires" do
118
- let(:ruby_string) { "require 'mergit/version'" }
170
+ let(:ruby_string) { "require 'no_requires'" }
119
171
  after { subject.scan_line ruby_string }
120
172
 
121
173
  it "should call scan_file()" do
122
- subject.should_receive(:scan_file).with(Pathname.new('../../../lib/mergit/version.rb').expand_path(__FILE__)).once
174
+ subject.should_receive(:scan_file).with('no_requires').once
175
+ end
176
+
177
+ context "that has a comment after it" do
178
+ let(:ruby_string) { "require 'no_requires' # this is a comment" }
179
+
180
+ it "should call scan_file()" do
181
+ subject.should_receive(:scan_file).with('no_requires').once
182
+ end
123
183
  end
124
184
  end
125
185
 
@@ -163,7 +223,6 @@ describe Mergit::Processor do
163
223
  end
164
224
 
165
225
  describe "string_split" do
166
- subject { Mergit::Processor.new(search_path, replacements, :string => '') }
167
226
  let(:example_parts) { [ 'one', '', 'two', 'three' ] }
168
227
 
169
228
  context "with unix newlines" do
@@ -182,15 +241,9 @@ describe Mergit::Processor do
182
241
  end
183
242
 
184
243
  context "with looping requires" do
244
+ let(:search_path) { [dir] }
245
+ let(:do_not_close) { true }
185
246
  let(:dir) { EXAMPLE_DIR + 'loop' }
186
- subject do
187
- Mergit::Processor.new(
188
- [ dir ],
189
- {},
190
- :string => '',
191
- :do_not_close => true
192
- )
193
- end
194
247
 
195
248
  it "should not go into an infinite loop" do
196
249
  subject.scan_file(dir + 'a.rb')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mergit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-18 00:00:00.000000000 Z
12
+ date: 2013-04-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -243,9 +243,12 @@ files:
243
243
  - lib/mergit/processor.rb
244
244
  - lib/mergit/version.rb
245
245
  - mergit.gemspec
246
+ - spec/examples/has_requires.rb
246
247
  - spec/examples/loop/a.rb
247
248
  - spec/examples/loop/b.rb
248
249
  - spec/examples/loop/c.rb
250
+ - spec/examples/no_requires.rb
251
+ - spec/examples/relative/path.rb
249
252
  - spec/mergit/processor_spec.rb
250
253
  - spec/mergit_spec.rb
251
254
  - spec/spec_helper.rb
@@ -264,7 +267,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
264
267
  version: '0'
265
268
  segments:
266
269
  - 0
267
- hash: 3687644075462403820
270
+ hash: -3347449453804380460
268
271
  required_rubygems_version: !ruby/object:Gem::Requirement
269
272
  none: false
270
273
  requirements:
@@ -273,7 +276,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
273
276
  version: '0'
274
277
  segments:
275
278
  - 0
276
- hash: 3687644075462403820
279
+ hash: -3347449453804380460
277
280
  requirements: []
278
281
  rubyforge_project:
279
282
  rubygems_version: 1.8.23
@@ -281,9 +284,12 @@ signing_key:
281
284
  specification_version: 3
282
285
  summary: Merge 'require'd files into one file.
283
286
  test_files:
287
+ - spec/examples/has_requires.rb
284
288
  - spec/examples/loop/a.rb
285
289
  - spec/examples/loop/b.rb
286
290
  - spec/examples/loop/c.rb
291
+ - spec/examples/no_requires.rb
292
+ - spec/examples/relative/path.rb
287
293
  - spec/mergit/processor_spec.rb
288
294
  - spec/mergit_spec.rb
289
295
  - spec/spec_helper.rb