Skip to content

Commit

Permalink
Added the possibility to add metapackages.
Browse files Browse the repository at this point in the history
Metapackages form a type of package that serve
as a container for several packages distributed
in one project, see for example homalg.
  • Loading branch information
sebasguts committed Sep 18, 2018
1 parent 0acbad3 commit 2fe1e03
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 57 deletions.
10 changes: 10 additions & 0 deletions lib/package.gd
Expand Up @@ -159,6 +159,16 @@ DeclareGlobalFunction( "RECORDS_FILE" );
DeclareGlobalFunction( "SetPackageInfo" );


#############################################################################
##
#F AddPackageInfo( files, pkgdir, ignore, metapackages... )
##
## Adds package info records from a file list to the global list
## of info records.
##
DeclareGlobalFunction( "AddPackageInfos" );


#############################################################################
##
#F InitializePackagesInfoRecords()
Expand Down
194 changes: 137 additions & 57 deletions lib/package.gi
Expand Up @@ -168,7 +168,13 @@ InstallGlobalFunction( SetPackageInfo, function( record )
##
BindGlobal( "FindPackageInfosInSubdirectories", function( pkgdir, name )
local pkgpath, file, files, subdir;

if name in [ ".", ".." ] then
return [];
fi;

pkgpath:= Filename( [ pkgdir ], name );

# This can be 'fail' if 'name' is a void link.
if pkgpath = fail then
return [];
Expand All @@ -177,9 +183,6 @@ BindGlobal( "FindPackageInfosInSubdirectories", function( pkgdir, name )
if not IsDirectoryPath( pkgpath ) then
return [];
fi;
if name in [ ".", ".." ] then
return [];
fi;

file:= Filename( [ pkgdir ],
Concatenation( name, "/PackageInfo.g" ) );
Expand Down Expand Up @@ -207,13 +210,49 @@ BindGlobal( "FindPackageInfosInSubdirectories", function( pkgdir, name )
return files;
end );

#############################################################################
##
#F EnrichMetapackageRecord( subpackagerecord, metapackagerecord )
##

BindGlobal( "EnrichMetapackageRecord", function( subpackagerecord, metapackagerecord )
local version, name;
if not IsBound( metapackagerecord.Dependencies.NeededOtherPackages ) then
metapackagerecord.Dependencies.NeededOtherPackages := [];
fi;

name := subpackagerecord.PackageName;
version := subpackagerecord.Version;
version := Concatenation( "= ", version );

Add( metapackagerecord.Dependencies.NeededOtherPackages, [ name, version ] );

end );

#############################################################################
##
#F EnrichSubpackageRecord( subpackagerecord, metapackagerecord )
##

BindGlobal( "EnrichSubpackageRecord", function( subpackagerecord, metapackagerecord )
if not IsBound( subpackagerecord.SubpackageOf ) then
subpackagerecord.SubpackageOf := metapackagerecord.PackageName;
fi;
end );

#############################################################################
##
#F AddPackageInfo( files )
##
BindGlobal( "AddPackageInfos", function( files, pkgdir, ignore )
local file, record, pkgname, version;
InstallGlobalFunction( AddPackageInfos, function( files, pkgdir, ignore, metapackagerecord... )
local file, record, pkgname, version, is_metapackage, name;
if Length( metapackagerecord ) = 1 then
is_metapackage := true;
metapackagerecord := metapackagerecord[ 1 ];
else
is_metapackage := false;
fi;

for file in files do
# Read the `PackageInfo.g' file.
Unbind( GAPInfo.PackageInfoCurrent );
Expand Down Expand Up @@ -246,6 +285,19 @@ BindGlobal( "AddPackageInfos", function( files, pkgdir, ignore )
elif IsRecord( record.PackageDoc ) then
record.PackageDoc:= [ record.PackageDoc ];
fi;

if IsBound( record.IsMetaPackage ) and record.IsMetaPackage = true then
for name in Set( DirectoryContents( record.InstallationPath ) ) do
files := FindPackageInfosInSubdirectories( Directory( record.InstallationPath ), name );
AddPackageInfos( files, Directory( record.InstallationPath ), ignore, record );
od;
fi;

if is_metapackage then
EnrichMetapackageRecord( record, metapackagerecord );
EnrichSubpackageRecord( record, metapackagerecord );
fi;

if IsHPCGAP then
# FIXME: we make the package info record immutable, to
# allow access from multiple threads; but that in turn
Expand Down Expand Up @@ -808,17 +860,19 @@ InstallGlobalFunction( PackageAvailabilityInfo,
fi;

# Locate the `init.g' file of the package.
if Filename( [ Directory( inforec.InstallationPath ) ], "init.g" )
= fail then
LogPackageLoadingMessage( PACKAGE_WARNING,
Concatenation( "PackageAvailabilityInfo: cannot locate `",
inforec.InstallationPath,
"/init.g', please check the installation" ),
inforec.PackageName );
if not checkall then
continue;
if not IsBound( inforec.IsMetaPackage ) or inforec.IsMetaPackage = false then
if Filename( [ Directory( inforec.InstallationPath ) ], "init.g" )
= fail then
LogPackageLoadingMessage( PACKAGE_WARNING,
Concatenation( "PackageAvailabilityInfo: cannot locate `",
inforec.InstallationPath,
"/init.g', please check the installation" ),
inforec.PackageName );
if not checkall then
continue;
fi;
skip:= true;
fi;
skip:= true;
fi;

record_local:= StructuralCopy( record );
Expand Down Expand Up @@ -1622,16 +1676,18 @@ InstallGlobalFunction( LoadPackage, function( arg )
# Notify the documentation (for the available version).
LoadPackageDocumentation( info );

# Read the `init.g' files.
LogPackageLoadingMessage( PACKAGE_DEBUG,
"start reading file 'init.g'",
info.PackageName );
GAPInfo.PackageCurrent:= info;
ReadPackage( pkgname, "init.g" );
Unbind( GAPInfo.PackageCurrent );
LogPackageLoadingMessage( PACKAGE_DEBUG,
"finish reading file 'init.g'",
info.PackageName );
# Read the `init.g' files if package is not a metapackage.
if not IsBound( info.IsMetaPackage ) or info.IsMetaPackage = false then
LogPackageLoadingMessage( PACKAGE_DEBUG,
"start reading file 'init.g'",
info.PackageName );
GAPInfo.PackageCurrent:= info;
ReadPackage( pkgname, "init.g" );
Unbind( GAPInfo.PackageCurrent );
LogPackageLoadingMessage( PACKAGE_DEBUG,
"finish reading file 'init.g'",
info.PackageName );
fi;

filename:= Filename( [ Directory( info.InstallationPath ) ],
"read.g" );
Expand Down Expand Up @@ -2101,7 +2157,7 @@ InstallGlobalFunction( DeclareAutoreadableVariables,
InstallGlobalFunction( ValidatePackageInfo, function( info )
local record, pkgdir, i, IsStringList, IsRecordList, IsProperBool, IsURL,
IsFilename, IsFilenameList, result, TestOption, TestMandat, subrec,
list;
list, is_metapackage, is_subpackage;

if IsString( info ) then
if IsReadableFile( info ) then
Expand Down Expand Up @@ -2129,7 +2185,7 @@ InstallGlobalFunction( ValidatePackageInfo, function( info )
else
Error( "<info> must be either a record or a filename" );
fi;

IsStringList:= x -> IsList( x ) and ForAll( x, IsString );
IsRecordList:= x -> IsList( x ) and ForAll( x, IsRecord );
IsProperBool:= x -> x = true or x = false;
Expand Down Expand Up @@ -2160,6 +2216,22 @@ InstallGlobalFunction( ValidatePackageInfo, function( info )
fi;
return true;
end;

TestOption( record, "IsMetaPackage", IsBool, "a bool" );

if IsBound( record.IsMetaPackage ) then
is_metapackage := record.IsMetaPackage;
else
is_metapackage := false;
fi;

TestOption( record, "SubpackageOf", IsString, "a string" );

if IsBound( record.SubpackageOf ) then
is_subpackage := true;
else
is_subpackage := false;
fi;

TestMandat( record, "PackageName",
x -> IsString(x) and 0 < Length(x),
Expand All @@ -2172,21 +2244,23 @@ InstallGlobalFunction( ValidatePackageInfo, function( info )
x -> IsString(x) and Length(x) = 10 and x{ [3,6] } = "//"
and ForAll( x{ [1,2,4,5,7,8,9,10] }, IsDigitChar ),
"a string of the form `dd/mm/yyyy'" );
TestMandat( record, "ArchiveURL", IsURL, "a string started with http://, https:// or ftp://" );
TestMandat( record, "ArchiveFormats", IsString, "a string" );
TestOption( record, "TextFiles", IsStringList, "a list of strings" );
TestOption( record, "BinaryFiles", IsStringList, "a list of strings" );
TestOption( record, "TextBinaryFilesPatterns",
x -> IsStringList(x) and
ForAll( x, i -> Length(i) > 0 ) and
ForAll( x, i -> i[1] in ['T','B'] ),
"a list of strings, each started with 'T' or 'B'" );
if Number( [ IsBound(record.TextFiles),
IsBound(record.BinaryFiles),
IsBound(record.TextBinaryFilesPatterns) ],
a -> a=true ) > 1 then
Print("#W only one of TextFiles, BinaryFiles or TextBinaryFilesPatterns\n");
Print("#W components must be bound\n");
if not is_subpackage then
TestMandat( record, "ArchiveURL", IsURL, "a string started with http://, https:// or ftp://" );
TestMandat( record, "ArchiveFormats", IsString, "a string" );
TestOption( record, "TextFiles", IsStringList, "a list of strings" );
TestOption( record, "BinaryFiles", IsStringList, "a list of strings" );
TestOption( record, "TextBinaryFilesPatterns",
x -> IsStringList(x) and
ForAll( x, i -> Length(i) > 0 ) and
ForAll( x, i -> i[1] in ['T','B'] ),
"a list of strings, each started with 'T' or 'B'" );
if Number( [ IsBound(record.TextFiles),
IsBound(record.BinaryFiles),
IsBound(record.TextBinaryFilesPatterns) ],
a -> a=true ) > 1 then
Print("#W only one of TextFiles, BinaryFiles or TextBinaryFilesPatterns\n");
Print("#W components must be bound\n");
fi;
fi;
if TestOption( record, "Persons", IsRecordList, "a list of records" )
and IsBound( record.Persons ) then
Expand Down Expand Up @@ -2220,21 +2294,23 @@ InstallGlobalFunction( ValidatePackageInfo, function( info )
od;
fi;

if TestMandat( record, "Status",
x -> x in [ "accepted", "submitted", "deposited", "dev", "other" ],
"one of \"accepted\", \"deposited\", \"dev\", \"other\"" )
and record.Status = "accepted" then
TestMandat( record, "CommunicatedBy",
x -> IsString(x) and PositionSublist( x, " (" ) <> fail
and x[ Length(x) ] = ')',
"a string of the form `<name> (<place>)'" );
TestMandat( record, "AcceptDate",
x -> IsString( x ) and Length( x ) = 7 and x[3] = '/'
and ForAll( x{ [1,2,4,5,6,7] }, IsDigitChar ),
"a string of the form `mm/yyyy'" );
if not is_subpackage then
if TestMandat( record, "Status",
x -> x in [ "accepted", "submitted", "deposited", "dev", "other" ],
"one of \"accepted\", \"deposited\", \"dev\", \"other\"" )
and record.Status = "accepted" then
TestMandat( record, "CommunicatedBy",
x -> IsString(x) and PositionSublist( x, " (" ) <> fail
and x[ Length(x) ] = ')',
"a string of the form `<name> (<place>)'" );
TestMandat( record, "AcceptDate",
x -> IsString( x ) and Length( x ) = 7 and x[3] = '/'
and ForAll( x{ [1,2,4,5,6,7] }, IsDigitChar ),
"a string of the form `mm/yyyy'" );
fi;
TestMandat( record, "README_URL", IsURL, "a string started with http://, https:// or ftp://" );
TestMandat( record, "PackageInfoURL", IsURL, "a string started with http://, https:// or ftp://" );
fi;
TestMandat( record, "README_URL", IsURL, "a string started with http://, https:// or ftp://" );
TestMandat( record, "PackageInfoURL", IsURL, "a string started with http://, https:// or ftp://" );

if TestOption( record, "SourceRepository", IsRecord, "a record" ) then
if IsBound( record.SourceRepository ) then
Expand All @@ -2245,7 +2321,11 @@ InstallGlobalFunction( ValidatePackageInfo, function( info )
TestOption( record, "IssueTrackerURL", IsURL, "a string started with http://, https:// or ftp://" );
TestOption( record, "SupportEmail", IsString, "a string" );
TestMandat( record, "AbstractHTML", IsString, "a string" );
TestMandat( record, "PackageWWWHome", IsURL, "a string started with http://, https:// or ftp://" );
if is_subpackage then
TestOption( record, "PackageWWWHome", IsURL, "a string started with http://, https:// or ftp://" );
else
TestMandat( record, "PackageWWWHome", IsURL, "a string started with http://, https:// or ftp://" );
fi;
if TestMandat( record, "PackageDoc",
x -> IsRecord( x ) or IsRecordList( x ),
"a record or a list of records" ) then
Expand Down

0 comments on commit 2fe1e03

Please sign in to comment.