-----------------------------------------------------------------------
-- gen-artifacts-distribs -- Artifact for distributions
-- Copyright (C) 2012, 2017, 2021 Stephane Carrez
-- Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-----------------------------------------------------------------------
with Ada.Containers.Vectors;
with Ada.Containers.Indefinite_Vectors;
with Ada.Containers.Indefinite_Ordered_Maps;
with GNAT.Regpat;
with DOM.Core;
with Gen.Model.Packages;
with Util.Log;
-- The Gen.Artifacts.Distribs package is an artifact for the generation of
-- application distributions.
--
-- 1/ The package.xml file contains a set of rules which describe how to build the distribution.
-- This file is read and distribution rules are collected in the Rules artifact.
--
-- 2/ The list of source paths to scan is obtained by looking at the GNAT project files
-- and looking at components which have a dynamo.xml configuration file.
--
-- 3/ The source paths are then scanned and a complete tree of source files is created
-- in the Trees artifact member.
--
-- 4/ The source paths are matched against the distribution rules and each distribution rule
-- is filled with the source files that they match.
--
-- 5/ The distribution rules are executed in the order defined in the package.xml file.
-- Each distribution rule can have its own way to make the distribution for the set of
-- files that matched the rule definition. A distribution rule can copy the file, another
-- can concatenate the source files, another can do some transformation on the source files
-- and prepare it for the distribution.
--
package Gen.Artifacts.Distribs is
-- ------------------------------
-- Distribution artifact
-- ------------------------------
type Artifact is new Gen.Artifacts.Artifact with private;
-- After the configuration file is read, processes the node whose root
-- is passed in Node and initializes the Model with the information.
overriding
procedure Initialize (Handler : in out Artifact;
Path : in String;
Node : in DOM.Core.Node;
Model : in out Gen.Model.Packages.Model_Definition'Class;
Context : in out Generator'Class);
-- Prepare the model after all the configuration files have been read and before
-- actually invoking the generation.
overriding
procedure Prepare (Handler : in out Artifact;
Model : in out Gen.Model.Packages.Model_Definition'Class;
Project : in out Gen.Model.Projects.Project_Definition'Class;
Context : in out Generator'Class);
private
type Directory_List;
type Directory_List_Access is access all Directory_List;
-- A File_Record refers to a source file that must be processed by a distribution
-- rule. It is linked to the directory which contains it through the Dir member.
-- The Name refers to the file name part.
type File_Record (Length : Natural) is record
Dir : Directory_List_Access;
Name : String (1 .. Length);
end record;
package File_Record_Vectors is
new Ada.Containers.Indefinite_Vectors (Index_Type => Positive,
Element_Type => File_Record);
subtype File_Vector is File_Record_Vectors.Vector;
subtype File_Cursor is File_Record_Vectors.Cursor;
-- Get the first source path from the list.
function Get_Source_Path (From : in File_Vector;
Use_First_File : in Boolean := False) return String;
-- The file tree represents the target distribution tree that must be built.
-- Each key represent a target file and it is associated with a File_Vector which
-- represents the list of source files that must be used to build the target.
package File_Tree is
new Ada.Containers.Indefinite_Ordered_Maps (Key_Type => String,
Element_Type => File_Vector,
"<" => "<",
"=" => File_Record_Vectors."=");
package Directory_List_Vector is
new Ada.Containers.Vectors (Index_Type => Positive,
Element_Type => Directory_List_Access);
-- The Directory_List describes the content of a source directory.
type Directory_List (Length : Positive;
Path_Length : Natural)
is record
Files : File_Record_Vectors.Vector;
Directories : Directory_List_Vector.Vector;
Rel_Pos : Positive := 1;
Name : String (1 .. Length);
Path : String (1 .. Path_Length);
end record;
-- Get the relative path of the directory.
function Get_Relative_Path (Dir : in Directory_List) return String;
-- Strip the base part of the path
function Get_Strip_Path (Base : in String;
Path : in String) return String;
-- Build a regular expression pattern from a pattern string.
function Make_Regexp (Pattern : in String) return String;
-- Build a regular expression pattern from a pattern string.
function Make_Regexp (Pattern : in String) return GNAT.Regpat.Pattern_Matcher;
-- Scan the directory whose root path is Path and with the relative path
-- Rel_Path and build in Dir the list of files and directories.
procedure Scan (Path : in String;
Rel_Path : in String;
Dir : in Directory_List_Access);
type Match_Rule is record
Base_Dir : UString;
Match : UString;
end record;
package Match_Rule_Vector is
new Ada.Containers.Vectors (Index_Type => Positive,
Element_Type => Match_Rule);
-- ------------------------------
-- Distribution rule
-- ------------------------------
-- The Distrib_Rule represents a distribution rule that must be executed on
-- a given file or set of files.
type Distrib_Rule is abstract tagged record
Dir : UString;
Matches : Match_Rule_Vector.Vector;
Excludes : Match_Rule_Vector.Vector;
Files : File_Tree.Map;
Level : Util.Log.Level_Type := Util.Log.DEBUG_LEVEL;
end record;
type Distrib_Rule_Access is access all Distrib_Rule'Class;
-- Get a name to qualify the installation rule (used for logs).
function Get_Install_Name (Rule : in Distrib_Rule) return String is abstract;
-- Install the file File according to the distribution rule.
procedure Install (Rule : in Distrib_Rule;
Target : in String;
File : in File_Vector;
Context : in out Generator'Class) is abstract;
-- Scan the directory tree whose root is defined by Dir and find the files
-- that match the current rule.
procedure Scan (Rule : in out Distrib_Rule;
Dir : in Directory_List);
procedure Scan (Rule : in out Distrib_Rule;
Dir : in Directory_List;
Base_Dir : in String;
Pattern : in String;
Exclude : in Boolean);
procedure Execute (Rule : in out Distrib_Rule;
Path : in String;
Context : in out Generator'Class);
-- Get the target path associate with the given source file for the distribution rule.
function Get_Target_Path (Rule : in Distrib_Rule;
Base : in String;
File : in File_Record) return String;
-- Get the source path of the file.
function Get_Source_Path (Rule : in Distrib_Rule;
File : in File_Record) return String;
-- Add the file to be processed by the distribution rule. The file has a relative
-- path represented by Path. The path is relative from the base directory
-- specified in Base_Dir.
procedure Add_Source_File (Rule : in out Distrib_Rule;
Path : in String;
File : in File_Record);
-- Remove the file to be processed by the distribution rule. This is the opposite of
-- Add_Source_File and used for the rules.
procedure Remove_Source_File (Rule : in out Distrib_Rule;
Path : in String;
File : in File_Record);
-- Create a distribution rule identified by Kind.
-- The distribution rule is configured according to the DOM tree whose node is Node.
function Create_Rule (Kind : in String;
Node : in DOM.Core.Node) return Distrib_Rule_Access;
-- A list of rules that define how to build the distribution.
package Distrib_Rule_Vectors is
new Ada.Containers.Vectors (Index_Type => Positive,
Element_Type => Distrib_Rule_Access);
type Artifact is new Gen.Artifacts.Artifact with record
Rules : Distrib_Rule_Vectors.Vector;
Trees : Directory_List_Vector.Vector;
end record;
end Gen.Artifacts.Distribs;