4.2.28. GNATCOLL.OS.Dir

package GNATCOLL.OS.Dir is

   package UTF8 renames Ada.Strings.UTF_Encoding;
   package Stat renames GNATCOLL.OS.Stat;

   type Dir_Handle is private;
   --  Handle on a directory

   type Dir_Entry is private;
   --  Directory entry

   function Open (Path : UTF8.UTF_8_String) return Dir_Handle;
   --  Open a directory at path Path. In case of error OS_Error exception is
   --  raised.

   procedure Close (Handle : in out Dir_Handle);
   --  Close a directory. In case of error OS_Error is raised.

   function Is_Opened (Handle : Dir_Handle) return Boolean;
   --  Return True of the handle is opened.

   function Read
      (Handle          : Dir_Handle;
       Follow_Symlinks : Boolean := True)
      return Dir_Entry;
   --  Read next entry in directory Handle. In case of error OS_Error is
   --  raised. When reaching the end of the entry list a special Dir_Entry E
   --  is returned for which End_Of_Iteration (E) is True. If Follow_Symlinks
   --  is set to True, the stat information stored is the Dir_Entry is the
   --  stat information of the file targeted by the link. Otherwise the stat
   --  information of the link itself is returned.

   function Path (Handle : Dir_Handle) return UTF8.UTF_8_String;
   --  Returned path associated with the handle. If Handle is not opened then
   --  OS_Error is raised.

   function End_Of_Iteration (Self : Dir_Entry) return Boolean;
   --  Return True if the entry represent the end of the iteration. Note that
   --  the entry for which En_Of_Iteration returns True is not a valid entry.
   --  (no name and no attributes are set).

   function Name (Self : Dir_Entry) return UTF8.UTF_8_String;
   --  Return the filename for Self (note that this is just the basename)

   function Path (Dir : Dir_Handle; Self : Dir_Entry) return UTF8.UTF_8_String;
   --  Return the full path for a given entry

   function Attributes (Self : Dir_Entry) return Stat.File_Attributes;
   --  Return the file attributes for Self

   function Is_File (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a regular file

   function Is_Directory (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a directory

   function Is_Symbolic_Link (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a symbolic link

   function Is_Executable (Self : Dir_Entry) return Boolean;
   --  Return True if the file is executable

   function Is_Readable (Self : Dir_Entry) return Boolean;
   --  Return True if the file is readable

   function Is_Writable (Self : Dir_Entry) return Boolean;
   --  Return True if the file is writable

   function Is_Executable_File (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a regular file and is executable

   function Modification_Time (Self : Dir_Entry) return Time;
   --  Return file modification time

   type Process_File is access
      procedure (Dir : Dir_Handle; Element : Dir_Entry);
   --  Function called on each file except directories found by Walk

   type Process_Directory is access
      function (Dir : Dir_Handle; Element : Dir_Entry) return Boolean;
   --  Function called on each directory found by Walk. If the handler returns
   --  True then the directory is also explored. If False then the directory
   --  is skipped.

   type Exit_Directory is access
      procedure (Dir : Dir_Handle);
   --  Function called on each directory found by Walk once the directory has
   --  been explored. Note that the Dir_Handle passed to Exit_Directory is
   --  closed and thus only the path is relevant.

   type Walk_Error is (OPEN_DIR_ERROR, OTHER_ERROR);

   type Process_Error is access
      procedure (Dir     : Dir_Handle;
                 Element : Dir_Entry;
                 Error   : Walk_Error;
                 Msg     : String);
   --  Function called in case an error occurs during a call to walk

   procedure Raise_Exception_On_Error
      (Dir     : Dir_Handle;
       Element : Dir_Entry;
       Error   : Walk_Error;
       Msg     : String);
   --  Raise exception in case of error

   Ignore         : constant Process_Error := null;
   Raise_OS_Error : constant Process_Error := Raise_Exception_On_Error'Access;

   procedure Walk
      (Path                 : UTF8.UTF_8_String;
       File_Handler         : Process_File;
       Dir_Handler          : Process_Directory := null;
       Max_Depth            : Positive          := 256;
       On_Error             : Process_Error     := Ignore;
       Follow_Symlinks      : Boolean           := False;
       Propagate_Exceptions : Boolean           := False;
       Exit_Dir_Handler     : Exit_Directory    := null);
   --  Explore recursively a directory Path. For each entry found, call
   --  Dir_Handler if the entry is a directory and File_Handler otherwise.
   --  if a call to Dir_Handler returns True then Walk explores that
   --  subdirectory. Otherwise the subdirectory is skipped. Note that if a null
   --  Dir_Handler is passed then Walk behaves as if Dir_Handler always returns
   --  True (and thus explore all subdirectories).
   --
   --  Max_Depth limits the depth of the exploration. For example a Max_Depth
   --  of 1 is equivalent to a non recursive call as it returns only direct
   --  entries of Path.
   --
   --  On_Error handler is called on each error during the exploration of Path.
   --  Two default handlers are already implemented: Ignore and Raise_OS_Error.
   --
   --  If Follow_Symlinks is True, each time a symbolic link is encountered the
   --  target of the link is returned. If False, the link itself is returned.
   --  Note that setting Follow_Symlink to True might lead in theory to
   --  infinite loop. In our case the Max_Depth parameter provides a limit.
   --
   --  If Propagate_Exceptions is True, exceptions raised during the dir and
   --  file handler are propagated to the caller.

end GNATCOLL.OS.Dir;