Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function ChangeDirectoryCurrent to change current directory (identical to the one provided by the IO package) #5585

Merged
merged 3 commits into from
Jan 14, 2024
Merged
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
1 change: 1 addition & 0 deletions doc/ref/files.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ for more information how to do this.
<#Include Label="Directory">
<#Include Label="DirectoryTemporary">
<#Include Label="DirectoryCurrent">
<#Include Label="ChangeDirectoryCurrent">
<#Include Label="DirectoriesLibrary">
<#Include Label="DirectoriesSystemPrograms">
<#Include Label="DirectoryContents">
Expand Down
29 changes: 27 additions & 2 deletions lib/files.gd
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@
InstallAtExit( function()
local path;
for path in GAPInfo.DirectoriesTemporary do
if IsDir(path) = 'D' then
if IS_DIR(path) then

Check warning on line 500 in lib/files.gd

View check run for this annotation

Codecov / codecov/patch

lib/files.gd#L500

Added line #L500 was not covered by tests
RemoveDirectoryRecursively(path);
else
PRINT_TO("*errout*", "Temporary directory already removed: ", path, "\n");
Expand All @@ -522,12 +522,37 @@
##
BIND_GLOBAL( "DirectoryCurrent", function()
if IsBool( GAPInfo.DirectoryCurrent ) then
GAPInfo.DirectoryCurrent := Directory("./");
GAPInfo.DirectoryCurrent := Directory(GAP_getcwd());
fi;
return GAPInfo.DirectoryCurrent;
end );


#############################################################################
##
#F ChangeDirectoryCurrent() . . . . . . . . . . . change current directory
##
## <#GAPDoc Label="ChangeDirectoryCurrent">
## <ManSection>
## <Func Name="ChangeDirectoryCurrent" Arg='path'/>
##
## <Description>
## Changes the current directory. Returns <K>true</K> on success and
## <K>fail</K> on failure.
## </Description>
## </ManSection>
## <#/GAPDoc>
##
BIND_GLOBAL( "ChangeDirectoryCurrent", function( path )
if GAP_chdir(path) = true then
GAPInfo.DirectoryCurrent := Directory(GAP_getcwd());
return true;
else
return fail;
fi;

Check warning on line 552 in lib/files.gd

View check run for this annotation

Codecov / codecov/patch

lib/files.gd#L547-L552

Added lines #L547 - L552 were not covered by tests
end );


#############################################################################
##
#F CrcFile( <filename> ) . . . . . . . . . . . . . . . . create crc value
Expand Down
7 changes: 3 additions & 4 deletions lib/files.gi
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ InstallGlobalFunction(RemoveDirectoryRecursively,
function(dirname)
# dirname must be a string
local Dowork;
if not(IsDir(dirname) = 'D') then
if not IS_DIR(dirname) then
Error("dirname must be a directory");
return fail;
fi;
Expand All @@ -383,13 +383,12 @@ InstallGlobalFunction(RemoveDirectoryRecursively,
fi;
Dowork := function(pathname)
# pathname does not end in a / and is known to be a proper directory
local c,f,fullname,what;
local c,f,fullname;
c := DirectoryContents(pathname);
for f in c do
if f <> "." and f <> ".." then
fullname := Concatenation(pathname,"/",f);
what := IsDir(fullname);
if what = 'D' then
if IS_DIR(fullname) then
Dowork(fullname);
else
RemoveFile(fullname);
Expand Down
43 changes: 38 additions & 5 deletions src/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -1037,17 +1037,48 @@

/****************************************************************************
**
*F FuncIsDir( <self>, <name> ) . . . . . check whether something is a dir
*F FuncIS_DIR( <self>, <path> ) . . . . . check whether something is a dir
*/
static Obj FuncIsDir(Obj self, Obj filename)
static Obj FuncIS_DIR(Obj self, Obj path)
{
RequireStringRep(SELF_NAME, filename);
RequireStringRep(SELF_NAME, path);

// call the system dependent function
return SyIsDir( CONST_CSTR_STRING(filename) );
return SyFileType(CONST_CSTR_STRING(path)) == 'D' ? True : False;
}

/****************************************************************************
**
*F FuncGAP_getcwd( <self> ) . . . . . . . . . get working directory pathname
*/
static Obj FuncGAP_getcwd(Obj self)
{
char * res;
char buf[GAP_PATH_MAX];

res = getcwd(buf, sizeof(buf));
if (res == NULL) {
SySetErrorNo();
return Fail;

Check warning on line 1062 in src/streams.c

View check run for this annotation

Codecov / codecov/patch

src/streams.c#L1061-L1062

Added lines #L1061 - L1062 were not covered by tests
}
return MakeImmString(buf);
}

/****************************************************************************
**
*F FuncGAP_chdir( <self>, <path> ) . . . . change current working directory
*/
static Obj FuncGAP_chdir(Obj self, Obj path)
{
RequireStringRep(SELF_NAME, path);

Check warning on line 1073 in src/streams.c

View check run for this annotation

Codecov / codecov/patch

src/streams.c#L1073

Added line #L1073 was not covered by tests

int res = chdir(CONST_CSTR_STRING(path));

Check warning on line 1075 in src/streams.c

View check run for this annotation

Codecov / codecov/patch

src/streams.c#L1075

Added line #L1075 was not covered by tests
if (res < 0) {
SySetErrorNo();
return Fail;

Check warning on line 1078 in src/streams.c

View check run for this annotation

Codecov / codecov/patch

src/streams.c#L1077-L1078

Added lines #L1077 - L1078 were not covered by tests
}
return True;

Check warning on line 1080 in src/streams.c

View check run for this annotation

Codecov / codecov/patch

src/streams.c#L1080

Added line #L1080 was not covered by tests
}


/****************************************************************************
Expand Down Expand Up @@ -1682,7 +1713,9 @@
GVAR_FUNC_1ARGS(RemoveFile, filename),
GVAR_FUNC_1ARGS(CreateDir, filename),
GVAR_FUNC_1ARGS(RemoveDir, filename),
GVAR_FUNC_1ARGS(IsDir, filename),
GVAR_FUNC_1ARGS(IS_DIR, path),
GVAR_FUNC_0ARGS(GAP_getcwd),
GVAR_FUNC_1ARGS(GAP_chdir, path),
GVAR_FUNC_0ARGS(LastSystemError),
GVAR_FUNC_1ARGS(IsExistingFile, filename),
GVAR_FUNC_1ARGS(IsReadableFile, filename),
Expand Down
55 changes: 34 additions & 21 deletions src/sysfiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -2949,38 +2949,51 @@

/****************************************************************************
**
*F SyIsDir( <name> ) . . . . . . . . . . . . . test if something is a dir
**
** Returns 'F' for a regular file, 'L' for a symbolic link and 'D'
** for a real directory, 'C' for a character device, 'B' for a block
** device 'P' for a FIFO (named pipe) and 'S' for a socket.
*F SyFileType( <path> )
**
** Return a character describing the filesystem object with the given path:
** - 'F' for a regular file
** - 'L' for a symbolic link
** - 'D' for a directory
** - 'C' for a character device
** - 'B' for a block device
** - 'P' for a FIFO (named pipe)
** - 'S' for a socket
** - `\0` if there was en error (e.g. invalid path, unknown type, etc.)
*/
Obj SyIsDir ( const Char * name )
char SyFileType(const Char * path)
{
Int res;
struct stat ourlstatbuf;
int res;
struct stat ourlstatbuf;

res = lstat(name,&ourlstatbuf);
if (res < 0) {
SySetErrorNo();
return Fail;
}
if (S_ISREG(ourlstatbuf.st_mode)) return ObjsChar['F'];
else if (S_ISDIR(ourlstatbuf.st_mode)) return ObjsChar['D'];
else if (S_ISLNK(ourlstatbuf.st_mode)) return ObjsChar['L'];
res = lstat(path, &ourlstatbuf);
if (res < 0) {
SySetErrorNo();
return 0;
}
if (S_ISREG(ourlstatbuf.st_mode))
return 'F';
if (S_ISDIR(ourlstatbuf.st_mode))
return 'D';
if (S_ISLNK(ourlstatbuf.st_mode))
return 'L';

Check warning on line 2979 in src/sysfiles.c

View check run for this annotation

Codecov / codecov/patch

src/sysfiles.c#L2979

Added line #L2979 was not covered by tests
#ifdef S_ISCHR
else if (S_ISCHR(ourlstatbuf.st_mode)) return ObjsChar['C'];
if (S_ISCHR(ourlstatbuf.st_mode))
return 'C';

Check warning on line 2982 in src/sysfiles.c

View check run for this annotation

Codecov / codecov/patch

src/sysfiles.c#L2982

Added line #L2982 was not covered by tests
#endif
#ifdef S_ISBLK
else if (S_ISBLK(ourlstatbuf.st_mode)) return ObjsChar['B'];
if (S_ISBLK(ourlstatbuf.st_mode))
return 'B';

Check warning on line 2986 in src/sysfiles.c

View check run for this annotation

Codecov / codecov/patch

src/sysfiles.c#L2986

Added line #L2986 was not covered by tests
#endif
#ifdef S_ISFIFO
else if (S_ISFIFO(ourlstatbuf.st_mode)) return ObjsChar['P'];
if (S_ISFIFO(ourlstatbuf.st_mode))
return 'P';

Check warning on line 2990 in src/sysfiles.c

View check run for this annotation

Codecov / codecov/patch

src/sysfiles.c#L2990

Added line #L2990 was not covered by tests
#endif
#ifdef S_ISSOCK
else if (S_ISSOCK(ourlstatbuf.st_mode)) return ObjsChar['S'];
if (S_ISSOCK(ourlstatbuf.st_mode))
return 'S';

Check warning on line 2994 in src/sysfiles.c

View check run for this annotation

Codecov / codecov/patch

src/sysfiles.c#L2994

Added line #L2994 was not covered by tests
#endif
else return ObjsChar['?'];
return 0;

Check warning on line 2996 in src/sysfiles.c

View check run for this annotation

Codecov / codecov/patch

src/sysfiles.c#L2996

Added line #L2996 was not covered by tests
}


Expand Down
20 changes: 13 additions & 7 deletions src/sysfiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,19 @@ Int SyRmdir(const Char * name);

/****************************************************************************
**
*F SyIsDir( <name> ) . . . . . . . . . . . . . test if something is a dir
**
** Returns 'F' for a regular file, 'L' for a symbolic link and 'D'
** for a real directory, 'C' for a character device, 'B' for a block
** device 'P' for a FIFO (named pipe) and 'S' for a socket.
*/
Obj SyIsDir(const Char * name);
*F SyFileType( <path> )
**
** Return a character describing the filesystem object with the given path:
** - 'F' for a regular file
** - 'L' for a symbolic link
** - 'D' for a directory
** - 'C' for a character device
** - 'B' for a block device
** - 'P' for a FIFO (named pipe)
** - 'S' for a socket
** - `\0` if there was en error (e.g. invalid path, unknown type, etc.)
*/
char SyFileType(const Char * path);


/****************************************************************************
Expand Down
24 changes: 12 additions & 12 deletions tst/testinstall/kernel/streams.tst
Original file line number Diff line number Diff line change
Expand Up @@ -169,32 +169,32 @@ gap> CreateDir(fail);
Error, CreateDir: <filename> must be a string (not the value 'fail')
gap> RemoveDir(fail);
Error, RemoveDir: <filename> must be a string (not the value 'fail')
gap> IsDir(fail);
Error, IsDir: <filename> must be a string (not the value 'fail')
gap> IS_DIR(fail);
Error, IS_DIR: <path> must be a string (not the value 'fail')

#
gap> tmpdir := MakeImmutable(TmpDirectory());;
gap> subdir := MakeImmutable(Concatenation(tmpdir, "/subdir"));;
gap> CreateDir(subdir);
true
gap> IsDir(subdir);
'D'
gap> IS_DIR(subdir);
true
gap> RemoveDir(subdir);
true
gap> IsDir(subdir);
fail
gap> IS_DIR(subdir);
false
gap> CreateDir(subdir);
true
gap> FileString(Concatenation(subdir, "/file"), "data");
4
gap> IsDir(subdir);
'D'
gap> IS_DIR(subdir);
true
gap> RemoveDirectoryRecursively(tmpdir);
true
gap> IsDir(subdir);
fail
gap> IsDir(tmpdir);
fail
gap> IS_DIR(subdir);
false
gap> IS_DIR(tmpdir);
false

#
gap> IsExistingFile(fail);
Expand Down