gout_index.c (2819B)
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 options->repo_dirs = NULL; 70 } 71 free(options); 72 } 73 74 void gout_index_init(const GoutIndexOptions* options, Git* git) { 75 assert(options != NULL); 76 assert(git != NULL); 77 const char** readonly_paths = options->repo_dirs; 78 size_t readonly_paths_count = options->repo_dir_count; 79 const char* readwrite_paths[1] = {NULL}; 80 size_t readwrite_paths_count = 0; 81 restrict_filesystem_access(readonly_paths, readonly_paths_count, 82 readwrite_paths, readwrite_paths_count); 83 restrict_system_operations(kGoutIndex); 84 85 git->initialize(git); 86 } 87 88 void gout_index_run(const GoutIndexOptions* options, Git* git) { 89 assert(options != NULL); 90 assert(git != NULL); 91 IndexWriter* writer = indexwriter_create(options->writer_type, stdout); 92 if (options->me_url) { 93 indexwriter_set_me_url(writer, options->me_url); 94 } 95 indexwriter_begin(writer); 96 for (size_t i = 0; i < options->repo_dir_count; i++) { 97 git->for_repo(git, options->repo_dirs[i], repo_callback, writer); 98 } 99 indexwriter_end(writer); 100 indexwriter_free(writer); 101 } 102 103 static void repo_callback(Git* git, void* user_data) { 104 assert(git != NULL); 105 assert(user_data != NULL); 106 IndexWriter* writer = (IndexWriter*)user_data; 107 indexwriter_add_repo(writer, git->repo); 108 }