indexing
	cluster: "demangler"
	namespace: "candidate"
	description: "Software representation of file system tree."
	original_author: "Justin Finnerty"
	original_date: "July 2005"
	current_date: "$Date: 2005/10/31 07:18:05 $"
	current_author: "$Author: finnerty $"
	revision: "$Revision: 2.8 $"	
	-- $Log: local_directory.ge,v $
	-- Revision 2.8  2005/10/31 07:18:05  finnerty
	-- Added ability to create symlinks between directories as an alternative to merging. The major changes are in DIRDUP_REPORT with others adding/changing features as required.
	--
	-- Revision 2.7  2005/10/30 03:40:59  finnerty
	-- Split REPORT_VIEW into REPORT_CONTROL and REPORT_VIEW. Made changes to other classes as necessary
	--
	-- Revision 2.6  2005/10/28 11:45:49  finnerty
	-- Removed unused variables left over during development of previous version
	--
	-- Revision 2.5  2005/10/28 04:57:37  finnerty
	-- Improved handling of store directory naming so that ".", ".." "test." and "test/" now get handled smoothly.
	--
	-- Revision 2.4  2005/09/30 06:48:16  finnerty
	-- Finalised for alpha release with SE and VE compilers
	--
	-- Revision 2.3  2005/09/28 13:42:02  finnerty
	-- Updated to work with ISE (handling strings to/from C)
	--
	-- Revision 2.2  2005/09/27 06:07:52  finnerty
	-- Updated to use GOBO and work with SE and VE
	--
	-- Revision 2.1  2005/09/06 23:00:30  finnerty
	-- Renamed *.e to *.ge for gepp
	--
	-- Revision 2.1  2005/09/02 07:32:12  finnerty
	-- Moved some features up to parent class
	--
	-- Revision 2.0  2005/08/26 23:18:23  finnerty
	-- == alpha version ==
	--
	-- Revision 1.1  2005/08/21 11:58:31  finnerty
	-- Alpha 1 version
	--
	--

class LOCAL_DIRECTORY
	-- Software representation of a local file system tree.

inherit
	SYNCHRONISED_DIRECTORY
#ifdef SE
	insert
#endif
	DT_SHARED_SYSTEM_CLOCK
	KL_SHARED_STANDARD_FILES
	KL_SHARED_FILE_SYSTEM
	
creation {ANY}
	make

feature {ANY}
	-- Manipulate the file system
	does_path_exist (a_parent_path, a_name: STRING): BOOLEAN is
			-- Is there a real file?
		local
			l_path: STRING
		do
			if a_name = Void or else a_name.is_empty then
				l_path := a_parent_path
			else
				l_path := file_system.pathname (a_parent_path, a_name)
			end
			if file_system.file_exists (l_path) then
				Result := True
			else
				if file_system.directory_exists (l_path) then
					Result := True
				end
			end
		end

	is_name_valid (a_parent_path, a_name: STRING): BOOLEAN is
			-- Can we combine the two to get a valid filename?
		local
			l_path: STRING
		do
			if a_name = Void or else a_name.is_empty then
				l_path := a_parent_path
			else
				l_path := file_system.pathname (a_parent_path, a_name)
			end
			if file_system.is_relative_pathname (l_path) then
				Result := True
			elseif file_system.is_absolute_pathname (l_path) then
				Result := True
			end
		end

	remove_empty_trash_directory is
			-- If the trash directory is empty, delete the real trash 
			-- directory.
		do
			file_system.delete_directory (to_delete_base.path)
			if file_system.directory_exists (to_delete_base.path) then
				std.output.put_string ("Error deleting unused trash directory: " + to_delete_base.path)
				std.output.put_new_line
			end
		end

	rename_to (a_parent_path, a_name, a_new_name: STRING) is
			-- Rename a file system object `an_name' in directory
			-- `a_parent_path' to `an_new_name'.
		local
			l_old_path, l_new_path: STRING
#ifdef ISE
			l_old_path_c, l_new_path_c: C_STRING
#endif
		do
			l_old_path := file_system.pathname (a_parent_path, a_name)
			l_new_path := file_system.pathname (a_parent_path, a_new_name)
			log_rename_to (a_parent_path, a_name, a_new_name)
			-- file_system.rename_file (l_old_path, l_new_path)
#ifdef ISE
			!!l_old_path_c.make (l_old_path)
			!!l_new_path_c.make (l_new_path)
			if -1 = move_file (l_old_path_c.item, l_new_path_c.item) then
#else
			if -1 = move_file (l_old_path.to_external, l_new_path.to_external) then
#endif
				print ("Unable to rename " + l_old_path + " to " + l_new_path + "%N")
			end
		end

	move_to (an_old_path, a_new_path: STRING) is
			-- Move file system object to new path; Assumes real change
			-- in parent path.
#ifdef ISE
		local
			l_old_path, l_new_path: C_STRING
#endif
		do
			log_move_to (an_old_path, a_new_path)
			-- file_system.rename_file (an_old_path, a_new_path)
#ifdef ISE
			!!l_old_path.make (an_old_path)
			!!l_new_path.make (a_new_path)
			if -1 = move_file (l_old_path.item, l_new_path.item) then
#else
			if -1 = move_file (an_old_path.to_external, a_new_path.to_external) then
#endif
				print ("Unable to rename " + an_old_path + " to " + a_new_path + "%N")
			end
		end

	symlink_to (a_from_path, a_to_path: STRING) is
			-- Create file system symlink; Assumes real change
			-- in parent path. `a_to_path' is the target.
#ifdef ISE
		local
			l_to_path, l_from_path: C_STRING
#endif
		do
			log_symlink_to (a_from_path, a_to_path)
#ifdef ISE
			!!l_to_path.make (a_to_path)
			!!l_from_path.make (a_from_path)
			if -1 = symlink_file (l_to_path.item, l_from_path.item) then
#else
			if -1 = symlink_file (a_to_path.to_external, a_from_path.to_external) then
#endif
				print ("Unable to create symlink " + a_from_path + " pointing to " + a_to_path + "%N")
			end
		end

	unlink_to (a_from_path, a_to_path: STRING) is
			-- Remove file system symlink object; Assumes real change
			-- in parent path.
#ifdef ISE
		local
			l_from_path: C_STRING
#endif
		do
			log_unlink_to (a_from_path, a_to_path)
#ifdef ISE
			!!l_from_path.make (a_from_path)
			if -1 = unlink_file (l_from_path.item) then
#else
			if -1 = unlink_file (a_from_path.to_external) then
#endif
				print ("Unable to create unlink " + a_from_path + "%N")
			end
		end

feature {NONE}
	-- Extra C methods
	move_file (an_old_path, a_new_path: POINTER): INTEGER is
			-- External C routines (Return value unreport = BUG!!)
		external
#ifdef SE || ISE
			"[
			 C use <stdio.h>
			 ]"
#else
			 "C"
#endif
		alias "rename" end

	symlink_file (a_to_path, a_from_path: POINTER): INTEGER is
			-- External C routines (Return value unreport = BUG!!)
		external
#ifdef SE || ISE
			"[
			 C use <unistd.h>
			 ]"
#else
			 "C"
#endif
		alias "symlink" end

	unlink_file (a_path: POINTER): INTEGER is
			-- External C routines (Return value unreport = BUG!!)
		external
#ifdef SE || ISE
			"[
			 C use <unistd.h>
			 ]"
#else
			 "C"
#endif
		alias "unlink" end

feature {NONE}
	-- Creation method, only usable during creation
	make (a_name: STRING; a_peer: BOOLEAN) is
			-- Construct software representation of file system tree.
		require
			String_not_empty: a_name /= Void and not a_name.is_empty
			Valid_path: file_system.is_directory_readable (a_name)
			-- Is_void: all links are at default setting
		local
			l_factory: FACTORY_FOR_FSO
			l_time: DT_DATE_TIME
			l_datetime: INTEGER
			l_datestamp: STRING
			l_name: STRING
#ifndef HAS_AGENT
			l_strategy: SD_BUILD_NAMELIST
#endif			
		do
			-- Initialise base class
			initialise (a_peer)

			-- print ("Directory = " + a_name + "%N")
			-- Create a TEST_FSO object and use it to virtualise 
			-- directories specified on the command line or the "/etc" 
			-- directory. This implementation will change as the class 
			-- is developed.
			
			!!l_factory
			!!l_name.make_from_string (a_name)
			!!m_controller
			l_time := system_clock.date_time_now
			l_datetime := l_time.year * 10000 + l_time.month * 100 + l_time.day
			l_datestamp := l_datetime.out
			l_datetime := l_time.hour * 10000 + l_time.minute * 100 + l_time.second
			if l_time.hour < 10 then
				l_datestamp.append_string ("0")
			end
			l_datestamp.append_string (l_datetime.out)
			-- print ("Backup Directory = " + a_name + "." + l_datestamp + 
			-- "%N")
			
			-- Change "a_name" for the following cases.
			if l_name.is_equal (".") then
				l_name := file_system.current_working_directory
			end
			if l_name.is_equal ("..") then
				l_name := file_system.dirname( file_system.current_working_directory)
			end
			if l_name.item (l_name.count) = '.' then
				l_name.remove_tail (1)
			end
			if l_name.item (l_name.count) = '/' then
				l_name.remove_tail (1)
			end
			print ("Directory = " + l_name + "%N")
			-- Attempt to create directory for deleted FSOs
			if	not does_path_exist (l_name + "." + l_datestamp, Void) then			
				file_system.create_directory (l_name + "." + l_datestamp)			
				if not file_system.is_directory_readable (l_name + "." + l_datestamp) then
					-- throw error: Unable to create directory
					print ("Unable to create backup directory: " + l_name + "." + l_datestamp + "%N")
				end
			end
			to_delete_base := l_factory.virtualise_file_system (l_name + "." + l_datestamp)
			-- Process the main directory
#ifdef HAS_AGENT
			l_factory.set_strategy(agent build_namelist)
#else
			!!l_strategy.make (Current)
			l_factory.set_strategy(l_strategy)
#endif
         root := l_factory.virtualise_file_system (l_name)
         if root /= Void then
				-- start log
				log_start ("LOG."+ l_datestamp)
			end
		end
end -- class LOCAL_DIRECTORY
