diff --git a/nob.c b/nob.c index a580562..f830103 100644 --- a/nob.c +++ b/nob.c @@ -24,6 +24,7 @@ const char *test_names[] = { "sb_appendf", "da_foreach", "temp_aligned_alloc", + "test_git_fetch" }; #define test_names_count ARRAY_LEN(test_names) diff --git a/nob.h b/nob.h index 737f61f..52eec21 100644 --- a/nob.h +++ b/nob.h @@ -232,6 +232,8 @@ NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path); NOBDEF bool nob_copy_directory_recursively(const char *src_path, const char *dst_path); NOBDEF bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children); NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t size); +NOBDEF bool nob_git_fetch(const char *repo_url, const char *dst_dir, const char *branch, bool shallow); + NOBDEF Nob_File_Type nob_get_file_type(const char *path); NOBDEF bool nob_delete_file(const char *path); @@ -952,6 +954,35 @@ NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path) #endif } +NOBDEF bool nob_git_fetch(const char *repo_url, const char *dst_dir, const char *branch, bool shallow) +{ + NOB_ASSERT(repo_url && dst_dir); + + /* we can do more git processing here, like checking if the current folder is dirty, + or if the brnach/tag is the correct one. etc */ + if (nob_file_exists(dst_dir) == 1) return true; + + nob_mkdir_if_not_exists(dst_dir); + + Nob_Cmd cmd = {0}; + nob_cmd_append(&cmd, "git", "clone"); + if (shallow) { + nob_cmd_append(&cmd, "--depth", "1"); + } + if (branch && branch[0] != '\0') { + nob_cmd_append(&cmd, "--branch", branch); + } + nob_cmd_append(&cmd, repo_url, dst_dir); + + if (!nob_cmd_run(&cmd)) { + nob_log(NOB_ERROR, "git clone failed for %s into %s", repo_url, dst_dir); + return false; + } + + nob_log(NOB_INFO, "Repository %s is available under %s", repo_url, dst_dir); + return true; +} + NOBDEF void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render) { for (size_t i = 0; i < cmd.count; ++i) { diff --git a/tests/test_git_fetch.c b/tests/test_git_fetch.c new file mode 100644 index 0000000..f4afc14 --- /dev/null +++ b/tests/test_git_fetch.c @@ -0,0 +1,63 @@ +#define NOB_IMPLEMENTATION +#include "nob.h" + +#include +#include +#include +#include + +int main(void) +{ + const char *dst = "flag_h"; + const char *repo_url = "https://github.com/tsoding/flag.h"; + + if (!nob_git_fetch(repo_url, dst, NULL, true)) { + nob_log(NOB_ERROR, "nob_git_fetch failed"); + return 1; + } + + srand(time(NULL) ); + int expected_number = rand(); + char expected_str[32]; + snprintf(expected_str, sizeof (expected_str), "%d", expected_number); + + char main_c[256]; + int main_c_len = snprintf(main_c, sizeof (main_c), + "#include \n" + "#include \"flag.h\"\n" + "int main(void){ (void)printf(\"%s\"); return 0; }\n", + expected_str); + + if (!nob_write_entire_file("git_fetch_main.c", main_c, (size_t)main_c_len)) { + nob_log(NOB_ERROR, "Could not write git_fetch_main.c"); + return 1; + } + + Nob_Cmd cmd = {0}; + nob_cmd_append(&cmd, "cc", "-I", dst, "-o", "./git_fetch_main", "git_fetch_main.c"); + if (!nob_cmd_run(&cmd)) { + nob_log(NOB_ERROR, "compile failed"); + return 1; + } + + nob_cmd_append(&cmd, "./git_fetch_main"); + if (!nob_cmd_run(&cmd, .stdout_path = "./git_fetch_main_out.txt")) { + nob_log(NOB_ERROR, "run failed"); + return 1; + } + + Nob_String_Builder sb = {0}; + + if (!nob_read_entire_file("./git_fetch_main_out.txt", &sb)) return 1; + + Nob_String_View out = nob_sb_to_sv(sb); + + Nob_String_View trimmed = nob_sv_trim(out); + if (!nob_sv_eq(trimmed, nob_sv_from_cstr(expected_str))) { + nob_log(NOB_ERROR, "Unexpected output (see file)"); + return 1; + } + + nob_log(NOB_INFO, "git_fetch_main test passed"); + return 0; +}