Class: Ekylibre::FirstRun::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/ekylibre/first_run/base.rb

Constant Summary collapse

LOADERS =
YAML.load_file(Pathname.new(__FILE__).dirname.join('loaders.yml')).deep_symbolize_keys.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, options = {}) ⇒ Base

Returns a new instance of Base.


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/ekylibre/first_run/base.rb', line 8

def initialize(path, options = {})
  @verbose = !options[:verbose].is_a?(FalseClass)
  @force = options[:force].is_a?(TrueClass)
  @mode = options[:mode].to_s.downcase
  @mode = 'normal' if @mode.blank?
  @mode = @mode.to_sym
  @path = path
  unless @path.exist?
    raise ArgumentError, "Need a valid folder path. #{@path} doesn't exist."
  end
  @term_width = begin
                  `/usr/bin/env tput cols`.to_i
                rescue
                  80
                end
  @term_width = 80 unless @term_width > 0
  ::I18n.locale = Preference[:language]
  @max = options[:max].to_i
end

Instance Attribute Details

#forceObject (readonly)

Returns the value of attribute force


6
7
8
# File 'lib/ekylibre/first_run/base.rb', line 6

def force
  @force
end

#maxObject (readonly)

Returns the value of attribute max


6
7
8
# File 'lib/ekylibre/first_run/base.rb', line 6

def max
  @max
end

#modeObject (readonly)

Returns the value of attribute mode


6
7
8
# File 'lib/ekylibre/first_run/base.rb', line 6

def mode
  @mode
end

#path(*args) ⇒ Object (readonly)

Compute a path for first run directory


29
30
31
# File 'lib/ekylibre/first_run/base.rb', line 29

def path
  @path
end

#verboseObject (readonly)

Returns the value of attribute verbose


6
7
8
# File 'lib/ekylibre/first_run/base.rb', line 6

def verbose
  @verbose
end

Class Method Details

.ellipse(text, size = 32) ⇒ Object


239
240
241
242
243
244
245
246
# File 'lib/ekylibre/first_run/base.rb', line 239

def self.ellipse(text, size = 32)
  ellipsis = '...'
  if text.size > size
    first = ((size - ellipsis.size).to_f / 2).round
    return text[0..(first - 1)] + ellipsis + text[-(size - first - ellipsis.size)..-1]
  end
  text
end

Instance Method Details

#check_archive(nature, target, files, options = {}) ⇒ Object

Check that archive exist if not try to build one if existing file Given files must exist


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
# File 'lib/ekylibre/first_run/base.rb', line 139

def check_archive(nature, target, files, options = {})
  working_path = @path.join(options[:in] ? options.delete(:in) : '.')
  target_path = working_path.join(target)
  files = files.each_with_object({}) { |f, h| h[f] = f } if files.is_a?(Array)
  files.each do |dest, source|
    files[dest] = working_path.join(source)
  end
  files_count = files.keys.count
  mimefile = working_path.join('mimetype')
  FileUtils.rm_rf(target_path) if target_path.exist?
  not_found = files.values.reject(&:exist?)
  if not_found.any?
    if not_found.size != files_count
      puts "#{nature.to_s.humanize} (#{target})".red
      puts ("   Missing files to build #{target} archive: " + not_found.map { |f| f.relative_path_from(@path) }.to_sentence).red
      return false
    end
  else
    if options[:mimetype]
      FileUtils.mkdir_p(mimefile.dirname)
      File.write(mimefile, options[:mimetype])
      files['mimetype'] = mimefile
    end
    begin
      Zip::File.open(target_path, Zip::File::CREATE) do |zile|
        files.each do |dest, source|
          zile.add(dest, source)
        end
      end
    # Zip Library can throw an us-ascii string error with utf-8 inside
    rescue Exception => e
      puts "Cannot create #{target_path}".red
      puts "Caused by: #{e.to_s.force_encoding('utf-8')}".blue
      ::Kernel.exit 1
    ensure
      FileUtils.rm_rf(mimefile) if options[:mimetype]
    end
  end
  target_path
end

#executed_preferenceObject


37
38
39
# File 'lib/ekylibre/first_run/base.rb', line 37

def executed_preference
  Preference.get('first_run.executed', false)
end

#hard?Boolean

Returns:

  • (Boolean)

33
34
35
# File 'lib/ekylibre/first_run/base.rb', line 33

def hard?
  @mode == :hard || Rails.env.production?
end

#import(nature, file, options = {}) ⇒ Object


235
236
237
# File 'lib/ekylibre/first_run/base.rb', line 235

def import(nature, file, options = {})
  import!(nature, file, options)
end

#import!(nature, file, options = {}) ⇒ Object

Import a given file


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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/ekylibre/first_run/base.rb', line 181

def import!(nature, file, options = {})
  # puts "> import(:#{nature.to_s}, '#{file.to_s}', #{options.inspect})"
  last = ''
  start = Time.zone.now
  basename = nature.to_s.humanize + ' (' + Pathname.new(file).basename.to_s + ') '
  total = 0
  max = options[:max] || @max
  Import.launch!(nature, file, options.fetch(:options, {})) do |progress, count|
    if @verbose
      status = [' + ' + basename]
      status << " #{progress.to_i}%"
      if progress > 0
        remaining = (100 - progress) * (Time.zone.now - start) / progress
        status << " #{remaining.round.to_i}s"
      end
      l = @term_width - status.join.length
      if l > 0
        status.insert(1, '|' * l)
      elsif l < 0
        status[0] = ' + ' + basename[0..(l - 4)] + '...'
      end
      line = status.join
      done = (progress * @term_width / 100.0).round.to_i
      done = @term_width if done > @term_width
      print "\r" * last.size + line[0..done].blue + (done == @term_width ? '' : line[(done + 1)..-1])
      last = line
      total = count
    end
    max <= 0 || count < max
  end
  if @verbose
    stop = Time.zone.now
    status = ['' + nature.to_s.humanize, ' (' + Pathname.new(file).basename.to_s + ') ']
    status << ' ' + total.to_s
    status << ' done in '
    status << "#{(stop - start).to_i}s"
    l = @term_width - status.join.length
    n = 1
    if l > 0
      status.insert(1 + n, ' ' * l)
      status[2 + n] = status[2 + n].green
      status[4 + n] = status[4 + n].green
    elsif l < 0
      status[0] = status[0][0..(l - 4)] + '...'
      status[1 + n] = status[1 + n].green
      status[3 + n] = status[3 + n].green
    end
    status[0] = status[0].green
    # status[1] = status[1].green
    # status[0 + n] = status[0 + n].green
    puts "\r" * last.size + status.join
  end
end

#import_archive(nature, target, files, options = {}) ⇒ Object


132
133
134
135
# File 'lib/ekylibre/first_run/base.rb', line 132

def import_archive(nature, target, files, options = {})
  file = check_archive(nature, target, files, options)
  import_file(nature, file) if file
end

#import_file(nature, file, options = {}) ⇒ Object


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ekylibre/first_run/base.rb', line 114

def import_file(nature, file, options = {})
  p = path(file)
  options[:options] = options[:options]&.map do |key, value|
    value = path(value).to_s if key.to_s =~ /path$/
    [key, value]
  end.to_h
  if p.exist?
    import(nature, p, options)
  elsif @verbose
    text = ["#{nature.to_s.humanize}", " (#{p.basename})"]
    if text.join.length < @term_width
      text << ' ' * (@term_width - text.join.length)
    end
    text[0] = text[0].yellow
    puts text.join
  end
end

#import_pictures(base, type, identifier) ⇒ Object


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
# File 'lib/ekylibre/first_run/base.rb', line 85

def import_pictures(base, type, identifier)
  if path("#{base}/pictures").exist?
    file = path("#{base}/pictures.zip")
    FileUtils.rm_rf file

    mimefile = path.join("#{base}/pictures.mimetype")
    File.write(mimefile, "application/vnd.ekylibre.pictures.#{type}")

    idenfile = path.join("#{base}/pictures.identifier")
    File.write(idenfile, identifier.to_s)

    files = {
      'mimetype' => 'pictures.mimetype',
      'identifier' => 'pictures.identifier'
    }
    Dir.chdir(path(base.to_s)) do
      Dir.glob('pictures/*').each do |picture|
        p = Pathname.new(picture).basename.to_s
        files[picture] = "pictures/#{p}"
      end
    end
    check_archive(:ekylibre_pictures, file, files, in: base.to_s)

    FileUtils.rm_f mimefile
    FileUtils.rm_f idenfile
  end
  import_file(:ekylibre_pictures, "#{base}/pictures.zip")
end

#runObject

Execute all loaders for a given base


42
43
44
45
46
47
48
49
# File 'lib/ekylibre/first_run/base.rb', line 42

def run
  secure_transaction(!hard?) do
    LOADERS.each do |loader, imports|
      run_loader(loader, imports)
    end
    executed_preference.update!(value: true)
  end
end

#run_loader(loader, imports) ⇒ Object

Execute given loader for a given base


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
# File 'lib/ekylibre/first_run/base.rb', line 52

def run_loader(loader, imports)
  ::I18n.locale = Preference[:language]
  ActiveRecord::Base.transaction do
    preference = Preference.get("first_run.executed_loaders.#{loader}", false)
    if force || !preference.value
      # @loaders[loader].call(base)
      imports.each do |import_name, options|
        format = options[:format] || :file
        path = options[:path]
        nature = options[:type] || import_name
        if format == :archive
          import_archive(nature, path, options[:files], options.slice(:in, :mimetype))
        elsif format == :pictures
          import_pictures(path, options[:table], options[:id_column])
        elsif format == :file
          import_file(nature, path, options)
        else
          raise 'Cannot import that format: ' + format.inspect
        end
      end
      preference.value = true
      preference.save!
    else
      puts 'Skip'.yellow + " #{loader} loader"
    end
  end
end

#secure_transaction(with_transaction = true, &block) ⇒ Object

Wrap code in a transaction if wanted


81
82
83
# File 'lib/ekylibre/first_run/base.rb', line 81

def secure_transaction(with_transaction = true, &block)
  (with_transaction ? ActiveRecord::Base.transaction(&block) : yield)
end