gemnasium 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rvmrc +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +52 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +157 -0
- data/Rakefile +6 -0
- data/bin/gemnasium +43 -0
- data/features/gemnasium.feature +58 -0
- data/features/gemnasium_create.feature +13 -0
- data/features/gemnasium_install.feature +119 -0
- data/features/step_definitions/gemnasium_steps.rb +52 -0
- data/features/support/env.rb +7 -0
- data/gemnasium.gemspec +24 -0
- data/lib/gemnasium.rb +328 -0
- data/lib/gemnasium/configuration.rb +110 -0
- data/lib/gemnasium/connection.rb +42 -0
- data/lib/gemnasium/dependency_files.rb +55 -0
- data/lib/gemnasium/errors.rb +16 -0
- data/lib/gemnasium/options.rb +107 -0
- data/lib/gemnasium/version.rb +3 -0
- data/lib/templates/gemnasium.rake +24 -0
- data/lib/templates/gemnasium.yml +10 -0
- data/lib/templates/post-commit +7 -0
- data/spec/gemnasium/configuration_spec.rb +195 -0
- data/spec/gemnasium/connection_spec.rb +47 -0
- data/spec/gemnasium/dependency_files_spec.rb +80 -0
- data/spec/gemnasium/options_spec.rb +135 -0
- data/spec/gemnasium_spec.rb +520 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/gemnasium_helper.rb +86 -0
- metadata +177 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
Then /^it should create the config directory$/ do
|
2
|
+
steps %{
|
3
|
+
Then the output should match:
|
4
|
+
"""
|
5
|
+
Creating config directory
|
6
|
+
"""
|
7
|
+
And a directory named "config" should exist
|
8
|
+
}
|
9
|
+
end
|
10
|
+
Then /^it should create the config file$/ do
|
11
|
+
steps %{
|
12
|
+
Then the output should match:
|
13
|
+
"""
|
14
|
+
File created in .*\/config\/gemnasium\.yml
|
15
|
+
Please fill configuration file with accurate values\.
|
16
|
+
"""
|
17
|
+
And a file named "config/gemnasium.yml" should exist
|
18
|
+
}
|
19
|
+
end
|
20
|
+
Then /^it should create the post-commit hook$/ do
|
21
|
+
steps %{
|
22
|
+
Then the output should match:
|
23
|
+
"""
|
24
|
+
File created in .*\/.git\/hooks\/post-commit
|
25
|
+
"""
|
26
|
+
And a file named ".git/hooks/post-commit" should exist
|
27
|
+
}
|
28
|
+
end
|
29
|
+
Then /^it should create the task file$/ do
|
30
|
+
steps %{
|
31
|
+
Then the output should match:
|
32
|
+
"""
|
33
|
+
File created in .*\/lib\/tasks\/gemnasium.rake
|
34
|
+
"""
|
35
|
+
And the output should contain:
|
36
|
+
"""
|
37
|
+
Usage:
|
38
|
+
rake gemnasium:push - to push your dependency files
|
39
|
+
rake gemnasium:create - to create your project on Gemnasium
|
40
|
+
"""
|
41
|
+
And a file named "lib/tasks/gemnasium.rake" should exist
|
42
|
+
}
|
43
|
+
end
|
44
|
+
Then /^it should create the tasks directory$/ do
|
45
|
+
steps %{
|
46
|
+
Then the output should match:
|
47
|
+
"""
|
48
|
+
Creating lib/tasks directory.
|
49
|
+
"""
|
50
|
+
And a directory named "lib/tasks" should exist
|
51
|
+
}
|
52
|
+
end
|
data/gemnasium.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require './lib/gemnasium/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.authors = ["Tech-Angels"]
|
5
|
+
gem.email = ["contact@tech-angels.com"]
|
6
|
+
gem.description = "Safely upload your dependency files on gemnasium.com to track dependencies and get notified about updates and security advisories." +
|
7
|
+
"WARNING! This gem has been deprecated and support will be discontinued. Please use Gemnasium Toolbelt (https://github.com/gemnasium/toolbelt) instead."
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.homepage = "https://gemnasium.com/"
|
10
|
+
gem.license = 'MIT'
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "gemnasium"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.executables = ["gemnasium"]
|
17
|
+
gem.version = Gemnasium::VERSION
|
18
|
+
|
19
|
+
gem.add_development_dependency 'rake', '~>10.3.1'
|
20
|
+
gem.add_development_dependency 'rspec', '~>3.0'
|
21
|
+
gem.add_development_dependency 'cucumber'
|
22
|
+
gem.add_development_dependency 'aruba'
|
23
|
+
gem.add_development_dependency 'webmock'
|
24
|
+
end
|
data/lib/gemnasium.rb
ADDED
@@ -0,0 +1,328 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'gemnasium/connection'
|
3
|
+
require 'gemnasium/configuration'
|
4
|
+
require 'gemnasium/dependency_files'
|
5
|
+
require 'gemnasium/errors'
|
6
|
+
|
7
|
+
module Gemnasium
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Push dependency files to Gemnasium
|
11
|
+
# @param options [Hash] Parsed options from the command line. Options supported:
|
12
|
+
# * :project_path - Path to the project (required)
|
13
|
+
def push options
|
14
|
+
@config = load_config(options[:project_path])
|
15
|
+
ensure_config_is_up_to_date!
|
16
|
+
|
17
|
+
unless current_branch == @config.project_branch
|
18
|
+
if options[:ignore_branch]
|
19
|
+
notify "Not on tracked branch (#{@config.project_branch}), but ignore-branch option set to true. Continuing.\n", :blue
|
20
|
+
elsif options[:silence_branch]
|
21
|
+
notify "Not on tracked branch (#{@config.project_branch}). Exiting silently.\n", :blue
|
22
|
+
return
|
23
|
+
else
|
24
|
+
quit_because_of("Not on tracked branch (#{@config.project_branch})")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
unless has_project_slug?
|
29
|
+
quit_because_of('Project slug not defined. Please create a new project or "resolve" the name of an existing project.')
|
30
|
+
end
|
31
|
+
|
32
|
+
dependency_files_hashes = DependencyFiles.get_sha1s_hash(options[:project_path])
|
33
|
+
quit_because_of("No supported dependency files detected.") if dependency_files_hashes.empty?
|
34
|
+
notify "#{dependency_files_hashes.keys.count} supported dependency file(s) found: #{dependency_files_hashes.keys.join(', ')}"
|
35
|
+
|
36
|
+
# Ask to Gemnasium server which dependency file should be uploaded (new or modified)
|
37
|
+
comparison_results = request("#{connection.api_path_for('dependency_files')}/compare", dependency_files_hashes)
|
38
|
+
files_to_upload = comparison_results['to_upload']
|
39
|
+
deleted_files = comparison_results['deleted']
|
40
|
+
notify "#{deleted_files.count} deleted file(s): #{deleted_files.join(', ')}", :blue unless deleted_files.empty?
|
41
|
+
|
42
|
+
unless files_to_upload.empty?
|
43
|
+
notify "#{files_to_upload.count} file(s) to upload: #{files_to_upload.join(', ')}"
|
44
|
+
|
45
|
+
# Upload requested dependency files content
|
46
|
+
upload_summary = request("#{connection.api_path_for('dependency_files')}/upload", DependencyFiles.get_content_to_upload(options[:project_path], files_to_upload))
|
47
|
+
notify "Added dependency files: #{upload_summary['added']}", :green
|
48
|
+
notify "Updated dependency files: #{upload_summary['updated']}", :green
|
49
|
+
notify "Unchanged dependency files: #{upload_summary['unchanged']}", :blue unless upload_summary['unchanged'].empty?
|
50
|
+
notify "Unsupported dependency files: #{upload_summary['unsupported']}", :blue unless upload_summary['unsupported'].empty?
|
51
|
+
else
|
52
|
+
notify "The project's dependency files are up-to-date.", :blue
|
53
|
+
end
|
54
|
+
rescue => exception
|
55
|
+
quit_because_of(exception.message)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Install needed file(s) to run gemnasium command
|
59
|
+
#
|
60
|
+
# @param options [Hash] Parsed options from the command line. Options supported:
|
61
|
+
# * :install_rake_task - Install a rake task to the project
|
62
|
+
# * :install_git_hook - Install a git post-commit hook
|
63
|
+
# * :project_path - Path to the project (required)
|
64
|
+
def install options
|
65
|
+
require 'fileutils'
|
66
|
+
|
67
|
+
# Install config file
|
68
|
+
config_file_dir = "#{options[:project_path]}/config"
|
69
|
+
|
70
|
+
unless File.exists? config_file_dir
|
71
|
+
notify "Creating config directory"
|
72
|
+
FileUtils.mkdir_p config_file_dir
|
73
|
+
end
|
74
|
+
|
75
|
+
# Try to add config/gemnasium.yml to .gitignore
|
76
|
+
if File.exists? "#{options[:project_path]}/.gitignore"
|
77
|
+
File.open("#{options[:project_path]}/.gitignore", 'a+') do |f|
|
78
|
+
f.write("\n# Gemnasium gem configuration file\nconfig/gemnasium.yml") unless f.read.include? 'config/gemnasium.yml'
|
79
|
+
notify "Configuration file added to your project's .gitignore."
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
notify 'Please fill configuration file with accurate values.', :blue if copy_template('gemnasium.yml', "#{config_file_dir}/gemnasium.yml")
|
84
|
+
|
85
|
+
# Install git hook
|
86
|
+
if options[:install_git_hook]
|
87
|
+
notify ''
|
88
|
+
if File.exists? "#{options[:project_path]}/.git/hooks"
|
89
|
+
copy_template('post-commit', "#{options[:project_path]}/.git/hooks/post-commit")
|
90
|
+
else
|
91
|
+
notify "#{options[:project_path]} is not a git repository. Try to run `git init`.", :red
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Install rake task
|
96
|
+
if options[:install_rake_task]
|
97
|
+
notify ''
|
98
|
+
if !File.exists? "#{options[:project_path]}/Rakefile"
|
99
|
+
notify "Rakefile not found.", :red
|
100
|
+
else
|
101
|
+
rake_file_dir = "#{options[:project_path]}/lib/tasks"
|
102
|
+
|
103
|
+
unless File.exists? rake_file_dir
|
104
|
+
notify "Creating lib/tasks directory"
|
105
|
+
FileUtils.mkdir_p rake_file_dir
|
106
|
+
end
|
107
|
+
|
108
|
+
if copy_template('gemnasium.rake', "#{rake_file_dir}/gemnasium.rake")
|
109
|
+
notify 'Usage:', :blue
|
110
|
+
notify "\trake gemnasium:push \t\t- to push your dependency files", :blue
|
111
|
+
notify "\trake gemnasium:create \t\t- to create your project on Gemnasium", :blue
|
112
|
+
notify "\trake gemnasium:migrate \t\t- to migrate your configuration file", :blue
|
113
|
+
notify "\trake gemnasium:resolve \t\t- to resolve the project name to an existing project", :blue
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Create the project on Gemnasium
|
120
|
+
#
|
121
|
+
# @param options [Hash] Parsed options from the command line. Options supported:
|
122
|
+
# * :project_path - Path to the project (required)
|
123
|
+
def create_project options
|
124
|
+
@config = load_config(options[:project_path])
|
125
|
+
ensure_config_is_up_to_date!
|
126
|
+
|
127
|
+
if has_project_slug?
|
128
|
+
quit_because_of("You already have a project slug refering to an existing project. Please remove this project slug from your configuration file to create a new project.")
|
129
|
+
end
|
130
|
+
|
131
|
+
project_params = { name: @config.project_name, branch: @config.project_branch}
|
132
|
+
|
133
|
+
result = request("#{connection.api_path_for('projects')}", project_params)
|
134
|
+
project_name, project_slug, remaining_slot_count = result.values_at 'name', 'slug', 'remaining_slot_count'
|
135
|
+
|
136
|
+
notify "Project `#{ project_name }` successfully created.", :green
|
137
|
+
notify "Project slug is `#{ project_slug }`.", :green
|
138
|
+
notify "Remaining private slots: #{ remaining_slot_count }", :blue
|
139
|
+
|
140
|
+
if @config.writable?
|
141
|
+
@config.store_value!(:project_slug, project_slug, "This unique project slug has been set by `gemnasium create`.")
|
142
|
+
notify "Your configuration file has been updated."
|
143
|
+
else
|
144
|
+
notify "Configuration file cannot be updated. Please edit the file and update the project slug manually."
|
145
|
+
end
|
146
|
+
|
147
|
+
rescue => exception
|
148
|
+
quit_because_of(exception.message)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Migrate the configuration file
|
152
|
+
#
|
153
|
+
# @param options [Hash] Parsed options from the command line. Options supported:
|
154
|
+
# * :project_path - Path to the project (required)
|
155
|
+
#
|
156
|
+
def migrate options
|
157
|
+
@config = load_config(options[:project_path])
|
158
|
+
|
159
|
+
if @config.needs_to_migrate?
|
160
|
+
@config.migrate!
|
161
|
+
notify "Your configuration has been updated.", :green
|
162
|
+
notify "Run `gemnasium resolve` if your config is related to an existing project."
|
163
|
+
notify "Run `gemnasium create` if you want to create a new project on Gemnasium."
|
164
|
+
else
|
165
|
+
notify "Your configuration file is already up-to-date.", :green
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Find and store the project slug matching the given project name.
|
170
|
+
#
|
171
|
+
# @param options [Hash] Parsed options from the command line. Options supported:
|
172
|
+
# * :project_path - Path to the project (required)
|
173
|
+
#
|
174
|
+
def resolve_project options
|
175
|
+
@config = load_config(options[:project_path])
|
176
|
+
ensure_config_is_up_to_date!
|
177
|
+
|
178
|
+
# REFACTOR: similar code in #create_project
|
179
|
+
if has_project_slug?
|
180
|
+
quit_because_of("You already have a project slug refering to an existing project. Please remove this project slug from your configuration file.")
|
181
|
+
end
|
182
|
+
|
183
|
+
project_name = @config.project_name
|
184
|
+
project_branch = @config.project_branch || 'master'
|
185
|
+
projects = request("#{connection.api_path_for('projects')}")
|
186
|
+
|
187
|
+
candidates = projects.select do |project|
|
188
|
+
project['name'] == project_name && project['origin'] == 'offline' && project['branch'] == project_branch
|
189
|
+
end
|
190
|
+
|
191
|
+
criterias = "name `#{ project_name }` and branch `#{ project_branch }`"
|
192
|
+
if candidates.size == 0
|
193
|
+
quit_because_of("You have no off-line project matching #{ criterias }.")
|
194
|
+
elsif candidates.size > 1
|
195
|
+
quit_because_of("You have more than one off-line project matching #{ criterias }.")
|
196
|
+
end
|
197
|
+
|
198
|
+
project = candidates.first
|
199
|
+
project_slug = project['slug']
|
200
|
+
notify "Project slug is `#{ project_slug }`.", :green
|
201
|
+
|
202
|
+
# REFACTOR: similar code in #create_project
|
203
|
+
if @config.writable?
|
204
|
+
@config.store_value!(:project_slug, project_slug, "This unique project slug has been set by `gemnasium resolve`.")
|
205
|
+
notify "Your configuration file has been updated."
|
206
|
+
else
|
207
|
+
notify "Configuration file cannot be updated. Please edit the file and update the project slug manually."
|
208
|
+
end
|
209
|
+
|
210
|
+
rescue => exception
|
211
|
+
quit_because_of(exception.message)
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def config
|
216
|
+
@config || quit_because_of('No configuration file loaded')
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
def has_project_slug?
|
222
|
+
!@config.project_slug.nil?
|
223
|
+
end
|
224
|
+
|
225
|
+
# Quit with an error message if the config file needs a migration.
|
226
|
+
#
|
227
|
+
def ensure_config_is_up_to_date!
|
228
|
+
if @config.needs_to_migrate?
|
229
|
+
quit_because_of('Your configuration file is not compatible with this version. Please run the `migrate` command first.')
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Issue a HTTP request
|
234
|
+
#
|
235
|
+
# @params path [String] Path of the request
|
236
|
+
# parameters [Hash] Parameters to send a POST request
|
237
|
+
def request(path, parameters = {})
|
238
|
+
if parameters.empty?
|
239
|
+
response = connection.get(path)
|
240
|
+
else
|
241
|
+
response = connection.post(path, JSON.generate(parameters))
|
242
|
+
end
|
243
|
+
|
244
|
+
raise Gemnasium::InvalidApiKeyError if response.code.to_i == 401
|
245
|
+
|
246
|
+
response_body = JSON.parse(response.body)
|
247
|
+
|
248
|
+
if response.code.to_i / 100 == 2
|
249
|
+
return {} if response_body.empty?
|
250
|
+
result = response_body
|
251
|
+
else
|
252
|
+
if error = "#{response_body['error']}_error".split('_').collect(&:capitalize).join
|
253
|
+
raise Gemnasium.const_get(error), response_body['message']
|
254
|
+
else
|
255
|
+
quit_because_of 'An unknown error has been returned by the server. Please contact Gemnasium support : http://support.gemnasium.com'
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Create a connection
|
261
|
+
def connection
|
262
|
+
@connection ||= Connection.new
|
263
|
+
end
|
264
|
+
|
265
|
+
# Load config from config file
|
266
|
+
#
|
267
|
+
# @param config_file [String] path to the project
|
268
|
+
# @return [Hash] config options
|
269
|
+
def load_config project_path
|
270
|
+
@config ||= Configuration.new("#{project_path}/config/gemnasium.yml")
|
271
|
+
rescue => exception
|
272
|
+
quit_because_of(exception.message)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Puts a message to the standard output
|
276
|
+
#
|
277
|
+
# @param message [String] message to display
|
278
|
+
def notify message, color = nil
|
279
|
+
if $stdout.tty? && !color.nil?
|
280
|
+
color_code = { red: "\e[31m", green: "\e[32m", blue: "\e[34m" }
|
281
|
+
reset_color = "\e[0m"
|
282
|
+
|
283
|
+
message = color_code[color] + message + reset_color
|
284
|
+
end
|
285
|
+
|
286
|
+
$stdout.puts message
|
287
|
+
end
|
288
|
+
|
289
|
+
# Abort the program and colorize the message if $stderr is tty
|
290
|
+
#
|
291
|
+
# @param error_message [String] message to be puts to $stderr
|
292
|
+
def quit_because_of(error_message)
|
293
|
+
error_message = "\e[31m#{error_message}\e[0m" if $stderr.tty?
|
294
|
+
abort error_message
|
295
|
+
end
|
296
|
+
|
297
|
+
# Get the current git branch
|
298
|
+
#
|
299
|
+
# @return [String] name of the current branch
|
300
|
+
def current_branch
|
301
|
+
branch = `git branch 2>/dev/null`.split("\n").delete_if { |branch| branch.chars.first != "*" }.first
|
302
|
+
branch.gsub("* ","") unless branch.nil?
|
303
|
+
end
|
304
|
+
|
305
|
+
# Copy a template file
|
306
|
+
#
|
307
|
+
# @param file [String] template to copy
|
308
|
+
# target_path [String] location where to copy the template
|
309
|
+
def copy_template(file, target_path)
|
310
|
+
if File.exists? target_path
|
311
|
+
notify "The file #{target_path} already exists"
|
312
|
+
else
|
313
|
+
template_file = File.expand_path("#{File.dirname(__FILE__)}/templates/#{file}")
|
314
|
+
FileUtils.cp template_file, target_path
|
315
|
+
|
316
|
+
if File.exists? target_path
|
317
|
+
notify "File created in #{target_path}", :green
|
318
|
+
|
319
|
+
return true
|
320
|
+
else
|
321
|
+
notify "Could not install #{file} file.", :red
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
false
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Gemnasium
|
5
|
+
class Configuration
|
6
|
+
attr_accessor :site, :api_key, :use_ssl, :api_version, :project_branch, :ignored_paths
|
7
|
+
|
8
|
+
attr_accessor :project_name # Name is required only to create the project, make it mandatory.
|
9
|
+
attr_accessor :project_slug # Slug is required only to push the dependency files, make it optional.
|
10
|
+
attr_accessor :profile_name # Keep profile name for backward compatibility with version =< 2.0
|
11
|
+
|
12
|
+
DEFAULT_CONFIG = { 'site' => 'gemnasium.com',
|
13
|
+
'use_ssl' => true,
|
14
|
+
'api_version' => 'v3',
|
15
|
+
'ignored_paths' => [] }
|
16
|
+
|
17
|
+
# Initialize the configuration object from a YAML file
|
18
|
+
#
|
19
|
+
# @param config_file [String] path to the configuration file
|
20
|
+
def initialize config_file
|
21
|
+
unless File.file?(config_file)
|
22
|
+
raise Errno::ENOENT,
|
23
|
+
"Configuration file (#{config_file}) does not exist.\nPlease run `gemnasium install`."
|
24
|
+
end
|
25
|
+
@path = config_file
|
26
|
+
|
27
|
+
config_hash = DEFAULT_CONFIG.merge(YAML.load(ERB.new(File.read(config_file)).result))
|
28
|
+
config_hash.each do |k, v|
|
29
|
+
writer_method = "#{k}="
|
30
|
+
if respond_to?(writer_method)
|
31
|
+
v = convert_ignored_paths_to_regexp(v) if k.to_s == 'ignored_paths'
|
32
|
+
send(writer_method, v)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
raise 'Your configuration file does not contain all mandatory parameters or contain invalid values. Please check the documentation.' unless is_valid?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Store a key-value pair in the configuration file with an optional comment.
|
40
|
+
# Try to preserve the comments and the indentation of the file.
|
41
|
+
# We assume the configuration file already features the given key.
|
42
|
+
#
|
43
|
+
# @param key [String] key
|
44
|
+
# @param value [String] value to store for given key
|
45
|
+
# @param comment [String] optional comment
|
46
|
+
#
|
47
|
+
def store_value!(key, value, comment = nil)
|
48
|
+
pattern = /\A#{ key }:.*\Z/
|
49
|
+
new_line = "#{ key }: #{ value }"
|
50
|
+
new_line += " # #{ comment }" if comment
|
51
|
+
|
52
|
+
content = File.readlines(path).map do |line|
|
53
|
+
line.rstrip.sub pattern, new_line
|
54
|
+
end.join("\n") + "\n"
|
55
|
+
|
56
|
+
File.write path, content
|
57
|
+
end
|
58
|
+
|
59
|
+
def writable?
|
60
|
+
File.writable? path
|
61
|
+
end
|
62
|
+
|
63
|
+
def needs_to_migrate?
|
64
|
+
!profile_name.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
def migrate!
|
68
|
+
# replace profile_name key with project_slug key (no value)
|
69
|
+
content = File.readlines(path).map do |line|
|
70
|
+
if line =~ /\Aprofile_name:.*\Z/
|
71
|
+
"project_slug:"
|
72
|
+
else
|
73
|
+
line
|
74
|
+
end
|
75
|
+
end.map{ |l| l.rstrip }.join("\n") + "\n"
|
76
|
+
|
77
|
+
File.write path, content
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
attr_reader :path
|
83
|
+
|
84
|
+
# Check that mandatory parameters are not nil and contain valid values
|
85
|
+
#
|
86
|
+
# @return [Boolean] if configuration is valid
|
87
|
+
def is_valid?
|
88
|
+
site_option_valid = !site.nil? && !site.empty?
|
89
|
+
api_key_option_valid = !api_key.nil? && !api_key.empty?
|
90
|
+
use_ssl_option_valid = !use_ssl.nil? && !!use_ssl == use_ssl # Check this is a boolean
|
91
|
+
api_version_option_valid = !api_version.nil? && !api_version.empty?
|
92
|
+
project_name_option_valid = !project_name.nil? && !project_name.empty?
|
93
|
+
ignored_paths_option_valid = ignored_paths.kind_of?(Array)
|
94
|
+
|
95
|
+
site_option_valid && api_key_option_valid && use_ssl_option_valid && api_version_option_valid &&
|
96
|
+
project_name_option_valid && ignored_paths_option_valid
|
97
|
+
end
|
98
|
+
|
99
|
+
def convert_ignored_paths_to_regexp(paths)
|
100
|
+
return [] unless paths.kind_of? Array
|
101
|
+
|
102
|
+
paths.inject([]) do |regexp_array, path|
|
103
|
+
path = path.insert(0,'^') # All path start from app root
|
104
|
+
.gsub('*','[^/]+') # Replace `*` to whatever char except slash
|
105
|
+
.gsub('.','\.') # Escape dots
|
106
|
+
regexp_array << Regexp.new(path)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|