Class: Braid::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/braid/config.rb

Defined Under Namespace

Classes: MirrorDoesNotExist, PathAlreadyInUse, RemoveMirrorDueToBreakingChange

Constant Summary collapse

MODE_UPGRADE =
1
MODE_READ_ONLY =
2
MODE_MAY_WRITE =
3
CURRENT_CONFIG_VERSION =
1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Config

options: config_file, old_config_files, mode



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
# File 'lib/braid/config.rb', line 76

def initialize(options = {})
  @config_file     = options['config_file']      || CONFIG_FILE
  old_config_files = options['old_config_files'] || [OLD_CONFIG_FILE]
  @mode            = options['mode']             || MODE_MAY_WRITE

  data = load_config(@config_file, old_config_files)
  @config_existed = !data.nil?
  if !@config_existed
    @config_version = CURRENT_CONFIG_VERSION
    @db = {}
  elsif data['config_version'].is_a?(Numeric)
    @config_version = data['config_version']
    @db = data['mirrors']
  else
    # Before config versioning (Braid < 1.1.0)
    @config_version = 0
    @db = data
  end

  if @config_version > CURRENT_CONFIG_VERSION
    raise BraidError, <<-MSG
This version of Braid (#{VERSION}) is too old to understand your project's Braid
configuration file (version #{@config_version}).  See the instructions at
https://cristibalan.github.io/braid/config_versions.html to install and use a
compatible newer version of Braid.
MSG
  end

  # In all modes, instantiate all mirrors to scan for breaking changes.
  @breaking_change_descs = []
  paths_to_delete = []
  @db.each do |path, attributes|
    begin
      mirror = Mirror.new(path, attributes,
        lambda {|desc| @breaking_change_descs.push(desc)})
      # In MODE_UPGRADE, update @db now.  In other modes, we won't write the
      # config if an upgrade is needed, so it doesn't matter that we don't
      # update @db.
      #
      # It's OK to change the values of existing keys during iteration:
      # https://groups.google.com/d/msg/comp.lang.ruby/r5OI6UaxAAg/SVpU0cktmZEJ
      write_mirror(mirror) if @mode == MODE_UPGRADE
    rescue RemoveMirrorDueToBreakingChange
      # I don't know if deleting during iteration is well-defined in all
      # Ruby versions we support, so defer the deletion.
      # ~ [email protected], 2017-12-31
      paths_to_delete.push(path) if @mode == MODE_UPGRADE
    end
  end
  paths_to_delete.each do |path|
    @db.delete(path)
  end

  if @mode != MODE_UPGRADE && !@breaking_change_descs.empty?
    raise BraidError, <<-MSG
This version of Braid (#{VERSION}) no longer supports a feature used by your
Braid configuration file (version #{@config_version}).  Run 'braid upgrade-config --dry-run'
for information about upgrading your configuration file, or see the instructions
at https://cristibalan.github.io/braid/config_versions.html to install and run a
compatible older version of Braid.
MSG
  end

  if @mode == MODE_MAY_WRITE && @config_version < CURRENT_CONFIG_VERSION
    raise BraidError, <<-MSG
This command may need to write to your Braid configuration file,
but this version of Braid (#{VERSION}) cannot write to your configuration file
(currently version #{config_version}) without upgrading it to configuration version #{CURRENT_CONFIG_VERSION},
which would force other developers on your project to upgrade Braid.  Run
'braid upgrade-config' to proceed with the upgrade, or see the instructions at
https://cristibalan.github.io/braid/config_versions.html to install and run a
compatible older version of Braid.
MSG
  end

end

Instance Attribute Details

#breaking_change_descsObject (readonly)

For upgrade-config command only. XXX: Ideally would be immutable.



73
74
75
# File 'lib/braid/config.rb', line 73

def breaking_change_descs
  @breaking_change_descs
end

#config_existedObject (readonly)

For upgrade-config command only. XXX: Ideally would be immutable.



73
74
75
# File 'lib/braid/config.rb', line 73

def config_existed
  @config_existed
end

#config_versionObject (readonly)

For upgrade-config command only. XXX: Ideally would be immutable.



73
74
75
# File 'lib/braid/config.rb', line 73

def config_version
  @config_version
end

Instance Method Details

#add(mirror) ⇒ Object

Raises:



176
177
178
179
180
# File 'lib/braid/config.rb', line 176

def add(mirror)
  raise PathAlreadyInUse, mirror.path if get(mirror.path)
  write_mirror(mirror)
  write_db
end

#add_from_options(url, options) ⇒ Object



153
154
155
156
157
158
# File 'lib/braid/config.rb', line 153

def add_from_options(url, options)
  mirror = Mirror.new_from_options(url, options)

  add(mirror)
  mirror
end

#get(path) ⇒ Object



164
165
166
167
168
# File 'lib/braid/config.rb', line 164

def get(path)
  key = path.to_s.sub(/\/$/, '')
  attributes = @db[key]
  attributes ? Mirror.new(path, attributes) : nil
end

#get!(path) ⇒ Object

Raises:



170
171
172
173
174
# File 'lib/braid/config.rb', line 170

def get!(path)
  mirror = get(path)
  raise MirrorDoesNotExist, path unless mirror
  mirror
end

#mirrorsObject



160
161
162
# File 'lib/braid/config.rb', line 160

def mirrors
  @db.keys
end

#remove(mirror) ⇒ Object



182
183
184
185
# File 'lib/braid/config.rb', line 182

def remove(mirror)
  @db.delete(mirror.path)
  write_db
end

#update(mirror) ⇒ Object

Raises:



187
188
189
190
191
# File 'lib/braid/config.rb', line 187

def update(mirror)
  raise MirrorDoesNotExist, mirror.path unless get(mirror.path)
  write_mirror(mirror)
  write_db
end

#write_dbObject

Public for upgrade-config command only.



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/braid/config.rb', line 194

def write_db
  new_db = {}
  @db.keys.sort.each do |key|
    new_db[key] = {}
    Braid::Mirror::ATTRIBUTES.each do |k|
      new_db[key][k] = @db[key][k] if @db[key].has_key?(k)
    end
  end
  new_data = {
    'config_version' => CURRENT_CONFIG_VERSION,
    'mirrors' => new_db
  }
  File.open(@config_file, 'wb') do |f|
    f.write JSON.pretty_generate(new_data)
    f.write "\n"
  end
end