local_pac 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/Gemfile +2 -0
  2. data/bin/local_pac +47 -2
  3. data/features/initializer.feature +23 -0
  4. data/features/show_config.feature +22 -0
  5. data/features/support/env.rb +1 -1
  6. data/files/config.yaml +6 -0
  7. data/files/git-hook.erb +24 -0
  8. data/lib/local_pac/actions/create_directory.rb +33 -0
  9. data/lib/local_pac/actions/create_file.rb +48 -0
  10. data/lib/local_pac/actions/create_repository.rb +38 -0
  11. data/lib/local_pac/config.rb +64 -0
  12. data/lib/local_pac/data.rb +23 -0
  13. data/lib/local_pac/erb_generator.rb +34 -0
  14. data/lib/local_pac/exceptions.rb +9 -0
  15. data/lib/local_pac/file_server.rb +10 -3
  16. data/lib/local_pac/fileable.rb +12 -0
  17. data/lib/local_pac/git.rb +63 -0
  18. data/lib/local_pac/git_file.rb +18 -0
  19. data/lib/local_pac/git_repository.rb +52 -0
  20. data/lib/local_pac/initializer.rb +28 -0
  21. data/lib/local_pac/local_storage.rb +21 -0
  22. data/lib/local_pac/logger.rb +0 -5
  23. data/lib/local_pac/main.rb +24 -0
  24. data/lib/local_pac/pac_file.rb +5 -5
  25. data/lib/local_pac/runner.rb +29 -0
  26. data/lib/local_pac/spec_helper_file_server.rb +41 -0
  27. data/lib/local_pac/template_file.rb +19 -0
  28. data/lib/local_pac/template_repository.rb +22 -0
  29. data/lib/local_pac/ui_logger.rb +12 -0
  30. data/lib/local_pac/version.rb +1 -1
  31. data/lib/local_pac.rb +30 -4
  32. data/local_pac.gemspec +1 -0
  33. data/share/examples/config.yaml +5 -0
  34. data/spec/actions/create_directory_spec.rb +47 -0
  35. data/spec/actions/create_file_spec.rb +95 -0
  36. data/spec/actions/create_repository_spec.rb +47 -0
  37. data/spec/config_spec.rb +113 -0
  38. data/spec/data_spec.rb +34 -0
  39. data/spec/erb_generator_spec.rb +31 -0
  40. data/spec/features/fetch_proxy_pac_spec.rb +30 -12
  41. data/spec/git_repository_spec.rb +60 -0
  42. data/spec/git_spec.rb +100 -0
  43. data/spec/initializer_spec.rb +29 -0
  44. data/spec/local_storage_spec.rb +59 -0
  45. data/spec/pac_file_spec.rb +14 -14
  46. data/spec/runner_spec.rb +42 -0
  47. data/spec/support/git.rb +52 -0
  48. data/spec/support/reporting.rb +1 -0
  49. data/spec/support/rspec.rb +3 -0
  50. data/spec/template_file_spec.rb +25 -0
  51. data/spec/template_repository_spec.rb +44 -0
  52. metadata +74 -5
  53. data/lib/local_pac/pac_manager.rb +0 -55
  54. data/spec/pac_manager_spec.rb +0 -52
data/Gemfile CHANGED
@@ -10,6 +10,8 @@ group :test do
10
10
  gem 'simplecov', require: false
11
11
  gem 'rubocop', require: false
12
12
  gem 'coveralls', require: false
13
+ gem 'cucumber', require: false
14
+ gem 'aruba', require: false
13
15
  end
14
16
 
15
17
  group :development do
data/bin/local_pac CHANGED
@@ -1,19 +1,64 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
3
  require 'thor'
4
+ require 'fileutils'
4
5
 
5
6
  $LOAD_PATH << File.expand_path('../../lib', __FILE__)
6
7
  require 'local_pac'
7
8
 
8
9
  class Default < Thor
10
+ class_option :config_file, type: :string, desc: 'Config file'
11
+ class_option :log_level, type: :string, desc: 'Log level for ui logging'
12
+
9
13
  desc 'serve', 'Serve pacfiles'
10
- option :logfile, type: :string, default: File.expand_path(File.join(ENV['HOME'], '.local', 'share', 'local_pac', 'access.log')), desc: 'File to write access log to'
14
+ option :access_log, type: :string, desc: 'File to write access log to'
11
15
  option :port, type: :numeric, default: 8000, desc: 'The port the server listens on'
12
16
  def serve
13
- LocalPac::FileServer.use Rack::CommonLogger, LocalPac::Logger.new(options[:logfile])
17
+ LocalPac.config(LocalPac::Config.new(options[:config_file])) if options[:config_file]
18
+ access_log = options[:access_log] || ::File.join(LocalPac.config.log_sink, 'access.log')
19
+
20
+ case options[:log_level]
21
+ when 'info'
22
+ LocalPac.ui_logger.level = Logger::INFO
23
+ when 'debug'
24
+ LocalPac.ui_logger.level = Logger::DEBUG
25
+ else
26
+ LocalPac.ui_logger.level = Logger::WARN
27
+ end
28
+
29
+ LocalPac.ui_logger.debug('Options: ' + options.to_s)
30
+ LocalPac.ui_logger.debug("Config:\n" + LocalPac.config.to_s)
31
+
32
+ LocalPac::FileServer.use Rack::CommonLogger, LocalPac::Logger.new(access_log)
14
33
  LocalPac::FileServer.set :port, options[:port]
15
34
  LocalPac::FileServer.run!
16
35
  end
36
+
37
+ desc 'init', 'Create files/directories to use local_pac in dir or $PWD'
38
+ option :force, type: :boolean, default: false, desc: 'Overwrite existing files?'
39
+ def init
40
+ LocalPac.config(LocalPac::Config.new(options[:config_file])) if options[:config_file]
41
+
42
+ case options[:log_level]
43
+ when 'info'
44
+ LocalPac.ui_logger.level = Logger::INFO
45
+ when 'debug'
46
+ LocalPac.ui_logger.level = Logger::DEBUG
47
+ else
48
+ LocalPac.ui_logger.level = Logger::WARN
49
+ end
50
+
51
+ LocalPac.ui_logger.debug('Options: ' + options.to_s)
52
+ LocalPac.ui_logger.debug("Config:\n" + LocalPac.config.to_s)
53
+
54
+ LocalPac::Initializer.new(force: options[:force]).run
55
+ end
56
+
57
+ desc 'config', 'Show configuration'
58
+ def config
59
+ LocalPac.config(LocalPac::Config.new(options[:config_file])) if options[:config_file]
60
+ puts LocalPac.config
61
+ end
17
62
  end
18
63
 
19
64
  Default.start
@@ -0,0 +1,23 @@
1
+ Feature: Initialize environment
2
+ As a administrator
3
+ I want to have utility to init environment for local_pac
4
+ In order to make less mistakes
5
+
6
+ @wip
7
+ Scenario: Not initialized
8
+ Given a file named "config.yaml" with:
9
+ """
10
+ pid_file: 'run/pid'
11
+ local_storage: 'storage'
12
+ log_sink: 'log'
13
+ executable: 'bin/local_pac'
14
+ """
15
+ When I successfully run `local_pac init --config-file config.yaml`
16
+ Then the following directories should exist:
17
+ | directory |
18
+ | 'run' |
19
+ | 'storage/cache.git' |
20
+ | 'log' |
21
+ And the following files should exist:
22
+ | file |
23
+ | 'storage/cache.git/hooks/pre-receive' |
@@ -0,0 +1,22 @@
1
+ Feature: Show config
2
+ As a administrator
3
+ I want to have utility to show config of local pac
4
+ In order to make less mistakes
5
+
6
+ @wip
7
+ Scenario: Default
8
+ Given a file named "config.yaml" with:
9
+ """
10
+ pid_file: 'run/pid'
11
+ local_storage: 'storage'
12
+ log_sink: 'log'
13
+ executable: 'bin/local_pac'
14
+ """
15
+ When I successfully run `local_pac config`
16
+ Then the stdout should contain:
17
+ """
18
+ pid_file: 'run/pid'
19
+ local_storage: 'storage'
20
+ log_sink: 'log'
21
+ executable: 'bin/local_pac'
22
+ """
@@ -1 +1 @@
1
- require 'local_pac'
1
+ require 'aruba/cucumber'
data/files/config.yaml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ :storage_path: ~/.local/share/pacfiles/cache/cache.pstore
3
+ :import_paths:
4
+ - ~/.local/share/pacfiles/new
5
+ - ~/.pacfiles/new
6
+ - /var/pacfiles/new
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ <% Array(lookup('gem_path')).each do |p| -%>
4
+ $LOAD_PATH.unshift '<%= p %>'
5
+ <% end -%>
6
+
7
+ require 'git_hook-pre_receive'
8
+ require 'pac'
9
+
10
+ class PacFileSyntaxChecker
11
+ def check(files)
12
+ files.each do |f|
13
+ begin
14
+ PAC.load f.content
15
+ rescue
16
+ $stderr.puts "Syntax error found in #{f.name}. Please check files locally again, fix the error and send update via git."
17
+ exit 1
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ parser = Git::PreReceiveHookParser.new($stdin.read)
24
+ PacFileSyntaxChecker.new.check(parser.files)
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Actions
4
+ class CreateDirectory
5
+ private
6
+
7
+ attr_reader :fs_engine, :path, :options
8
+
9
+ public
10
+
11
+ def initialize(path, options = {}, fs_engine = FileUtils)
12
+ @path = path
13
+ @options = options
14
+ @fs_engine = fs_engine
15
+ end
16
+
17
+ def run
18
+ if need_to_run? || options[:force] == true
19
+ LocalPac.ui_logger.warn "Creating repository \"#{path}\"."
20
+ fs_engine.mkdir_p(path)
21
+ else
22
+ LocalPac.ui_logger.warn "Repository \"#{path}\" already exists. Do not create it again!."
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def need_to_run?
29
+ !File.exists?(path)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Actions
4
+ class CreateFile
5
+ private
6
+
7
+ attr_reader :name, :destination, :data, :options, :engine, :repository
8
+
9
+ public
10
+
11
+ def initialize(name, destination, data, options = {}, engine = ErbGenerator, repository = TemplateRepository.new)
12
+ @name = name
13
+ @destination = destination
14
+ @data = data
15
+ @options = options
16
+ @engine = engine
17
+ @repository = repository
18
+ end
19
+
20
+ def run
21
+ if need_to_run? || options[:force] == true
22
+ LocalPac.ui_logger.warn "Creating file \"#{destination}\"."
23
+
24
+ FileUtils.chmod('+x', template(name, destination, data)) if options[:executable] == true
25
+ else
26
+ LocalPac.ui_logger.warn "File \"#{destination}\" already exists. Do not create it again!."
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def template(local_name, local_destination, local_data)
33
+ template = repository.find(local_name)
34
+
35
+ generator = engine.new(local_data)
36
+ generator.compile(template, ::File.new(local_destination, 'w'))
37
+
38
+ local_destination
39
+ rescue Errno::ENOENT
40
+ fail Exceptions::ErbTemplateIsUnknown, "Unknown erb template \"#{template_path}\"."
41
+ end
42
+
43
+ def need_to_run?
44
+ !File.exists?(destination)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Actions
4
+ class CreateRepository
5
+ private
6
+
7
+ attr_reader :vcs_engine, :path, :options
8
+
9
+ public
10
+
11
+ def initialize(path, options = {}, vcs_engine = LocalPac::Git)
12
+ @path = path
13
+ @options = options
14
+ @vcs_engine = vcs_engine
15
+ end
16
+
17
+ def run
18
+ if need_to_run? || options[:force] == true
19
+ LocalPac.ui_logger.warn "Creating repository \"#{path}\"."
20
+
21
+ if options[:bare] == true
22
+ vcs_engine.init(path, true)
23
+ else
24
+ vcs_engine.init(path)
25
+ end
26
+ else
27
+ LocalPac.ui_logger.warn "Repository \"#{path}\" already exists. Do not create it again!."
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def need_to_run?
34
+ !File.exists?(path)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ class Config
4
+ private
5
+
6
+ attr_reader :config
7
+
8
+ @options = []
9
+ class << self
10
+
11
+ attr_reader :options
12
+
13
+ def option(option, default_value)
14
+ define_method option.to_sym do
15
+ config.transaction do
16
+ config.fetch(option.to_sym, default_value)
17
+ end
18
+ end
19
+
20
+ @options << option
21
+ end
22
+ end
23
+
24
+ public
25
+
26
+ def initialize(file = available_config_file, config_engine = YAML::Store)
27
+ @config = config_engine.new(file)
28
+ end
29
+
30
+ option :log_sink, File.join(ENV['HOME'], '.local', 'share', 'local_pac', 'log')
31
+ option :local_storage, File.join(ENV['HOME'], '.local', 'share', 'local_pac', 'data')
32
+ option :executable, File.expand_path('../../../bin/local_pac', __FILE__)
33
+ option :pid_file, File.join(ENV['HOME'], '.local', 'share', 'local_pac', 'run', 'pid')
34
+ option :gem_path, Gem.path
35
+
36
+ def to_s
37
+ result = []
38
+ result << sprintf("%20s | %s", 'option', 'value')
39
+ result << sprintf("%s + %s", '-' * 20, '-' * 80)
40
+
41
+ Config.options.each do |o|
42
+ result << sprintf("%20s | %s", o, Array(public_send(o)).join(', '))
43
+ end
44
+
45
+ result.join("\n")
46
+ end
47
+
48
+ private
49
+
50
+ def candiate_files
51
+ [
52
+ File.expand_path(File.join(Dir.getwd, 'config.yaml')),
53
+ File.expand_path(File.join(ENV['HOME'], '.config', 'local_pac', 'config.yaml')),
54
+ File.expand_path(File.join(ENV['HOME'], '.local_pac', 'config.yaml')),
55
+ File.expand_path(File.join('/etc', 'local_pac', 'config.yaml')),
56
+ File.expand_path('../../../files/config.yaml', __FILE__),
57
+ ]
58
+ end
59
+
60
+ def available_config_file
61
+ candiate_files.find { |f| File.exists? f }
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,23 @@
1
+ module LocalPac
2
+ class Data
3
+ private
4
+
5
+ attr_reader :config
6
+
7
+ public
8
+
9
+ def initialize(config = LocalPac.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,34 @@
1
+ # encoding: utf-8
2
+ module LocalPac
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,9 @@
1
+ module LocalPac
2
+ module Exceptions
3
+ # raise if there are template syntax errrors
4
+ class ErbTemplateHasSyntaxErrors < Exception; end
5
+
6
+ # raised if Template does not exist
7
+ class ErbTemplateIsUnknown < Exception; end
8
+ end
9
+ end
@@ -2,6 +2,15 @@ module LocalPac
2
2
  class FileServer < Sinatra::Base
3
3
  use Rack::Deflater
4
4
 
5
+ configure do
6
+ if settings.environment == :test
7
+ require_relative 'spec_helper_file_server'
8
+ SpecHelperFileServer.new
9
+ end
10
+
11
+ set :local_storage, LocalPac::LocalStorage.new
12
+ end
13
+
5
14
  configure do
6
15
  mime_type :proxy_pac_file, 'application/x-ns-proxy-autoconfig'
7
16
  end
@@ -16,9 +25,7 @@ module LocalPac
16
25
 
17
26
  get '/v1/pac/:name' do
18
27
  content_type :proxy_pac_file
19
-
20
- manager = PacManager.new
21
- file = manager.find(params[:name])
28
+ file = settings.local_storage.find(params[:name])
22
29
 
23
30
  if file.nil?
24
31
  fail Sinatra::NotFound, params[:name]
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ module Fileable
4
+ def mkdir_p(*args)
5
+ FileUtils.mkdir_p(*args)
6
+ end
7
+
8
+ def exist?(*args)
9
+ File.exist?(*args)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,63 @@
1
+ module LocalPac
2
+ class Git
3
+ def self.ls_files(filter = nil)
4
+ cmd = ['git ls-files']
5
+ cmd << " #{filter}" if filter
6
+
7
+ runner = Runner.new(cmd.join(" "))
8
+ runner.result
9
+ end
10
+
11
+ def self.ls_tree(git_dir = nil)
12
+ cmd = ['git']
13
+ cmd << "--git-dir #{git_dir}" if git_dir
14
+ cmd << 'ls-tree -r HEAD'
15
+
16
+ runner = Runner.new(cmd.join(" "))
17
+ runner.result
18
+ end
19
+
20
+ def self.init(path, is_bare = false)
21
+ cmd = ["git init #{path}"]
22
+ cmd << "--bare" if is_bare
23
+
24
+ runner = Runner.new(cmd.join(" "))
25
+ runner.result
26
+ end
27
+
28
+ def self.add(object)
29
+ runner = Runner.new("git add #{object}")
30
+ runner.result
31
+ end
32
+
33
+ def self.commit(message)
34
+ runner = Runner.new("git commit -m \"#{message}\"")
35
+ runner.result
36
+ end
37
+
38
+ def self.status
39
+ runner = Runner.new('git status')
40
+ runner.result
41
+ end
42
+
43
+ def self.show(sha = nil, git_dir = nil)
44
+ cmd = ['git']
45
+ cmd << "--git-dir #{git_dir}" if git_dir
46
+ cmd << 'show'
47
+ cmd << " #{sha}" if sha
48
+
49
+ runner = Runner.new(cmd.join(" "))
50
+ runner.result
51
+ end
52
+
53
+ def self.cat_file(sha, git_dir = nil)
54
+ cmd = ['git']
55
+ cmd << "--git-dir #{git_dir}" if git_dir
56
+ cmd << 'cat-file -p'
57
+ cmd << sha
58
+
59
+ runner = Runner.new(cmd.join(" "))
60
+ runner.result
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ class GitFile
4
+ attr_reader :path, :name, :content, :sha
5
+
6
+ def initialize(data, git_dir = nil)
7
+ data = data.split(" ")
8
+ @path = data.last
9
+ @sha = data[2]
10
+ @name = path.sub(/.pac$/, '').camelize.downcase.to_sym
11
+ @content = Git.cat_file(@sha, git_dir).join("\n")
12
+ end
13
+
14
+ def to_s
15
+ "#{name}: #{path} (#{content})"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+
4
+ class GitRepository
5
+ private
6
+
7
+ attr_reader :storage_path, :data
8
+
9
+ public
10
+
11
+ def initialize(storage_path, compressor_engine = JavaScriptCompressor, file_creator = PacFile)
12
+ @storage_path = storage_path
13
+ javascript_compressor = compressor_engine.new
14
+
15
+ create unless ::File.exists? storage_path
16
+
17
+ mutex = Mutex.new
18
+ mutex.synchronize do
19
+ @data = pac_files.reduce({}) do |memo, git_file|
20
+ pac_file = file_creator.new(git_file)
21
+ javascript_compressor.prepare(pac_file)
22
+ memo[pac_file.name.to_sym] = pac_file
23
+
24
+ memo
25
+ end
26
+ end
27
+ end
28
+
29
+ def [](name)
30
+ data[name]
31
+ end
32
+
33
+ private
34
+
35
+ def create
36
+ Git.init(storage_path)
37
+ end
38
+
39
+ def pac_files
40
+ Dir.chdir(storage_path) do
41
+ LocalPac.ui_logger.debug "I'm using the following storage path: \"#{storage_path}\"."
42
+
43
+ files = Git.ls_tree(storage_path).collect do |l|
44
+ GitFile.new(l)
45
+ end
46
+
47
+ LocalPac.ui_logger.debug "Found the following files: \"#{files.join(", ")}\"."
48
+ files
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ module LocalPac
2
+ class Initializer
3
+
4
+ private
5
+
6
+ attr_reader :config, :vcs, :options
7
+
8
+ include Fileable
9
+
10
+ public
11
+
12
+ def initialize(options = {}, config = LocalPac.config)
13
+ @config = config
14
+ @options = options
15
+ end
16
+
17
+ def run
18
+ LocalPac.ui_logger.info "Creating pid directory: #{::File.dirname(config.pid_file)}"
19
+ Actions::CreateDirectory.new(::File.dirname(config.pid_file), force: options[:force]).run
20
+ LocalPac.ui_logger.info "Creating log sink: #{config.log_sink}"
21
+ Actions::CreateDirectory.new(config.log_sink, force: options[:force]).run
22
+ LocalPac.ui_logger.info "Creating local storage: #{config.local_storage}"
23
+ Actions::CreateRepository.new(config.local_storage, bare: true, force: options[:force]).run
24
+ LocalPac.ui_logger.info "Creating pre-receive hook in local storage \"#{config.local_storage}\"."
25
+ Actions::CreateFile.new(:'git-hook', File.join(config.local_storage, 'hooks', 'pre-receive'), Data.new(config), force: options[:force]).run
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+ class LocalStorage
4
+ private
5
+
6
+ attr_reader :storage, :null_file
7
+
8
+ public
9
+
10
+ def initialize(storage = GitRepository.new(LocalPac.config.local_storage), null_file = NullPacFile.new )
11
+ @storage = storage
12
+ @null_file = null_file
13
+ end
14
+
15
+ def find(name)
16
+ name = name.sub(/.pac$/, '').camelize.downcase.to_sym
17
+ LocalPac.ui_logger.debug "Using the following name to find pac file: \":#{name}\"."
18
+ storage[name] || null_file
19
+ end
20
+ end
21
+ end
@@ -8,10 +8,5 @@ module LocalPac
8
8
  def write(*args, &block)
9
9
  @logger.<<(*args, &block)
10
10
  end
11
-
12
- private
13
-
14
- def default_path
15
- end
16
11
  end
17
12
  end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ module LocalPac
3
+
4
+ @config_semaphore = Mutex.new
5
+ @logger_semaphore = Mutex.new
6
+
7
+ class << self
8
+ attr_reader :config_semaphore
9
+ attr_reader :logger_semaphore
10
+ attr_accessor :debug_mode
11
+
12
+ def config(local_config = LocalPac::Config.new)
13
+ config_semaphore.synchronize do
14
+ @config ||= local_config
15
+ end
16
+ end
17
+
18
+ def ui_logger(local_logger = LocalPac::UiLogger.new)
19
+ logger_semaphore.synchronize do
20
+ @ui_logger ||= local_logger
21
+ end
22
+ end
23
+ end
24
+ end