642 lines
19 KiB
Plaintext
642 lines
19 KiB
Plaintext
note
|
|
description: "Installation command."
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
|
|
class
|
|
ROC_INSTALL_COMMAND
|
|
|
|
inherit
|
|
ROC_COMMAND
|
|
|
|
create
|
|
make
|
|
|
|
feature -- Access
|
|
|
|
help: STRING_32
|
|
once
|
|
Result := "[--module|-m <MODULE_PATH>] [--theme <THEME_PATH>] [(--dir|-d <CMS_PATH>) | <MODULE_NAME>] [--site-dir <CMS_SITE_PATH>]"
|
|
end
|
|
|
|
feature -- Status report
|
|
|
|
is_valid (args: ARRAY [READABLE_STRING_32]): BOOLEAN
|
|
-- Is the submitted install command valid?
|
|
local
|
|
i, n: INTEGER
|
|
optional_theme: BOOLEAN
|
|
optional_module: BOOLEAN
|
|
optional_config: BOOLEAN
|
|
cms_path: BOOLEAN
|
|
do
|
|
n := args.upper
|
|
-- TODO add error reporting.
|
|
if n >= 1 and then n <= 5 then
|
|
from
|
|
i := 1
|
|
until
|
|
i > n
|
|
loop
|
|
if args [i].same_string ("-f") then
|
|
optional_config := True
|
|
elseif args [i].same_string ("--config") then
|
|
optional_config := True
|
|
elseif
|
|
args [i].same_string ("-m") or args [i].same_string ("--module")
|
|
then
|
|
optional_module := True
|
|
elseif
|
|
args [i].same_string ("--theme")
|
|
then
|
|
optional_theme := True
|
|
elseif args [i].same_string ("-d") then
|
|
cms_path := True
|
|
elseif args [i].same_string ("--dir") then
|
|
cms_path := True
|
|
end
|
|
i := i + 1
|
|
end
|
|
if optional_config then
|
|
Result := True
|
|
else
|
|
if n <= 5 then
|
|
if cms_path and optional_module then
|
|
-- valid command
|
|
Result := True
|
|
else
|
|
print ("Error check the optional argument --module|-m and --dir|-d")
|
|
end
|
|
elseif n <= 3 then
|
|
if cms_path and not optional_module then
|
|
Result := True
|
|
else
|
|
print ("Error missing value for dir")
|
|
Result := False
|
|
end
|
|
else
|
|
Result := True
|
|
end
|
|
end
|
|
else
|
|
Result := False
|
|
if n > 5 then
|
|
print ("Too many arguments")
|
|
end
|
|
if n < 1 then
|
|
print ("Too few argumetns")
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Helpers
|
|
|
|
module_name (a_path: PATH): STRING_32
|
|
do
|
|
-- FIXME: better implementation needed. Either based on "a" new module.info file, or parsing the .ecf
|
|
if attached a_path.entry as e then
|
|
Result := e.name
|
|
else
|
|
Result := a_path.name
|
|
end
|
|
end
|
|
|
|
theme_name (a_path: PATH): STRING_32
|
|
do
|
|
-- FIXME: better implementation needed. Either based on "a" new theme.info file, or parsing the .ecf
|
|
if attached a_path.entry as e then
|
|
Result := e.name
|
|
else
|
|
Result := a_path.name
|
|
end
|
|
end
|
|
|
|
feature -- Execution
|
|
|
|
execute (args: ARRAY [READABLE_STRING_32])
|
|
-- Install a module into a cms application.
|
|
-- Pattern: module_src/site/* => cms/site/modules/$module_name/*
|
|
local
|
|
l_config_path, l_site_path, l_cms_path, p: detachable PATH
|
|
l_module_source_locations, l_theme_source_locations: ARRAYED_LIST [ROC_INSTALL_COPY_PARAMETERS]
|
|
l_site_dir: DIRECTORY
|
|
l_modules_dir: DIRECTORY
|
|
l_themes_dir: DIRECTORY
|
|
l_dest_dir: DIRECTORY
|
|
l_cp_params: ROC_INSTALL_COPY_PARAMETERS
|
|
i,n: INTEGER
|
|
l_modules_count, l_themes_count, l_global_file_changes, l_errors_count: INTEGER
|
|
do
|
|
create l_module_source_locations.make (1)
|
|
create l_theme_source_locations.make (1)
|
|
from
|
|
i := 1
|
|
n := args.upper
|
|
until
|
|
i > n
|
|
loop
|
|
if attached args[i] as arg then
|
|
if
|
|
arg.same_string ("-f")
|
|
or arg.same_string ("--config")
|
|
then
|
|
i := i + 1
|
|
if i <= n then
|
|
create l_config_path.make_from_string (args[i])
|
|
end
|
|
elseif
|
|
arg.same_string ("-d")
|
|
or arg.same_string ("--dir")
|
|
then
|
|
i := i + 1
|
|
if i <= n then
|
|
create l_cms_path.make_from_string (args[i])
|
|
end
|
|
elseif
|
|
arg.same_string ("--site-dir")
|
|
then
|
|
i := i + 1
|
|
if i <= n then
|
|
create l_site_path.make_from_string (args[i])
|
|
end
|
|
elseif
|
|
arg.same_string ("-m")
|
|
or arg.same_string ("--module")
|
|
then
|
|
i := i + 1
|
|
if i <= n then
|
|
l_module_source_locations.force (create {PATH}.make_from_string (args[i]))
|
|
end
|
|
elseif
|
|
arg.same_string ("--theme")
|
|
then
|
|
i := i + 1
|
|
if i <= n then
|
|
l_theme_source_locations.force (create {PATH}.make_from_string (args[i]))
|
|
end
|
|
elseif
|
|
arg.same_string ("-v")
|
|
or arg.same_string ("--verbose")
|
|
then
|
|
is_verbose := True
|
|
end
|
|
end
|
|
i := i + 1
|
|
end
|
|
|
|
if l_config_path /= Void and then attached {CONFIG_READER} roc_configuration (l_config_path) as cfg then
|
|
if attached cfg.resolved_text_item ("location") as cfg_location then
|
|
create p.make_from_string (cfg_location)
|
|
if not p.is_absolute then
|
|
p := l_config_path.parent.extended_path (p)
|
|
end
|
|
l_cms_path := p.canonical_path
|
|
end
|
|
if l_cms_path = Void then
|
|
l_cms_path := l_config_path.parent
|
|
end
|
|
|
|
if attached cfg.resolved_text_item ("site_directory") as cfg_site_dir then
|
|
create p.make_from_string (cfg_site_dir)
|
|
if not p.is_absolute then
|
|
p := l_cms_path.extended_path (p)
|
|
end
|
|
l_site_path := p.canonical_path
|
|
end
|
|
if attached cfg.resolved_text_table_item ("modules") as tb then
|
|
across
|
|
tb as ic
|
|
loop
|
|
l_module_source_locations.extend (create {PATH}.make_from_string (ic.item))
|
|
end
|
|
elseif attached cfg.table_keys ("modules") as tb_keys then
|
|
across
|
|
tb_keys as ic
|
|
loop
|
|
if attached cfg.resolved_text_item ({STRING_32} "modules." + ic.item + ".location") as l_loc then
|
|
create p.make_from_string (l_loc)
|
|
if not p.is_absolute then
|
|
p := l_cms_path.extended_path (p)
|
|
end
|
|
create l_cp_params.make_with_location (p.canonical_path)
|
|
if attached cfg.resolved_text_item ({STRING_32} "modules." + ic.item + ".mode") as l_mode and then l_mode.is_case_insensitive_equal_general ("link") then
|
|
l_cp_params.set_link_mode (True)
|
|
end
|
|
l_module_source_locations.extend (l_cp_params)
|
|
end
|
|
end
|
|
end
|
|
if attached cfg.resolved_text_table_item ("themes") as tb then
|
|
across
|
|
tb as ic
|
|
loop
|
|
l_theme_source_locations.extend (create {PATH}.make_from_string (ic.item))
|
|
end
|
|
elseif attached cfg.table_keys ("themes") as tb_keys then
|
|
across
|
|
tb_keys as ic
|
|
loop
|
|
if attached cfg.resolved_text_item ({STRING_32} "themes." + ic.item + ".location") as l_loc then
|
|
create p.make_from_string (l_loc)
|
|
if not p.is_absolute then
|
|
p := l_cms_path.extended_path (p)
|
|
end
|
|
create l_cp_params.make_with_location (p.canonical_path)
|
|
if attached cfg.resolved_text_item ({STRING_32} "modules." + ic.item + ".mode") as l_mode and then l_mode.is_case_insensitive_equal_general ("link") then
|
|
l_cp_params.set_link_mode (True)
|
|
end
|
|
l_theme_source_locations.extend (l_cp_params)
|
|
end
|
|
end
|
|
end
|
|
elseif l_config_path /= Void then
|
|
l_errors_count := l_errors_count + 1
|
|
localized_print_error ({STRING_32} "Unable to read configuration file %"" + l_config_path.name + "%"!%N")
|
|
end
|
|
|
|
if l_cms_path = Void then
|
|
l_cms_path := Execution_environment.current_working_path.extended ("modules")
|
|
end
|
|
-- If l_site_path is not set; initialize it to $cms_path/site.
|
|
if l_site_path = Void then
|
|
l_site_path := l_cms_path.extended ("site").canonical_path
|
|
end
|
|
|
|
across
|
|
l_module_source_locations as ic
|
|
loop
|
|
if
|
|
attached ic.item as l_module_source_path and then
|
|
attached module_name (l_module_source_path.location) as l_mod_name
|
|
then
|
|
-- Install configuration files.
|
|
create l_site_dir.make_with_path (l_site_path)
|
|
if l_site_dir.exists then
|
|
l_modules_count := l_modules_count + 1
|
|
create l_modules_dir.make_with_path (l_site_path.extended ("modules"))
|
|
if not l_modules_dir.exists then
|
|
l_modules_dir.create_dir
|
|
end
|
|
|
|
create l_dest_dir.make_with_path (l_modules_dir.path.extended (l_mod_name))
|
|
if not l_dest_dir.exists then
|
|
l_dest_dir.create_dir
|
|
end
|
|
if is_verbose then
|
|
print ("Install module ")
|
|
print (l_mod_name)
|
|
print (" in %"")
|
|
print (l_dest_dir.path.name)
|
|
print ("%":%N")
|
|
end
|
|
install_module_elements (l_mod_name, l_module_source_path, l_dest_dir.path, Void)
|
|
l_global_file_changes := l_global_file_changes + files_changes_count
|
|
if is_verbose then
|
|
print (" - ")
|
|
print (directories_count.out + " director" + if directories_count > 1 then "ies" else "y" end + ", ")
|
|
print (files_count.out + " file" + if files_count > 1 then "s" else "" end)
|
|
if files_changes_count > 0 then
|
|
print (" (+" + files_changes_count.out + ")")
|
|
end
|
|
print (".%N")
|
|
elseif files_changes_count > 0 then
|
|
print ("Install module ")
|
|
print (l_mod_name)
|
|
print (" in %"")
|
|
print (l_dest_dir.path.name)
|
|
print ("%": ")
|
|
print (files_changes_count.out)
|
|
if files_changes_count = 1 then
|
|
print (" change.%N")
|
|
else
|
|
print (" changes.%N")
|
|
end
|
|
end
|
|
else
|
|
l_errors_count := l_errors_count + 1
|
|
print ({STRING_32} "The CMS Application located at " + l_cms_path.name + "does not have the site or modules folders.%N")
|
|
end
|
|
else
|
|
print ("Error: could not retrieve module name.%N")
|
|
end
|
|
end
|
|
across
|
|
l_theme_source_locations as ic
|
|
loop
|
|
if
|
|
attached ic.item as l_theme_source_path and then
|
|
attached theme_name (l_theme_source_path.location) as l_theme_name
|
|
then
|
|
-- Install configuration files.
|
|
create l_site_dir.make_with_path (l_site_path)
|
|
if l_site_dir.exists then
|
|
l_themes_count := l_themes_count + 1
|
|
create l_themes_dir.make_with_path (l_site_path.extended ("themes"))
|
|
if not l_themes_dir.exists then
|
|
l_themes_dir.create_dir
|
|
end
|
|
|
|
create l_dest_dir.make_with_path (l_themes_dir.path.extended (l_theme_name))
|
|
if not l_dest_dir.exists then
|
|
l_dest_dir.create_dir
|
|
end
|
|
if is_verbose then
|
|
print ("Install theme ")
|
|
print (l_theme_name)
|
|
print (" in %"")
|
|
print (l_dest_dir.path.name)
|
|
print ("%":%N")
|
|
end
|
|
install_theme_elements (l_theme_source_path, l_dest_dir.path, Void)
|
|
l_global_file_changes := l_global_file_changes + files_changes_count
|
|
if is_verbose then
|
|
print (" - ")
|
|
print (directories_count.out + " director" + if directories_count > 1 then "ies" else "y" end + ", ")
|
|
print (files_count.out + " file" + if files_count > 1 then "s" else "" end)
|
|
if files_changes_count > 0 then
|
|
print (" (+" + files_changes_count.out + ")")
|
|
end
|
|
print (".%N")
|
|
elseif files_changes_count > 0 then
|
|
print ("Install theme ")
|
|
print (l_theme_name)
|
|
print (" in %"")
|
|
print (l_dest_dir.path.name)
|
|
print ("%": ")
|
|
print (files_changes_count.out)
|
|
if files_changes_count = 1 then
|
|
print (" change.%N")
|
|
else
|
|
print (" changes.%N")
|
|
end
|
|
end
|
|
else
|
|
l_errors_count := l_errors_count + 1
|
|
print ({STRING_32} "The CMS Application located at " + l_cms_path.name + "does not have the site or themes folders.%N")
|
|
end
|
|
else
|
|
l_errors_count := l_errors_count + 1
|
|
print ("Error: could not retrieve theme name.%N")
|
|
end
|
|
end
|
|
if l_modules_count > 0 then
|
|
if l_modules_count = 1 then
|
|
print ("One module updated.%N")
|
|
else
|
|
print (l_modules_count.out + " modules updated.%N")
|
|
end
|
|
end
|
|
if l_themes_count > 0 then
|
|
if l_themes_count = 1 then
|
|
print ("One theme updated.%N")
|
|
else
|
|
print (l_themes_count.out + " themes updated.%N")
|
|
end
|
|
end
|
|
if l_global_file_changes > 0 then
|
|
if l_global_file_changes = 1 then
|
|
print ("One file updated.%N")
|
|
else
|
|
print (l_global_file_changes.out + " files updated.%N")
|
|
end
|
|
else
|
|
print ("No file updated.%N")
|
|
end
|
|
if l_errors_count > 0 then
|
|
print (l_errors_count.out + " errors.%N")
|
|
end
|
|
end
|
|
|
|
roc_configuration (a_cfg_location: PATH): detachable CONFIG_READER
|
|
do
|
|
create {JSON_CONFIG} Result.make_from_file (a_cfg_location)
|
|
if Result.has_error then
|
|
Result := Void
|
|
end
|
|
end
|
|
|
|
ecf_location (a_module_name: READABLE_STRING_GENERAL; a_module_source_path: ROC_INSTALL_COPY_PARAMETERS): detachable PATH
|
|
-- ecf location if exists.
|
|
-- Try to find based on `a_module_name`, or dir name from `a_module_source_path`, or .. search unique .ecf file (ignoring -safe.ecf).
|
|
local
|
|
l_name: READABLE_STRING_GENERAL
|
|
p: PATH
|
|
ut: FILE_UTILITIES
|
|
do
|
|
p := a_module_source_path.location
|
|
Result := p.extended (a_module_name).appended_with_extension ("ecf")
|
|
if ut.file_path_exists (Result) then
|
|
-- Found.
|
|
else
|
|
Result := Void
|
|
if attached p.entry as e then
|
|
Result := p.extended (e.name).appended_with_extension ("ecf")
|
|
if not ut.file_path_exists (Result) then
|
|
Result := Void
|
|
end
|
|
end
|
|
if Result = Void then
|
|
if attached ut.file_names (p.name) as l_filenames then
|
|
across
|
|
l_filenames as ic
|
|
until
|
|
Result /= Void
|
|
loop
|
|
l_name := ic.item
|
|
if l_name.ends_with (".ecf") then
|
|
if l_name.ends_with ("-safe.ecf") then
|
|
-- Ignore
|
|
else
|
|
Result := p.extended (l_name)
|
|
if not ut.file_path_exists (Result) then
|
|
check existing_file: False end
|
|
Result := Void
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
install_module_elements (a_module_name: READABLE_STRING_GENERAL; a_module_source_path: ROC_INSTALL_COPY_PARAMETERS; a_cms_module_target_path: PATH; a_element: detachable READABLE_STRING_GENERAL)
|
|
-- Install module site files from `a_module_source_path' to cms application `a_cms_module_target_path' under expected modules folder.
|
|
-- If `a_element' is set, take into account only sub folder `a_element'.
|
|
local
|
|
l_path: PATH
|
|
l_dest_dir: DIRECTORY
|
|
l_src_dir: DIRECTORY
|
|
do
|
|
l_path := a_module_source_path.location.extended ("site")
|
|
if a_element /= Void then
|
|
-- Copy all files under "site/$a_element" into "site/modules/$module_name/$a_element" location.
|
|
create l_src_dir.make_with_path (l_path.extended (a_element))
|
|
create l_dest_dir.make_with_path (a_cms_module_target_path.extended (a_element))
|
|
else
|
|
-- Copy all files under "site" into "site/modules/$module_name/" location.
|
|
create l_src_dir.make_with_path (l_path)
|
|
create l_dest_dir.make_with_path (a_cms_module_target_path)
|
|
end
|
|
if not l_dest_dir.exists then
|
|
l_dest_dir.create_dir
|
|
end
|
|
files_count := 0
|
|
directories_count := -1
|
|
files_changes_count := 0
|
|
|
|
if a_module_source_path.is_link_mode then
|
|
copy_directory (l_src_dir, l_dest_dir, True)
|
|
else
|
|
link_directory (l_src_dir, l_dest_dir, True)
|
|
end
|
|
-- Detect ecf file (in the future, update main ecf file).
|
|
if attached ecf_location (a_module_name, a_module_source_path) as l_ecf_loc then
|
|
-- Found ecf file.
|
|
elseif not a_module_name.is_case_insensitive_equal ("core") then
|
|
localized_print_error ({STRING_32} "Missing .ecf file for " + a_module_name + "!%N")
|
|
end
|
|
end
|
|
|
|
install_theme_elements (a_theme_source_path: ROC_INSTALL_COPY_PARAMETERS; a_cms_theme_target_path: PATH; a_element: detachable READABLE_STRING_GENERAL)
|
|
-- Install theme site files from `a_theme_source_path' to cms application `a_cms_theme_target_path' under expected "themes" folder.
|
|
-- If `a_element' is set, take into account only sub folder `a_element'.
|
|
local
|
|
l_path: PATH
|
|
l_dest_dir: DIRECTORY
|
|
l_src_dir: DIRECTORY
|
|
do
|
|
l_path := a_theme_source_path.location
|
|
if a_element /= Void then
|
|
-- Copy all files under "site/$a_element" into "site/themes/$theme_name/$a_element" location.
|
|
create l_src_dir.make_with_path (l_path.extended (a_element))
|
|
create l_dest_dir.make_with_path (a_cms_theme_target_path.extended (a_element))
|
|
else
|
|
-- Copy all files under "site" into "site/themes/$theme_name/" location.
|
|
create l_src_dir.make_with_path (l_path)
|
|
create l_dest_dir.make_with_path (a_cms_theme_target_path)
|
|
end
|
|
if not l_dest_dir.exists then
|
|
l_dest_dir.create_dir
|
|
end
|
|
files_count := 0
|
|
directories_count := -1
|
|
files_changes_count := 0
|
|
|
|
if a_theme_source_path.is_link_mode then
|
|
copy_directory (l_src_dir, l_dest_dir, True)
|
|
else
|
|
link_directory (l_src_dir, l_dest_dir, True)
|
|
end
|
|
end
|
|
|
|
is_verbose: BOOLEAN
|
|
|
|
files_count: INTEGER
|
|
-- Number of copied files during installation.
|
|
|
|
files_changes_count: INTEGER
|
|
-- Number of files changed during installation.
|
|
|
|
directories_count: INTEGER
|
|
-- Number of copied directories during installation.
|
|
|
|
|
|
feature {NONE} -- System/copy files
|
|
|
|
copy_directory (a_src: DIRECTORY; a_dest: DIRECTORY; is_recursive: BOOLEAN)
|
|
-- Copy all elements from `a_src' to `a_dest'.
|
|
local
|
|
l_dir: DIRECTORY
|
|
l_new_dir: DIRECTORY
|
|
entry: PATH
|
|
l_path: PATH
|
|
l_file: FILE
|
|
ut: FILE_UTILITIES
|
|
do
|
|
directories_count := directories_count + 1
|
|
across
|
|
a_src.entries as ic
|
|
loop
|
|
entry := ic.item
|
|
if not (entry.is_current_symbol or else entry.is_parent_symbol) then
|
|
l_path := a_src.path.extended_path (entry)
|
|
create {RAW_FILE} l_file.make_with_path (l_path)
|
|
if not l_file.is_directory then
|
|
copy_file_in_directory (l_file, a_dest.path)
|
|
elseif is_recursive then
|
|
create l_dir.make_with_path (l_path)
|
|
create l_new_dir.make_with_path (a_dest.path.extended_path (entry))
|
|
ut.create_directory_path (l_new_dir.path)
|
|
if l_dir.exists then
|
|
copy_directory (l_dir, l_new_dir, is_recursive)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
link_directory (a_src: DIRECTORY; a_dest: DIRECTORY; is_recursive: BOOLEAN)
|
|
-- Link all elements from `a_src' to `a_dest'.
|
|
do
|
|
-- TODO: implement symbolic link ...
|
|
copy_directory (a_src, a_dest, is_recursive)
|
|
end
|
|
|
|
copy_file_in_directory (a_file: FILE; a_dir: PATH)
|
|
-- Copy file `a_file' to dir `a_dir'.
|
|
local
|
|
retried: BOOLEAN
|
|
l_dest: RAW_FILE
|
|
do
|
|
if not retried then
|
|
if attached a_file.path.entry as e then
|
|
a_file.open_read
|
|
-- Copy file source to destination
|
|
if
|
|
a_file.exists and then
|
|
a_file.is_access_readable
|
|
then
|
|
create l_dest.make_with_path (a_dir.extended_path (e))
|
|
if
|
|
not l_dest.exists or else
|
|
l_dest.is_writable
|
|
then
|
|
if not l_dest.exists or else (a_file.date > l_dest.date) then
|
|
files_changes_count := files_changes_count + 1
|
|
if is_verbose then
|
|
print ({STRING_32} " - file %"" + l_dest.path.name + "%"%N")
|
|
end
|
|
end
|
|
|
|
l_dest.create_read_write
|
|
a_file.copy_to (l_dest)
|
|
a_file.close
|
|
l_dest.close
|
|
files_count := files_count + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
rescue
|
|
retried := True
|
|
retry
|
|
end
|
|
|
|
--feature -- Constants
|
|
|
|
-- Config_dir: STRING = "config"
|
|
-- -- Configuration dir.
|
|
|
|
-- Scripts_dir: STRING = "scripts"
|
|
-- -- Scripts dir.
|
|
|
|
-- Themes_dir: STRING = "themes"
|
|
-- -- Themes dir.
|
|
|
|
|
|
note
|
|
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
|
end
|