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.


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

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


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

def force
  @force
end

#maxObject (readonly)

Returns the value of attribute max


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

def max
  @max
end

#modeObject (readonly)

Returns the value of attribute mode


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

def mode
  @mode
end

#path(*args) ⇒ Object (readonly)

Compute a path for first run directory


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

def path
  @path
end

#verboseObject (readonly)

Returns the value of attribute verbose


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

def verbose
  @verbose
end

Class Method Details

.ellipse(text, size = 32) ⇒ Object


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

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


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

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.select { |source| !source.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


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

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

#hard?Boolean

Returns:

  • (Boolean)

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

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

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


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

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

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

Import a given file


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

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) 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


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

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


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

def import_file(nature, file, options = {})
  p = path(file)
  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


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

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


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

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

#run_loader(loader, imports) ⇒ Object

Execute given loader for a given base


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

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


84
85
86
# File 'lib/ekylibre/first_run/base.rb', line 84

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