Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions lib/package.gi
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ InstallGlobalFunction( InitializePackagesInfoRecords, function( arg )
# the first time this is called, add the cmd line args to the list
if IsEmpty(GAPInfo.PackageDirectories) then
for pkgdirstrs in GAPInfo.CommandLineOptions.packagedirs do
pkgdirs:= List( SplitString( pkgdirstrs, ";" ), Directory );
pkgdirs:= List( List( SplitString( pkgdirstrs, ";" ), GAP_realpath ), Directory );
for pkgdir in pkgdirs do
if not pkgdir in GAPInfo.PackageDirectories then
Add( GAPInfo.PackageDirectories, pkgdir );
Expand Down Expand Up @@ -1858,14 +1858,15 @@ InstallGlobalFunction( SetPackagePath, function( pkgname, pkgpath )
InstallGlobalFunction( ExtendRootDirectories, function( rootpaths )
local i;

rootpaths:= List( rootpaths, GAP_realpath );
# 'DirectoriesLibrary' concatenates root paths with directory names.
for i in [ 1 .. Length( rootpaths ) ] do
if not EndsWith( rootpaths[i], "/" ) then
rootpaths[i]:= Concatenation( rootpaths[i], "/" );
fi;
od;
rootpaths:= Filtered( rootpaths, path -> not path in GAPInfo.RootPaths );
if not IsEmpty( rootpaths ) then
# 'DirectoriesLibrary' concatenates root paths with directory names.
for i in [ 1 .. Length( rootpaths ) ] do
if not EndsWith( rootpaths[i], "/" ) then
rootpaths[i]:= Concatenation( rootpaths[i], "/" );
fi;
od;
# Append the new root paths.
GAPInfo.RootPaths:= Immutable( Concatenation( GAPInfo.RootPaths,
rootpaths ) );
Expand All @@ -1889,11 +1890,12 @@ InstallGlobalFunction( ExtendPackageDirectories, function( paths_or_dirs )
local p, changed;
changed:= false;
for p in paths_or_dirs do
if IsString( p ) then
p:= Directory( p );
elif not IsDirectory( p ) then
if IsDirectory( p ) then
p:= Filename( p, "" );
elif not IsString( p ) then
Error("input must be a list of path strings or directory objects");
fi;
p:= Directory( GAP_realpath( p ) );
if not p in GAPInfo.PackageDirectories then
Add( GAPInfo.PackageDirectories, p );
changed:= true;
Expand Down
6 changes: 1 addition & 5 deletions src/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -1163,11 +1163,7 @@ static Obj FuncGAP_realpath(Obj self, Obj path)
RequireStringRep(SELF_NAME, path);
char resolved_path[GAP_PATH_MAX];

#ifdef SYS_IS_MINGW
if (NULL == _fullpath(resolved_path, CONST_CSTR_STRING(path), sizeof(resolved_path))) {
#else
if (NULL == realpath(CONST_CSTR_STRING(path), resolved_path)) {
#endif
if (NULL == SyRealpath(CONST_CSTR_STRING(path), resolved_path)) {
SySetErrorNo();
return Fail;
}
Expand Down
14 changes: 14 additions & 0 deletions src/sysfiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -2912,6 +2912,20 @@ Int SyIsExistingFile ( const Char * name )
return res;
}

/****************************************************************************
**
*F SyRealpath( <path>, <buf> ) . . . . . . . . . absolute canonical path
*/
Char * SyRealpath(const Char * path, Char * buf)
{
#ifdef SYS_IS_MINGW
return _fullpath(buf, path, GAP_PATH_MAX);
#else
return realpath(path, buf);
#endif
}


/****************************************************************************
**
*F SyIsReadableFile( <name> ) . . . . . . . . . . . is file <name> readable
Expand Down
12 changes: 12 additions & 0 deletions src/sysfiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,18 @@ void SySetErrorNo(void);
Int SyIsExistingFile(const Char * name);


/****************************************************************************
**
*F SyRealpath( <path>, <buf> ) . . . . . . . . . absolute canonical path
**
** 'SyRealpath' stores the absolute path of <path> with all symlinks
** resolved in <buf>, which must have room for 'GAP_PATH_MAX' characters,
** and returns <buf>. On failure, e.g. if <path> does not exist, it returns
** NULL and sets 'errno'.
*/
Char * SyRealpath(const Char * path, Char * buf);


/****************************************************************************
**
*F SyIsReadableFile( <name> ) . . . . . . . . . . . is file <name> readable
Expand Down
30 changes: 20 additions & 10 deletions src/sysroots.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,27 @@ void SySetGapRootPath(const Char * string)
// TODO; instead of iterating over all entries each time, just
// do this for the new entries
char * userhome = getenv("HOME");
if (!userhome || !*userhome)
return;
const UInt userhomelen = strlen(userhome);
if (userhome && *userhome) {
const UInt userhomelen = strlen(userhome);
for (i = 0; i < MAX_GAP_DIRS && SyGapRootPaths[i][0]; i++) {
const UInt pathlen = strlen(SyGapRootPaths[i]);
if (SyGapRootPaths[i][0] == '~' &&
userhomelen + pathlen < sizeof(SyGapRootPaths[i])) {
SyMemmove(SyGapRootPaths[i] + userhomelen,
// don't copy the ~ but the trailing '\0'
SyGapRootPaths[i] + 1, pathlen);
memcpy(SyGapRootPaths[i], userhome, userhomelen);
}
}
}

// make all paths absolute; paths that do not exist are left as is
for (i = 0; i < MAX_GAP_DIRS && SyGapRootPaths[i][0]; i++) {
const UInt pathlen = strlen(SyGapRootPaths[i]);
if (SyGapRootPaths[i][0] == '~' &&
userhomelen + pathlen < sizeof(SyGapRootPaths[i])) {
SyMemmove(SyGapRootPaths[i] + userhomelen,
// don't copy the ~ but the trailing '\0'
SyGapRootPaths[i] + 1, pathlen);
memcpy(SyGapRootPaths[i], userhome, userhomelen);
char buf[GAP_PATH_MAX];
if (SyRealpath(SyGapRootPaths[i], buf)) {
strxcpy(SyGapRootPaths[i], buf, sizeof(SyGapRootPaths[i]));
if (SyGapRootPaths[i][strlen(SyGapRootPaths[i]) - 1] != '/')
strxcat(SyGapRootPaths[i], "/", sizeof(SyGapRootPaths[i]));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/sysroots.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void SySetGapRootPath(const Char * string);
**
** <buf> must point to a buffer of at least <size> characters. This function
** then searches for a readable file with the name <filename> in the system
** area. If sich a file is found then its absolute path is copied into
** area. If such a file is found then its absolute path is copied into
** <buf>, and <buf> is returned. If no file is found or if <buf> is not big
** enough, then <buf> is set to an empty string and NULL is returned.
*/
Expand Down
12 changes: 12 additions & 0 deletions tst/testinstall/package.tst
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,18 @@ gap> Last( GAPInfo.PackagesInfo.mockpkg ).InstallationPath =
> GAPInfo.PackagesLoaded.mockpkg[1];
true

# paths are made absolute, so equivalent paths are not added again
gap> n:= Length( GAPInfo.PackageDirectories );;
gap> ExtendPackageDirectories( [ Concatenation( Filename( mockpkgpath, "" ),
> "../mockpkg" ) ] );
gap> Length( GAPInfo.PackageDirectories ) = n;
true
gap> n:= Length( GAPInfo.RootPaths );;
gap> ExtendRootDirectories( List( Filtered( GAPInfo.RootPaths, IsDirectoryPath ),
> path -> Concatenation( path, "./" ) ) );
gap> Length( GAPInfo.RootPaths ) = n;
true

#
gap> SetPackagePath( "mockpkg", Filename( mockpkgpath, "" ) );
gap> SetPackagePath( "mockpkg", "/some/other/directory" );
Expand Down
Loading