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 +1 -1
- data/lib/mergit/processor.rb +26 -42
- data/lib/mergit/version.rb +1 -1
- data/spec/examples/has_requires.rb +5 -0
- data/spec/examples/no_requires.rb +3 -0
- data/spec/examples/relative/path.rb +2 -0
- data/spec/mergit/processor_spec.rb +108 -55
- metadata +10 -4
data/README.md
CHANGED
data/lib/mergit/processor.rb
CHANGED
@@ -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
|
-
|
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]
|
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
|
44
|
+
def find_requirement filename
|
45
|
+
filename = Pathname.new filename
|
41
46
|
@search_path.each do |directory|
|
42
|
-
possible_path = directory + "#{
|
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+'([^']+)'
|
76
|
-
|
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 [
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
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.
|
data/lib/mergit/version.rb
CHANGED
@@ -2,87 +2,139 @@ require 'spec_helper'
|
|
2
2
|
require 'mergit/processor'
|
3
3
|
|
4
4
|
describe Mergit::Processor do
|
5
|
-
let(:search_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
|
-
|
26
|
+
let(:expected_filename) { has_requires_file }
|
10
27
|
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
16
|
-
subject.find_requirement(
|
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 "
|
26
|
-
|
63
|
+
describe "scan_file" do
|
64
|
+
let(:do_not_close) { true }
|
27
65
|
|
28
|
-
|
29
|
-
|
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
|
33
|
-
subject.
|
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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
44
|
-
|
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) {
|
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).
|
92
|
+
subject.should_receive(:scan_line).exactly(3).times
|
53
93
|
subject.scan_file(lib_file)
|
54
94
|
end
|
55
95
|
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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(
|
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
|
-
|
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
|
-
|
167
|
+
let(:do_not_close) { true }
|
116
168
|
|
117
169
|
context "given a single requires" do
|
118
|
-
let(:ruby_string) { "require '
|
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(
|
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.
|
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-
|
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:
|
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:
|
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
|