require 'fileutils' require 'fedux_org/stdlib/filesystem/exceptions' # helper for file system module FeduxOrg module Stdlib module Filesystem # The root directory of the project # # @return [String] # the root directory def root_directory #::File.expand_path('../../../', __FILE__) raise Exceptions::InvalidUsageOfLibrary , "Sorry, but you need to define the root directory yourself" end # The temporary directory for the project # # @return [String] # the directory created for the tests def working_directory ::File.join(root_directory, 'tmp', 'test') end # Create temporary directory def create_working_directory FileUtils.mkdir_p(working_directory) unless ::File.exists? working_directory end # Delete temporary directory def delete_working_directory FileUtils.rm_rf(working_directory) if ::File.exists? working_directory end # Clean up test directory def cleanup_working_directory delete_working_directory create_working_directory end # Switch the current working directory to # the temporary one and execute code block def switch_to_working_directory(&block) Dir.chdir(working_directory, &block) end # Create directory(ies) # # @param [String,Array] dirs # the directories to be created, multiple arguments are possible as well # # @return [String,Array] # returns a string if there was only one file given, and an array with # muliple files def create_directory(*dirs) raise_if_forbidden_path_for_create_operation(dirs) directories = expand_path(dirs.flatten) FileUtils.mkdir_p(directories) if directories.size == 1 return directories.first else return directories end end # Delete directory(ies) # # @param [String, Array] dirs # the directories to be deleted, multiple arguments are possible as well # # @return [String,Array] # returns a string if there was only one file given, and an array with # muliple files def delete_directory(*dirs) raise_if_forbidden_path_for_delete_operation(dirs) directories = expand_path(dirs.flatten) FileUtils.rm_r(directories) if directories.size == 1 return directories.first else return directories end end # Check existence of path(s) # # @param [String,Array] paths # which path(s) should be checked, multiple arguments are possible as well # # @return [TrueClass,FalseClass] # the result of all checks done def path_exists?(*paths) raise_if_forbidden_path_for_create_operation(paths) paths_expanded = expand_path(paths.flatten) paths_expanded.flatten.all? { |p| ::File.exists?(p) } end # Check absence of path(s) # # @param [String,Array] paths # which path(s) should be checked, multiple arguments are possible as well # # @return [TrueClass,FalseClass] # the result of all checks done def path_does_not_exist?(*paths) not path_exists?(paths) end # Create a single file # # @param [String] path # the path for the new file (can include directories) # # @param [String] content # the content written to the file # # @return [String] # the path to the created file def create_file(path, content='', mode=0644) raise_if_forbidden_path_for_create_operation(path) file = expand_path(path).first directory = ::File.dirname(file) FileUtils.mkdir_p(directory) unless directory == '.' ::File.open(file, "wb") do |f| f.write content end FileUtils.chmod(mode, file) file end # Delete a single file # # @param [String] files # the path for the new file (can include directories) # # @return [String] # the path to the deleted file def delete_file(*files) raise_if_forbidden_path_for_delete_operation(files) files_to_be_deleted = expand_path(files.flatten) FileUtils.rm(files_to_be_deleted) if files_to_be_deleted.size == 1 return files_to_be_deleted.first else return files_to_be_deleted end end # Read the content of a file # # @param [String] path # the path to the file # # @return [String,Binary] # the content of the file def read_file(path) raise_if_forbidden_path_for_create_operation(path) file_path = expand_path(path).first return ::File.read(file_path) end # Expand path based on temporary directory # # @param [String, Array, Multiple Values] paths # the paths to be expanded # # @return [Array, String] # the expanded arrays def expand_path(*paths) raise_if_forbidden_path_for_create_operation(paths) paths.flatten.map do |p| case p when /^~/ ::File.expand_path(p) else ::File.join(working_directory, p ) end end end # Check if path is forbidden for delete operation # # @param [String, Array] paths # paths which should be checked # # @return [TrueClass, FalseClass] # true if path is forbidden, false if path is not forbidden def raise_if_forbidden_path_for_create_operation(*paths) flattend_paths = paths.flatten strings = [] regex = %r[\.\.] raise FileSystem::Exceptions::InvalidPath , "Sorry, but you cannot use paths matching \"#{strings.join(', ')}\" or \"#{regex.to_s}\" here!" if path_matches?(strings, regex, flattend_paths) end # Check if path is forbidden for delete operation # # @param [String, Array] paths # paths which should be checked # # @return [TrueClass, FalseClass] # true if path is forbidden, false if path is not forbidden def raise_if_forbidden_path_for_delete_operation(*paths) flattend_paths = paths.flatten strings = %w[ / ] regex = %r[\.\.] raise FileSystem::Exceptions::InvalidPath , "Sorry, but you cannot use paths matching \"#{strings.join(', ')}\" or \"#{regex.to_s}\" here!" if path_matches?(strings, regex, flattend_paths) end # Check if path matches # # @param [Array, String] strings # strings which are checked against paths # # @param [Array, String] regex # regex which is checked against path # # @param [Array, String] paths # the paths to be checked # # @return [TrueClass, FalseClass] # true if path is valid, false if invalid def path_matches?(strings, regex, *paths) flattend_paths = paths.flatten flattend_strings = strings.flatten flattend_paths.any? { |f| f =~ regex or flattend_strings.include?(f) } end end end end