proxy_tester 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/.rdebugrc +7 -0
- data/.rspec +3 -0
- data/.simplecov +8 -0
- data/Gemfile +37 -0
- data/Gemfile.lock +199 -0
- data/LICENSE.txt +22 -0
- data/Procfile +1 -0
- data/README.md +582 -0
- data/Rakefile +64 -0
- data/bin/proxy_tester +11 -0
- data/db/migrate/20140314_create_environment.rb +8 -0
- data/files/config.yaml +1 -0
- data/files/example-config.erb +12 -0
- data/files/example-spec_helper.rb.erb +23 -0
- data/files/example-test_case.rb.erb +27 -0
- data/files/example-test_cases-gemfile.rb.erb +9 -0
- data/files/example-user_file.erb +4 -0
- data/lib/proxy_tester/actions/add_examples_to_test_cases_directory.rb +125 -0
- data/lib/proxy_tester/actions/clone_repository.rb +39 -0
- data/lib/proxy_tester/actions/create_directory.rb +33 -0
- data/lib/proxy_tester/actions/create_file.rb +55 -0
- data/lib/proxy_tester/actions/create_output.rb +36 -0
- data/lib/proxy_tester/actions/handle_error.rb +37 -0
- data/lib/proxy_tester/actions/initialize_application.rb +70 -0
- data/lib/proxy_tester/actions/show_config.rb +10 -0
- data/lib/proxy_tester/capybara_proxy.rb +54 -0
- data/lib/proxy_tester/capybara_proxy_pac.rb +62 -0
- data/lib/proxy_tester/cli/main.rb +59 -0
- data/lib/proxy_tester/config.rb +100 -0
- data/lib/proxy_tester/data.rb +23 -0
- data/lib/proxy_tester/database_session.rb +15 -0
- data/lib/proxy_tester/environment.rb +21 -0
- data/lib/proxy_tester/erb_generator.rb +34 -0
- data/lib/proxy_tester/error_handler.rb +107 -0
- data/lib/proxy_tester/error_messages.rb +82 -0
- data/lib/proxy_tester/exceptions.rb +53 -0
- data/lib/proxy_tester/git_file.rb +31 -0
- data/lib/proxy_tester/git_null_file.rb +32 -0
- data/lib/proxy_tester/git_repository.rb +120 -0
- data/lib/proxy_tester/handle_error.rb +37 -0
- data/lib/proxy_tester/locales/en-rails.yml +205 -0
- data/lib/proxy_tester/locales/en.yml +42 -0
- data/lib/proxy_tester/main.rb +46 -0
- data/lib/proxy_tester/models/user.rb +17 -0
- data/lib/proxy_tester/pac_result.rb +50 -0
- data/lib/proxy_tester/rspec/helper.rb +211 -0
- data/lib/proxy_tester/rspec_runner.rb +43 -0
- data/lib/proxy_tester/template_file.rb +19 -0
- data/lib/proxy_tester/template_repository.rb +22 -0
- data/lib/proxy_tester/ui_logger.rb +30 -0
- data/lib/proxy_tester/user_database.rb +24 -0
- data/lib/proxy_tester/version.rb +3 -0
- data/lib/proxy_tester.rb +54 -0
- data/proxy_tester.gemspec +34 -0
- data/script/acceptance_test +4 -0
- data/script/bootstrap +56 -0
- data/script/ci +3 -0
- data/script/console +14 -0
- data/script/release +3 -0
- data/script/test_web +22 -0
- data/script/unit_test +3 -0
- data/spec/actions/add_examples_to_test_cases_directory_spec.rb +52 -0
- data/spec/actions/clone_repository_spec.rb +83 -0
- data/spec/actions/create_directory_spec.rb +59 -0
- data/spec/actions/create_file_spec.rb +139 -0
- data/spec/actions/create_output_spec.rb +46 -0
- data/spec/actions/handle_error_spec.rb +74 -0
- data/spec/actions/initialize_application_spec.rb +40 -0
- data/spec/actions/show_config_spec.rb +22 -0
- data/spec/capybara_proxy_pac_spec.rb +42 -0
- data/spec/capybara_proxy_spec.rb +76 -0
- data/spec/config_spec.rb +86 -0
- data/spec/data_spec.rb +34 -0
- data/spec/environment_spec.rb +25 -0
- data/spec/erb_generator_spec.rb +31 -0
- data/spec/examples/proxy.pac +7 -0
- data/spec/factories.rb +8 -0
- data/spec/features/check_ssl_sites_spec.rb +8 -0
- data/spec/git_file_spec.rb +46 -0
- data/spec/git_repository_spec.rb +111 -0
- data/spec/main_spec.rb +25 -0
- data/spec/pac_result_spec.rb +20 -0
- data/spec/proxy_tester_spec_helper_spec.rb +137 -0
- data/spec/rspec_runner_spec.rb +29 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/capybara.rb +11 -0
- data/spec/support/database_cleaner.rb +14 -0
- data/spec/support/debugging.rb +3 -0
- data/spec/support/environment.rb +33 -0
- data/spec/support/example.rb +16 -0
- data/spec/support/factory_girl.rb +15 -0
- data/spec/support/filesystem.rb +19 -0
- data/spec/support/helper_features.rb +31 -0
- data/spec/support/matcher.rb +17 -0
- data/spec/support/reporting.rb +1 -0
- data/spec/support/rspec.rb +5 -0
- data/spec/support/string.rb +2 -0
- data/spec/template_file_spec.rb +25 -0
- data/spec/template_repository_spec.rb +44 -0
- data/spec/user_database_spec.rb +63 -0
- data/spec/user_spec.rb +62 -0
- metadata +398 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
class Config
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :config
|
8
|
+
|
9
|
+
@options = Set.new
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
public
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
def option_reader(option, default_value)
|
18
|
+
define_method option.to_sym do
|
19
|
+
config.fetch(option.to_sym, default_value)
|
20
|
+
end
|
21
|
+
|
22
|
+
@options << option
|
23
|
+
end
|
24
|
+
|
25
|
+
def option_writer(option)
|
26
|
+
define_method "#{option}=".to_sym do |value|
|
27
|
+
begin
|
28
|
+
config[option.to_sym] = value
|
29
|
+
rescue RuntimeError
|
30
|
+
raise Exceptions::ConfigLocked
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
@options << option
|
35
|
+
end
|
36
|
+
|
37
|
+
def option(option, default_value)
|
38
|
+
option_reader(option, default_value)
|
39
|
+
option_writer(option)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
public
|
44
|
+
|
45
|
+
def initialize(file = available_config_file, config_engine = Psych)
|
46
|
+
config_mutex = Mutex.new
|
47
|
+
config_mutex.synchronize do
|
48
|
+
yaml = Psych.load_file(file)
|
49
|
+
|
50
|
+
if yaml.respond_to? :[]
|
51
|
+
@config = yaml.symbolize_keys
|
52
|
+
else
|
53
|
+
@config = {}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
rescue StandardError => e
|
57
|
+
fail Exceptions::ConfigFileNotReadable, JSON.dump(message: e.message, file: file)
|
58
|
+
end
|
59
|
+
|
60
|
+
def lock
|
61
|
+
config.freeze
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
result = []
|
66
|
+
result << sprintf("%20s | %s", 'option', 'value')
|
67
|
+
result << sprintf("%s + %s", '-' * 20, '-' * 80)
|
68
|
+
|
69
|
+
Config.options.each do |o|
|
70
|
+
result << sprintf("%20s | %s", o, Array(public_send(o)).join(', '))
|
71
|
+
end
|
72
|
+
|
73
|
+
result.join("\n")
|
74
|
+
end
|
75
|
+
|
76
|
+
def allowed_config_file_paths
|
77
|
+
[
|
78
|
+
::File.expand_path(::File.join(ENV['HOME'], '.config', 'proxy_tester', 'config.yaml')),
|
79
|
+
::File.expand_path(::File.join(ENV['HOME'], '.proxy_tester', 'config.yaml')),
|
80
|
+
::File.expand_path(::File.join('/etc', 'proxy_tester', 'config.yaml')),
|
81
|
+
::File.expand_path('../../../files/config.yaml', __FILE__),
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
option :config_file, ::File.expand_path(::File.join(ENV['HOME'], '.config', 'proxy_tester', 'config.yaml'))
|
86
|
+
option :user_file, ::File.expand_path(::File.join(ENV['HOME'], '.config', 'proxy_tester', 'user.csv'))
|
87
|
+
option :test_cases_directory, ::File.expand_path(::File.join(ENV['HOME'], '.config', 'proxy_tester', 'test_cases.d'))
|
88
|
+
option :debug_mode, false
|
89
|
+
option :log_level, :info
|
90
|
+
option :examples_directory, ::File.expand_path(::File.join(ENV['HOME'], '.config', 'proxy_tester', 'test_cases.d', 'examples'))
|
91
|
+
option :reports_directory, ::File.expand_path(::File.join(ENV['HOME'], '.local', 'share', 'proxy_tester', 'reports.d'))
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def available_config_file
|
96
|
+
allowed_config_file_paths.find { |f| ::File.exists? f }
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ProxyTester
|
2
|
+
class Data
|
3
|
+
private
|
4
|
+
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
public
|
8
|
+
|
9
|
+
def initialize(config = ProxyTester.config)
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def instance_binding
|
14
|
+
binding
|
15
|
+
end
|
16
|
+
|
17
|
+
def lookup(variable)
|
18
|
+
config.public_send variable.to_sym
|
19
|
+
rescue NoMethodError
|
20
|
+
fail "Variable \"#{variable}\" not found."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ProxyTester
|
2
|
+
class DatabaseSession
|
3
|
+
def initialize
|
4
|
+
database = ':memory:'
|
5
|
+
#database = File.expand_path('../../../tmp/database.db', __FILE__)
|
6
|
+
|
7
|
+
FileUtils.rm database if database != ':memory:' and File.exists?( database)
|
8
|
+
|
9
|
+
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: database
|
10
|
+
silence :stdout do
|
11
|
+
ActiveRecord::Migrator.up File.expand_path( '../../../db/migrate', __FILE__ )
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
class Environment
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :stdin, :stderr
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize(stdin = $stdin, stderr = $stderr)
|
12
|
+
@stdin = stdin
|
13
|
+
@stderr = stderr
|
14
|
+
end
|
15
|
+
|
16
|
+
def password
|
17
|
+
stderr.printf "Please enter password: "
|
18
|
+
@password = stdin.readline.chomp
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
# Used to generate the template
|
4
|
+
class ErbGenerator
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :data
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
# Create erb generator
|
12
|
+
#
|
13
|
+
# @param [Data] data
|
14
|
+
# The data class to be used within the template
|
15
|
+
def initialize(data)
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
|
19
|
+
# Compile the template
|
20
|
+
#
|
21
|
+
# @param [IO] source
|
22
|
+
# The source template to be used
|
23
|
+
# @param [IO] destination
|
24
|
+
# The output io handle
|
25
|
+
def compile(source, destination)
|
26
|
+
erb = ERB.new(source.read, nil, '-')
|
27
|
+
begin
|
28
|
+
destination.puts erb.result(data.instance_binding)
|
29
|
+
rescue SyntaxError => e
|
30
|
+
raise Exceptions::ErbTemplateHasSyntaxErrors, e.message
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
class ErrorHandler
|
4
|
+
|
5
|
+
@handlers = []
|
6
|
+
@mutex = Mutex.new
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_reader :handlers, :mutex
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_reader :details_i18n, :summary_i18n, :exit_code
|
15
|
+
|
16
|
+
public
|
17
|
+
|
18
|
+
attr_reader :exception
|
19
|
+
attr_accessor :original_message
|
20
|
+
|
21
|
+
def initialize(options = {})
|
22
|
+
@exception = options.fetch(:exception)
|
23
|
+
@details_i18n = options.fetch(:details)
|
24
|
+
@summary_i18n = options.fetch(:summary)
|
25
|
+
@exit_code = options.fetch(:exit_code)
|
26
|
+
rescue KeyError => e
|
27
|
+
raise ArgumentError, e.message
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def create(options = {}, &block)
|
32
|
+
handler = new(options, &block)
|
33
|
+
handlers << handler
|
34
|
+
|
35
|
+
handler
|
36
|
+
end
|
37
|
+
|
38
|
+
def find(exception)
|
39
|
+
handlers.find(proc { default_handler }) { |h| h.exception == exception }
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def default_handler
|
45
|
+
mutex.synchronize do
|
46
|
+
@default_handler ||= new(
|
47
|
+
exception: StandardError,
|
48
|
+
details: 'errors.default.details',
|
49
|
+
summary: 'errors.default.summary',
|
50
|
+
exit_code: 99,
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def details(format = :plain)
|
57
|
+
case format
|
58
|
+
when :plain
|
59
|
+
@details
|
60
|
+
when :html
|
61
|
+
Rack::Utils.escape_html(@details)
|
62
|
+
else
|
63
|
+
@details
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def summary(format = :plain)
|
68
|
+
case format
|
69
|
+
when :plain
|
70
|
+
@summary
|
71
|
+
when :html
|
72
|
+
Rack::Utils.escape_html(@summary)
|
73
|
+
else
|
74
|
+
@summary
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def use(data)
|
79
|
+
data = JSON.parse(data).symbolize_keys if data.kind_of? String
|
80
|
+
|
81
|
+
@details = I18n.t(details_i18n, data)
|
82
|
+
@summary = I18n.t(summary_i18n, data)
|
83
|
+
end
|
84
|
+
|
85
|
+
def execute(data = {})
|
86
|
+
use(data)
|
87
|
+
|
88
|
+
ProxyTester.ui_logger.fatal details
|
89
|
+
ProxyTester.ui_logger.debug original_message if original_message
|
90
|
+
Kernel.exit exit_code
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_json
|
94
|
+
ErrorHandler.mutex.synchronize do
|
95
|
+
@details ||= I18n.t(details_i18n)
|
96
|
+
@summary ||= I18n.t(summary_i18n)
|
97
|
+
end
|
98
|
+
|
99
|
+
JSON.dump(
|
100
|
+
error_summary: summary,
|
101
|
+
error_details: details,
|
102
|
+
result: :failure,
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
module ErrorMessages
|
4
|
+
|
5
|
+
ErrorHandler.create(
|
6
|
+
exception: StandardError,
|
7
|
+
summary: 'errors.default.summary',
|
8
|
+
details: 'errors.default.details',
|
9
|
+
exit_code: 99,
|
10
|
+
)
|
11
|
+
|
12
|
+
ErrorHandler.create(
|
13
|
+
exception: Exceptions::InternalError,
|
14
|
+
details: 'errors.internal_error.details',
|
15
|
+
summary: 'errors.internal_error.summary',
|
16
|
+
exit_code: 1,
|
17
|
+
)
|
18
|
+
|
19
|
+
ErrorHandler.create(
|
20
|
+
exception: Exceptions::ConfigFileNotReadable,
|
21
|
+
details: 'errors.unreadable_config_file.details',
|
22
|
+
summary: 'errors.unreadable_config_file.summary',
|
23
|
+
exit_code: 2,
|
24
|
+
)
|
25
|
+
|
26
|
+
ErrorHandler.create(
|
27
|
+
exception: Exceptions::UserError,
|
28
|
+
details: 'errors.user_error.details',
|
29
|
+
summary: 'errors.user_error.summary',
|
30
|
+
exit_code: 3,
|
31
|
+
)
|
32
|
+
|
33
|
+
ErrorHandler.create(
|
34
|
+
exception: Exceptions::UserRecordInvalid,
|
35
|
+
details: 'errors.invalid_user_record.details',
|
36
|
+
summary: 'errors.invalid_user_record.summary',
|
37
|
+
exit_code: 4,
|
38
|
+
)
|
39
|
+
|
40
|
+
ErrorHandler.create(
|
41
|
+
exception: Exceptions::UserFileNotFound,
|
42
|
+
details: 'errors.unreadable_user_file.details',
|
43
|
+
summary: 'errors.unreadable_user_file.summary',
|
44
|
+
exit_code: 5,
|
45
|
+
)
|
46
|
+
|
47
|
+
ErrorHandler.create(
|
48
|
+
exception: Exceptions::FetchUrlTimeout,
|
49
|
+
details: 'errors.request_timeout.details',
|
50
|
+
summary: 'errors.request_timeout.summary',
|
51
|
+
exit_code: 6,
|
52
|
+
)
|
53
|
+
|
54
|
+
ErrorHandler.create(
|
55
|
+
exception: Exceptions::SyntaxInvalid,
|
56
|
+
details: 'errors.invalid_syntax.details',
|
57
|
+
summary: 'errors.invalid_syntax.summary',
|
58
|
+
exit_code: 7,
|
59
|
+
)
|
60
|
+
|
61
|
+
ErrorHandler.create(
|
62
|
+
exception: Exceptions::PacFileNotFound,
|
63
|
+
details: 'errors.not_found_pac_file.details',
|
64
|
+
summary: 'errors.not_found_pac_file.summary',
|
65
|
+
exit_code: 8,
|
66
|
+
)
|
67
|
+
|
68
|
+
ErrorHandler.create(
|
69
|
+
exception: Exceptions::PacResultInvalid,
|
70
|
+
details: 'errors.invalid_pac_result.details',
|
71
|
+
summary: 'errors.invalid_pac_result.summary',
|
72
|
+
exit_code: 19,
|
73
|
+
)
|
74
|
+
|
75
|
+
ErrorHandler.create(
|
76
|
+
exception: Exceptions::ProxyTypeInvalid,
|
77
|
+
details: 'errors.invalid_proxy_type.details',
|
78
|
+
summary: 'errors.invalid_proxy_type.summary',
|
79
|
+
exit_code: 19,
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
# Exceptions
|
4
|
+
module Exceptions
|
5
|
+
# raised if user error occurred
|
6
|
+
class UserError < StandardError; end
|
7
|
+
|
8
|
+
# raised if an internal error occurred
|
9
|
+
class InternalError < StandardError; end
|
10
|
+
|
11
|
+
# raised if config file does not exist
|
12
|
+
class ConfigFileNotReadable < UserError; end
|
13
|
+
|
14
|
+
# raised if one tries to access a lockec config
|
15
|
+
class ConfigLocked < UserError; end
|
16
|
+
|
17
|
+
# raise if there are template syntax errrors
|
18
|
+
class ErbTemplateHasSyntaxErrors < InternalError; end
|
19
|
+
|
20
|
+
# raised if Template does not exist
|
21
|
+
class ErbTemplateIsUnknown < InternalError; end
|
22
|
+
|
23
|
+
# raised if commit does not exist
|
24
|
+
class CommitDoesNotExist < InternalError; end
|
25
|
+
|
26
|
+
# raised if repository does not exist
|
27
|
+
class RepositoryDoesNotExist < UserError; end
|
28
|
+
|
29
|
+
# raised if proxy user does not exist
|
30
|
+
class ProxyUserInvalid < UserError; end
|
31
|
+
|
32
|
+
# raised if proxy user record is invalid (missing name, password)
|
33
|
+
class UserRecordInvalid < UserError; end
|
34
|
+
|
35
|
+
# raised if user file not found
|
36
|
+
class UserFileNotFound < UserError; end
|
37
|
+
|
38
|
+
# raised if user file not found
|
39
|
+
class SyntaxInvalid < UserError; end
|
40
|
+
|
41
|
+
# raised if pac file not found
|
42
|
+
class PacFileNotFound < UserError; end
|
43
|
+
|
44
|
+
# raised if pac result is invalid
|
45
|
+
class PacResultInvalid < UserError; end
|
46
|
+
|
47
|
+
# raised if pac result is invalid
|
48
|
+
class FetchUrlTimeout < UserError; end
|
49
|
+
|
50
|
+
# raised if chosen proxy type is invalid
|
51
|
+
class ProxyTypeInvalid < UserError; end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
class GitFile
|
4
|
+
private
|
5
|
+
|
6
|
+
attr_reader :extension
|
7
|
+
|
8
|
+
public
|
9
|
+
|
10
|
+
attr_reader :path, :name, :content
|
11
|
+
|
12
|
+
def initialize(path, content = '')
|
13
|
+
@path = path
|
14
|
+
@extension = ::File.extname(path)
|
15
|
+
@name = path.sub(/\.[^.]+$/, '').gsub(%r{/}, '::').downcase.to_sym
|
16
|
+
@content = content
|
17
|
+
end
|
18
|
+
|
19
|
+
def nil?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def extension?(ext)
|
24
|
+
extension == ext
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare(handler)
|
28
|
+
handler.prepare(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
class GitNullFile
|
4
|
+
def path
|
5
|
+
nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def extension
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def content
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def compressed_content=(val)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def prepare(val)
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def nil?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
class GitRepository
|
4
|
+
private
|
5
|
+
|
6
|
+
attr_reader :repository, :root_commit, :null_file, :file_creator
|
7
|
+
|
8
|
+
public
|
9
|
+
|
10
|
+
attr_reader :storage_path
|
11
|
+
|
12
|
+
def initialize(storage_path, file_creator = ProxyTester::GitFile, null_file = ProxyTester::GitNullFile.new)
|
13
|
+
@storage_path = ::File.expand_path(storage_path)
|
14
|
+
@repository = Rugged::Repository.new(storage_path)
|
15
|
+
@file_creator = file_creator
|
16
|
+
@null_file = null_file
|
17
|
+
|
18
|
+
rescue Rugged::RepositoryError
|
19
|
+
raise Exceptions::RepositoryDoesNotExist, "Sorry, but #{storage_path} is not a git repository."
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.create(storage_path)
|
23
|
+
storage_path = ::File.expand_path(storage_path)
|
24
|
+
Rugged::Repository.init_at(storage_path, :bare)
|
25
|
+
|
26
|
+
new(storage_path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.clone(source, destination, options = {})
|
30
|
+
bare = options.fetch(:bare, false)
|
31
|
+
|
32
|
+
source = Addressable::URI.heuristic_parse(::File.expand_path(source))
|
33
|
+
if source.scheme.blank?
|
34
|
+
source.scheme = 'file'
|
35
|
+
source.authority = ''
|
36
|
+
end
|
37
|
+
source = source.to_s
|
38
|
+
|
39
|
+
destination = ::File.expand_path(destination)
|
40
|
+
|
41
|
+
if bare
|
42
|
+
Rugged::Repository.clone_at(source, destination, bare: true)
|
43
|
+
else
|
44
|
+
Rugged::Repository.clone_at(source, destination)
|
45
|
+
end
|
46
|
+
|
47
|
+
new(destination)
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_content(path, content = '', mode = 0100644, commit_info = default_commit_info)
|
51
|
+
index = Rugged::Index.new
|
52
|
+
|
53
|
+
unless repository.empty?
|
54
|
+
root_commit = repository.lookup(repository.head.target)
|
55
|
+
|
56
|
+
root_commit.tree.walk_blobs(:postorder) do |r, e|
|
57
|
+
e.merge!( { path: "#{r}#{e[:name]}" } )
|
58
|
+
e.delete(:name)
|
59
|
+
|
60
|
+
index.add(e)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
oid = repository.write(content, :blob)
|
65
|
+
index.add(:path => path, :oid => oid, :mode => mode)
|
66
|
+
|
67
|
+
options = {}
|
68
|
+
options[:tree] = index.write_tree(repository)
|
69
|
+
options[:parents] = repository.empty? ? [] : [ repository.head.target ].compact
|
70
|
+
options[:update_ref] = 'HEAD'
|
71
|
+
options.merge! commit_info
|
72
|
+
|
73
|
+
Rugged::Commit.create(repository, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
def find_file(name)
|
77
|
+
files.fetch(name, null_file)
|
78
|
+
end
|
79
|
+
|
80
|
+
def all_files
|
81
|
+
files.collect { |_,f| f }
|
82
|
+
end
|
83
|
+
|
84
|
+
def each_file(&block)
|
85
|
+
all_files.each(&block)
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def files
|
91
|
+
files_in_repository.reduce({}) do |memo, file|
|
92
|
+
memo[file.name.to_sym] = file
|
93
|
+
|
94
|
+
memo
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def files_in_repository
|
99
|
+
return [] if repository.empty?
|
100
|
+
|
101
|
+
head_commit = repository.lookup(repository.head.target)
|
102
|
+
|
103
|
+
files = []
|
104
|
+
head_commit.tree.walk_blobs(:postorder) do |root, entry|
|
105
|
+
files << file_creator.new("#{root}#{entry[:name]}", repository.lookup(entry[:oid]).content )
|
106
|
+
end
|
107
|
+
|
108
|
+
files
|
109
|
+
end
|
110
|
+
|
111
|
+
def default_commit_info
|
112
|
+
options = {}
|
113
|
+
options[:author] = { :email => 'local_pac@local_pac', :name => 'Local Pac', :time => Time.now }
|
114
|
+
options[:committer] = { :email => 'local_pac@local_pac', :name => 'Local Pac', :time => Time.now }
|
115
|
+
options[:message] = 'Commit made by local pac itself'
|
116
|
+
|
117
|
+
options
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyTester
|
3
|
+
module Actions
|
4
|
+
class HandleError
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
attr_reader :exception, :original_message, :handler_klass
|
9
|
+
|
10
|
+
public
|
11
|
+
|
12
|
+
def initialize(exception, handler_klass = ErrorHandler)
|
13
|
+
@exception = exception.class
|
14
|
+
@original_message = exception.message
|
15
|
+
@handler_klass = handler_klass
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
handler = handler_klass.find exception
|
20
|
+
handler.original_message = original_message
|
21
|
+
|
22
|
+
handler.execute(parsed_message)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parsed_message
|
28
|
+
result = JSON.parse(original_message)
|
29
|
+
return {} unless result.kind_of? Hash
|
30
|
+
|
31
|
+
result
|
32
|
+
rescue JSON::ParserError
|
33
|
+
{}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|