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