Git fork
at reftables-rust 202 lines 5.3 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#include "builtin.h" 3#include "config.h" 4#include "fsck.h" 5#include "pack-refs.h" 6#include "parse-options.h" 7#include "refs.h" 8#include "strbuf.h" 9#include "worktree.h" 10#include "for-each-ref.h" 11#include "refs/refs-internal.h" 12 13#define REFS_MIGRATE_USAGE \ 14 N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]") 15 16#define REFS_VERIFY_USAGE \ 17 N_("git refs verify [--strict] [--verbose]") 18 19#define REFS_EXISTS_USAGE \ 20 N_("git refs exists <ref>") 21 22#define REFS_OPTIMIZE_USAGE \ 23 N_("git refs optimize " PACK_REFS_OPTS) 24 25static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, 26 struct repository *repo UNUSED) 27{ 28 const char * const migrate_usage[] = { 29 REFS_MIGRATE_USAGE, 30 NULL, 31 }; 32 const char *format_str = NULL; 33 enum ref_storage_format format; 34 unsigned int flags = 0; 35 struct option options[] = { 36 OPT_STRING_F(0, "ref-format", &format_str, N_("format"), 37 N_("specify the reference format to convert to"), 38 PARSE_OPT_NONEG), 39 OPT_BIT(0, "dry-run", &flags, 40 N_("perform a non-destructive dry-run"), 41 REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN), 42 OPT_BIT(0, "no-reflog", &flags, 43 N_("drop reflogs entirely during the migration"), 44 REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG), 45 OPT_END(), 46 }; 47 struct strbuf errbuf = STRBUF_INIT; 48 int err; 49 50 argc = parse_options(argc, argv, prefix, options, migrate_usage, 0); 51 if (argc) 52 usage(_("too many arguments")); 53 if (!format_str) 54 usage(_("missing --ref-format=<format>")); 55 56 format = ref_storage_format_by_name(format_str); 57 if (format == REF_STORAGE_FORMAT_UNKNOWN) { 58 err = error(_("unknown ref storage format '%s'"), format_str); 59 goto out; 60 } 61 62 if (the_repository->ref_storage_format == format) { 63 err = error(_("repository already uses '%s' format"), 64 ref_storage_format_to_name(format)); 65 goto out; 66 } 67 68 if (repo_migrate_ref_storage_format(the_repository, format, flags, &errbuf) < 0) { 69 err = error("%s", errbuf.buf); 70 goto out; 71 } 72 73 err = 0; 74 75out: 76 strbuf_release(&errbuf); 77 return err; 78} 79 80static int cmd_refs_verify(int argc, const char **argv, const char *prefix, 81 struct repository *repo UNUSED) 82{ 83 struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT; 84 struct worktree **worktrees; 85 const char * const verify_usage[] = { 86 REFS_VERIFY_USAGE, 87 NULL, 88 }; 89 struct option options[] = { 90 OPT_BOOL(0, "verbose", &fsck_refs_options.verbose, N_("be verbose")), 91 OPT_BOOL(0, "strict", &fsck_refs_options.strict, N_("enable strict checking")), 92 OPT_END(), 93 }; 94 int ret = 0; 95 96 argc = parse_options(argc, argv, prefix, options, verify_usage, 0); 97 if (argc) 98 usage(_("'git refs verify' takes no arguments")); 99 100 repo_config(the_repository, git_fsck_config, &fsck_refs_options); 101 prepare_repo_settings(the_repository); 102 103 worktrees = get_worktrees_without_reading_head(); 104 for (size_t i = 0; worktrees[i]; i++) 105 ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), 106 &fsck_refs_options, worktrees[i]); 107 108 fsck_options_clear(&fsck_refs_options); 109 free_worktrees(worktrees); 110 return ret; 111} 112 113static int cmd_refs_list(int argc, const char **argv, const char *prefix, 114 struct repository *repo) 115{ 116 static char const * const refs_list_usage[] = { 117 N_("git refs list " COMMON_USAGE_FOR_EACH_REF), 118 NULL 119 }; 120 121 return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage); 122} 123 124static int cmd_refs_exists(int argc, const char **argv, const char *prefix, 125 struct repository *repo UNUSED) 126{ 127 struct strbuf unused_referent = STRBUF_INIT; 128 struct object_id unused_oid; 129 unsigned int unused_type; 130 int failure_errno = 0; 131 const char *ref; 132 int ret = 0; 133 const char * const exists_usage[] = { 134 REFS_EXISTS_USAGE, 135 NULL, 136 }; 137 struct option options[] = { 138 OPT_END(), 139 }; 140 141 argc = parse_options(argc, argv, prefix, options, exists_usage, 0); 142 if (argc != 1) 143 die(_("'git refs exists' requires a reference")); 144 145 ref = *argv++; 146 if (refs_read_raw_ref(get_main_ref_store(the_repository), ref, 147 &unused_oid, &unused_referent, &unused_type, 148 &failure_errno)) { 149 if (failure_errno == ENOENT || failure_errno == EISDIR) { 150 error(_("reference does not exist")); 151 ret = 2; 152 } else { 153 errno = failure_errno; 154 error_errno(_("failed to look up reference")); 155 ret = 1; 156 } 157 158 goto out; 159 } 160 161out: 162 strbuf_release(&unused_referent); 163 return ret; 164} 165 166static int cmd_refs_optimize(int argc, const char **argv, const char *prefix, 167 struct repository *repo) 168{ 169 static char const * const refs_optimize_usage[] = { 170 REFS_OPTIMIZE_USAGE, 171 NULL 172 }; 173 174 return pack_refs_core(argc, argv, prefix, repo, refs_optimize_usage); 175} 176 177int cmd_refs(int argc, 178 const char **argv, 179 const char *prefix, 180 struct repository *repo) 181{ 182 const char * const refs_usage[] = { 183 REFS_MIGRATE_USAGE, 184 REFS_VERIFY_USAGE, 185 "git refs list " COMMON_USAGE_FOR_EACH_REF, 186 REFS_EXISTS_USAGE, 187 REFS_OPTIMIZE_USAGE, 188 NULL, 189 }; 190 parse_opt_subcommand_fn *fn = NULL; 191 struct option opts[] = { 192 OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate), 193 OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify), 194 OPT_SUBCOMMAND("list", &fn, cmd_refs_list), 195 OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists), 196 OPT_SUBCOMMAND("optimize", &fn, cmd_refs_optimize), 197 OPT_END(), 198 }; 199 200 argc = parse_options(argc, argv, prefix, opts, refs_usage, 0); 201 return fn(argc, argv, prefix, repo); 202}