local_pac 0.5.0 → 0.6.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.
Files changed (46) hide show
  1. data/.travis.yml +1 -1
  2. data/Gemfile.lock +1 -3
  3. data/app/controllers/git_hook_controller.rb +25 -4
  4. data/app/controllers/lookup_controller.rb +1 -0
  5. data/app/locales/en.yml +9 -1
  6. data/bin/local_pac +5 -129
  7. data/config.ru +2 -2
  8. data/features/{show_status.feature_ → show_status.feature} +2 -1
  9. data/features/step_definitions.rb +4 -0
  10. data/lib/local_pac.rb +9 -2
  11. data/lib/local_pac/actions/get_system_information.rb +2 -2
  12. data/lib/local_pac/actions/handle_error.rb +26 -0
  13. data/lib/local_pac/actions/initialize_application.rb +71 -0
  14. data/lib/local_pac/actions/reload_local_storage.rb +2 -0
  15. data/lib/local_pac/actions/show_application_status.rb +39 -0
  16. data/lib/local_pac/actions/show_pac_file.rb +29 -0
  17. data/lib/local_pac/actions/validate_pac_file.rb +34 -0
  18. data/lib/local_pac/cli/main.rb +122 -0
  19. data/lib/local_pac/cli/reload.rb +8 -4
  20. data/lib/local_pac/cli/show.rb +34 -0
  21. data/lib/local_pac/cli/validate.rb +22 -0
  22. data/lib/local_pac/config.rb +1 -1
  23. data/lib/local_pac/error_handler.rb +60 -0
  24. data/lib/local_pac/exceptions.rb +6 -0
  25. data/lib/local_pac/git_storage.rb +30 -10
  26. data/lib/local_pac/pac_file_validator.rb +17 -2
  27. data/lib/local_pac/version.rb +1 -1
  28. data/local_pac.gemspec +0 -2
  29. data/script/acceptance_test +4 -0
  30. data/script/bootstrap +5 -0
  31. data/script/ci +3 -0
  32. data/script/release +3 -0
  33. data/script/unit_test +3 -0
  34. data/spec/actions/handle_error_spec.rb +29 -0
  35. data/spec/{initializer_spec.rb → actions/initialize_application_spec.rb} +3 -3
  36. data/spec/{application_status_spec.rb → actions/show_application_status_spec.rb} +5 -5
  37. data/spec/actions/show_pac_file_spec.rb +36 -0
  38. data/spec/actions/validate_pac_file_spec.rb +62 -0
  39. data/spec/error_handler_spec.rb +70 -0
  40. data/spec/features/check_git_push_spec.rb +34 -6
  41. data/spec/git_repository_spec.rb +1 -0
  42. data/spec/git_storage_spec.rb +33 -0
  43. data/spec/pac_file_validator_spec.rb +19 -10
  44. metadata +30 -26
  45. data/lib/local_pac/application_status.rb +0 -37
  46. data/lib/local_pac/initializer.rb +0 -69
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Actions
4
+ class ShowPacFile
5
+ private
6
+
7
+ attr_reader :name, :repo, :options, :vcs_engine, :storage_path
8
+
9
+ public
10
+
11
+ def initialize(file, storage_path, options = {}, vcs_engine = GitStorage)
12
+ @name = ::File.basename(file, '.pac').to_sym
13
+ @storage_path = storage_path
14
+ @options = options
15
+ @vcs_engine = vcs_engine
16
+ end
17
+
18
+ def run
19
+ begin
20
+ @repo = vcs_engine.new(storage_path)
21
+ rescue Rugged::OSError
22
+ raise Exceptions::RepositoryDoesNotExist, "Sorry, but the repository at #{storage_path} does not exist" unless ::Dir.exists? storage_path
23
+ end
24
+
25
+ puts repo[name].content
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Actions
4
+ class ValidatePacFile
5
+
6
+ private
7
+
8
+ attr_reader :path, :validator, :creator
9
+
10
+ public
11
+
12
+ def initialize(path, creator = File, validator = PacFileValidator.new)
13
+ @path = path
14
+ @validator = validator
15
+ @creator = creator
16
+ end
17
+
18
+ def run
19
+ file = creator.new(path, ::File.read(path))
20
+
21
+ if validator.valid?(file)
22
+ puts "File \"#{file.path}\" is a valid pac file."
23
+ else
24
+ puts "File \"#{file.path}\" is not a valid pac file:"
25
+ puts validator.errors(file)
26
+ end
27
+ rescue Errno::EISDIR => e
28
+ raise Exceptions::PacFileInvalid, e.message
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Cli
4
+ class Main < Thor
5
+ class_option :config_file, type: :string, desc: 'Config file'
6
+ class_option :log_level, default: 'info', type: :string, desc: 'Log level for ui logging'
7
+ class_option :debug_mode, type: :boolean, desc: 'Run application in debug mode'
8
+
9
+ no_commands {
10
+ include LocalPac::Cli::Helper
11
+ }
12
+
13
+ desc 'serve', 'Serve pacfiles'
14
+ option :access_log, type: :string, desc: 'File to write access log to'
15
+ option :listen, type: :string, desc: 'Listen for requests'
16
+ option :environment, type: :string, desc: 'Rack environment for application'
17
+ option :with, type: :string, default: 'puma', desc: 'Server used to serve proxy pac'
18
+ def serve
19
+ LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
20
+ LocalPac.config.access_log = options[:access_log] if options[:access_log]
21
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
22
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
23
+ LocalPac.config.environment = options[:environment] if options[:environment]
24
+ LocalPac.config.listen = options[:listen] if options[:listen]
25
+ LocalPac.config.lock
26
+
27
+ LocalPac.ui_logger.level = LocalPac.config.log_level
28
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
29
+
30
+ LocalPac.ui_logger.debug('Options: ' + options.to_s)
31
+ LocalPac.ui_logger.debug("Config:\n" + LocalPac.config.to_s)
32
+
33
+ command_klass = case options[:with].to_sym
34
+ when :puma
35
+ ServerCommands::Puma
36
+ when :rackup
37
+ ServerCommands::Rackup
38
+ else
39
+ ServerCommands::Rackup
40
+ end
41
+
42
+ command = command_klass.new(
43
+ listen: LocalPac.config.listen,
44
+ environment: LocalPac.config.environment,
45
+ )
46
+
47
+ ENV['DEBUG'] = LocalPac.config.debug_mode.to_s if LocalPac.config.debug_mode
48
+ ENV['ACCESS_LOG'] = LocalPac.config.access_log.to_s if LocalPac.config.access_log
49
+ ENV['LOG_LEVEL'] = LocalPac.config.log_level.to_s if LocalPac.config.log_level
50
+
51
+ Server.new(command).start
52
+ end
53
+
54
+ desc 'init', 'Create files/directories to use local_pac in dir or $PWD'
55
+ option :force, type: :boolean, default: false, desc: 'Overwrite existing files?'
56
+ option :pre_seed, type: :boolean, default: false, desc: 'Add some example files to git repository'
57
+ option :config_file, type: :string, desc: 'Path to config file'
58
+
59
+ option :local_storage, type: :string, desc: 'Path to local storage'
60
+ option :pid_file, type: :string, desc: 'Path to pid file'
61
+ option :access_log, type: :string, desc: 'Path to access log'
62
+ option :sass_cache, type: :string, desc: 'Path to sass cache'
63
+ option :reload_config_signal, type: :string, desc: 'Signal to reload config'
64
+ option :reload_storage_signal, type: :string, desc: 'Signal to reload local storage'
65
+ option :api_key, type: :string, desc: 'API key for communication between git hook and web application'
66
+ option :listen, type: :string, desc: 'Listen statement for rack server'
67
+ option :environment, type: :string, desc: 'Default environment for rack server'
68
+
69
+ option :create_pid_directory, type: :boolean, desc: 'Create pid directory', default: true
70
+ option :create_log_directory, type: :boolean, desc: 'Create log directory', default: true
71
+ option :create_sass_cache, type: :boolean, desc: 'Create sass cache directory', default: true
72
+ option :create_local_storage, type: :boolean, desc: 'Create local storage directory', default: true
73
+ option :create_pre_receive_hook, type: :boolean, desc: 'Create pre receive hook', default: true
74
+ option :create_config_file, type: :boolean, desc: 'Create config_directory', default: true
75
+ def init
76
+ LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
77
+
78
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
79
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
80
+ LocalPac.config.local_storage = options[:local_storage] if options[:local_storage]
81
+ LocalPac.config.pid_file = options[:pid_file] if options[:pid_file]
82
+ LocalPac.config.access_log = options[:access_log] if options[:access_log]
83
+ LocalPac.config.sass_cache = options[:sass_cache] if options[:sass_cache]
84
+ LocalPac.config.reload_config_signal = options[:reload_config_signal] if options[:reload_config_signal]
85
+ LocalPac.config.reload_storage_signal = options[:reload_storage_signal] if options[:reload_storage_signal]
86
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
87
+ LocalPac.config.api_key = options[:api_key] if options[:api_key]
88
+ LocalPac.config.listen = options[:listen] if options[:listen]
89
+ LocalPac.config.environment = options[:environment] if options[:environment]
90
+
91
+ LocalPac.config.lock
92
+
93
+ LocalPac.ui_logger.level = LocalPac.config.log_level
94
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
95
+
96
+ LocalPac.ui_logger.debug('Options: ' + options.to_s)
97
+ LocalPac.ui_logger.debug("Config:\n" + LocalPac.config.to_s)
98
+
99
+ Actions::InitializeApplication.new(
100
+ force: options[:force],
101
+ pre_seed: options[:pre_seed],
102
+ create_pid_directory: options[:create_pid_directory],
103
+ create_log_directory: options[:create_log_directory],
104
+ create_sass_cache: options[:create_sass_cache],
105
+ create_local_storage: options[:create_local_storage],
106
+ create_pre_receive_hook: options[:create_pre_receive_hook],
107
+ create_config_file: options[:create_config_file],
108
+ ).run
109
+ end
110
+
111
+ desc 'reload', 'Reload configuration, local storage etc.'
112
+ option :pid_file, type: :string, desc: 'Pid file of daemon'
113
+ subcommand 'reload', LocalPac::Cli::Reload
114
+
115
+ desc 'show', 'Show information about status.'
116
+ subcommand 'show', LocalPac::Cli::Show
117
+
118
+ desc 'validate', 'Validate information about status.'
119
+ subcommand 'validate', LocalPac::Cli::Validate
120
+ end
121
+ end
122
+ end
@@ -9,11 +9,13 @@ module LocalPac
9
9
  desc 'configuration', 'Reload configuration'
10
10
  def configuration
11
11
  LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
12
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
13
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
12
14
  LocalPac.config.pid_file = options[:pid_file] if options[:pid_file]
13
15
  LocalPac.config.lock
14
16
 
15
- set_log_level(options[:log_level])
16
- set_debug(options[:debug])
17
+ LocalPac.ui_logger.level = LocalPac.config.log_level
18
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
17
19
 
18
20
  LocalPac.ui_logger.info "Ask web application (PID: #{pid(LocalPac.config)}) to reload configuration"
19
21
  Actions::SendSignal.new(LocalPac.config.reload_config_signal).run
@@ -22,11 +24,13 @@ module LocalPac
22
24
  desc 'local_storage', 'Reload local_storage'
23
25
  def local_storage
24
26
  LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
27
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
28
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
25
29
  LocalPac.config.pid_file = options[:pid_file] if options[:pid_file]
26
30
  LocalPac.config.lock
27
31
 
28
- set_log_level(options[:log_level])
29
- set_debug(options[:debug])
32
+ LocalPac.ui_logger.level = LocalPac.config.log_level
33
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
30
34
 
31
35
  LocalPac.ui_logger.info "Ask web application (PID: #{pid(LocalPac.config)}) to reload storage"
32
36
  Actions::SendSignal.new(LocalPac.config.reload_storage_signal).run
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Cli
4
+ class Show < Thor
5
+
6
+ desc 'status', 'Show status of local_pac: configuration, known proxy pacs, server running etc.'
7
+ def status
8
+ LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
9
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
10
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
11
+ LocalPac.config.lock
12
+
13
+ LocalPac.ui_logger.level = LocalPac.config.log_level
14
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
15
+
16
+ Actions::ShowApplicationStatus.new.run
17
+ end
18
+
19
+ desc 'pac_fiel', 'Show pac file.'
20
+ def pac_file(file)
21
+ LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
22
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
23
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
24
+ LocalPac.config.lock
25
+
26
+ LocalPac.ui_logger.level = LocalPac.config.log_level
27
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
28
+
29
+ Actions::PrintTitle.new("Content of \"#{file}\"").run
30
+ Actions::ShowPacFile.new(file, LocalPac.config.local_storage).run
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Cli
4
+ class Validate < Thor
5
+
6
+ desc 'configuration', 'Reload configuration'
7
+ def pac_file(path)
8
+ LocalPac.config = LocalPac::Config.new(options[:config_file]) if options[:config_file]
9
+ LocalPac.config.log_level = options[:log_level] if options[:log_level]
10
+ LocalPac.config.debug_mode = options[:debug_mode] if options[:debug_mode]
11
+ LocalPac.config.lock
12
+
13
+ LocalPac.ui_logger.level = LocalPac.config.log_level
14
+ LocalPac.enable_debug_mode if LocalPac.config.debug_mode
15
+
16
+ LocalPac.ui_logger.info "Validating pac file #{path}"
17
+ Actions::ValidatePacFile.new(path).run
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -49,7 +49,7 @@ module LocalPac
49
49
  @config = {}
50
50
  end
51
51
  end
52
- rescue => e
52
+ rescue StandardError => e
53
53
  fail Exceptions::ConfigFileNotReadable, "Sorry, but there was a problem reading the config file: #{e.message}."
54
54
  end
55
55
 
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ module LocalPac
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 :message, :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
+ @message = options.fetch(:message)
24
+ @exit_code = options.fetch(:exit_code)
25
+ rescue KeyError => e
26
+ raise ArgumentError, e.message
27
+ end
28
+
29
+ class << self
30
+ def create(options = {}, &block)
31
+ handler = new(options, &block)
32
+ handlers << handler
33
+
34
+ handler
35
+ end
36
+
37
+ def find(exception)
38
+ handlers.find(proc { default_handler }) { |h| h.exception == exception }
39
+ end
40
+
41
+ private
42
+
43
+ def default_handler
44
+ mutex.synchronize do
45
+ @default_handler ||= new(
46
+ exception: StandardError,
47
+ message: 'Sorry, but I cannot fullfil your request. An unexpected error occured.',
48
+ exit_code: 99,
49
+ )
50
+ end
51
+ end
52
+ end
53
+
54
+ def run
55
+ LocalPac.ui_logger.fatal message
56
+ LocalPac.ui_logger.debug original_message if original_message
57
+ Kernel.exit exit_code
58
+ end
59
+ end
60
+ end
@@ -12,12 +12,18 @@ module LocalPac
12
12
  # raised if listen statement is invalid
13
13
  class ServerListenStatementInvalid < StandardError; end
14
14
 
15
+ # raised if reload of local storage failed
16
+ class ReloadOfLocalStorageFailed < StandardError; end
17
+
15
18
  # raised if entered url is invalid
16
19
  class URLToSearchForInvalid < StandardError; end
17
20
 
18
21
  # raised if pac file is invalid
19
22
  class PacFileInvalid < StandardError; end
20
23
 
24
+ # raised if api key is invalid
25
+ class ApiKeyInvalid < StandardError; end
26
+
21
27
  # raised if request is invalid
22
28
  class GivenUrlInvalid < StandardError; end
23
29
 
@@ -1,9 +1,10 @@
1
1
  # encoding: utf-8
2
2
  module LocalPac
3
3
  class GitStorage
4
+
4
5
  private
5
6
 
6
- attr_reader :storage_path, :data, :repository, :file_creator, :null_file, :vcs_engine
7
+ attr_reader :storage_path, :repository, :file_creator, :null_file, :vcs_engine, :compressor_engine
7
8
 
8
9
  public
9
10
 
@@ -11,16 +12,33 @@ module LocalPac
11
12
  @storage_path = ::File.expand_path(storage_path)
12
13
  @null_file = null_file
13
14
  @vcs_engine = vcs_engine
15
+ @compressor_engine = compressor_engine
14
16
 
15
17
  begin
16
18
  @repository = vcs_engine.new(storage_path)
17
19
  rescue Exceptions::RepositoryDoesNotExist
18
20
  @repository = vcs_engine.create(storage_path)
19
21
  end
22
+ end
23
+
24
+ def [](key)
25
+ data.fetch(key, null_file)
26
+ end
27
+
28
+ def each_pac_file(&block)
29
+ pac_files.each(&block)
30
+ end
31
+
32
+ def each_added_pac_file(old_commit_id, new_commit_id, &block)
33
+ added_pac_files(old_commit_id, new_commit_id).each(&block)
34
+ end
20
35
 
36
+ private
37
+
38
+ def data
21
39
  mutex = Mutex.new
22
40
  mutex.synchronize do
23
- @data = pac_files.reduce({}) do |memo, file|
41
+ @data ||= pac_files.reduce({}) do |memo, file|
24
42
  compressor_engine.new.prepare(file)
25
43
  memo[file.name.to_sym] = file
26
44
 
@@ -29,19 +47,21 @@ module LocalPac
29
47
  end
30
48
  end
31
49
 
32
- def [](key)
33
- data.fetch(key, null_file)
50
+ def added_pac_files(old_commit_id, new_commit_id)
51
+ logging_for_repo_action do
52
+ repository.added_files(old_commit_id, new_commit_id).keep_if { |f| f.extension? '.pac' }
53
+ end
34
54
  end
35
55
 
36
- def each_pac_file(&block)
37
- pac_files.each(&block)
56
+ def pac_files
57
+ logging_for_repo_action do
58
+ repository.all_files.keep_if { |f| f.extension? '.pac' }
59
+ end
38
60
  end
39
61
 
40
- private
41
-
42
- def pac_files
62
+ def logging_for_repo_action(&block)
43
63
  LocalPac.ui_logger.debug "I'm using the following storage path: \"#{storage_path}\"."
44
- files = repository.all_files.keep_if { |f| f.extension? '.pac' }
64
+ files = block.call
45
65
  LocalPac.ui_logger.debug "Found the following files: #{files.collect { |f| "\"#{f.path}\"" }.join(", ")}."
46
66
 
47
67
  files
@@ -1,13 +1,28 @@
1
1
  # encoding: utf-8
2
2
  module LocalPac
3
3
  class PacFileValidator
4
+
4
5
  def valid?(file)
5
- pac = PAC.source(file.content)
6
- pac.find('http://www.example.com')
6
+ validate(file)
7
7
 
8
8
  true
9
9
  rescue StandardError
10
10
  false
11
11
  end
12
+
13
+ def errors(file)
14
+ validate(file)
15
+
16
+ ''
17
+ rescue StandardError => e
18
+ e.message
19
+ end
20
+
21
+ private
22
+
23
+ def validate(file)
24
+ pac = PAC.source(file.content)
25
+ pac.find('http://www.example.com')
26
+ end
12
27
  end
13
28
  end