2014-02-03 19:23:00 +00:00
|
|
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
2013-06-12 15:59:58 +00:00
|
|
|
|
2012-12-26 22:02:16 +00:00
|
|
|
class Package < ApplicationModel
|
2015-05-08 13:47:27 +00:00
|
|
|
@@root = Rails.root.to_s # rubocop:disable Style/ClassVars
|
2012-12-26 22:02:16 +00:00
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
verify if package is installed correctly
|
|
|
|
|
|
|
|
package = Package.find(123)
|
|
|
|
|
|
|
|
issues = package.verify
|
|
|
|
|
|
|
|
returns:
|
|
|
|
|
|
|
|
# if no issue exists
|
|
|
|
nil
|
|
|
|
|
|
|
|
# list of issues
|
|
|
|
{
|
|
|
|
'path/to/file' => 'missing',
|
|
|
|
'path/to/file' => 'changed',
|
|
|
|
}
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def verify
|
|
|
|
|
|
|
|
# get package
|
|
|
|
json_file = self.class._get_bin(name, version)
|
|
|
|
package = JSON.parse(json_file)
|
|
|
|
|
|
|
|
# verify installed files
|
|
|
|
issues = {}
|
|
|
|
package['files'].each { |file|
|
|
|
|
if !File.exist?(file['location'])
|
|
|
|
logger.error "File #{file['location']} is missing"
|
|
|
|
issues[file['location']] = 'missing'
|
|
|
|
next
|
|
|
|
end
|
|
|
|
content_package = Base64.decode64(file['content'])
|
|
|
|
content_fs = self.class._read_file(file['location'])
|
|
|
|
next if content_package == content_fs
|
|
|
|
logger.error "File #{file['location']} is different"
|
|
|
|
issues[file['location']] = 'changed'
|
|
|
|
}
|
|
|
|
return nil if issues.empty?
|
|
|
|
issues
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
install all packages located under auto_install/*.zpm
|
|
|
|
|
|
|
|
Package.auto_install
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2013-01-07 08:32:48 +00:00
|
|
|
def self.auto_install
|
2016-01-21 22:25:05 +00:00
|
|
|
path = "#{@@root}/auto_install/"
|
|
|
|
return if !File.exist?(path)
|
2013-01-07 08:32:48 +00:00
|
|
|
data = []
|
2016-01-21 22:25:05 +00:00
|
|
|
Dir.foreach(path) do |entry|
|
2014-03-10 15:45:52 +00:00
|
|
|
if entry =~ /\.zpm/ && entry !~ /^\./
|
2013-01-07 08:32:48 +00:00
|
|
|
data.push entry
|
|
|
|
end
|
|
|
|
end
|
|
|
|
data.each {|file|
|
2016-01-21 22:25:05 +00:00
|
|
|
install(file: "#{path}/#{file}")
|
2013-01-07 08:32:48 +00:00
|
|
|
}
|
2015-01-10 10:13:20 +00:00
|
|
|
data
|
2013-01-07 08:32:48 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
remove all linked files in application
|
|
|
|
|
|
|
|
note: will not take down package migrations, use Package.unlink instead
|
|
|
|
|
|
|
|
Package.unlink_all
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2013-01-16 20:09:27 +00:00
|
|
|
def self.unlink_all
|
|
|
|
# link files
|
2016-01-21 22:25:05 +00:00
|
|
|
Dir.glob("#{@@root}/**/*") do |entry|
|
|
|
|
if File.symlink?(entry)
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "unlink: #{entry}"
|
2016-01-21 22:25:05 +00:00
|
|
|
File.delete(entry)
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
2013-03-19 15:39:31 +00:00
|
|
|
backup_file = entry + '.link_backup'
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.exist?(backup_file)
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "Restore backup file of #{backup_file} -> #{entry}."
|
2016-01-21 22:25:05 +00:00
|
|
|
File.rename(backup_file, entry)
|
2013-03-19 15:39:31 +00:00
|
|
|
end
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-12 15:59:58 +00:00
|
|
|
# check if zpm is a package source repo
|
2013-01-16 20:09:27 +00:00
|
|
|
def self._package_base_dir?(package_base_dir)
|
|
|
|
package = false
|
2016-01-21 22:25:05 +00:00
|
|
|
Dir.glob(package_base_dir + '/*.szpm') do |entry|
|
|
|
|
package = entry.sub(%r{^.*/(.+?)\.szpm$}, '\1')
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
if package == false
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "Can't link package, '#{package_base_dir}' is no package source directory!"
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.debug package.inspect
|
2015-01-10 10:13:20 +00:00
|
|
|
package
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
execute migration down + unlink files
|
|
|
|
|
|
|
|
Package.unlink('/path/to/src/extention')
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2013-01-16 20:09:27 +00:00
|
|
|
def self.unlink(package_base_dir)
|
|
|
|
|
2013-06-12 15:59:58 +00:00
|
|
|
# check if zpm is a package source repo
|
2016-01-15 17:22:57 +00:00
|
|
|
package = _package_base_dir?(package_base_dir)
|
2013-01-16 20:09:27 +00:00
|
|
|
|
|
|
|
# migration down
|
2016-01-21 22:25:05 +00:00
|
|
|
Package::Migration.migrate(package, 'reverse')
|
2013-01-16 20:09:27 +00:00
|
|
|
|
|
|
|
# link files
|
2016-01-21 22:25:05 +00:00
|
|
|
Dir.glob(package_base_dir + '/**/*') do |entry|
|
|
|
|
entry = entry.sub('//', '/')
|
2013-01-16 20:09:27 +00:00
|
|
|
file = entry
|
2016-01-21 22:25:05 +00:00
|
|
|
file = file.sub(/#{package_base_dir.to_s}/, '')
|
2013-01-16 20:09:27 +00:00
|
|
|
dest = @@root + '/' + file
|
2013-06-12 15:59:58 +00:00
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.symlink?(dest.to_s)
|
2015-05-06 09:30:39 +00:00
|
|
|
logger.info "Unlink file: #{dest}"
|
2016-01-21 22:25:05 +00:00
|
|
|
File.delete(dest.to_s)
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
2013-03-19 15:39:31 +00:00
|
|
|
|
|
|
|
backup_file = dest.to_s + '.link_backup'
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.exist?(backup_file)
|
2015-05-06 09:30:39 +00:00
|
|
|
logger.info "Restore backup file of #{backup_file} -> #{dest}."
|
2016-01-21 22:25:05 +00:00
|
|
|
File.rename(backup_file, dest.to_s)
|
2013-03-19 15:39:31 +00:00
|
|
|
end
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
link files + execute migration up
|
|
|
|
|
|
|
|
Package.link('/path/to/src/extention')
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2013-01-16 20:09:27 +00:00
|
|
|
def self.link(package_base_dir)
|
|
|
|
|
2013-06-12 15:59:58 +00:00
|
|
|
# check if zpm is a package source repo
|
2016-01-15 17:22:57 +00:00
|
|
|
package = _package_base_dir?(package_base_dir)
|
2013-01-16 20:09:27 +00:00
|
|
|
|
|
|
|
# link files
|
2016-01-21 22:25:05 +00:00
|
|
|
Dir.glob(package_base_dir + '/**/*') do |entry|
|
|
|
|
entry = entry.sub('//', '/')
|
2013-01-16 20:09:27 +00:00
|
|
|
file = entry
|
2016-01-21 22:25:05 +00:00
|
|
|
file = file.sub(/#{package_base_dir.to_s}/, '')
|
|
|
|
file = file.sub(%r{^/}, '')
|
2013-02-02 18:52:31 +00:00
|
|
|
|
|
|
|
# ignore files
|
|
|
|
if file =~ /^README/
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: Ignore #{file}"
|
2013-02-02 18:52:31 +00:00
|
|
|
next
|
|
|
|
end
|
|
|
|
|
|
|
|
# get new file destination
|
2013-01-16 20:09:27 +00:00
|
|
|
dest = @@root + '/' + file
|
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.directory?(entry.to_s)
|
|
|
|
if !File.exist?(dest.to_s)
|
2015-05-06 09:30:39 +00:00
|
|
|
logger.info "Create dir: #{dest}"
|
2016-01-21 22:25:05 +00:00
|
|
|
FileUtils.mkdir_p(dest.to_s)
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.file?(entry.to_s) && (File.file?(dest.to_s) && !File.symlink?(dest.to_s))
|
2013-03-19 15:39:31 +00:00
|
|
|
backup_file = dest.to_s + '.link_backup'
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.exist?(backup_file)
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "Can't link #{entry} -> #{dest}, destination and .link_backup already exists!"
|
2013-03-19 15:39:31 +00:00
|
|
|
else
|
2015-05-06 09:30:39 +00:00
|
|
|
logger.info "Create backup file of #{dest} -> #{backup_file}."
|
2016-01-21 22:25:05 +00:00
|
|
|
File.rename(dest.to_s, backup_file)
|
2013-03-19 15:39:31 +00:00
|
|
|
end
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.file?(entry)
|
|
|
|
if File.symlink?(dest.to_s)
|
|
|
|
File.delete(dest.to_s)
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
2015-05-06 09:30:39 +00:00
|
|
|
logger.info "Link file: #{entry} -> #{dest}"
|
2016-01-21 22:25:05 +00:00
|
|
|
File.symlink(entry.to_s, dest.to_s)
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# migration up
|
2016-01-21 22:25:05 +00:00
|
|
|
Package::Migration.migrate(package)
|
2013-01-16 20:09:27 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
install zpm package
|
|
|
|
|
|
|
|
package = Package.install(file: '/path/to/package.zpm')
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
package = Package.install(string: zpm_as_string)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
package # record of new created packae
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2012-12-27 14:41:28 +00:00
|
|
|
def self.install(data)
|
|
|
|
if data[:file]
|
2016-01-31 17:25:31 +00:00
|
|
|
json = _read_file(data[:file], true)
|
|
|
|
package = JSON.parse(json)
|
2012-12-27 14:41:28 +00:00
|
|
|
elsif data[:string]
|
2016-01-31 17:25:31 +00:00
|
|
|
package = JSON.parse(data[:string])
|
2012-12-27 14:41:28 +00:00
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# package meta data
|
2012-12-27 14:41:28 +00:00
|
|
|
meta = {
|
2016-01-31 17:25:31 +00:00
|
|
|
name: package['name'],
|
|
|
|
version: package['version'],
|
|
|
|
vendor: package['vendor'],
|
2015-04-27 13:42:53 +00:00
|
|
|
state: 'uninstalled',
|
|
|
|
created_by_id: 1,
|
|
|
|
updated_by_id: 1,
|
2012-12-26 22:02:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# verify if package can get installed
|
2016-01-21 22:25:05 +00:00
|
|
|
package_db = Package.find_by(name: meta[:name])
|
2012-12-26 22:02:16 +00:00
|
|
|
if package_db
|
2013-03-19 12:12:22 +00:00
|
|
|
if !data[:reinstall]
|
2016-01-21 22:25:05 +00:00
|
|
|
if Gem::Version.new(package_db.version) == Gem::Version.new(meta[:version])
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "Package '#{meta[:name]}-#{meta[:version]}' already installed!"
|
2013-03-19 12:12:22 +00:00
|
|
|
end
|
2016-01-21 22:25:05 +00:00
|
|
|
if Gem::Version.new(package_db.version) > Gem::Version.new(meta[:version])
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "Newer version (#{package_db.version}) of package '#{meta[:name]}-#{meta[:version]}' already installed!"
|
2013-03-19 12:12:22 +00:00
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
2013-03-22 12:48:47 +00:00
|
|
|
# uninstall files of old package
|
2015-05-07 12:10:38 +00:00
|
|
|
uninstall(
|
2015-04-27 13:42:53 +00:00
|
|
|
name: package_db.name,
|
|
|
|
version: package_db.version,
|
|
|
|
migration_not_down: true,
|
2016-02-01 00:42:30 +00:00
|
|
|
reinstall: data[:reinstall],
|
2015-04-27 15:21:17 +00:00
|
|
|
)
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# store package
|
2013-03-19 12:12:22 +00:00
|
|
|
if !data[:reinstall]
|
2016-02-01 00:42:30 +00:00
|
|
|
package_db = Package.create(meta)
|
2013-03-19 12:12:22 +00:00
|
|
|
Store.add(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: 'Package',
|
2016-02-01 00:42:30 +00:00
|
|
|
o_id: package_db.id,
|
2016-01-31 17:25:31 +00:00
|
|
|
data: package.to_json,
|
2016-01-21 22:25:05 +00:00
|
|
|
filename: "#{meta[:name]}-#{meta[:version]}.zpm",
|
2015-04-27 13:42:53 +00:00
|
|
|
preferences: {},
|
|
|
|
created_by_id: UserInfo.current_user_id || 1,
|
2013-03-19 12:12:22 +00:00
|
|
|
)
|
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# write files
|
2016-01-31 17:25:31 +00:00
|
|
|
package['files'].each { |file|
|
|
|
|
permission = file['permission'] || '644'
|
|
|
|
content = Base64.decode64(file['content'])
|
|
|
|
_write_file(file['location'], permission, content)
|
|
|
|
}
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# update package state
|
2016-02-01 00:42:30 +00:00
|
|
|
package_db.state = 'installed'
|
|
|
|
package_db.save
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# up migrations
|
2016-01-21 22:25:05 +00:00
|
|
|
Package::Migration.migrate(meta[:name])
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# prebuild assets
|
|
|
|
|
2016-02-01 00:42:30 +00:00
|
|
|
package_db
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
reinstall package
|
|
|
|
|
|
|
|
package = Package.reinstall(package_name)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
package # record of new created packae
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2013-03-19 12:12:22 +00:00
|
|
|
def self.reinstall(package_name)
|
2016-01-21 22:25:05 +00:00
|
|
|
package = Package.find_by(name: package_name)
|
2013-05-10 21:48:29 +00:00
|
|
|
if !package
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "No such package '#{package_name}'"
|
2013-05-10 21:48:29 +00:00
|
|
|
end
|
2016-01-21 22:25:05 +00:00
|
|
|
file = _get_bin(package.name, package.version)
|
|
|
|
install(string: file, reinstall: true)
|
2016-01-31 23:20:14 +00:00
|
|
|
package
|
2013-03-19 12:12:22 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
uninstall package
|
|
|
|
|
|
|
|
package = Package.uninstall(name: 'package', version: '0.1.1')
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
package = Package.uninstall(string: zpm_as_string)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
package # record of new created packae
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
def self.uninstall(data)
|
2012-12-26 22:02:16 +00:00
|
|
|
|
2012-12-27 14:41:28 +00:00
|
|
|
if data[:string]
|
2016-01-31 17:25:31 +00:00
|
|
|
package = JSON.parse(data[:string])
|
2012-12-27 14:41:28 +00:00
|
|
|
else
|
2016-01-31 17:25:31 +00:00
|
|
|
json_file = _get_bin(data[:name], data[:version])
|
|
|
|
package = JSON.parse(json_file)
|
2012-12-27 14:41:28 +00:00
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# down migrations
|
2012-12-27 14:41:28 +00:00
|
|
|
if !data[:migration_not_down]
|
2016-01-31 17:25:31 +00:00
|
|
|
Package::Migration.migrate(package['name'], 'reverse')
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 17:25:31 +00:00
|
|
|
package['files'].each { |file|
|
|
|
|
permission = file['permission'] || '644'
|
|
|
|
content = Base64.decode64(file['content'])
|
|
|
|
_delete_file(file['location'], permission, content)
|
|
|
|
}
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# delete package
|
2016-02-01 00:42:30 +00:00
|
|
|
if !data[:reinstall]
|
|
|
|
record = Package.find_by(
|
|
|
|
name: package['name'],
|
|
|
|
version: package['version'],
|
|
|
|
)
|
|
|
|
record.destroy
|
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
|
2016-01-31 23:20:14 +00:00
|
|
|
record
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
2016-06-01 08:32:13 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
execute all pending package migrations at once
|
|
|
|
|
|
|
|
Package.migration_execute
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.migration_execute
|
|
|
|
Package.all.each {|package|
|
|
|
|
json_file = Package._get_bin(package.name, package.version)
|
|
|
|
package = JSON.parse(json_file)
|
|
|
|
Package::Migration.migrate(package['name'])
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
def self._get_bin(name, version)
|
2015-05-07 10:15:40 +00:00
|
|
|
package = Package.find_by(
|
2015-04-27 13:42:53 +00:00
|
|
|
name: name,
|
|
|
|
version: version,
|
2015-05-07 10:15:40 +00:00
|
|
|
)
|
2012-12-26 22:02:16 +00:00
|
|
|
if !package
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "No such package '#{name}' version '#{version}'"
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
list = Store.list(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: 'Package',
|
|
|
|
o_id: package.id,
|
2012-12-26 22:02:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# find file
|
2013-05-10 21:48:29 +00:00
|
|
|
if !list || !list.first
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "No such file in storage list #{name} #{version}"
|
2013-05-10 21:48:29 +00:00
|
|
|
end
|
2014-04-28 07:44:36 +00:00
|
|
|
if !list.first.content
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "No such file in storage #{name} #{version}"
|
2013-05-10 21:48:29 +00:00
|
|
|
end
|
2014-04-28 07:44:36 +00:00
|
|
|
list.first.content
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def self._read_file(file, fullpath = false)
|
2016-01-15 17:22:57 +00:00
|
|
|
location = if fullpath == false
|
|
|
|
@@root + '/' + file
|
|
|
|
elsif fullpath == true
|
|
|
|
file
|
|
|
|
else
|
|
|
|
fullpath + '/' + file
|
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
begin
|
2016-01-21 22:25:05 +00:00
|
|
|
data = File.open(location, 'rb')
|
2012-12-26 22:02:16 +00:00
|
|
|
contents = data.read
|
|
|
|
rescue => e
|
|
|
|
raise 'ERROR: ' + e.inspect
|
|
|
|
end
|
2014-04-28 07:44:36 +00:00
|
|
|
contents
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def self._write_file(file, permission, data)
|
2016-01-21 22:25:05 +00:00
|
|
|
location = "#{@@root}/#{file}"
|
2012-12-26 22:02:16 +00:00
|
|
|
|
2016-01-31 23:48:43 +00:00
|
|
|
# rename existing file if not already the same file
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.exist?(location)
|
2016-01-31 23:48:43 +00:00
|
|
|
content_fs = _read_file(file)
|
|
|
|
if content_fs == data
|
|
|
|
logger.debug "NOTICE: file '#{location}' already exists, skip install"
|
|
|
|
return true
|
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
backup_location = location + '.save'
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: backup old file '#{location}' to #{backup_location}"
|
2016-01-21 22:25:05 +00:00
|
|
|
File.rename(location, backup_location)
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# check if directories need to be created
|
|
|
|
directories = location.split '/'
|
2015-04-27 14:41:03 +00:00
|
|
|
(0..(directories.length - 2) ).each {|position|
|
2012-12-26 22:02:16 +00:00
|
|
|
tmp_path = ''
|
|
|
|
(1..position).each {|count|
|
2016-01-21 22:25:05 +00:00
|
|
|
tmp_path = "#{tmp_path}/#{directories[count]}"
|
2012-12-26 22:02:16 +00:00
|
|
|
}
|
2015-05-07 09:04:40 +00:00
|
|
|
|
|
|
|
next if tmp_path == ''
|
|
|
|
next if File.exist?(tmp_path)
|
|
|
|
|
|
|
|
Dir.mkdir(tmp_path, 0755)
|
2012-12-26 22:02:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# install file
|
|
|
|
begin
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: install '#{location}' (#{permission})"
|
2016-01-21 22:25:05 +00:00
|
|
|
file = File.new(location, 'wb')
|
|
|
|
file.write(data)
|
2012-12-26 22:02:16 +00:00
|
|
|
file.close
|
2016-01-31 23:54:54 +00:00
|
|
|
File.chmod(permission.to_s.to_i(8), location)
|
2012-12-26 22:02:16 +00:00
|
|
|
rescue => e
|
|
|
|
raise 'ERROR: ' + e.inspect
|
|
|
|
end
|
2014-04-28 07:44:36 +00:00
|
|
|
true
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
2015-05-07 08:01:35 +00:00
|
|
|
def self._delete_file(file, _permission, _data)
|
2016-01-21 22:25:05 +00:00
|
|
|
location = "#{@@root}/#{file}"
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# install file
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: uninstall '#{location}'"
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.exist?(location)
|
|
|
|
File.delete(location)
|
2013-03-05 16:16:33 +00:00
|
|
|
end
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# rename existing file
|
|
|
|
backup_location = location + '.save'
|
2016-01-21 22:25:05 +00:00
|
|
|
if File.exist?(backup_location)
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: restore old file '#{backup_location}' to #{location}"
|
2016-01-21 22:25:05 +00:00
|
|
|
File.rename(backup_location, location)
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
2015-01-10 10:13:20 +00:00
|
|
|
true
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
class Migration < ApplicationModel
|
2015-05-08 13:47:27 +00:00
|
|
|
@@root = Rails.root.to_s # rubocop:disable Style/ClassVars
|
2012-12-26 22:02:16 +00:00
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
def self.migrate(package, direction = 'normal')
|
|
|
|
location = "#{@@root}/db/addon/#{package.underscore}"
|
2012-12-26 22:02:16 +00:00
|
|
|
|
2016-01-21 22:25:05 +00:00
|
|
|
return true if !File.exist?(location)
|
|
|
|
migrations_done = Package::Migration.where(name: package.underscore)
|
2012-12-26 22:02:16 +00:00
|
|
|
|
|
|
|
# get existing migrations
|
|
|
|
migrations_existing = []
|
|
|
|
Dir.foreach(location) {|entry|
|
|
|
|
next if entry == '.'
|
|
|
|
next if entry == '..'
|
|
|
|
migrations_existing.push entry
|
|
|
|
}
|
|
|
|
|
|
|
|
# up
|
|
|
|
migrations_existing = migrations_existing.sort
|
|
|
|
|
|
|
|
# down
|
|
|
|
if direction == 'reverse'
|
|
|
|
migrations_existing = migrations_existing.reverse
|
|
|
|
end
|
|
|
|
|
|
|
|
migrations_existing.each {|migration|
|
|
|
|
next if migration !~ /\.rb$/
|
|
|
|
version = nil
|
|
|
|
name = nil
|
|
|
|
if migration =~ /^(.+?)_(.*)\.rb$/
|
|
|
|
version = $1
|
|
|
|
name = $2
|
|
|
|
end
|
|
|
|
if !version || !name
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "Invalid package migration '#{migration}'"
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# down
|
|
|
|
if direction == 'reverse'
|
2016-01-21 22:25:05 +00:00
|
|
|
done = Package::Migration.find_by(name: package.underscore, version: version)
|
2012-12-26 22:02:16 +00:00
|
|
|
next if !done
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: down package migration '#{migration}'"
|
2012-12-26 22:02:16 +00:00
|
|
|
load "#{location}/#{migration}"
|
|
|
|
classname = name.camelcase
|
|
|
|
Kernel.const_get(classname).down
|
2016-01-21 22:25:05 +00:00
|
|
|
record = Package::Migration.find_by(name: package.underscore, version: version)
|
2012-12-26 22:02:16 +00:00
|
|
|
if record
|
|
|
|
record.destroy
|
|
|
|
end
|
|
|
|
|
2013-06-12 15:59:58 +00:00
|
|
|
# up
|
2012-12-26 22:02:16 +00:00
|
|
|
else
|
2016-01-21 22:25:05 +00:00
|
|
|
done = Package::Migration.find_by(name: package.underscore, version: version)
|
2012-12-26 22:02:16 +00:00
|
|
|
next if done
|
2014-10-26 12:17:00 +00:00
|
|
|
logger.info "NOTICE: up package migration '#{migration}'"
|
2012-12-26 22:02:16 +00:00
|
|
|
load "#{location}/#{migration}"
|
|
|
|
classname = name.camelcase
|
|
|
|
Kernel.const_get(classname).up
|
2016-01-21 22:25:05 +00:00
|
|
|
Package::Migration.create(name: package.underscore, version: version)
|
2012-12-26 22:02:16 +00:00
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2015-04-27 14:15:29 +00:00
|
|
|
end
|