local_pac 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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