$:.unshift File.dirname(__FILE__) require 'stringio' require 'file_not_found_error' module BuildMaster class InMemorySystem attr_reader :executed_commands def initialize @executed_commands = [] @content = "" @file_system = Hash.new @file_system[Pathname.new('/')] = DirectoryContent.new('/') @file_system[Pathname.new('.')] = DirectoryContent.new('.') @output_map = Hash.new end def shell(command) @executed_commands.push(command) end def shell_output(command) result = @output_map[command] raise "#{command} not found in expectation" unless result return result end def output_for_command(command, output) @output_map[command] = output end def dir_exists?(pathname) content = path_content(pathname) return !content.nil? && content.directory? end def file_exists?(pathname) content = path_content(pathname) return !content.nil? && content.file? end def list(pathname) content = path_content(pathname) return content.children.collect {|item| item.name} end def mkdir(pathname) path_content(pathname.parent).add(create_dir(pathname)) end def io(*args) file_content = retrieve_file_content(args[0], args[1]) return StringIO.new(file_content.content, *args[1, args.size - 1]) end def copy(source, target) copy_file(source, target) end def copy_file(source, target) file_content = retrieve_file_content(source, 'r').content create_file(target).content = file_content.clone end def move(source, target) move_file(source, target) end def move_file(source, target) copy(source, target) delete_file(source) end def copy_dir(source, target) mkdir(target) path_content(source).children.each do |item| item.copy_to_dir(self, source, target) end end def move_dir(source, target) copy_dir(source, target) delete_dir(source) end def delete_file(pathname) raise Errno::ENOENT.new(pathname) unless file_exists? pathname delete_entry(pathname) end def delete_dir(pathname) raise Errno::ENOENT.new(pathname) unless dir_exists? pathname delete_entry(pathname) end def to_s return 'InMemorySystem' end private def gather_paths_to_create(pathname) paths = Array.new path_to_create = pathname while (! dir_exists?(path_to_create)) paths.push(path_to_create) path_to_create = path_to_create.parent end return paths end def create_dir(pathname) content = DirectoryContent.new(pathname.basename.to_s) @file_system[pathname] = content return content end def create_file(pathname) content = FileContent.new(pathname.basename.to_s) parent_dir = pathname.parent path_content(parent_dir).add(content) @file_system[pathname] = content return content end def path_content(pathname) return @file_system[pathname] end def retrieve_file_content(pathname, options) file_content = path_content(pathname) if (file_content.nil?) if (options =~ /r/) raise Errno::ENOENT.new(pathname) end file_content = create_file(pathname) end return file_content end def delete_entry(pathname) @file_system.delete pathname @file_system[pathname.parent].delete(pathname.basename.to_s) end end class DirectoryContent attr_reader :name, :children def initialize(name) @name = name @children = Array.new end def file? return false end def directory? return true end def add(content) @children.push(content) end def delete(name) @children.delete_if {|file_content| file_content.name == name} end def copy_to_dir(system, parent_dir, target_dir) source_path = parent_dir.join(name) target_path = target_dir.join(name) system.copy_dir(source_path, target_path) end end class FileContent attr_reader :name, :content attr_writer :content def initialize(name) @name = name @content = '' end def file? return true end def directory? return false end def copy_to_dir(system, parent_dir, target_dir) target_path = target_dir.join(name) source_path = parent_dir.join(name) system.copy_file(source_path, target_path) end end end