/** Parse arguments as copied from git-diff. */ static void parse_opts(struct opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; for (args.pos = 1; args.pos < argc; ++args.pos) { const char *a = argv[args.pos]; if (a[0] != '-') { if (o->treeish1 == NULL) o->treeish1 = a; else if (o->treeish2 == NULL) o->treeish2 = a; else usage("Only one or two tree identifiers can be provided", NULL); } else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) { o->output |= OUTPUT_DIFF; o->format = GIT_DIFF_FORMAT_PATCH; } else if (!strcmp(a, "--cached")) o->cache = CACHE_ONLY; else if (!strcmp(a, "--nocache")) o->cache = CACHE_NONE; else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name")) o->format = GIT_DIFF_FORMAT_NAME_ONLY; else if (!strcmp(a, "--name-status") || !strcmp(a, "--format=name-status")) o->format = GIT_DIFF_FORMAT_NAME_STATUS; else if (!strcmp(a, "--raw") || !strcmp(a, "--format=raw")) o->format = GIT_DIFF_FORMAT_RAW; else if (!strcmp(a, "--format=diff-index")) { o->format = GIT_DIFF_FORMAT_RAW; o->diffopts.id_abbrev = 40; } else if (!strcmp(a, "--color")) o->color = 0; else if (!strcmp(a, "--no-color")) o->color = -1; else if (!strcmp(a, "-R")) o->diffopts.flags |= GIT_DIFF_REVERSE; else if (!strcmp(a, "-a") || !strcmp(a, "--text")) o->diffopts.flags |= GIT_DIFF_FORCE_TEXT; else if (!strcmp(a, "--ignore-space-at-eol")) o->diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE_EOL; else if (!strcmp(a, "-b") || !strcmp(a, "--ignore-space-change")) o->diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE_CHANGE; else if (!strcmp(a, "-w") || !strcmp(a, "--ignore-all-space")) o->diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE; else if (!strcmp(a, "--ignored")) o->diffopts.flags |= GIT_DIFF_INCLUDE_IGNORED; else if (!strcmp(a, "--untracked")) o->diffopts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; else if (!strcmp(a, "--patience")) o->diffopts.flags |= GIT_DIFF_PATIENCE; else if (!strcmp(a, "--minimal")) o->diffopts.flags |= GIT_DIFF_MINIMAL; else if (!strcmp(a, "--stat")) o->output |= OUTPUT_STAT; else if (!strcmp(a, "--numstat")) o->output |= OUTPUT_NUMSTAT; else if (!strcmp(a, "--shortstat")) o->output |= OUTPUT_SHORTSTAT; else if (!strcmp(a, "--summary")) o->output |= OUTPUT_SUMMARY; else if (match_uint16_arg( &o->findopts.rename_threshold, &args, "-M") || match_uint16_arg( &o->findopts.rename_threshold, &args, "--find-renames")) o->findopts.flags |= GIT_DIFF_FIND_RENAMES; else if (match_uint16_arg( &o->findopts.copy_threshold, &args, "-C") || match_uint16_arg( &o->findopts.copy_threshold, &args, "--find-copies")) o->findopts.flags |= GIT_DIFF_FIND_COPIES; else if (!strcmp(a, "--find-copies-harder")) o->findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; else if (is_prefixed(a, "-B") || is_prefixed(a, "--break-rewrites")) /* TODO: parse thresholds */ o->findopts.flags |= GIT_DIFF_FIND_REWRITES; else if (!match_uint32_arg( &o->diffopts.context_lines, &args, "-U") && !match_uint32_arg( &o->diffopts.context_lines, &args, "--unified") && !match_uint32_arg( &o->diffopts.interhunk_lines, &args, "--inter-hunk-context") && !match_uint16_arg( &o->diffopts.id_abbrev, &args, "--abbrev") && !match_str_arg(&o->diffopts.old_prefix, &args, "--src-prefix") && !match_str_arg(&o->diffopts.new_prefix, &args, "--dst-prefix") && !match_str_arg(&o->dir, &args, "--git-dir")) usage("Unknown command line argument", a); } }
int main(int argc, char * argv[]) { bool no_options = true, quiet = false, bare = false, initial_commit = false; uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK; const char *templ = nullptr, *gitdir = nullptr, *dir = nullptr; auto_git_initializer; /* Process arguments */ for (int i = 1; i < argc; ++i) { auto arg = argv[i]; StringView a = arg; if (arg[0] == '-') no_options = false; if (arg[0] != '-') { if (dir) usage("extra argument", arg); dir = arg; } else if (a == "-q" || a == "--quiet") quiet = true; else if (a == "--bare") bare = true; else if (auto pfxlen = is_prefixed(a, "--template=")) templ = arg + pfxlen; else if (a == "--separate-git-dir") gitdir = argv[++i]; else if (auto pfxlen = is_prefixed(a, "--separate-git-dir=")) gitdir = arg + pfxlen; else if (a == "--shared") shared = GIT_REPOSITORY_INIT_SHARED_GROUP; else if (auto pfxlen = is_prefixed(a, "--shared=")) shared = parse_shared(arg + pfxlen); else if (a == "--initial-commit") initial_commit = true; else usage("unknown option", arg); } if (!dir) usage("must specify directory to init", nullptr); /* Initialize repository */ Repository repo = no_options ? Repository(dir, Repository::init) : Repository(dir, Repository::init, make_opts(bare, templ, shared, gitdir, dir)); /* Print a message to stdout like "git init" does */ if (!quiet) { printf("Initialized empty Git repository in %s\n", (bare || gitdir) ? repo.path() : repo.workdir()); } /* As an extension to the basic "git init" command, this example * gives the option to create an empty initial commit. This is * mostly to demonstrate what it takes to do that, but also some * people like to have that empty base commit in their repo. */ if (initial_commit) { create_initial_commit(repo); printf("Created empty initial commit\n"); } return 0; }