From e739e524dd39cdfcd924494932949c684cc97933 Mon Sep 17 00:00:00 2001 From: Thomas Nilefalk Date: Fri, 10 Feb 2023 14:01:00 +0100 Subject: [PATCH] [filemanager] Add a small TDD step --- src/TODO.org | 6 +- src/fileio.c | 139 ++++++++++++++++++++++++++++++++++++++++ src/fileio.h | 29 +++++++++ src/fileio.mock | 72 +++++++++++++++++++++ src/filemanager.c | 11 ++++ src/filemanager_tests.c | 5 +- src/sources.mk | 2 +- 7 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 src/fileio.c create mode 100644 src/fileio.h create mode 100644 src/fileio.mock diff --git a/src/TODO.org b/src/TODO.org index 3077534..cb221a6 100644 --- a/src/TODO.org +++ b/src/TODO.org @@ -18,4 +18,8 @@ Some useful commands: * TODO Get a list of files from compile_commands.json * TODO If no compile_commands.json use all *.c files in current directory * TODO Take one argument which is the directory to 'cd' to before operating -* TODO +* TODO Option to prune a directory (tree) +Any file in it will not be considered even if it they are included, +handy for `/usr` where files "never" change so it is unnecessary to +check their time stamps + diff --git a/src/fileio.c b/src/fileio.c new file mode 100644 index 0000000..c23217f --- /dev/null +++ b/src/fileio.c @@ -0,0 +1,139 @@ +#include "fileio.h" + +#include +#include + +#include "log.h" +#include "head.h" + + +bool exists(char *path) { + struct stat st; + int rc = stat(path, &st); + return rc == 0; +} + +FILE *openFile(char *fileName, char *modes) { + return fopen(fileName, modes); +} + +int closeFile(FILE *file) { + return fclose(file); +} + +void createDirectory(char *dirname) { + struct stat st; + + if (exists(dirname)) { + stat(dirname, &st); + if (S_ISDIR(st.st_mode)) + return; + removeFile(dirname); + } +#ifdef __WIN32__ + mkdir(dirname); +#else + mkdir(dirname, 0777); +#endif +} + + +void recursivelyCreateFileDirIfNotExists(char *fpath) { + char *p; + int ch, len; + bool loopFlag = true; + + /* Check each level from the deepest, stop when it exists */ + len = strlen(fpath); + for (p=fpath+len; p>fpath && loopFlag; p--) { + if (*p!=FILE_PATH_SEPARATOR) + continue; + ch = *p; *p = 0; /* Truncate here, remember the char */ + if (directoryExists(fpath)) { + loopFlag=false; + } + *p = ch; /* Restore the char */ + } + /* Create each of the remaining levels */ + for (p+=2; *p; p++) { + if (*p!=FILE_PATH_SEPARATOR) + continue; + ch = *p; *p = 0; + createDirectory(fpath); + *p = ch; + } +} + + +void removeFile(char *fileName) { + log_trace("removing file '%s'", fileName); + unlink(fileName); +} + +int fileStatus(char *path, struct stat *statP) { + struct stat st; + int return_value; + + return_value = stat(path, &st); /* Returns 0 on success */ + if (statP != NULL) + *statP = st; + return return_value; +} + +time_t fileModificationTime(char *path) { + struct stat st; + if (fileStatus(path, &st) !=0) + return 0; /* File not found? */ + return st.st_mtime; +} + +size_t fileSize(char *path) { + struct stat st; + if (fileStatus(path, &st) !=0) + return 0; /* File not found? */ + return st.st_size; +} + +bool isDirectory(char *path) { + return directoryExists(path); +} + +bool directoryExists(char *path) { + struct stat st; + int statResult; + + statResult = stat(path, &st); + return statResult==0 && S_ISDIR(st.st_mode); +} + +bool fileExists(char *fullPath) { + struct stat st; + int statResult; + + statResult = stat(fullPath, &st); + return statResult==0 && S_ISREG(st.st_mode); +} + +size_t readFile(FILE *file, void *buffer, size_t size, size_t count) { + return fread(buffer, size, count, file); +} + +size_t writeFile(FILE *file, void *buffer, size_t size, size_t count) { + return fwrite(buffer, size, count, file); +} + +int readChar(FILE *file) { + return getc(file); +} + +char *getEnv(const char *variable) { + return getenv(variable); +} + +char *getCwd(char *buffer, size_t size) { + return getcwd(buffer, size); +} + +const char **getFilesInCurrentDirectory(void) { + return NULL; +} diff --git a/src/fileio.h b/src/fileio.h new file mode 100644 index 0000000..f2a2739 --- /dev/null +++ b/src/fileio.h @@ -0,0 +1,29 @@ +#ifndef FILEIO_H_INCLUDED +#define FILEIO_H_INCLUDED + +#include +#include +#include + + +extern bool exists(char *path); +extern int fileStatus(char *path, struct stat *statbuf); +extern time_t fileModificationTime(char *path); +extern size_t fileSize(char *path); +extern FILE *openFile(char *fileName, char *modes); +extern int closeFile(FILE *file); +extern void createDirectory(char *dirname); +extern void recursivelyCreateFileDirIfNotExists(char *fpath); +extern void removeFile(char *dirname); +extern bool isDirectory(char *fullPath); +extern bool directoryExists(char *fullPath); +extern bool fileExists(char *fullPath); +extern size_t readFile(FILE *file, void *buffer, size_t size, size_t count); +extern size_t writeFile(FILE *file, void *buffer, size_t size, size_t count); +extern int readChar(FILE *file); +extern const char **getFilesInCurrentDirectory(void); + +extern char *getEnv(const char *variable); +extern char *getCwd(char *buf, size_t size); + +#endif diff --git a/src/fileio.mock b/src/fileio.mock new file mode 100644 index 0000000..630a099 --- /dev/null +++ b/src/fileio.mock @@ -0,0 +1,72 @@ +/* -*- c -*-*/ +#include +#include "fileio.h" + + +const char **getFilesInCurrentDirectory(void) { + return (const char **)mock(); +} + +bool isDirectory(char *fullPath) { + return (bool)mock(fullPath); +} + +bool directoryExists(char *fullPath) { + return (bool)mock(fullPath); +} + +bool fileExists(char *fullPath) { + return (bool)mock(fullPath); +} + +int fileStatus(char *path, struct stat *statbuf) { + return (int)mock(path, statbuf); +} + +time_t fileModificationTime(char *path) { + return (time_t)mock(path); +} + +size_t fileSize(char *path) { + return (size_t)mock(path); +} + +FILE *openFile(char *fileName, char *modes) { + return (FILE *)mock(fileName, modes); +} + +int closeFile(FILE *file) { + return (int)mock(file); +} + +void createDirectory(char *dirName) { + mock(dirName); +} + +void recursivelyCreateFileDirIfNotExists(char *fpath) { + mock(fpath); +} + +void removeFile(char *fileName) { + mock(fileName); +} + +size_t readFile(FILE *file, void *buffer, size_t size, size_t count) { + return (size_t)mock(buffer, size, count, file); +} + +size_t writeFile(FILE *file, void *buffer, size_t size, size_t count) { + return (size_t)mock(buffer, size, count, file); +} + +int readChar(FILE *file) { + return (int)mock(file); +} + +char *getEnv(const char *variable) { + return (char *)mock(variable); +} + +char *getCwd(char *buffer, size_t size) { + return (char *)mock(buffer, size); +} diff --git a/src/filemanager.c b/src/filemanager.c index 8fc0606..eec90eb 100644 --- a/src/filemanager.c +++ b/src/filemanager.c @@ -1,6 +1,17 @@ #include "filemanager.h" +#include + +#include "common.h" +#include "fileio.h" + FileTable getFilesFromCompilationDatabase(void) { + const char **fileNameTable = getFilesInCurrentDirectory(); + UNUSED fileNameTable; + + FileTable fileTable = (FileTable)malloc(sizeof(FileTableElement)); + UNUSED fileTable; + return NULL; } diff --git a/src/filemanager_tests.c b/src/filemanager_tests.c index 1e7fd58..400c1a0 100644 --- a/src/filemanager_tests.c +++ b/src/filemanager_tests.c @@ -6,7 +6,8 @@ #include "filemanager.h" -#include "common.h" +#include "fileio.mock" + Describe(Filemananger); @@ -15,6 +16,8 @@ AfterEach(Filemananger) {} Ensure(Filemananger, will_create_an_empty_filetable_for_an_empty_directory) { + const char *fileNameList[] = {NULL}; + expect(getFilesInCurrentDirectory, will_return(fileNameList)); FileTable fileTable = getFilesFromCompilationDatabase(); assert_that(fileTable, is_null); } diff --git a/src/sources.mk b/src/sources.mk index 725bf15..09b02ba 100644 --- a/src/sources.mk +++ b/src/sources.mk @@ -1,4 +1,4 @@ -MODULES = main dispatcher exports clang_adaptor indexer includes references filemanager +MODULES = main dispatcher exports clang_adaptor indexer includes references filemanager fileio OBJDIR = .objects SRCS = ${MODULES:=.c}