gout

A static git page generator
git clone https://git.bracken.jp/gout.git
Log | Files | Refs | README | LICENSE

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 }