File: database.rb

package info (click to toggle)
ruby-librarian 1.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 624 kB
  • sloc: ruby: 6,109; makefile: 11
file content (205 lines) | stat: -rw-r--r-- 5,119 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
require "pathname"

require "librarian/config/file_source"
require "librarian/config/hash_source"

module Librarian
  module Config
    class Database

      class << self
        def library
          name.split("::").first.downcase
        end
      end

      attr_accessor :adapter_name
      private :adapter_name=

      attr_accessor :root, :assigned_specfile_name
      private :root=, :assigned_specfile_name=

      attr_accessor :underlying_env, :underlying_pwd, :underlying_home
      private :underlying_env=, :underlying_pwd=, :underlying_home=

      def initialize(adapter_name, options = { })
        self.adapter_name = adapter_name or raise ArgumentError, "must provide adapter_name"

        options[:project_path] || options[:pwd] or raise ArgumentError, "must provide project_path or pwd"

        self.root = options[:project_path] && Pathname(options[:project_path])
        self.assigned_specfile_name = options[:specfile_name]
        self.underlying_env = options[:env] or raise ArgumentError, "must provide env"
        self.underlying_pwd = options[:pwd] && Pathname(options[:pwd])
        self.underlying_home = options[:home] && Pathname(options[:home])
      end

      def global
        memo(__method__) { new_file_source(global_config_path) }
      end

      def env
        memo(__method__) { HashSource.new(adapter_name, :name => "environment", :raw => env_source_data) }
      end

      def local
        memo(__method__) { new_file_source(local_config_path) }
      end

      def [](key, scope = nil)
        case scope
        when "local", :local then local[key]
        when "env", :env then env[key]
        when "global", :global then global[key]
        when nil then local[key] || env[key] || global[key]
        else raise Error, "bad scope"
        end
      end

      def []=(key, scope, value)
        case scope
        when "local", :local then local[key] = value
        when "global", :global then global[key] = value
        else raise Error, "bad scope"
        end
      end

      def keys
        [local, env, global].inject([]){|a, e| a.concat(e.keys) ; a}.sort.uniq
      end

      def project_path
        root || specfile_path.dirname
      end

      def specfile_path
        if root
          root + (assigned_specfile_name || default_specfile_name)
        else
          env_specfile_path || default_specfile_path
        end
      end

      def specfile_name
        specfile_path.basename.to_s
      end

      def lockfile_path
        project_path + lockfile_name
      end

      def lockfile_name
        "#{specfile_name}.lock"
      end

    private

      def new_file_source(config_path)
        return unless config_path

        FileSource.new(adapter_name,
          :config_path => config_path,
          :forbidden_keys => [config_key, specfile_key]
        )
      end

      def global_config_path
        env_global_config_path || default_global_config_path
      end

      def env_global_config_path
        memo(__method__) { env[config_key] }
      end

      def default_global_config_path
        underlying_home && underlying_home + config_name
      end

      def local_config_path
        root_local_config_path || env_local_config_path || default_local_config_path
      end

      def root_local_config_path
        root && root + config_name
      end

      def env_specfile_path
        memo(__method__) do
          path = env[specfile_key]
          path && Pathname(path)
        end
      end

      def default_specfile_path
        default_project_root_path + (assigned_specfile_name || default_specfile_name)
      end

      def env_local_config_path
        return unless env_specfile_path

        env_specfile_path.dirname + config_name
      end

      def default_local_config_path
        default_project_root_path + config_name
      end

      def default_project_root_path
        if root
          root
        else
          path = underlying_pwd
          path = path.dirname until project_root_path?(path) || path.dirname == path
          project_root_path?(path) ? path : underlying_pwd
        end
      end

      def project_root_path?(path)
        File.file?(path + default_specfile_name)
      end

      def config_key
        "config"
      end

      def specfile_key
        "#{adapter_name}file"
      end

      def default_specfile_name
        "#{adapter_name.capitalize}file"
      end

      def library
        self.class.library
      end

      def config_name_prefix
        ".#{library}"
      end

      def config_name
        File.join(*[config_name_prefix, adapter_name, "config"])
      end

      def raw_key_prefix
        "#{library.upcase}_#{adapter_name.upcase}_"
      end

      def env_source_data
        prefix = raw_key_prefix

        data = underlying_env.dup
        data.reject!{|k, _| !k.start_with?(prefix) || k.size <= prefix.size}
        data
      end

      def memo(key)
        key = "@#{key}"
        instance_variable_set(key, yield) unless instance_variable_defined?(key)
        instance_variable_get(key)
      end

    end
  end
end