return 0;
 }
 
-static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result cacheinfo_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        struct object_id oid;
        unsigned int mode;
        const char *path;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) {
                if (add_cacheinfo(mode, &oid, path, 0))
        return 0;
 }
 
-static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx,
-                             const struct option *opt, int unset)
+static enum parse_opt_result stdin_cacheinfo_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *nul_term_line = opt->value;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
        return 0;
 }
 
-static int stdin_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result stdin_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *read_from_stdin = opt->value;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
        return 0;
 }
 
-static int unresolve_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result unresolve_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *has_errors = opt->value;
        const char *prefix = startup_info->prefix;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        /* consume remaining arguments. */
        *has_errors = do_unresolve(ctx->argc, ctx->argv,
        return 0;
 }
 
-static int reupdate_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int unset)
+static enum parse_opt_result reupdate_callback(
+       struct parse_opt_ctx_t *ctx, const struct option *opt,
+       const char *arg, int unset)
 {
        int *has_errors = opt->value;
        const char *prefix = startup_info->prefix;
 
        BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
 
        /* consume remaining arguments. */
        setup_work_tree();
                        N_("add the specified entry to the index"),
                        PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
                        PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
-                       (parse_opt_cb *) cacheinfo_callback},
+                       NULL, 0,
+                       cacheinfo_callback},
                {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, "(+|-)x",
                        N_("override the executable bit of the listed files"),
                        PARSE_OPT_NONEG,
                {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
                        N_("read list of paths to be updated from standard input"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) stdin_callback},
+                       NULL, 0, stdin_callback},
                {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL,
                        N_("add entries from standard input to the index"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) stdin_cacheinfo_callback},
+                       NULL, 0, stdin_cacheinfo_callback},
                {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
                        N_("repopulate stages #2 and #3 for the listed paths"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) unresolve_callback},
+                       NULL, 0, unresolve_callback},
                {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
                        N_("only update entries that differ from HEAD"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-                       (parse_opt_cb *) reupdate_callback},
+                       NULL, 0, reupdate_callback},
                OPT_BIT(0, "ignore-missing", &refresh_args.flags,
                        N_("ignore files missing from worktree"),
                        REFRESH_IGNORE_MISSING),
                case PARSE_OPT_HELP:
                case PARSE_OPT_ERROR:
                        exit(129);
+               case PARSE_OPT_COMPLETE:
+                       exit(0);
                case PARSE_OPT_NON_OPTION:
                case PARSE_OPT_DONE:
                {