Diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/ui-snapshot.c | 118 | |
| -rw-r--r-- | source/ui-snapshot.h | 9 |
2 files changed, 45 insertions, 82 deletions
diff --git a/source/ui-snapshot.c b/source/ui-snapshot.c index bd5ebf2..0d8ecdf 100644 --- a/source/ui-snapshot.c +++ b/source/ui-snapshot.c @@ -1,13 +1,13 @@ /* * Serves a commit as a downloadable archive. Writing the archive is git's - * work, so each format here is a thin wrapper that either calls write_archive - * directly or pipes its tar output through an external compressor. The table - * of formats also lives here, and since a repository's snapshots mask is one - * bit per table position, that order is part of what cgitrc means. When the - * request carries no revision the file name is worked backwards to find one, - * so that a link to cgit-1.2.tar.gz can serve the tag it was named after. A - * name ending in .asc asks for the detached signature kept under refs/notes - * instead of the archive itself. + * work, so each format here is only a row in a table, naming the archive + * format git writes and, for a compressed tar, the compressor its output is + * piped through. A repository's snapshots mask is one bit per table position, + * so that order is part of what cgitrc means. When the request carries no + * revision the file name is worked backwards to find one, so that a link to + * cgit-1.2.tar.gz can serve the tag it was named after. A name ending in .asc + * asks for the detached signature kept under refs/notes instead of the archive + * itself. */ #define USE_THE_REPOSITORY_VARIABLE @@ -21,11 +21,10 @@ #define SIG_SUFFIX ".asc" -static int write_archive_format(const char *format_arg, const char *hex, const char *prefix) +static void write_archive_format(const char *format_arg, const char *hex, const char *prefix) { struct strvec argv = STRVEC_INIT; const char **args; - int result; strvec_push(&argv, "snapshot"); strvec_push(&argv, format_arg); @@ -48,20 +47,25 @@ static int write_archive_format(const char *format_arg, const char *hex, const c args = xmalloc(sizeof(char *) * (argv.nr + 1)); memcpy(args, argv.v, sizeof(char *) * (argv.nr + 1)); - result = write_archive(argv.nr, args, NULL, the_repository, NULL, 0); + write_archive(argv.nr, args, NULL, the_repository, NULL, 0); strvec_clear(&argv); free(args); - return result; } -static int write_tar_archive(const char *hex, const char *prefix) +static void write_snapshot(const struct cgit_snapshot_format *format, + const char *hex, const char *prefix) { - return write_archive_format("--format=tar", hex, prefix); -} + struct cgit_exec_filter compressor; + struct cgit_filter *filter = NULL; -static int write_zip_archive(const char *hex, const char *prefix) -{ - return write_archive_format("--format=zip", hex, prefix); + if (format->compressor) { + cgit_exec_filter_init(&compressor, format->compressor[0], + format->compressor); + filter = &compressor.base; + } + cgit_open_filter(filter); + write_archive_format(format->format_arg, hex, prefix); + cgit_close_filter(filter); } static int program_on_path(const char *program) @@ -101,66 +105,25 @@ static int program_on_path(const char *program) return found; } -static int write_compressed_tar_archive(const char *hex, const char *prefix, const char *argv[]) -{ - struct cgit_exec_filter filter; - int result; - - cgit_exec_filter_init(&filter, argv[0], argv); - cgit_open_filter(&filter.base); - result = write_tar_archive(hex, prefix); - cgit_close_filter(&filter.base); - return result; -} - -static int write_tar_gzip_archive(const char *hex, const char *prefix) -{ - const char *argv[] = { "gzip", "-n", NULL }; - - return write_compressed_tar_archive(hex, prefix, argv); -} - -static int write_tar_bzip2_archive(const char *hex, const char *prefix) -{ - const char *argv[] = { "bzip2", NULL }; - - return write_compressed_tar_archive(hex, prefix, argv); -} - -static int write_tar_lzip_archive(const char *hex, const char *prefix) -{ - const char *argv[] = { "lzip", NULL }; - - return write_compressed_tar_archive(hex, prefix, argv); -} - -static int write_tar_xz_archive(const char *hex, const char *prefix) -{ - // Current xz runs a thread per core unless told otherwise. - const char *argv[] = { "xz", "-T1", NULL }; - - return write_compressed_tar_archive(hex, prefix, argv); -} - -static int write_tar_zstd_archive(const char *hex, const char *prefix) -{ - // Single-threaded like the other compressors, since -T0 would let one - // request pin every core. - const char *argv[] = { "zstd", NULL }; - - return write_compressed_tar_archive(hex, prefix, argv); -} +static const char *gzip_argv[] = { "gzip", "-n", NULL }; +static const char *bzip2_argv[] = { "bzip2", NULL }; +static const char *lzip_argv[] = { "lzip", NULL }; +// Current xz runs a thread per core unless told otherwise. +static const char *xz_argv[] = { "xz", "-T1", NULL }; +// Single-threaded like the other compressors, since -T0 would let one +// request pin every core. +static const char *zstd_argv[] = { "zstd", NULL }; // ui-shared.c reads entry zero as the tar whose signature stands in for every // tar variant, so this order cannot change. const struct cgit_snapshot_format cgit_snapshot_formats[] = { - { ".tar", "application/x-tar", write_tar_archive, NULL }, - { ".tar.gz", "application/gzip", write_tar_gzip_archive, "gzip" }, - { ".tar.bz2", "application/x-bzip2", write_tar_bzip2_archive, "bzip2" }, - { ".tar.lz", "application/x-lzip", write_tar_lzip_archive, "lzip" }, - { ".tar.xz", "application/x-xz", write_tar_xz_archive, "xz" }, - { ".tar.zst", "application/zstd", write_tar_zstd_archive, "zstd" }, - { ".zip", "application/zip", write_zip_archive, NULL }, + { ".tar", "application/x-tar", "--format=tar", NULL }, + { ".tar.gz", "application/gzip", "--format=tar", gzip_argv }, + { ".tar.bz2", "application/x-bzip2", "--format=tar", bzip2_argv }, + { ".tar.lz", "application/x-lzip", "--format=tar", lzip_argv }, + { ".tar.xz", "application/x-xz", "--format=tar", xz_argv }, + { ".tar.zst", "application/zstd", "--format=tar", zstd_argv }, + { ".zip", "application/zip", "--format=zip", NULL }, { 0 } }; @@ -277,8 +240,9 @@ static int send_snapshot(const struct cgit_snapshot_format *format, const char * // A compressor that cannot run only shows up as a broken pipe once // the tar is under way, so it is looked for while a status can still // say so. - if (format->program && !program_on_path(format->program)) { - cgit_print_error_page(500, "Internal Server Error", "Unable to run %s", format->program); + if (format->compressor && !program_on_path(format->compressor[0])) { + cgit_print_error_page(500, "Internal Server Error", "Unable to run %s", + format->compressor[0]); return 1; } ctx.page.mimetype = xstrdup(format->mimetype); @@ -287,7 +251,7 @@ static int send_snapshot(const struct cgit_snapshot_format *format, const char * init_archivers(); // The archiver reads its arguments as a command line, so it gets the // resolved id and never the name. - format->write_func(oid_to_hex(&oid), prefix); + write_snapshot(format, oid_to_hex(&oid), prefix); return 0; } diff --git a/source/ui-snapshot.h b/source/ui-snapshot.h index 412807e..2278f4c 100644 --- a/source/ui-snapshot.h +++ b/source/ui-snapshot.h @@ -11,14 +11,13 @@ #include "cgit.h" -typedef int (*write_archive_fn_t)(const char *hex, const char *prefix); - struct cgit_snapshot_format { const char *suffix; const char *mimetype; - write_archive_fn_t write_func; - // The compressor the writer runs, or NULL when it needs none. - const char *program; + const char *format_arg; + // The command line git's output is piped through, or NULL when the + // archive goes out as git writes it. + const char **compressor; }; // Terminated by an entry with a NULL suffix. |
