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