proxy_tester 0.0.1
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/.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
|