------------------------------------------------------------------------------ -- -- -- GPR2 PROJECT MANAGER -- -- -- -- Copyright (C) 2019-2024, AdaCore -- -- -- -- This is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- -- ware Foundation; either version 3, or (at your option) any later ver- -- -- sion. This software is distributed in the hope that it will be useful, -- -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -- -- License for more details. You should have received a copy of the GNU -- -- General Public License distributed with GNAT; see file COPYING. If not, -- -- see . -- -- -- ------------------------------------------------------------------------------ with Ada.Containers.Indefinite_Hashed_Maps; with Ada.Directories; with Ada.Strings.Hash; with GNATCOLL.OS.Dir; package body GPRinstall is use GNATCOLL.OS.Dir; use GNAT.OS_Lib; Delete_Dir : Boolean := True; package P_Directory_Map is new Ada.Containers.Indefinite_Hashed_Maps (String, Boolean, Ada.Strings.Hash, "="); Directory_Map : P_Directory_Map.Map; procedure Delete_Directory (Root_Dir, Dir : String); -- Deletes Dir if it is empty -- If so, recursively calls Delete_Directory on containing directories -- until it cannot delete (not empty) or it reaches Root_Dir. function Process_Dir (Dir : Dir_Handle; Element : Dir_Entry) return Boolean; -- Used by GNATCOLL.OS.Dir.Walk. It detects Dir contains a directory and -- tags it not to be deleted. procedure Process_File (Dir : Dir_Handle; Element : Dir_Entry); -- Used by GNATCOLL.OS.Dir.Walk. It detects Dir contains a file and -- tags it not to be deleted. ---------------------- -- Delete_Directory -- ---------------------- procedure Delete_Directory (Root_Dir, Dir : String) is begin Delete_Dir := True; -- Walk in the directory so detect if it is empty Walk (Path => Dir, File_Handler => Process_File'Access, Dir_Handler => Process_Dir'Access, Max_Depth => 1); if Delete_Dir then Ada.Directories.Delete_Directory (Directory => Dir); -- if the Map contained the element, tag it "deleted" so we won't -- try to delete it again. if Directory_Map.Contains (Dir) then Directory_Map.Replace (Key => Dir, New_Item => True); end if; -- Recursively call Delete_Directory until we can't delete the dir -- (not empty) or we reach Root_Dir. if Dir /= Root_Dir then Delete_Directory (Root_Dir => Root_Dir, Dir => Ada.Directories.Containing_Directory (Dir)); end if; end if; end Delete_Directory; --------------------------------- -- Delete_Registered_Directory -- --------------------------------- procedure Delete_Registered_Directory (Root_Dir : String) is N_Root_Dir : constant String := Normalize_Pathname (Root_Dir); procedure Delete (Position : P_Directory_Map.Cursor); procedure Delete (Position : P_Directory_Map.Cursor) is Dir : constant String := P_Directory_Map.Key (Position => Position); Deleted : constant Boolean := P_Directory_Map.Element (Position => Position); begin -- Only call Delete_Directory if the element was not already -- deleted by a previous Delete_Directory recursive call. if not Deleted then Delete_Directory (Root_Dir => N_Root_Dir, Dir => Dir); end if; end Delete; begin -- Iteratively delete all registered directories Directory_Map.Iterate (Process => Delete'Access); end Delete_Registered_Directory; ----------------- -- Process_Dir -- ----------------- function Process_Dir (Dir : Dir_Handle; Element : Dir_Entry) return Boolean is pragma Unreferenced (Dir, Element); begin Delete_Dir := False; return False; end Process_Dir; ------------------ -- Process_File -- ------------------ procedure Process_File (Dir : Dir_Handle; Element : Dir_Entry) is pragma Unreferenced (Dir, Element); begin Delete_Dir := False; end Process_File; ------------------------ -- Register_Directory -- ------------------------ procedure Register_Directory (Dir : String) is N_Dir : constant String := Normalize_Pathname (Dir); begin -- Only cache the directory if the map does not already contains the -- element and if the directory actually exists. if not Directory_Map.Contains (N_Dir) and then Is_Directory (N_Dir) then Directory_Map.Insert (Key => N_Dir, New_Item => False); end if; end Register_Directory; end GPRinstall;