This commit is contained in:
2025-08-11 11:31:52 -04:00
parent 0e6e155c15
commit a189c0ebc2
4 changed files with 126 additions and 71 deletions

View File

@@ -1,3 +1,11 @@
/* Copyright (C) vx_clutch
*
* This file is part of yait
*
* This project and file is licenced under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -10,15 +18,14 @@
#include "contents.h" #include "contents.h"
#include "yait.h" #include "yait.h"
#error "TODO: make path project root"
#define DEFAULT_USER_NAME "unknown" #define DEFAULT_USER_NAME "unknown"
#define DEFAULT_PROJECT_NAME "Project" #define DEFAULT_PROJECT_NAME "Project"
#define DEFAULT_LICENCE BSD3 #define DEFAULT_LICENCE BSD3
#define DEFAULT_GIT_INIT true #define DEFAULT_GIT_INIT true
#define DEFAULT_CLANG_FORMAT true #define DEFAULT_CLANG_FORMAT true
#define DEFAULT_GNU false
int depth; int depth = 0;
static int reset_path(void) static int reset_path(void)
{ {
@@ -175,9 +182,12 @@ int setup_git(manifest_t manifest)
return ret; return ret;
int status = system("git init --quiet"); int status = system("git init --quiet");
if (status != 0) if (status == -1) {
fprintf(stderr, "setup_git: failed to initialize git: %s\n", fprintf(stderr, "...: %s\n", strerror(errno));
strerror(status)); } else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
fprintf(stderr, "...: exited with status %d\n",
WEXITSTATUS(status));
}
return status; return status;
} }
@@ -201,7 +211,8 @@ int create_makefile(manifest_t manifest)
return ret; return ret;
} }
int status = create_file_with_content("Makefile", makefile_template, M, m, M, m, M, M, m, M, m, M, m); int status = create_file_with_content("Makefile", makefile_template, M,
m, M, m, M, M, m, M, m, M, m);
free(m); free(m);
free(M); free(M);
@@ -242,14 +253,15 @@ int generate_source_code(manifest_t manifest, char *licence_line)
struct tm tm = *localtime(&t); struct tm tm = *localtime(&t);
int year = tm.tm_year + 1900; int year = tm.tm_year + 1900;
// Uncomment or fix when create_file_with_content supports this status = create_file_with_content("config.h", config_h_template,
// status = create_file_with_content("config.h", manifest.project, licence_line, year); manifest.project, licence_line, year);
// if (status != 0) { if (status != 0) {
// fprintf(stderr, "generate_source_code: failed to create config.h: %s\n", strerror(status)); fprintf(stderr,
// return status; "generate_source_code: failed to create config.h: %s\n",
// } strerror(status));
return status;
}
status = create_and_enter_directory(manifest.project);
if (status != 0) { if (status != 0) {
fprintf(stderr, fprintf(stderr,
"generate_source_code: failed to create or enter directory: %s\n", "generate_source_code: failed to create or enter directory: %s\n",
@@ -259,13 +271,13 @@ int generate_source_code(manifest_t manifest, char *licence_line)
depth++; depth++;
if (manifest.flag.GNU) { if (manifest.flag.GNU) {
status = create_file_with_content("main.c", main_c_gnu_template, status = create_file_with_content(
manifest.project, strcat(manifest.project, "main.c"), main_c_gnu_template,
manifest.name); manifest.project, manifest.name);
} else { } else {
status = create_file_with_content("main.c", main_c_template, status = create_file_with_content(
manifest.project, strcat(manifest.project, "main.c"), main_c_template,
manifest.name); manifest.project, manifest.name);
} }
return status; return status;
@@ -277,9 +289,8 @@ int create_project(manifest_t manifest)
sanitize(&manifest); sanitize(&manifest);
depth = 0; // TODO(vx-clutch): make the path the project root.
if (strcmp(manifest.path, ".") != 0) { if (strcmp(manifest.path, ".") != 0) {
status = create_and_enter_directory(manifest.project);
if (status != 0) { if (status != 0) {
fprintf(stderr, fprintf(stderr,
"create_project: failed to create or enter directory: %s\n", "create_project: failed to create or enter directory: %s\n",
@@ -305,13 +316,6 @@ int create_project(manifest_t manifest)
return status; return status;
} }
status = setup_git(manifest);
if (status != 0) {
fprintf(stderr,
"create_project: warning: git initialization failed: %s\n",
strerror(status));
}
status = maybe_create_clang_format(manifest); status = maybe_create_clang_format(manifest);
if (status != 0) { if (status != 0) {
fprintf(stderr, fprintf(stderr,
@@ -353,5 +357,15 @@ int create_project(manifest_t manifest)
return status; return status;
} }
status = setup_git(manifest);
if (status != 0) {
fprintf(stderr,
"create_project: warning: git initialization failed: %s\n",
strerror(status));
}
// TODO(vx-clutch): Make path absolute.
fprintf(stderr, "Created %s at\n %s", manifest.project, manifest.path);
return 0; return 0;
} }

View File

@@ -9,56 +9,80 @@
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "yait.h" #include "yait.h"
int create_file_with_content(char *path, char *format, ...) int files_made = 0;
static int mkdir_p(const char *path)
{ {
FILE *fp = fopen(path, "w"); char *copypath = strdup(path);
if (!fp) { char *p = copypath;
int status = 0;
if (!copypath)
return -1;
if (copypath[0] == '/')
p++;
for (; *p; p++) {
if (*p == '/') {
*p = '\0';
if (mkdir(copypath, 0777) && errno != EEXIST) {
status = -1;
break;
}
*p = '/';
}
}
if (!status && mkdir(copypath, 0777) && errno != EEXIST)
status = -1;
free(copypath);
return status;
}
int create_file_with_content(const char *path, const char *format, ...)
{
char *dirpath;
const char *slash = strrchr(path, '/');
if (slash) {
size_t len = slash - path;
dirpath = malloc(len + 1);
if (!dirpath)
return -1;
memcpy(dirpath, path, len);
dirpath[len] = '\0';
if (mkdir_p(dirpath)) {
free(dirpath);
return -1; return -1;
} }
free(dirpath);
}
FILE *fp = fopen(path, "w");
if (!fp)
return -1;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
vfprintf(fp, format, args); if (vfprintf(fp, format, args) < 0) {
va_end(args); va_end(args);
fclose(fp);
return -1;
}
va_end(args);
++files_made;
emit_progress("Creating files", files_made);
fclose(fp); fclose(fp);
return 0; return 0;
} }
int create_directory(char *format, ...)
{
va_list args;
va_start(args, format);
char path[MAX_PATH_LENGTH];
int result = vsnprintf(path, sizeof(path), format, args);
va_end(args);
/* Check if the path was truncated */
if (result >= (int)sizeof(path)) {
return ENAMETOOLONG;
}
if (mkdir(path, DEFAULT_DIR_PERMISSIONS) < 0) {
return errno;
}
return 0;
}
int create_and_enter_directory(const char *dirname)
{
int err = create_directory("%s", dirname);
if (err) {
return err;
}
if (chdir(dirname) != 0) {
return errno;
}
return 0;
}

19
core/util.c Normal file
View File

@@ -0,0 +1,19 @@
/* Copyright (C) vx_clutch
*
* This file is part of yait
*
* This project and file is licenced under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#include "yait.h"
void emit_progress(const char *action, int count)
{
if (count > 0) {
fprintf(stderr, "%s %d", strcat("\r", action), count);
fflush(stderr);
} else {
fprintf(stderr, ", done\n");
}
}

View File

@@ -15,11 +15,7 @@
int printfn(char *format, ...); int printfn(char *format, ...);
int create_and_enter_directory(const char *dirname); int create_file_with_content(const char *path, const char *format, ...);
int create_file_with_content(char *path, char *format, ...);
int create_directory(char *format, ...);
int parse_standard_options(void (*usage_func)(), int argc, char **argv); int parse_standard_options(void (*usage_func)(), int argc, char **argv);
@@ -28,4 +24,6 @@ int program_exists(const char *prog);
#include "manifest.h" #include "manifest.h"
int create_project(manifest_t manifest); int create_project(manifest_t manifest);
void emit_progress(const char *action, int count);
#endif // YAIT_H #endif // YAIT_H