t / helper / test-ref-store.con commit completion: add and use --list-cmds=nohelpers (e11dca1)
   1#include "test-tool.h"
   2#include "cache.h"
   3#include "refs.h"
   4#include "worktree.h"
   5#include "object-store.h"
   6
   7static const char *notnull(const char *arg, const char *name)
   8{
   9        if (!arg)
  10                die("%s required", name);
  11        return arg;
  12}
  13
  14static unsigned int arg_flags(const char *arg, const char *name)
  15{
  16        return atoi(notnull(arg, name));
  17}
  18
  19static const char **get_store(const char **argv, struct ref_store **refs)
  20{
  21        const char *gitdir;
  22
  23        if (!argv[0]) {
  24                die("ref store required");
  25        } else if (!strcmp(argv[0], "main")) {
  26                *refs = get_main_ref_store();
  27        } else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
  28                struct strbuf sb = STRBUF_INIT;
  29                int ret;
  30
  31                ret = strbuf_git_path_submodule(&sb, gitdir, "objects/");
  32                if (ret)
  33                        die("strbuf_git_path_submodule failed: %d", ret);
  34                add_to_alternates_memory(sb.buf);
  35                strbuf_release(&sb);
  36
  37                *refs = get_submodule_ref_store(gitdir);
  38        } else if (skip_prefix(argv[0], "worktree:", &gitdir)) {
  39                struct worktree **p, **worktrees = get_worktrees(0);
  40
  41                for (p = worktrees; *p; p++) {
  42                        struct worktree *wt = *p;
  43
  44                        if (!wt->id) {
  45                                /* special case for main worktree */
  46                                if (!strcmp(gitdir, "main"))
  47                                        break;
  48                        } else if (!strcmp(gitdir, wt->id))
  49                                break;
  50                }
  51                if (!*p)
  52                        die("no such worktree: %s", gitdir);
  53
  54                *refs = get_worktree_ref_store(*p);
  55        } else
  56                die("unknown backend %s", argv[0]);
  57
  58        if (!*refs)
  59                die("no ref store");
  60
  61        /* consume store-specific optional arguments if needed */
  62
  63        return argv + 1;
  64}
  65
  66
  67static int cmd_pack_refs(struct ref_store *refs, const char **argv)
  68{
  69        unsigned int flags = arg_flags(*argv++, "flags");
  70
  71        return refs_pack_refs(refs, flags);
  72}
  73
  74static int cmd_peel_ref(struct ref_store *refs, const char **argv)
  75{
  76        const char *refname = notnull(*argv++, "refname");
  77        struct object_id oid;
  78        int ret;
  79
  80        ret = refs_peel_ref(refs, refname, &oid);
  81        if (!ret)
  82                puts(oid_to_hex(&oid));
  83        return ret;
  84}
  85
  86static int cmd_create_symref(struct ref_store *refs, const char **argv)
  87{
  88        const char *refname = notnull(*argv++, "refname");
  89        const char *target = notnull(*argv++, "target");
  90        const char *logmsg = *argv++;
  91
  92        return refs_create_symref(refs, refname, target, logmsg);
  93}
  94
  95static int cmd_delete_refs(struct ref_store *refs, const char **argv)
  96{
  97        unsigned int flags = arg_flags(*argv++, "flags");
  98        const char *msg = *argv++;
  99        struct string_list refnames = STRING_LIST_INIT_NODUP;
 100
 101        while (*argv)
 102                string_list_append(&refnames, *argv++);
 103
 104        return refs_delete_refs(refs, msg, &refnames, flags);
 105}
 106
 107static int cmd_rename_ref(struct ref_store *refs, const char **argv)
 108{
 109        const char *oldref = notnull(*argv++, "oldref");
 110        const char *newref = notnull(*argv++, "newref");
 111        const char *logmsg = *argv++;
 112
 113        return refs_rename_ref(refs, oldref, newref, logmsg);
 114}
 115
 116static int each_ref(const char *refname, const struct object_id *oid,
 117                    int flags, void *cb_data)
 118{
 119        printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
 120        return 0;
 121}
 122
 123static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
 124{
 125        const char *prefix = notnull(*argv++, "prefix");
 126
 127        return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
 128}
 129
 130static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
 131{
 132        struct object_id oid;
 133        const char *refname = notnull(*argv++, "refname");
 134        int resolve_flags = arg_flags(*argv++, "resolve-flags");
 135        int flags;
 136        const char *ref;
 137
 138        ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
 139                                      &oid, &flags);
 140        printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
 141        return ref ? 0 : 1;
 142}
 143
 144static int cmd_verify_ref(struct ref_store *refs, const char **argv)
 145{
 146        const char *refname = notnull(*argv++, "refname");
 147        struct strbuf err = STRBUF_INIT;
 148        int ret;
 149
 150        ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err);
 151        if (err.len)
 152                puts(err.buf);
 153        return ret;
 154}
 155
 156static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
 157{
 158        return refs_for_each_reflog(refs, each_ref, NULL);
 159}
 160
 161static int each_reflog(struct object_id *old_oid, struct object_id *new_oid,
 162                       const char *committer, timestamp_t timestamp,
 163                       int tz, const char *msg, void *cb_data)
 164{
 165        printf("%s %s %s %"PRItime" %d %s\n",
 166               oid_to_hex(old_oid), oid_to_hex(new_oid),
 167               committer, timestamp, tz, msg);
 168        return 0;
 169}
 170
 171static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv)
 172{
 173        const char *refname = notnull(*argv++, "refname");
 174
 175        return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
 176}
 177
 178static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
 179{
 180        const char *refname = notnull(*argv++, "refname");
 181
 182        return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
 183}
 184
 185static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
 186{
 187        const char *refname = notnull(*argv++, "refname");
 188
 189        return !refs_reflog_exists(refs, refname);
 190}
 191
 192static int cmd_create_reflog(struct ref_store *refs, const char **argv)
 193{
 194        const char *refname = notnull(*argv++, "refname");
 195        int force_create = arg_flags(*argv++, "force-create");
 196        struct strbuf err = STRBUF_INIT;
 197        int ret;
 198
 199        ret = refs_create_reflog(refs, refname, force_create, &err);
 200        if (err.len)
 201                puts(err.buf);
 202        return ret;
 203}
 204
 205static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
 206{
 207        const char *refname = notnull(*argv++, "refname");
 208
 209        return refs_delete_reflog(refs, refname);
 210}
 211
 212static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
 213{
 214        die("not supported yet");
 215}
 216
 217static int cmd_delete_ref(struct ref_store *refs, const char **argv)
 218{
 219        const char *msg = notnull(*argv++, "msg");
 220        const char *refname = notnull(*argv++, "refname");
 221        const char *sha1_buf = notnull(*argv++, "old-sha1");
 222        unsigned int flags = arg_flags(*argv++, "flags");
 223        struct object_id old_oid;
 224
 225        if (get_oid_hex(sha1_buf, &old_oid))
 226                die("not sha-1");
 227
 228        return refs_delete_ref(refs, msg, refname, &old_oid, flags);
 229}
 230
 231static int cmd_update_ref(struct ref_store *refs, const char **argv)
 232{
 233        const char *msg = notnull(*argv++, "msg");
 234        const char *refname = notnull(*argv++, "refname");
 235        const char *new_sha1_buf = notnull(*argv++, "old-sha1");
 236        const char *old_sha1_buf = notnull(*argv++, "old-sha1");
 237        unsigned int flags = arg_flags(*argv++, "flags");
 238        struct object_id old_oid;
 239        struct object_id new_oid;
 240
 241        if (get_oid_hex(old_sha1_buf, &old_oid) ||
 242            get_oid_hex(new_sha1_buf, &new_oid))
 243                die("not sha-1");
 244
 245        return refs_update_ref(refs, msg, refname,
 246                               &new_oid, &old_oid,
 247                               flags, UPDATE_REFS_DIE_ON_ERR);
 248}
 249
 250struct command {
 251        const char *name;
 252        int (*func)(struct ref_store *refs, const char **argv);
 253};
 254
 255static struct command commands[] = {
 256        { "pack-refs", cmd_pack_refs },
 257        { "peel-ref", cmd_peel_ref },
 258        { "create-symref", cmd_create_symref },
 259        { "delete-refs", cmd_delete_refs },
 260        { "rename-ref", cmd_rename_ref },
 261        { "for-each-ref", cmd_for_each_ref },
 262        { "resolve-ref", cmd_resolve_ref },
 263        { "verify-ref", cmd_verify_ref },
 264        { "for-each-reflog", cmd_for_each_reflog },
 265        { "for-each-reflog-ent", cmd_for_each_reflog_ent },
 266        { "for-each-reflog-ent-reverse", cmd_for_each_reflog_ent_reverse },
 267        { "reflog-exists", cmd_reflog_exists },
 268        { "create-reflog", cmd_create_reflog },
 269        { "delete-reflog", cmd_delete_reflog },
 270        { "reflog-expire", cmd_reflog_expire },
 271        /*
 272         * backend transaction functions can't be tested separately
 273         */
 274        { "delete-ref", cmd_delete_ref },
 275        { "update-ref", cmd_update_ref },
 276        { NULL, NULL }
 277};
 278
 279int cmd__ref_store(int argc, const char **argv)
 280{
 281        struct ref_store *refs;
 282        const char *func;
 283        struct command *cmd;
 284
 285        setup_git_directory();
 286
 287        argv = get_store(argv + 1, &refs);
 288
 289        func = *argv++;
 290        if (!func)
 291                die("ref function required");
 292        for (cmd = commands; cmd->name; cmd++) {
 293                if (!strcmp(func, cmd->name))
 294                        return cmd->func(refs, argv);
 295        }
 296        die("unknown function %s", func);
 297        return 0;
 298}