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