librariesio-gem-parser 1.0.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.
@@ -0,0 +1,38 @@
1
+ module Gemnasium
2
+ module Parser
3
+ class Podspec
4
+ attr_reader :content
5
+
6
+ def initialize(content)
7
+ @content = content
8
+ end
9
+
10
+ def dependencies
11
+ @dependencies ||= [].tap do |deps|
12
+ runtime_matches.each do |match|
13
+ dep = dependency(match)
14
+ deps << dep
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+ def runtime_matches
21
+ @runtime_matches ||= matches(Patterns::ADD_POD_DEPENDENCY_CALL)
22
+ end
23
+
24
+ def matches(pattern)
25
+ [].tap{|m| content.scan(pattern){ m << Regexp.last_match } }
26
+ end
27
+
28
+ def dependency(match)
29
+ name, reqs = match["name"], [match["req1"], match["req2"]].compact
30
+ type = :runtime
31
+ Bundler::Dependency.new(name, reqs, "type" => type).tap do |dep|
32
+ line = content.slice(0, match.begin(0)).count("\n") + 1
33
+ dep.instance_variable_set(:@line, line)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "librariesio-gem-parser"
5
+ gem.version = "1.0.0"
6
+
7
+ gem.authors = "Andrew Nesbitt"
8
+ gem.email = "andrewnez@gmail.com"
9
+ gem.description = "Fork of gemnasium-parser"
10
+ gem.summary = gem.description
11
+ gem.homepage = "https://github.com/librariesio/gemnasium-parser"
12
+
13
+ gem.add_development_dependency "bundler", "~> 1.0"
14
+ gem.add_development_dependency "rake", ">= 0.8.7"
15
+ gem.add_development_dependency "rspec", "~> 2.4"
16
+
17
+ gem.files = `git ls-files`.split($\)
18
+ gem.test_files = gem.files.grep(/^spec\//)
19
+ gem.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,294 @@
1
+ require "spec_helper"
2
+
3
+ describe Gemnasium::Parser::Gemfile do
4
+ def content(string)
5
+ @content ||= begin
6
+ indent = string.scan(/^[ \t]*(?=\S)/)
7
+ n = indent ? indent.size : 0
8
+ string.gsub(/^[ \t]{#{n}}/, "")
9
+ end
10
+ end
11
+
12
+ def gemfile
13
+ @gemfile ||= Gemnasium::Parser::Gemfile.new(@content)
14
+ end
15
+
16
+ def dependencies
17
+ @dependencies ||= gemfile.dependencies
18
+ end
19
+
20
+ def dependency
21
+ dependencies.size.should == 1
22
+ dependencies.first
23
+ end
24
+
25
+ def reset
26
+ @content = @gemfile = @dependencies = nil
27
+ end
28
+
29
+ it "parses double quotes" do
30
+ content(%(gem "rake", ">= 0.8.7"))
31
+ dependency.name.should == "rake"
32
+ dependency.requirement.as_list.should == [">= 0.8.7"]
33
+ end
34
+
35
+ it "parses single quotes" do
36
+ content(%(gem 'rake', '>= 0.8.7'))
37
+ dependency.name.should == "rake"
38
+ dependency.requirement.as_list.should == [">= 0.8.7"]
39
+ end
40
+
41
+ it "ignores mixed quotes" do
42
+ content(%(gem "rake', ">= 0.8.7"))
43
+ dependencies.size.should == 0
44
+ end
45
+
46
+ it "parses gems with a period in the name" do
47
+ content(%(gem "pygment.rb", ">= 0.8.7"))
48
+ dependency.name.should == "pygment.rb"
49
+ dependency.requirement.as_list.should == [">= 0.8.7"]
50
+ end
51
+
52
+ it "parses non-requirement gems" do
53
+ content(%(gem "rake"))
54
+ dependency.name.should == "rake"
55
+ dependency.requirement.as_list.should == [">= 0"]
56
+ end
57
+
58
+ it "parses multi-requirement gems" do
59
+ content(%(gem "rake", ">= 0.8.7", "<= 0.9.2"))
60
+ dependency.name.should == "rake"
61
+ dependency.requirement.as_list.should == ["<= 0.9.2", ">= 0.8.7"]
62
+ end
63
+
64
+ it "parses gems with options" do
65
+ content(%(gem "rake", ">= 0.8.7", :require => false))
66
+ dependency.name.should == "rake"
67
+ dependency.requirement.as_list.should == [">= 0.8.7"]
68
+ end
69
+
70
+ it "listens for gemspecs" do
71
+ content(%(gemspec))
72
+ gemfile.should be_gemspec
73
+ gemfile.gemspec.should == "*.gemspec"
74
+ reset
75
+ content(%(gem "rake"))
76
+ gemfile.should_not be_gemspec
77
+ gemfile.gemspec.should be_nil
78
+ end
79
+
80
+ it "parses gemspecs with a name option" do
81
+ content(%(gemspec :name => "gemnasium-parser"))
82
+ gemfile.gemspec.should == "gemnasium-parser.gemspec"
83
+ end
84
+
85
+ it "parses gemspecs with a path option" do
86
+ content(%(gemspec :path => "lib/gemnasium"))
87
+ gemfile.gemspec.should == "lib/gemnasium/*.gemspec"
88
+ end
89
+
90
+ it "parses gemspecs with name and path options" do
91
+ content(%(gemspec :name => "parser", :path => "lib/gemnasium"))
92
+ gemfile.gemspec.should == "lib/gemnasium/parser.gemspec"
93
+ end
94
+
95
+ it "parses gemspecs with parentheses" do
96
+ content(%(gemspec(:name => "gemnasium-parser")))
97
+ gemfile.should be_gemspec
98
+ end
99
+
100
+ it "parses gems of a type" do
101
+ content(%(gem "rake"))
102
+ dependency.type.should == :runtime
103
+ reset
104
+ content(%(gem "rake", :type => :development))
105
+ dependency.type.should == :development
106
+ end
107
+
108
+ it "parses gems of a group" do
109
+ content(%(gem "rake"))
110
+ dependency.groups.should == [:default]
111
+ reset
112
+ content(%(gem "rake", :group => :development))
113
+ dependency.groups.should == [:development]
114
+ end
115
+
116
+ it "parses gems of multiple groups" do
117
+ content(%(gem "rake", :group => [:development, :test]))
118
+ dependency.groups.should == [:development, :test]
119
+ end
120
+
121
+ it "recognizes :groups" do
122
+ content(%(gem "rake", :groups => [:development, :test]))
123
+ dependency.groups.should == [:development, :test]
124
+ end
125
+
126
+ it "parses gems in a group" do
127
+ content(<<-EOF)
128
+ gem "rake"
129
+ group :production do
130
+ gem "pg"
131
+ end
132
+ group :development do
133
+ gem "sqlite3"
134
+ end
135
+ EOF
136
+ dependencies[0].groups.should == [:default]
137
+ dependencies[1].groups.should == [:production]
138
+ dependencies[2].groups.should == [:development]
139
+ end
140
+
141
+ it "parses gems in a group with parentheses" do
142
+ content(<<-EOF)
143
+ group(:production) do
144
+ gem "pg"
145
+ end
146
+ EOF
147
+ dependency.groups.should == [:production]
148
+ end
149
+
150
+ it "parses gems in multiple groups" do
151
+ content(<<-EOF)
152
+ group :development, :test do
153
+ gem "sqlite3"
154
+ end
155
+ EOF
156
+ dependency.groups.should == [:development, :test]
157
+ end
158
+
159
+ it "parses multiple gems in a group" do
160
+ content(<<-EOF)
161
+ group :development do
162
+ gem "rake"
163
+ gem "sqlite3"
164
+ end
165
+ EOF
166
+ dependencies[0].groups.should == [:development]
167
+ dependencies[1].groups.should == [:development]
168
+ end
169
+
170
+ it "parses multiple gems in multiple groups" do
171
+ content(<<-EOF)
172
+ group :development, :test do
173
+ gem "rake"
174
+ gem "sqlite3"
175
+ end
176
+ EOF
177
+ dependencies[0].groups.should == [:development, :test]
178
+ dependencies[1].groups.should == [:development, :test]
179
+ end
180
+
181
+ it "ignores h4x" do
182
+ path = File.expand_path("../h4x.txt", __FILE__)
183
+ content(%(gem "h4x", :require => "\#{`touch #{path}`}"))
184
+ dependencies.size.should == 0
185
+ begin
186
+ File.should_not exist(path)
187
+ ensure
188
+ FileUtils.rm_f(path)
189
+ end
190
+ end
191
+
192
+ it "ignores gems with a git option" do
193
+ content(%(gem "rails", :git => "https://github.com/rails/rails.git"))
194
+ dependencies.size.should == 1
195
+ end
196
+
197
+ it "ignores gems with a github option" do
198
+ content(%(gem "rails", :github => "rails/rails"))
199
+ dependencies.size.should == 1
200
+ end
201
+
202
+ it "ignores gems with a path option" do
203
+ content(%(gem "rails", :path => "vendor/rails"))
204
+ dependencies.size.should == 1
205
+ end
206
+
207
+ it "ignores gems in a git block" do
208
+ content(<<-EOF)
209
+ git "https://github.com/rails/rails.git" do
210
+ gem "rails"
211
+ end
212
+ EOF
213
+ dependencies.size.should == 1
214
+ end
215
+
216
+ it "ignores gems in a git block with parentheses" do
217
+ content(<<-EOF)
218
+ git("https://github.com/rails/rails.git") do
219
+ gem "rails"
220
+ end
221
+ EOF
222
+ dependencies.size.should == 1
223
+ end
224
+
225
+ it "ignores gems in a path block" do
226
+ content(<<-EOF)
227
+ path "vendor/rails" do
228
+ gem "rails"
229
+ end
230
+ EOF
231
+ dependencies.size.should == 1
232
+ end
233
+
234
+ it "ignores gems in a path block with parentheses" do
235
+ content(<<-EOF)
236
+ path("vendor/rails") do
237
+ gem "rails"
238
+ end
239
+ EOF
240
+ dependencies.size.should == 1
241
+ end
242
+
243
+ it "records dependency line numbers" do
244
+ content(<<-EOF)
245
+ gem "rake"
246
+
247
+ gem "rails"
248
+ EOF
249
+ dependencies[0].instance_variable_get(:@line).should == 1
250
+ dependencies[1].instance_variable_get(:@line).should == 3
251
+ end
252
+
253
+ it "maps groups to types" do
254
+ content(<<-EOF)
255
+ gem "rake"
256
+ gem "pg", :group => :production
257
+ gem "mysql2", :group => :staging
258
+ gem "sqlite3", :group => :development
259
+ EOF
260
+ dependencies[0].type.should == :runtime
261
+ dependencies[1].type.should == :runtime
262
+ dependencies[2].type.should == :development
263
+ dependencies[3].type.should == :development
264
+ reset
265
+ Gemnasium::Parser.runtime_groups << :staging
266
+ content(<<-EOF)
267
+ gem "rake"
268
+ gem "pg", :group => :production
269
+ gem "mysql2", :group => :staging
270
+ gem "sqlite3", :group => :development
271
+ EOF
272
+ dependencies[0].type.should == :runtime
273
+ dependencies[1].type.should == :runtime
274
+ dependencies[2].type.should == :runtime
275
+ dependencies[3].type.should == :development
276
+ end
277
+
278
+ it "parses parentheses" do
279
+ content(%(gem("rake", ">= 0.8.7")))
280
+ dependency.name.should == "rake"
281
+ dependency.requirement.as_list.should == [">= 0.8.7"]
282
+ end
283
+
284
+ it "parses gems followed by inline comments" do
285
+ content(%(gem "rake", ">= 0.8.7" # Comment))
286
+ dependency.name.should == "rake"
287
+ dependency.requirement.as_list.should == [">= 0.8.7"]
288
+ end
289
+
290
+ it "parses oddly quoted gems" do
291
+ content(%(gem %q<rake>))
292
+ dependency.name.should == "rake"
293
+ end
294
+ end
@@ -0,0 +1,159 @@
1
+ require "spec_helper"
2
+
3
+ describe Gemnasium::Parser::Gemspec do
4
+ def content(string)
5
+ @content ||= begin
6
+ indent = string.scan(/^[ \t]*(?=\S)/)
7
+ n = indent ? indent.size : 0
8
+ string.gsub(/^[ \t]{#{n}}/, "")
9
+ end
10
+ end
11
+
12
+ def gemspec
13
+ @gemspec ||= Gemnasium::Parser::Gemspec.new(@content)
14
+ end
15
+
16
+ def dependencies
17
+ @dependencies ||= gemspec.dependencies
18
+ end
19
+
20
+ def dependency
21
+ dependencies.size.should == 1
22
+ dependencies.first
23
+ end
24
+
25
+ def reset
26
+ @content = @gemspec = @dependencies = nil
27
+ end
28
+
29
+ it "parses double quotes" do
30
+ content(<<-EOF)
31
+ Gem::Specification.new do |gem|
32
+ gem.add_dependency "rake", ">= 0.8.7"
33
+ end
34
+ EOF
35
+ dependency.name.should == "rake"
36
+ dependency.requirement.as_list.should == [">= 0.8.7"]
37
+ end
38
+
39
+ it "parses single quotes" do
40
+ content(<<-EOF)
41
+ Gem::Specification.new do |gem|
42
+ gem.add_dependency 'rake', '>= 0.8.7'
43
+ end
44
+ EOF
45
+ dependency.name.should == "rake"
46
+ dependency.requirement.as_list.should == [">= 0.8.7"]
47
+ end
48
+
49
+ it "ignores mixed quotes" do
50
+ content(<<-EOF)
51
+ Gem::Specification.new do |gem|
52
+ gem.add_dependency "rake', ">= 0.8.7"
53
+ end
54
+ EOF
55
+ dependencies.size.should == 0
56
+ end
57
+
58
+ it "parses gems with a period in the name" do
59
+ content(<<-EOF)
60
+ Gem::Specification.new do |gem|
61
+ gem.add_dependency "pygment.rb", ">= 0.8.7"
62
+ end
63
+ EOF
64
+ dependency.name.should == "pygment.rb"
65
+ dependency.requirement.as_list.should == [">= 0.8.7"]
66
+ end
67
+
68
+ it "parses non-requirement gems" do
69
+ content(<<-EOF)
70
+ Gem::Specification.new do |gem|
71
+ gem.add_dependency "rake"
72
+ end
73
+ EOF
74
+ dependency.name.should == "rake"
75
+ dependency.requirement.as_list.should == [">= 0"]
76
+ end
77
+
78
+ it "parses multi-requirement gems" do
79
+ content(<<-EOF)
80
+ Gem::Specification.new do |gem|
81
+ gem.add_dependency "rake", ">= 0.8.7", "<= 0.9.2"
82
+ end
83
+ EOF
84
+ dependency.name.should == "rake"
85
+ dependency.requirement.as_list.should == ["<= 0.9.2", ">= 0.8.7"]
86
+ end
87
+
88
+ it "parses single-element array requirement gems" do
89
+ content(<<-EOF)
90
+ Gem::Specification.new do |gem|
91
+ gem.add_dependency "rake", [">= 0.8.7"]
92
+ end
93
+ EOF
94
+ dependency.name.should == "rake"
95
+ dependency.requirement.as_list.should == [">= 0.8.7"]
96
+ end
97
+
98
+ it "parses multi-element array requirement gems" do
99
+ content(<<-EOF)
100
+ Gem::Specification.new do |gem|
101
+ gem.add_dependency "rake", [">= 0.8.7", "<= 0.9.2"]
102
+ end
103
+ EOF
104
+ dependency.name.should == "rake"
105
+ dependency.requirement.as_list.should == ["<= 0.9.2", ">= 0.8.7"]
106
+ end
107
+
108
+ it "parses runtime gems" do
109
+ content(<<-EOF)
110
+ Gem::Specification.new do |gem|
111
+ gem.add_dependency "rake"
112
+ gem.add_runtime_dependency "rails"
113
+ end
114
+ EOF
115
+ dependencies[0].type.should == :runtime
116
+ dependencies[1].type.should == :runtime
117
+ end
118
+
119
+ it "parses dependency gems" do
120
+ content(<<-EOF)
121
+ Gem::Specification.new do |gem|
122
+ gem.add_development_dependency "rake"
123
+ end
124
+ EOF
125
+ dependency.type.should == :development
126
+ end
127
+
128
+ it "records dependency line numbers" do
129
+ content(<<-EOF)
130
+ Gem::Specification.new do |gem|
131
+ gem.add_dependency "rake"
132
+
133
+ gem.add_dependency "rails"
134
+ end
135
+ EOF
136
+ dependencies[0].instance_variable_get(:@line).should == 2
137
+ dependencies[1].instance_variable_get(:@line).should == 4
138
+ end
139
+
140
+ it "parses parentheses" do
141
+ content(<<-EOF)
142
+ Gem::Specification.new do |gem|
143
+ gem.add_dependency("rake", ">= 0.8.7")
144
+ end
145
+ EOF
146
+ dependency.name.should == "rake"
147
+ dependency.requirement.as_list.should == [">= 0.8.7"]
148
+ end
149
+
150
+ it "parses gems followed by inline comments" do
151
+ content(<<-EOF)
152
+ Gem::Specification.new do |gem|
153
+ gem.add_dependency "rake", ">= 0.8.7" # Comment
154
+ end
155
+ EOF
156
+ dependency.name.should == "rake"
157
+ dependency.requirement.as_list.should == [">= 0.8.7"]
158
+ end
159
+ end