Git fork
at reftables-rust 255 lines 7.1 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#include "builtin.h" 3#include "abspath.h" 4#include "gettext.h" 5#include "setup.h" 6#include "strvec.h" 7#include "parse-options.h" 8#include "pkt-line.h" 9#include "bundle.h" 10 11/* 12 * Basic handler for bundle files to connect repositories via sneakernet. 13 * Invocation must include action. 14 * This function can create a bundle or provide information on an existing 15 * bundle supporting "fetch", "pull", and "ls-remote". 16 */ 17 18#define BUILTIN_BUNDLE_CREATE_USAGE \ 19 N_("git bundle create [-q | --quiet | --progress]\n" \ 20 " [--version=<version>] <file> <git-rev-list-args>") 21#define BUILTIN_BUNDLE_VERIFY_USAGE \ 22 N_("git bundle verify [-q | --quiet] <file>") 23#define BUILTIN_BUNDLE_LIST_HEADS_USAGE \ 24 N_("git bundle list-heads <file> [<refname>...]") 25#define BUILTIN_BUNDLE_UNBUNDLE_USAGE \ 26 N_("git bundle unbundle [--progress] <file> [<refname>...]") 27 28static char const * const builtin_bundle_usage[] = { 29 BUILTIN_BUNDLE_CREATE_USAGE, 30 BUILTIN_BUNDLE_VERIFY_USAGE, 31 BUILTIN_BUNDLE_LIST_HEADS_USAGE, 32 BUILTIN_BUNDLE_UNBUNDLE_USAGE, 33 NULL, 34}; 35 36static const char * const builtin_bundle_create_usage[] = { 37 BUILTIN_BUNDLE_CREATE_USAGE, 38 NULL 39}; 40 41static const char * const builtin_bundle_verify_usage[] = { 42 BUILTIN_BUNDLE_VERIFY_USAGE, 43 NULL 44}; 45 46static const char * const builtin_bundle_list_heads_usage[] = { 47 BUILTIN_BUNDLE_LIST_HEADS_USAGE, 48 NULL 49}; 50 51static const char * const builtin_bundle_unbundle_usage[] = { 52 BUILTIN_BUNDLE_UNBUNDLE_USAGE, 53 NULL 54}; 55 56static int parse_options_cmd_bundle(int argc, 57 const char **argv, 58 const char* prefix, 59 const char * const usagestr[], 60 const struct option options[], 61 char **bundle_file) { 62 argc = parse_options(argc, argv, NULL, options, usagestr, 63 PARSE_OPT_STOP_AT_NON_OPTION); 64 if (!argc) 65 usage_msg_opt(_("need a <file> argument"), usagestr, options); 66 *bundle_file = prefix_filename_except_for_dash(prefix, argv[0]); 67 return argc; 68} 69 70static int cmd_bundle_create(int argc, const char **argv, const char *prefix, 71 struct repository *repo UNUSED) { 72 struct strvec pack_opts = STRVEC_INIT; 73 int version = -1; 74 int ret; 75 struct option options[] = { 76 OPT_PASSTHRU_ARGV('q', "quiet", &pack_opts, NULL, 77 N_("do not show progress meter"), 78 PARSE_OPT_NOARG), 79 OPT_PASSTHRU_ARGV(0, "progress", &pack_opts, NULL, 80 N_("show progress meter"), 81 PARSE_OPT_NOARG), 82 OPT_PASSTHRU_ARGV(0, "all-progress", &pack_opts, NULL, 83 N_("historical; same as --progress"), 84 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN), 85 OPT_PASSTHRU_ARGV(0, "all-progress-implied", &pack_opts, NULL, 86 N_("historical; does nothing"), 87 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN), 88 OPT_INTEGER(0, "version", &version, 89 N_("specify bundle format version")), 90 OPT_END() 91 }; 92 char *bundle_file; 93 94 if (isatty(STDERR_FILENO)) 95 strvec_push(&pack_opts, "--progress"); 96 strvec_push(&pack_opts, "--all-progress-implied"); 97 98 argc = parse_options_cmd_bundle(argc, argv, prefix, 99 builtin_bundle_create_usage, options, &bundle_file); 100 /* bundle internals use argv[1] as further parameters */ 101 102 if (!startup_info->have_repository) 103 die(_("Need a repository to create a bundle.")); 104 ret = !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts, version); 105 strvec_clear(&pack_opts); 106 free(bundle_file); 107 return ret; 108} 109 110/* 111 * Similar to read_bundle_header(), but handle "-" as stdin. 112 */ 113static int open_bundle(const char *path, struct bundle_header *header, 114 const char **name) 115{ 116 if (!strcmp(path, "-")) { 117 if (name) 118 *name = "<stdin>"; 119 return read_bundle_header_fd(0, header, "<stdin>"); 120 } 121 122 if (name) 123 *name = path; 124 return read_bundle_header(path, header); 125} 126 127static int cmd_bundle_verify(int argc, const char **argv, const char *prefix, 128 struct repository *repo UNUSED) { 129 struct bundle_header header = BUNDLE_HEADER_INIT; 130 int bundle_fd = -1; 131 int quiet = 0; 132 int ret; 133 struct option options[] = { 134 OPT_BOOL('q', "quiet", &quiet, 135 N_("do not show bundle details")), 136 OPT_END() 137 }; 138 char *bundle_file; 139 const char *name; 140 141 argc = parse_options_cmd_bundle(argc, argv, prefix, 142 builtin_bundle_verify_usage, options, &bundle_file); 143 /* bundle internals use argv[1] as further parameters */ 144 145 if (!startup_info->have_repository) { 146 ret = error(_("need a repository to verify a bundle")); 147 goto cleanup; 148 } 149 150 if ((bundle_fd = open_bundle(bundle_file, &header, &name)) < 0) { 151 ret = 1; 152 goto cleanup; 153 } 154 close(bundle_fd); 155 if (verify_bundle(the_repository, &header, 156 quiet ? VERIFY_BUNDLE_QUIET : VERIFY_BUNDLE_VERBOSE)) { 157 ret = 1; 158 goto cleanup; 159 } 160 161 fprintf(stderr, _("%s is okay\n"), name); 162 ret = 0; 163cleanup: 164 free(bundle_file); 165 bundle_header_release(&header); 166 return ret; 167} 168 169static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix, 170 struct repository *repo UNUSED) { 171 struct bundle_header header = BUNDLE_HEADER_INIT; 172 int bundle_fd = -1; 173 int ret; 174 struct option options[] = { 175 OPT_END() 176 }; 177 char *bundle_file; 178 179 argc = parse_options_cmd_bundle(argc, argv, prefix, 180 builtin_bundle_list_heads_usage, options, &bundle_file); 181 /* bundle internals use argv[1] as further parameters */ 182 183 if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) { 184 ret = 1; 185 goto cleanup; 186 } 187 close(bundle_fd); 188 ret = !!list_bundle_refs(&header, argc, argv); 189cleanup: 190 free(bundle_file); 191 bundle_header_release(&header); 192 return ret; 193} 194 195static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix, 196 struct repository *repo UNUSED) { 197 struct bundle_header header = BUNDLE_HEADER_INIT; 198 int bundle_fd = -1; 199 int ret; 200 int progress = isatty(2); 201 202 struct option options[] = { 203 OPT_BOOL(0, "progress", &progress, 204 N_("show progress meter")), 205 OPT_END() 206 }; 207 char *bundle_file; 208 struct strvec extra_index_pack_args = STRVEC_INIT; 209 210 argc = parse_options_cmd_bundle(argc, argv, prefix, 211 builtin_bundle_unbundle_usage, options, &bundle_file); 212 /* bundle internals use argv[1] as further parameters */ 213 214 if (!startup_info->have_repository) 215 die(_("Need a repository to unbundle.")); 216 217 if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) { 218 ret = 1; 219 goto cleanup; 220 } 221 if (progress) 222 strvec_pushl(&extra_index_pack_args, "-v", "--progress-title", 223 _("Unbundling objects"), NULL); 224 ret = !!unbundle(the_repository, &header, bundle_fd, 225 &extra_index_pack_args, NULL) || 226 list_bundle_refs(&header, argc, argv); 227 bundle_header_release(&header); 228 229cleanup: 230 strvec_clear(&extra_index_pack_args); 231 free(bundle_file); 232 return ret; 233} 234 235int cmd_bundle(int argc, 236 const char **argv, 237 const char *prefix, 238 struct repository *repo) 239{ 240 parse_opt_subcommand_fn *fn = NULL; 241 struct option options[] = { 242 OPT_SUBCOMMAND("create", &fn, cmd_bundle_create), 243 OPT_SUBCOMMAND("verify", &fn, cmd_bundle_verify), 244 OPT_SUBCOMMAND("list-heads", &fn, cmd_bundle_list_heads), 245 OPT_SUBCOMMAND("unbundle", &fn, cmd_bundle_unbundle), 246 OPT_END() 247 }; 248 249 argc = parse_options(argc, argv, prefix, options, builtin_bundle_usage, 250 0); 251 252 packet_trace_identity("bundle"); 253 254 return !!fn(argc, argv, prefix, repo); 255}