/* * Copyright (C) the libgit2 contributors. All rights reserved. * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ #include #include #include "common.h" #include "cmd.h" static int show_help = 0; static int show_version = 0; static char *command = NULL; static char **args = NULL; const cli_opt_spec cli_common_opts[] = { { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1, CLI_OPT_USAGE_DEFAULT, NULL, "display help information" }, { CLI_OPT_TYPE_VALUE, NULL, 'c', NULL, 0, CLI_OPT_USAGE_DEFAULT, "key=value", "add configuration value" }, { CLI_OPT_TYPE_VALUE, "config-env", 0, NULL, 0, CLI_OPT_USAGE_DEFAULT, "key=value", "set configuration value to environment variable" }, { CLI_OPT_TYPE_SWITCH, "version", 0, &show_version, 1, CLI_OPT_USAGE_DEFAULT, NULL, "display the version" }, { CLI_OPT_TYPE_ARG, "command", 0, &command, 0, CLI_OPT_USAGE_REQUIRED, "command", "the command to run" }, { CLI_OPT_TYPE_ARGS, "args", 0, &args, 0, CLI_OPT_USAGE_DEFAULT, "args", "arguments for the command" }, { 0 } }; const cli_cmd_spec cli_cmds[] = { { "cat-file", cmd_cat_file, "Display an object in the repository" }, { "clone", cmd_clone, "Clone a repository into a new directory" }, { "config", cmd_config, "View or set configuration values " }, { "hash-object", cmd_hash_object, "Hash a raw object and product its object ID" }, { "help", cmd_help, "Display help information" }, { "index-pack", cmd_index_pack, "Create an index for a packfile" }, { NULL } }; /* * Reorder the argv as it was given, since git has the notion of global * options (like `--help` or `-c key=val`) that we want to pass to the * subcommand, and that can appear early in the arguments, before the * command name. Put the command-name in argv[1] to allow easier parsing. */ static void reorder_args(char **argv, size_t first) { char *tmp; size_t i; if (first == 1) return; tmp = argv[first]; for (i = first; i > 1; i--) argv[i] = argv[i - 1]; argv[1] = tmp; } int main(int argc, char **argv) { const cli_cmd_spec *cmd; cli_opt_parser optparser; cli_opt opt; int ret = 0; if (git_libgit2_init() < 0) { cli_error("failed to initialize libgit2"); exit(CLI_EXIT_GIT); } cli_opt_parser_init(&optparser, cli_common_opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU); /* Parse the top-level (common) options and command information */ while (cli_opt_parser_next(&opt, &optparser)) { if (!opt.spec) { cli_opt_status_fprint(stderr, PROGRAM_NAME, &opt); cli_opt_usage_fprint(stderr, PROGRAM_NAME, NULL, cli_common_opts); ret = CLI_EXIT_USAGE; goto done; } /* * When we see a command, stop parsing and capture the * remaining arguments as args for the command itself. */ if (command) { reorder_args(argv, optparser.idx); break; } } if (show_version) { printf("%s version %s\n", PROGRAM_NAME, LIBGIT2_VERSION); goto done; } if (!command) { ret = cmd_help(argc, argv); goto done; } if ((cmd = cli_cmd_spec_byname(command)) == NULL) { ret = cli_error("'%s' is not a %s command. See '%s help'.", command, PROGRAM_NAME, PROGRAM_NAME); goto done; } ret = cmd->fn(argc - 1, &argv[1]); done: git_libgit2_shutdown(); return ret; }