gout_index.c (2788B)
1 #include "gout_index.h" 2 3 #include <assert.h> 4 #include <err.h> 5 #include <stddef.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 9 #include "git/git.h" 10 #include "security.h" 11 #include "third_party/openbsd/reallocarray.h" 12 #include "utils.h" 13 #include "writer/index_writer.h" 14 15 static void repo_callback(Git* git, void* user_data); 16 17 GoutIndexOptions* gout_index_options_create(int argc, const char* argv[]) { 18 assert(argv != NULL); 19 GoutIndexOptions options = { 20 .repo_dirs = NULL, 21 .repo_dir_count = 0, 22 .me_url = NULL, 23 .writer_type = kIndexWriterTypeHtml, 24 }; 25 26 int ch; 27 optind = 1; 28 opterr = 0; 29 while ((ch = getopt(argc, (char* const*)argv, "m:HGM")) != -1) { 30 switch (ch) { 31 case 'm': 32 options.me_url = optarg; 33 break; 34 case 'H': 35 options.writer_type = kIndexWriterTypeHtml; 36 break; 37 case 'G': 38 options.writer_type = kIndexWriterTypeGopher; 39 break; 40 case 'M': 41 options.writer_type = kIndexWriterTypeGemini; 42 break; 43 default: 44 return NULL; 45 } 46 } 47 argc -= optind; 48 argv += optind; 49 50 if (argc > 0) { 51 options.repo_dirs = ecalloc(argc, sizeof(char*)); 52 for (int i = 0; i < argc; i++) { 53 options.repo_dirs[i] = argv[i]; 54 } 55 options.repo_dir_count = argc; 56 } 57 58 GoutIndexOptions* options_out = ecalloc(1, sizeof(GoutIndexOptions)); 59 *options_out = options; 60 return options_out; 61 } 62 63 void gout_index_options_free(GoutIndexOptions* options) { 64 if (!options) { 65 return; 66 } 67 if (options->repo_dirs) { 68 free(options->repo_dirs); 69 } 70 free(options); 71 } 72 73 void gout_index_init(const GoutIndexOptions* options, Git* git) { 74 assert(options != NULL); 75 assert(git != NULL); 76 const char** readonly_paths = options->repo_dirs; 77 size_t readonly_paths_count = options->repo_dir_count; 78 const char* readwrite_paths[1] = {NULL}; 79 size_t readwrite_paths_count = 0; 80 restrict_filesystem_access(readonly_paths, readonly_paths_count, 81 readwrite_paths, readwrite_paths_count); 82 restrict_system_operations(kGoutIndex); 83 84 git->initialize(git); 85 } 86 87 void gout_index_run(const GoutIndexOptions* options, Git* git) { 88 assert(options != NULL); 89 assert(git != NULL); 90 IndexWriter* writer = indexwriter_create(options->writer_type, stdout); 91 if (options->me_url) { 92 indexwriter_set_me_url(writer, options->me_url); 93 } 94 indexwriter_begin(writer); 95 for (size_t i = 0; i < options->repo_dir_count; i++) { 96 git->for_repo(git, options->repo_dirs[i], repo_callback, writer); 97 } 98 indexwriter_end(writer); 99 indexwriter_free(writer); 100 } 101 102 static void repo_callback(Git* git, void* user_data) { 103 assert(git != NULL); 104 assert(user_data != NULL); 105 IndexWriter* writer = (IndexWriter*)user_data; 106 indexwriter_add_repo(writer, git->repo); 107 }