Merge branch 'ph/parseopt'
* ph/parseopt: (24 commits) gc: use parse_options Fixed a command line option type for builtin-fsck.c Make builtin-pack-refs.c use parse_options. Make builtin-name-rev.c use parse_options. Make builtin-count-objects.c use parse_options. Make builtin-fsck.c use parse_options. Update manpages to reflect new short and long option aliases Make builtin-for-each-ref.c use parse-opts. Make builtin-symbolic-ref.c use parse_options. Make builtin-update-ref.c use parse_options Make builtin-revert.c use parse_options. Make builtin-describe.c use parse_options Make builtin-branch.c use parse_options. Make builtin-mv.c use parse-options Make builtin-rm.c use parse_options. Port builtin-add.c to use the new option parser. parse-options: allow callbacks to take no arguments at all. parse-options: Allow abbreviated options when unambiguous Add shortcuts for very often used options. parse-options: make some arguments optional, add callbacks. ... Conflicts: Makefile builtin-add.c
This commit is contained in:
commit
3d66dc9657
1
.gitignore
vendored
1
.gitignore
vendored
@ -153,6 +153,7 @@ test-delta
|
|||||||
test-dump-cache-tree
|
test-dump-cache-tree
|
||||||
test-genrandom
|
test-genrandom
|
||||||
test-match-trees
|
test-match-trees
|
||||||
|
test-parse-options
|
||||||
test-sha1
|
test-sha1
|
||||||
common-cmds.h
|
common-cmds.h
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
@ -50,10 +50,10 @@ OPTIONS
|
|||||||
and `dir/file2`) can be given to add all files in the
|
and `dir/file2`) can be given to add all files in the
|
||||||
directory, recursively.
|
directory, recursively.
|
||||||
|
|
||||||
-n::
|
-n, \--dry-run::
|
||||||
Don't actually add the file(s), just show if they exist.
|
Don't actually add the file(s), just show if they exist.
|
||||||
|
|
||||||
-v::
|
-v, \--verbose::
|
||||||
Be verbose.
|
Be verbose.
|
||||||
|
|
||||||
-f::
|
-f::
|
||||||
|
@ -85,7 +85,7 @@ OPTIONS
|
|||||||
-a::
|
-a::
|
||||||
List both remote-tracking branches and local branches.
|
List both remote-tracking branches and local branches.
|
||||||
|
|
||||||
-v::
|
-v, --verbose::
|
||||||
Show sha1 and commit subject line for each head.
|
Show sha1 and commit subject line for each head.
|
||||||
|
|
||||||
--abbrev=<length>::
|
--abbrev=<length>::
|
||||||
|
@ -34,7 +34,7 @@ OPTIONS
|
|||||||
condition. An error happens when a source is neither existing nor
|
condition. An error happens when a source is neither existing nor
|
||||||
controlled by GIT, or when it would overwrite an existing
|
controlled by GIT, or when it would overwrite an existing
|
||||||
file unless '-f' is given.
|
file unless '-f' is given.
|
||||||
-n::
|
-n, \--dry-run::
|
||||||
Do nothing; only show what would happen
|
Do nothing; only show what would happen
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ OPTIONS
|
|||||||
-f::
|
-f::
|
||||||
Override the up-to-date check.
|
Override the up-to-date check.
|
||||||
|
|
||||||
-n::
|
-n, \--dry-run::
|
||||||
Don't actually remove the file(s), just show if they exist in
|
Don't actually remove the file(s), just show if they exist in
|
||||||
the index.
|
the index.
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ OPTIONS
|
|||||||
\--ignore-unmatch::
|
\--ignore-unmatch::
|
||||||
Exit with a zero status even if no files matched.
|
Exit with a zero status even if no files matched.
|
||||||
|
|
||||||
\--quiet::
|
-q, \--quiet::
|
||||||
git-rm normally outputs one line (in the form of an "rm" command)
|
git-rm normally outputs one line (in the form of an "rm" command)
|
||||||
for each file removed. This option suppresses that output.
|
for each file removed. This option suppresses that output.
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ a regular file whose contents is `ref: refs/heads/master`.
|
|||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
-q::
|
-q, --quiet::
|
||||||
Do not issue an error message if the <name> is not a
|
Do not issue an error message if the <name> is not a
|
||||||
symbolic ref but a detached HEAD; instead exit with
|
symbolic ref but a detached HEAD; instead exit with
|
||||||
non-zero status silently.
|
non-zero status silently.
|
||||||
|
6
Makefile
6
Makefile
@ -289,7 +289,7 @@ LIB_H = \
|
|||||||
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
|
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
|
||||||
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
|
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
|
||||||
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
|
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
|
||||||
mailmap.h remote.h transport.h diffcore.h hash.h
|
mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
|
||||||
|
|
||||||
DIFF_OBJS = \
|
DIFF_OBJS = \
|
||||||
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
|
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
|
||||||
@ -312,7 +312,7 @@ LIB_OBJS = \
|
|||||||
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
|
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
|
||||||
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
|
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
|
||||||
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
|
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
|
||||||
transport.o bundle.o walker.o
|
transport.o bundle.o walker.o parse-options.o
|
||||||
|
|
||||||
BUILTIN_OBJS = \
|
BUILTIN_OBJS = \
|
||||||
builtin-add.o \
|
builtin-add.o \
|
||||||
@ -974,7 +974,7 @@ endif
|
|||||||
|
|
||||||
### Testing rules
|
### Testing rules
|
||||||
|
|
||||||
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X
|
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
|
||||||
|
|
||||||
all:: $(TEST_PROGRAMS)
|
all:: $(TEST_PROGRAMS)
|
||||||
|
|
||||||
|
@ -13,9 +13,12 @@
|
|||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "revision.h"
|
#include "revision.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static const char builtin_add_usage[] =
|
static const char * const builtin_add_usage[] = {
|
||||||
"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] <filepattern>...";
|
"git-add [options] [--] <filepattern>...",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int take_worktree_changes;
|
static int take_worktree_changes;
|
||||||
static const char *excludes_file;
|
static const char *excludes_file;
|
||||||
@ -162,21 +165,30 @@ static struct lock_file lock_file;
|
|||||||
static const char ignore_error[] =
|
static const char ignore_error[] =
|
||||||
"The following paths are ignored by one of your .gitignore files:\n";
|
"The following paths are ignored by one of your .gitignore files:\n";
|
||||||
|
|
||||||
|
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
|
||||||
|
static int add_interactive = 0;
|
||||||
|
|
||||||
|
static struct option builtin_add_options[] = {
|
||||||
|
OPT__DRY_RUN(&show_only),
|
||||||
|
OPT__VERBOSE(&verbose),
|
||||||
|
OPT_GROUP(""),
|
||||||
|
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
|
||||||
|
OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"),
|
||||||
|
OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"),
|
||||||
|
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
int cmd_add(int argc, const char **argv, const char *prefix)
|
int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, newfd;
|
int i, newfd, orig_argc = argc;
|
||||||
int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
|
|
||||||
const char **pathspec;
|
const char **pathspec;
|
||||||
struct dir_struct dir;
|
struct dir_struct dir;
|
||||||
int add_interactive = 0;
|
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
argc = parse_options(argc, argv, builtin_add_options,
|
||||||
if (!strcmp("--interactive", argv[i]) ||
|
builtin_add_usage, 0);
|
||||||
!strcmp("-i", argv[i]))
|
|
||||||
add_interactive++;
|
|
||||||
}
|
|
||||||
if (add_interactive) {
|
if (add_interactive) {
|
||||||
if (argc != 2)
|
if (add_interactive != 1 || orig_argc != 2)
|
||||||
die("add --interactive does not take any parameters");
|
die("add --interactive does not take any parameters");
|
||||||
exit(interactive_add());
|
exit(interactive_add());
|
||||||
}
|
}
|
||||||
@ -185,51 +197,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
newfd = hold_locked_index(&lock_file, 1);
|
newfd = hold_locked_index(&lock_file, 1);
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
const char *arg = argv[i];
|
|
||||||
|
|
||||||
if (arg[0] != '-')
|
|
||||||
break;
|
|
||||||
if (!strcmp(arg, "--")) {
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-n")) {
|
|
||||||
show_only = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-f")) {
|
|
||||||
ignored_too = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-v")) {
|
|
||||||
verbose = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-u")) {
|
|
||||||
take_worktree_changes = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--refresh")) {
|
|
||||||
refresh_only = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
usage(builtin_add_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (take_worktree_changes) {
|
if (take_worktree_changes) {
|
||||||
if (read_cache() < 0)
|
if (read_cache() < 0)
|
||||||
die("index file corrupt");
|
die("index file corrupt");
|
||||||
add_files_to_cache(verbose, prefix, argv + i);
|
add_files_to_cache(verbose, prefix, argv);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc <= i) {
|
if (argc == 0) {
|
||||||
fprintf(stderr, "Nothing specified, nothing added.\n");
|
fprintf(stderr, "Nothing specified, nothing added.\n");
|
||||||
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
|
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pathspec = get_pathspec(prefix, argv + i);
|
pathspec = get_pathspec(prefix, argv);
|
||||||
|
|
||||||
if (refresh_only) {
|
if (refresh_only) {
|
||||||
refresh(verbose, pathspec);
|
refresh(verbose, pathspec);
|
||||||
|
143
builtin-branch.c
143
builtin-branch.c
@ -11,9 +11,15 @@
|
|||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static const char builtin_branch_usage[] =
|
static const char * const builtin_branch_usage[] = {
|
||||||
"git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
|
"git-branch [options] [-r | -a]",
|
||||||
|
"git-branch [options] [-l] [-f] <branchname> [<start-point>]",
|
||||||
|
"git-branch [options] [-r] (-d | -D) <branchname>",
|
||||||
|
"git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
#define REF_UNKNOWN_TYPE 0x00
|
#define REF_UNKNOWN_TYPE 0x00
|
||||||
#define REF_LOCAL_BRANCH 0x01
|
#define REF_LOCAL_BRANCH 0x01
|
||||||
@ -505,93 +511,45 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
|||||||
int rename = 0, force_rename = 0;
|
int rename = 0, force_rename = 0;
|
||||||
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
|
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
|
||||||
int reflog = 0, track;
|
int reflog = 0, track;
|
||||||
int kinds = REF_LOCAL_BRANCH;
|
int kinds = REF_LOCAL_BRANCH, kind_remote = 0, kind_any = 0;
|
||||||
int i;
|
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_GROUP("Generic options"),
|
||||||
|
OPT__VERBOSE(&verbose),
|
||||||
|
OPT_BOOLEAN( 0 , "track", &track, "set up tracking mode (see git-pull(1))"),
|
||||||
|
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
|
||||||
|
OPT_BOOLEAN('r', NULL, &kind_remote, "act on remote-tracking branches"),
|
||||||
|
OPT__ABBREV(&abbrev),
|
||||||
|
|
||||||
|
OPT_GROUP("Specific git-branch actions:"),
|
||||||
|
OPT_BOOLEAN('a', NULL, &kind_any, "list both remote-tracking and local branches"),
|
||||||
|
OPT_BOOLEAN('d', NULL, &delete, "delete fully merged branch"),
|
||||||
|
OPT_BOOLEAN('D', NULL, &force_delete, "delete branch (even if not merged)"),
|
||||||
|
OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
|
||||||
|
OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"),
|
||||||
|
OPT_BOOLEAN('m', NULL, &rename, "move/rename a branch and its reflog"),
|
||||||
|
OPT_BOOLEAN('M', NULL, &force_rename, "move/rename a branch, even if target exists"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
git_config(git_branch_config);
|
git_config(git_branch_config);
|
||||||
track = branch_track;
|
track = branch_track;
|
||||||
|
argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
delete |= force_delete;
|
||||||
const char *arg = argv[i];
|
rename |= force_rename;
|
||||||
|
if (kind_remote)
|
||||||
if (arg[0] != '-')
|
kinds = REF_REMOTE_BRANCH;
|
||||||
break;
|
if (kind_any)
|
||||||
if (!strcmp(arg, "--")) {
|
kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;
|
||||||
i++;
|
if (abbrev && abbrev < MINIMUM_ABBREV)
|
||||||
break;
|
abbrev = MINIMUM_ABBREV;
|
||||||
}
|
else if (abbrev > 40)
|
||||||
if (!strcmp(arg, "--track")) {
|
abbrev = 40;
|
||||||
track = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--no-track")) {
|
|
||||||
track = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-d")) {
|
|
||||||
delete = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-D")) {
|
|
||||||
delete = 1;
|
|
||||||
force_delete = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-f")) {
|
|
||||||
force_create = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-m")) {
|
|
||||||
rename = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-M")) {
|
|
||||||
rename = 1;
|
|
||||||
force_rename = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-r")) {
|
|
||||||
kinds = REF_REMOTE_BRANCH;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-a")) {
|
|
||||||
kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-l")) {
|
|
||||||
reflog = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(arg, "--no-abbrev")) {
|
|
||||||
abbrev = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(arg, "--abbrev=")) {
|
|
||||||
abbrev = strtoul(arg + 9, NULL, 10);
|
|
||||||
if (abbrev < MINIMUM_ABBREV)
|
|
||||||
abbrev = MINIMUM_ABBREV;
|
|
||||||
else if (abbrev > 40)
|
|
||||||
abbrev = 40;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-v")) {
|
|
||||||
verbose = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--color")) {
|
|
||||||
branch_use_color = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--no-color")) {
|
|
||||||
branch_use_color = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
usage(builtin_branch_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((delete && rename) || (delete && force_create) ||
|
if ((delete && rename) || (delete && force_create) ||
|
||||||
(rename && force_create))
|
(rename && force_create))
|
||||||
usage(builtin_branch_usage);
|
usage_with_options(builtin_branch_usage, options);
|
||||||
|
|
||||||
head = resolve_ref("HEAD", head_sha1, 0, NULL);
|
head = resolve_ref("HEAD", head_sha1, 0, NULL);
|
||||||
if (!head)
|
if (!head)
|
||||||
@ -599,26 +557,25 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
|||||||
head = xstrdup(head);
|
head = xstrdup(head);
|
||||||
if (!strcmp(head, "HEAD")) {
|
if (!strcmp(head, "HEAD")) {
|
||||||
detached = 1;
|
detached = 1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (prefixcmp(head, "refs/heads/"))
|
if (prefixcmp(head, "refs/heads/"))
|
||||||
die("HEAD not found below refs/heads!");
|
die("HEAD not found below refs/heads!");
|
||||||
head += 11;
|
head += 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delete)
|
if (delete)
|
||||||
return delete_branches(argc - i, argv + i, force_delete, kinds);
|
return delete_branches(argc, argv, force_delete, kinds);
|
||||||
else if (i == argc)
|
else if (argc == 0)
|
||||||
print_ref_list(kinds, detached, verbose, abbrev);
|
print_ref_list(kinds, detached, verbose, abbrev);
|
||||||
else if (rename && (i == argc - 1))
|
else if (rename && (argc == 1))
|
||||||
rename_branch(head, argv[i], force_rename);
|
rename_branch(head, argv[0], force_rename);
|
||||||
else if (rename && (i == argc - 2))
|
else if (rename && (argc == 2))
|
||||||
rename_branch(argv[i], argv[i + 1], force_rename);
|
rename_branch(argv[0], argv[1], force_rename);
|
||||||
else if (i == argc - 1 || i == argc - 2)
|
else if (argc <= 2)
|
||||||
create_branch(argv[i], (i == argc - 2) ? argv[i+1] : head,
|
create_branch(argv[0], (argc == 2) ? argv[1] : head,
|
||||||
force_create, reflog, track);
|
force_create, reflog, track);
|
||||||
else
|
else
|
||||||
usage(builtin_branch_usage);
|
usage_with_options(builtin_branch_usage, options);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
|
#include "parse-options.h"
|
||||||
static const char count_objects_usage[] = "git-count-objects [-v]";
|
|
||||||
|
|
||||||
static void count_objects(DIR *d, char *path, int len, int verbose,
|
static void count_objects(DIR *d, char *path, int len, int verbose,
|
||||||
unsigned long *loose,
|
unsigned long *loose,
|
||||||
@ -67,29 +66,28 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_count_objects(int ac, const char **av, const char *prefix)
|
static char const * const count_objects_usage[] = {
|
||||||
|
"git-count-objects [-v]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
int cmd_count_objects(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i;
|
int i, verbose = 0;
|
||||||
int verbose = 0;
|
|
||||||
const char *objdir = get_object_directory();
|
const char *objdir = get_object_directory();
|
||||||
int len = strlen(objdir);
|
int len = strlen(objdir);
|
||||||
char *path = xmalloc(len + 50);
|
char *path = xmalloc(len + 50);
|
||||||
unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
|
unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
|
||||||
unsigned long loose_size = 0;
|
unsigned long loose_size = 0;
|
||||||
|
struct option opts[] = {
|
||||||
|
OPT__VERBOSE(&verbose),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
for (i = 1; i < ac; i++) {
|
argc = parse_options(argc, argv, opts, count_objects_usage, 0);
|
||||||
const char *arg = av[i];
|
|
||||||
if (*arg != '-')
|
|
||||||
break;
|
|
||||||
else if (!strcmp(arg, "-v"))
|
|
||||||
verbose = 1;
|
|
||||||
else
|
|
||||||
usage(count_objects_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we do not take arguments other than flags for now */
|
/* we do not take arguments other than flags for now */
|
||||||
if (i < ac)
|
if (argc)
|
||||||
usage(count_objects_usage);
|
usage_with_options(count_objects_usage, opts);
|
||||||
memcpy(path, objdir, len);
|
memcpy(path, objdir, len);
|
||||||
if (len && objdir[len-1] != '/')
|
if (len && objdir[len-1] != '/')
|
||||||
path[len++] = '/';
|
path[len++] = '/';
|
||||||
|
@ -4,12 +4,15 @@
|
|||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "exec_cmd.h"
|
#include "exec_cmd.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
#define SEEN (1u<<0)
|
#define SEEN (1u<<0)
|
||||||
#define MAX_TAGS (FLAG_BITS - 1)
|
#define MAX_TAGS (FLAG_BITS - 1)
|
||||||
|
|
||||||
static const char describe_usage[] =
|
static const char * const describe_usage[] = {
|
||||||
"git-describe [--all] [--tags] [--abbrev=<n>] <committish>*";
|
"git-describe [options] <committish>*",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int debug; /* Display lots of verbose info */
|
static int debug; /* Display lots of verbose info */
|
||||||
static int all; /* Default to annotated tags only */
|
static int all; /* Default to annotated tags only */
|
||||||
@ -242,57 +245,42 @@ static void describe(const char *arg, int last_one)
|
|||||||
|
|
||||||
int cmd_describe(int argc, const char **argv, const char *prefix)
|
int cmd_describe(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int contains = 0;
|
int contains = 0;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_BOOLEAN(0, "contains", &contains, "find the tag that comes after the commit"),
|
||||||
|
OPT_BOOLEAN(0, "debug", &debug, "debug search strategy on stderr"),
|
||||||
|
OPT_BOOLEAN(0, "all", &all, "use any ref in .git/refs"),
|
||||||
|
OPT_BOOLEAN(0, "tags", &tags, "use any tag in .git/refs/tags"),
|
||||||
|
OPT__ABBREV(&abbrev),
|
||||||
|
OPT_INTEGER(0, "candidates", &max_candidates,
|
||||||
|
"consider <n> most recent tags (default: 10)"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
argc = parse_options(argc, argv, options, describe_usage, 0);
|
||||||
const char *arg = argv[i];
|
if (max_candidates < 1)
|
||||||
|
max_candidates = 1;
|
||||||
if (*arg != '-')
|
else if (max_candidates > MAX_TAGS)
|
||||||
break;
|
max_candidates = MAX_TAGS;
|
||||||
else if (!strcmp(arg, "--contains"))
|
|
||||||
contains = 1;
|
|
||||||
else if (!strcmp(arg, "--debug"))
|
|
||||||
debug = 1;
|
|
||||||
else if (!strcmp(arg, "--all"))
|
|
||||||
all = 1;
|
|
||||||
else if (!strcmp(arg, "--tags"))
|
|
||||||
tags = 1;
|
|
||||||
else if (!prefixcmp(arg, "--abbrev=")) {
|
|
||||||
abbrev = strtoul(arg + 9, NULL, 10);
|
|
||||||
if (abbrev != 0 && (abbrev < MINIMUM_ABBREV || 40 < abbrev))
|
|
||||||
abbrev = DEFAULT_ABBREV;
|
|
||||||
}
|
|
||||||
else if (!prefixcmp(arg, "--candidates=")) {
|
|
||||||
max_candidates = strtoul(arg + 13, NULL, 10);
|
|
||||||
if (max_candidates < 1)
|
|
||||||
max_candidates = 1;
|
|
||||||
else if (max_candidates > MAX_TAGS)
|
|
||||||
max_candidates = MAX_TAGS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
usage(describe_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
save_commit_buffer = 0;
|
save_commit_buffer = 0;
|
||||||
|
|
||||||
if (contains) {
|
if (contains) {
|
||||||
const char **args = xmalloc((4 + argc - i) * sizeof(char*));
|
const char **args = xmalloc((4 + argc) * sizeof(char*));
|
||||||
args[0] = "name-rev";
|
args[0] = "name-rev";
|
||||||
args[1] = "--name-only";
|
args[1] = "--name-only";
|
||||||
args[2] = "--tags";
|
args[2] = "--tags";
|
||||||
memcpy(args + 3, argv + i, (argc - i) * sizeof(char*));
|
memcpy(args + 3, argv, argc * sizeof(char*));
|
||||||
args[3 + argc - i] = NULL;
|
args[3 + argc] = NULL;
|
||||||
return cmd_name_rev(3 + argc - i, args, prefix);
|
return cmd_name_rev(3 + argc, args, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc <= i)
|
if (argc == 0) {
|
||||||
describe("HEAD", 1);
|
describe("HEAD", 1);
|
||||||
else
|
} else {
|
||||||
while (i < argc) {
|
while (argc-- > 0) {
|
||||||
describe(argv[i], (i == argc - 1));
|
describe(*argv++, argc == 0);
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
/* Quoting styles */
|
/* Quoting styles */
|
||||||
#define QUOTE_NONE 0
|
#define QUOTE_NONE 0
|
||||||
@ -158,17 +159,18 @@ static const char *find_next(const char *cp)
|
|||||||
* Make sure the format string is well formed, and parse out
|
* Make sure the format string is well formed, and parse out
|
||||||
* the used atoms.
|
* the used atoms.
|
||||||
*/
|
*/
|
||||||
static void verify_format(const char *format)
|
static int verify_format(const char *format)
|
||||||
{
|
{
|
||||||
const char *cp, *sp;
|
const char *cp, *sp;
|
||||||
for (cp = format; *cp && (sp = find_next(cp)); ) {
|
for (cp = format; *cp && (sp = find_next(cp)); ) {
|
||||||
const char *ep = strchr(sp, ')');
|
const char *ep = strchr(sp, ')');
|
||||||
if (!ep)
|
if (!ep)
|
||||||
die("malformatted format string %s", sp);
|
return error("malformatted format string %s", sp);
|
||||||
/* sp points at "%(" and ep points at the closing ")" */
|
/* sp points at "%(" and ep points at the closing ")" */
|
||||||
parse_atom(sp + 2, ep);
|
parse_atom(sp + 2, ep);
|
||||||
cp = ep + 1;
|
cp = ep + 1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -800,94 +802,76 @@ static struct ref_sort *default_sort(void)
|
|||||||
return sort;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_for_each_ref(int ac, const char **av, const char *prefix)
|
int opt_parse_sort(const struct option *opt, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
struct ref_sort **sort_tail = opt->value;
|
||||||
|
struct ref_sort *s;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!arg) /* should --no-sort void the list ? */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*sort_tail = s = xcalloc(1, sizeof(*s));
|
||||||
|
sort_tail = &s->next;
|
||||||
|
|
||||||
|
if (*arg == '-') {
|
||||||
|
s->reverse = 1;
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
len = strlen(arg);
|
||||||
|
s->atom = parse_atom(arg, arg+len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char const * const for_each_ref_usage[] = {
|
||||||
|
"git-for-each-ref [options] [<pattern>]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, num_refs;
|
int i, num_refs;
|
||||||
const char *format = NULL;
|
const char *format = "%(objectname) %(objecttype)\t%(refname)";
|
||||||
struct ref_sort *sort = NULL, **sort_tail = &sort;
|
struct ref_sort *sort = NULL, **sort_tail = &sort;
|
||||||
int maxcount = 0;
|
int maxcount = 0, quote_style;
|
||||||
int quote_style = -1; /* unspecified yet */
|
int quote_shell = 0, quote_perl = 0, quote_python = 0, quote_tcl = 0;
|
||||||
struct refinfo **refs;
|
struct refinfo **refs;
|
||||||
struct grab_ref_cbdata cbdata;
|
struct grab_ref_cbdata cbdata;
|
||||||
|
|
||||||
for (i = 1; i < ac; i++) {
|
struct option opts[] = {
|
||||||
const char *arg = av[i];
|
OPT_BOOLEAN('s', "shell", "e_shell, "quote placeholders suitably for shells"),
|
||||||
if (arg[0] != '-')
|
OPT_BOOLEAN('p', "perl", "e_perl, "quote placeholders suitably for perl"),
|
||||||
break;
|
OPT_BOOLEAN( 0 , "python", "e_python, "quote placeholders suitably for python"),
|
||||||
if (!strcmp(arg, "--")) {
|
OPT_BOOLEAN( 0 , "tcl", "e_tcl, "quote placeholders suitably for tcl"),
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(arg, "--format=")) {
|
|
||||||
if (format)
|
|
||||||
die("more than one --format?");
|
|
||||||
format = arg + 9;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
|
|
||||||
if (0 <= quote_style)
|
|
||||||
die("more than one quoting style?");
|
|
||||||
quote_style = QUOTE_SHELL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
|
|
||||||
if (0 <= quote_style)
|
|
||||||
die("more than one quoting style?");
|
|
||||||
quote_style = QUOTE_PERL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--python") ) {
|
|
||||||
if (0 <= quote_style)
|
|
||||||
die("more than one quoting style?");
|
|
||||||
quote_style = QUOTE_PYTHON;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--tcl") ) {
|
|
||||||
if (0 <= quote_style)
|
|
||||||
die("more than one quoting style?");
|
|
||||||
quote_style = QUOTE_TCL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(arg, "--count=")) {
|
|
||||||
if (maxcount)
|
|
||||||
die("more than one --count?");
|
|
||||||
maxcount = atoi(arg + 8);
|
|
||||||
if (maxcount <= 0)
|
|
||||||
die("The number %s did not parse", arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(arg, "--sort=")) {
|
|
||||||
struct ref_sort *s = xcalloc(1, sizeof(*s));
|
|
||||||
int len;
|
|
||||||
|
|
||||||
s->next = NULL;
|
OPT_GROUP(""),
|
||||||
*sort_tail = s;
|
OPT_INTEGER( 0 , "count", &maxcount, "show only <n> matched refs"),
|
||||||
sort_tail = &s->next;
|
OPT_STRING( 0 , "format", &format, "format", "format to use for the output"),
|
||||||
|
OPT_CALLBACK(0 , "sort", &sort_tail, "key",
|
||||||
|
"field name to sort on", &opt_parse_sort),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
arg += 7;
|
parse_options(argc, argv, opts, for_each_ref_usage, 0);
|
||||||
if (*arg == '-') {
|
if (maxcount < 0) {
|
||||||
s->reverse = 1;
|
error("invalid --count argument: `%d'", maxcount);
|
||||||
arg++;
|
usage_with_options(for_each_ref_usage, opts);
|
||||||
}
|
|
||||||
len = strlen(arg);
|
|
||||||
sort->atom = parse_atom(arg, arg+len);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (quote_style < 0)
|
if (quote_shell + quote_perl + quote_python + quote_tcl > 1) {
|
||||||
quote_style = QUOTE_NONE;
|
error("more than one quoting style ?");
|
||||||
|
usage_with_options(for_each_ref_usage, opts);
|
||||||
|
}
|
||||||
|
if (verify_format(format))
|
||||||
|
usage_with_options(for_each_ref_usage, opts);
|
||||||
|
|
||||||
|
quote_style = QUOTE_SHELL * quote_shell + QUOTE_PERL * quote_perl +
|
||||||
|
QUOTE_PYTHON * quote_python + QUOTE_TCL * quote_tcl;
|
||||||
if (!sort)
|
if (!sort)
|
||||||
sort = default_sort();
|
sort = default_sort();
|
||||||
sort_atom_limit = used_atom_cnt;
|
sort_atom_limit = used_atom_cnt;
|
||||||
if (!format)
|
|
||||||
format = "%(objectname) %(objecttype)\t%(refname)";
|
|
||||||
|
|
||||||
verify_format(format);
|
|
||||||
|
|
||||||
memset(&cbdata, 0, sizeof(cbdata));
|
memset(&cbdata, 0, sizeof(cbdata));
|
||||||
cbdata.grab_pattern = av + i;
|
cbdata.grab_pattern = argv;
|
||||||
for_each_ref(grab_single_ref, &cbdata);
|
for_each_ref(grab_single_ref, &cbdata);
|
||||||
refs = cbdata.grab_array;
|
refs = cbdata.grab_array;
|
||||||
num_refs = cbdata.grab_cnt;
|
num_refs = cbdata.grab_cnt;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
#include "tree-walk.h"
|
#include "tree-walk.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
#define REACHABLE 0x0001
|
#define REACHABLE 0x0001
|
||||||
#define SEEN 0x0002
|
#define SEEN 0x0002
|
||||||
@ -666,9 +667,24 @@ static int fsck_cache_tree(struct cache_tree *it)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char fsck_usage[] =
|
static char const * const fsck_usage[] = {
|
||||||
"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
|
"git-fsck [options] [<object>...]",
|
||||||
"[--strict] [--verbose] <head-sha1>*]";
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct option fsck_opts[] = {
|
||||||
|
OPT__VERBOSE(&verbose),
|
||||||
|
OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"),
|
||||||
|
OPT_BOOLEAN(0, "tags", &show_tags, "report tags"),
|
||||||
|
OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
|
||||||
|
OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
|
||||||
|
OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"),
|
||||||
|
OPT_BOOLEAN(0, "full", &check_full, "also consider alternate objects"),
|
||||||
|
OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
|
||||||
|
OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
|
||||||
|
"write dangling objects in .git/lost-found"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
int cmd_fsck(int argc, const char **argv, const char *prefix)
|
int cmd_fsck(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
@ -677,49 +693,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
track_object_refs = 1;
|
track_object_refs = 1;
|
||||||
errors_found = 0;
|
errors_found = 0;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
|
||||||
const char *arg = argv[i];
|
if (write_lost_and_found) {
|
||||||
|
check_full = 1;
|
||||||
if (!strcmp(arg, "--unreachable")) {
|
include_reflogs = 0;
|
||||||
show_unreachable = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--tags")) {
|
|
||||||
show_tags = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--root")) {
|
|
||||||
show_root = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--cache")) {
|
|
||||||
keep_cache_objects = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--no-reflogs")) {
|
|
||||||
include_reflogs = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--full")) {
|
|
||||||
check_full = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--strict")) {
|
|
||||||
check_strict = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--verbose")) {
|
|
||||||
verbose = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--lost-found")) {
|
|
||||||
check_full = 1;
|
|
||||||
include_reflogs = 0;
|
|
||||||
write_lost_and_found = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*arg == '-')
|
|
||||||
usage(fsck_usage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fsck_head_link();
|
fsck_head_link();
|
||||||
@ -741,22 +718,18 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
verify_pack(p, 0);
|
verify_pack(p, 0);
|
||||||
|
|
||||||
for (p = packed_git; p; p = p->next) {
|
for (p = packed_git; p; p = p->next) {
|
||||||
uint32_t i, num;
|
uint32_t j, num;
|
||||||
if (open_pack_index(p))
|
if (open_pack_index(p))
|
||||||
continue;
|
continue;
|
||||||
num = p->num_objects;
|
num = p->num_objects;
|
||||||
for (i = 0; i < num; i++)
|
for (j = 0; j < num; j++)
|
||||||
fsck_sha1(nth_packed_object_sha1(p, i));
|
fsck_sha1(nth_packed_object_sha1(p, j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heads = 0;
|
heads = 0;
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
|
|
||||||
if (*arg == '-')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!get_sha1(arg, head_sha1)) {
|
if (!get_sha1(arg, head_sha1)) {
|
||||||
struct object *obj = lookup_object(head_sha1);
|
struct object *obj = lookup_object(head_sha1);
|
||||||
|
|
||||||
@ -783,7 +756,6 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (keep_cache_objects) {
|
if (keep_cache_objects) {
|
||||||
int i;
|
|
||||||
read_cache();
|
read_cache();
|
||||||
for (i = 0; i < active_nr; i++) {
|
for (i = 0; i < active_nr; i++) {
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
|
44
builtin-gc.c
44
builtin-gc.c
@ -12,11 +12,15 @@
|
|||||||
|
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "parse-options.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
|
|
||||||
#define FAILED_RUN "failed to run %s"
|
#define FAILED_RUN "failed to run %s"
|
||||||
|
|
||||||
static const char builtin_gc_usage[] = "git-gc [--prune] [--aggressive]";
|
static const char * const builtin_gc_usage[] = {
|
||||||
|
"git-gc [options]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int pack_refs = 1;
|
static int pack_refs = 1;
|
||||||
static int aggressive_window = -1;
|
static int aggressive_window = -1;
|
||||||
@ -165,38 +169,34 @@ static int need_to_gc(void)
|
|||||||
|
|
||||||
int cmd_gc(int argc, const char **argv, const char *prefix)
|
int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int prune = 0;
|
int prune = 0;
|
||||||
|
int aggressive = 0;
|
||||||
int auto_gc = 0;
|
int auto_gc = 0;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
|
||||||
|
struct option builtin_gc_options[] = {
|
||||||
|
OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced loose objects"),
|
||||||
|
OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
|
||||||
|
OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
git_config(gc_config);
|
git_config(gc_config);
|
||||||
|
|
||||||
if (pack_refs < 0)
|
if (pack_refs < 0)
|
||||||
pack_refs = !is_bare_repository();
|
pack_refs = !is_bare_repository();
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
|
||||||
const char *arg = argv[i];
|
if (argc > 0)
|
||||||
if (!strcmp(arg, "--prune")) {
|
usage_with_options(builtin_gc_usage, builtin_gc_options);
|
||||||
prune = 1;
|
|
||||||
continue;
|
if (aggressive) {
|
||||||
|
append_option(argv_repack, "-f", MAX_ADD);
|
||||||
|
if (aggressive_window > 0) {
|
||||||
|
sprintf(buf, "--window=%d", aggressive_window);
|
||||||
|
append_option(argv_repack, buf, MAX_ADD);
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--aggressive")) {
|
|
||||||
append_option(argv_repack, "-f", MAX_ADD);
|
|
||||||
if (aggressive_window > 0) {
|
|
||||||
sprintf(buf, "--window=%d", aggressive_window);
|
|
||||||
append_option(argv_repack, buf, MAX_ADD);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--auto")) {
|
|
||||||
auto_gc = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (i != argc)
|
|
||||||
usage(builtin_gc_usage);
|
|
||||||
|
|
||||||
if (auto_gc) {
|
if (auto_gc) {
|
||||||
/*
|
/*
|
||||||
|
84
builtin-mv.c
84
builtin-mv.c
@ -8,9 +8,12 @@
|
|||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
#include "path-list.h"
|
#include "path-list.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static const char builtin_mv_usage[] =
|
static const char * const builtin_mv_usage[] = {
|
||||||
"git-mv [-n] [-f] (<source> <destination> | [-k] <source>... <destination>)";
|
"git-mv [options] <source>... <destination>",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const char **copy_pathspec(const char *prefix, const char **pathspec,
|
static const char **copy_pathspec(const char *prefix, const char **pathspec,
|
||||||
int count, int base_name)
|
int count, int base_name)
|
||||||
@ -61,8 +64,14 @@ static struct lock_file lock_file;
|
|||||||
|
|
||||||
int cmd_mv(int argc, const char **argv, const char *prefix)
|
int cmd_mv(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, newfd, count;
|
int i, newfd;
|
||||||
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
|
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
|
||||||
|
struct option builtin_mv_options[] = {
|
||||||
|
OPT__DRY_RUN(&show_only),
|
||||||
|
OPT_BOOLEAN('f', NULL, &force, "force move/rename even if target exists"),
|
||||||
|
OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
const char **source, **destination, **dest_path;
|
const char **source, **destination, **dest_path;
|
||||||
enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
|
enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -78,52 +87,29 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
|||||||
if (read_cache() < 0)
|
if (read_cache() < 0)
|
||||||
die("index file corrupt");
|
die("index file corrupt");
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
|
||||||
const char *arg = argv[i];
|
if (--argc < 1)
|
||||||
|
usage_with_options(builtin_mv_usage, builtin_mv_options);
|
||||||
|
|
||||||
if (arg[0] != '-')
|
source = copy_pathspec(prefix, argv, argc, 0);
|
||||||
break;
|
modes = xcalloc(argc, sizeof(enum update_mode));
|
||||||
if (!strcmp(arg, "--")) {
|
dest_path = copy_pathspec(prefix, argv + argc, 1, 0);
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-n")) {
|
|
||||||
show_only = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-f")) {
|
|
||||||
force = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "-k")) {
|
|
||||||
ignore_errors = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
usage(builtin_mv_usage);
|
|
||||||
}
|
|
||||||
count = argc - i - 1;
|
|
||||||
if (count < 1)
|
|
||||||
usage(builtin_mv_usage);
|
|
||||||
|
|
||||||
source = copy_pathspec(prefix, argv + i, count, 0);
|
|
||||||
modes = xcalloc(count, sizeof(enum update_mode));
|
|
||||||
dest_path = copy_pathspec(prefix, argv + argc - 1, 1, 0);
|
|
||||||
|
|
||||||
if (dest_path[0][0] == '\0')
|
if (dest_path[0][0] == '\0')
|
||||||
/* special case: "." was normalized to "" */
|
/* special case: "." was normalized to "" */
|
||||||
destination = copy_pathspec(dest_path[0], argv + i, count, 1);
|
destination = copy_pathspec(dest_path[0], argv, argc, 1);
|
||||||
else if (!lstat(dest_path[0], &st) &&
|
else if (!lstat(dest_path[0], &st) &&
|
||||||
S_ISDIR(st.st_mode)) {
|
S_ISDIR(st.st_mode)) {
|
||||||
dest_path[0] = add_slash(dest_path[0]);
|
dest_path[0] = add_slash(dest_path[0]);
|
||||||
destination = copy_pathspec(dest_path[0], argv + i, count, 1);
|
destination = copy_pathspec(dest_path[0], argv, argc, 1);
|
||||||
} else {
|
} else {
|
||||||
if (count != 1)
|
if (argc != 1)
|
||||||
usage(builtin_mv_usage);
|
usage_with_options(builtin_mv_usage, builtin_mv_options);
|
||||||
destination = dest_path;
|
destination = dest_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking */
|
/* Checking */
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
const char *src = source[i], *dst = destination[i];
|
const char *src = source[i], *dst = destination[i];
|
||||||
int length, src_is_dir;
|
int length, src_is_dir;
|
||||||
const char *bad = NULL;
|
const char *bad = NULL;
|
||||||
@ -167,13 +153,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (last - first > 0) {
|
if (last - first > 0) {
|
||||||
source = xrealloc(source,
|
source = xrealloc(source,
|
||||||
(count + last - first)
|
(argc + last - first)
|
||||||
* sizeof(char *));
|
* sizeof(char *));
|
||||||
destination = xrealloc(destination,
|
destination = xrealloc(destination,
|
||||||
(count + last - first)
|
(argc + last - first)
|
||||||
* sizeof(char *));
|
* sizeof(char *));
|
||||||
modes = xrealloc(modes,
|
modes = xrealloc(modes,
|
||||||
(count + last - first)
|
(argc + last - first)
|
||||||
* sizeof(enum update_mode));
|
* sizeof(enum update_mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,13 +169,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
|||||||
for (j = 0; j < last - first; j++) {
|
for (j = 0; j < last - first; j++) {
|
||||||
const char *path =
|
const char *path =
|
||||||
active_cache[first + j]->name;
|
active_cache[first + j]->name;
|
||||||
source[count + j] = path;
|
source[argc + j] = path;
|
||||||
destination[count + j] =
|
destination[argc + j] =
|
||||||
prefix_path(dst, dst_len,
|
prefix_path(dst, dst_len,
|
||||||
path + length);
|
path + length);
|
||||||
modes[count + j] = INDEX;
|
modes[argc + j] = INDEX;
|
||||||
}
|
}
|
||||||
count += last - first;
|
argc += last - first;
|
||||||
}
|
}
|
||||||
} else if (lstat(dst, &st) == 0) {
|
} else if (lstat(dst, &st) == 0) {
|
||||||
bad = "destination exists";
|
bad = "destination exists";
|
||||||
@ -216,12 +202,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (bad) {
|
if (bad) {
|
||||||
if (ignore_errors) {
|
if (ignore_errors) {
|
||||||
if (--count > 0) {
|
if (--argc > 0) {
|
||||||
memmove(source + i, source + i + 1,
|
memmove(source + i, source + i + 1,
|
||||||
(count - i) * sizeof(char *));
|
(argc - i) * sizeof(char *));
|
||||||
memmove(destination + i,
|
memmove(destination + i,
|
||||||
destination + i + 1,
|
destination + i + 1,
|
||||||
(count - i) * sizeof(char *));
|
(argc - i) * sizeof(char *));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
die ("%s, source=%s, destination=%s",
|
die ("%s, source=%s, destination=%s",
|
||||||
@ -229,7 +215,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
const char *src = source[i], *dst = destination[i];
|
const char *src = source[i], *dst = destination[i];
|
||||||
enum update_mode mode = modes[i];
|
enum update_mode mode = modes[i];
|
||||||
if (show_only || verbose)
|
if (show_only || verbose)
|
||||||
@ -253,7 +239,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
|||||||
path_list_insert(dst, &added);
|
path_list_insert(dst, &added);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_only) {
|
if (show_only) {
|
||||||
show_list("Changed : ", &changed);
|
show_list("Changed : ", &changed);
|
||||||
show_list("Adding : ", &added);
|
show_list("Adding : ", &added);
|
||||||
show_list("Deleting : ", &deleted);
|
show_list("Deleting : ", &deleted);
|
||||||
|
@ -3,12 +3,10 @@
|
|||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
#define CUTOFF_DATE_SLOP 86400 /* one day */
|
#define CUTOFF_DATE_SLOP 86400 /* one day */
|
||||||
|
|
||||||
static const char name_rev_usage[] =
|
|
||||||
"git-name-rev [--tags | --refs=<pattern>] ( --all | --stdin | committish [committish...] )\n";
|
|
||||||
|
|
||||||
typedef struct rev_name {
|
typedef struct rev_name {
|
||||||
const char *tip_name;
|
const char *tip_name;
|
||||||
int generation;
|
int generation;
|
||||||
@ -153,51 +151,41 @@ static const char* get_rev_name(struct object *o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char const * const name_rev_usage[] = {
|
||||||
|
"git-name-rev [options] ( --all | --stdin | <commit>... )",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct object_array revs = { 0, 0, NULL };
|
struct object_array revs = { 0, 0, NULL };
|
||||||
int as_is = 0, all = 0, transform_stdin = 0;
|
int all = 0, transform_stdin = 0;
|
||||||
struct name_ref_data data = { 0, 0, NULL };
|
struct name_ref_data data = { 0, 0, NULL };
|
||||||
|
struct option opts[] = {
|
||||||
|
OPT_BOOLEAN(0, "name-only", &data.name_only, "print only names (no SHA-1)"),
|
||||||
|
OPT_BOOLEAN(0, "tags", &data.tags_only, "only use tags to name the commits"),
|
||||||
|
OPT_STRING(0, "refs", &data.ref_filter, "pattern",
|
||||||
|
"only use refs matching <pattern>"),
|
||||||
|
OPT_GROUP(""),
|
||||||
|
OPT_BOOLEAN(0, "all", &all, "list all commits reachable from all refs"),
|
||||||
|
OPT_BOOLEAN(0, "stdin", &transform_stdin, "read from stdin"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
git_config(git_default_config);
|
git_config(git_default_config);
|
||||||
|
argc = parse_options(argc, argv, opts, name_rev_usage, 0);
|
||||||
|
if (!!all + !!transform_stdin + !!argc > 1) {
|
||||||
|
error("Specify either a list, or --all, not both!");
|
||||||
|
usage_with_options(name_rev_usage, opts);
|
||||||
|
}
|
||||||
|
if (all || transform_stdin)
|
||||||
|
cutoff = 0;
|
||||||
|
|
||||||
if (argc < 2)
|
for (; argc; argc--, argv++) {
|
||||||
usage(name_rev_usage);
|
|
||||||
|
|
||||||
for (--argc, ++argv; argc; --argc, ++argv) {
|
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
struct object *o;
|
struct object *o;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
|
|
||||||
if (!as_is && (*argv)[0] == '-') {
|
|
||||||
if (!strcmp(*argv, "--")) {
|
|
||||||
as_is = 1;
|
|
||||||
continue;
|
|
||||||
} else if (!strcmp(*argv, "--name-only")) {
|
|
||||||
data.name_only = 1;
|
|
||||||
continue;
|
|
||||||
} else if (!strcmp(*argv, "--tags")) {
|
|
||||||
data.tags_only = 1;
|
|
||||||
continue;
|
|
||||||
} else if (!prefixcmp(*argv, "--refs=")) {
|
|
||||||
data.ref_filter = *argv + 7;
|
|
||||||
continue;
|
|
||||||
} else if (!strcmp(*argv, "--all")) {
|
|
||||||
if (argc > 1)
|
|
||||||
die("Specify either a list, or --all, not both!");
|
|
||||||
all = 1;
|
|
||||||
cutoff = 0;
|
|
||||||
continue;
|
|
||||||
} else if (!strcmp(*argv, "--stdin")) {
|
|
||||||
if (argc > 1)
|
|
||||||
die("Specify either a list, or --stdin, not both!");
|
|
||||||
transform_stdin = 1;
|
|
||||||
cutoff = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
usage(name_rev_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_sha1(*argv, sha1)) {
|
if (get_sha1(*argv, sha1)) {
|
||||||
fprintf(stderr, "Could not get sha1 for %s. Skipping.\n",
|
fprintf(stderr, "Could not get sha1 for %s. Skipping.\n",
|
||||||
*argv);
|
*argv);
|
||||||
@ -212,10 +200,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
commit = (struct commit *)o;
|
commit = (struct commit *)o;
|
||||||
|
|
||||||
if (cutoff > commit->date)
|
if (cutoff > commit->date)
|
||||||
cutoff = commit->date;
|
cutoff = commit->date;
|
||||||
|
|
||||||
add_object_array((struct object *)commit, *argv, &revs);
|
add_object_array((struct object *)commit, *argv, &revs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
#include "parse-options.h"
|
||||||
static const char builtin_pack_refs_usage[] =
|
|
||||||
"git-pack-refs [--all] [--prune | --no-prune]";
|
|
||||||
|
|
||||||
struct ref_to_prune {
|
struct ref_to_prune {
|
||||||
struct ref_to_prune *next;
|
struct ref_to_prune *next;
|
||||||
@ -117,31 +115,26 @@ static int pack_refs(unsigned int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char const * const pack_refs_usage[] = {
|
||||||
|
"git-pack-refs [options]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
int cmd_pack_refs(int argc, const char **argv, const char *prefix)
|
int cmd_pack_refs(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i;
|
int all = 0, prune = 1;
|
||||||
unsigned int flags;
|
unsigned int flags = 0;
|
||||||
|
struct option opts[] = {
|
||||||
flags = PACK_REFS_PRUNE;
|
OPT_BOOLEAN(0, "all", &all, "pack everything"),
|
||||||
for (i = 1; i < argc; i++) {
|
OPT_BOOLEAN(0, "prune", &prune, "prune loose refs (default)"),
|
||||||
const char *arg = argv[i];
|
OPT_END(),
|
||||||
if (!strcmp(arg, "--prune")) {
|
};
|
||||||
flags |= PACK_REFS_PRUNE; /* now the default */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--no-prune")) {
|
|
||||||
flags &= ~PACK_REFS_PRUNE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "--all")) {
|
|
||||||
flags |= PACK_REFS_ALL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* perhaps other parameters later... */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i != argc)
|
|
||||||
usage(builtin_pack_refs_usage);
|
|
||||||
|
|
||||||
|
if (parse_options(argc, argv, opts, pack_refs_usage, 0))
|
||||||
|
usage_with_options(pack_refs_usage, opts);
|
||||||
|
if (prune)
|
||||||
|
flags |= PACK_REFS_PRUNE;
|
||||||
|
if (all)
|
||||||
|
flags |= PACK_REFS_ALL;
|
||||||
return pack_refs(flags);
|
return pack_refs(flags);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
#include "exec_cmd.h"
|
#include "exec_cmd.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This implements the builtins revert and cherry-pick.
|
* This implements the builtins revert and cherry-pick.
|
||||||
@ -19,51 +20,42 @@
|
|||||||
* Copyright (c) 2005 Junio C Hamano
|
* Copyright (c) 2005 Junio C Hamano
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>";
|
static const char * const revert_usage[] = {
|
||||||
|
"git-revert [options] <commit-ish>",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>";
|
static const char * const cherry_pick_usage[] = {
|
||||||
|
"git-cherry-pick [options] <commit-ish>",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int edit;
|
static int edit, no_replay, no_commit, needed_deref;
|
||||||
static int replay;
|
|
||||||
static enum { REVERT, CHERRY_PICK } action;
|
static enum { REVERT, CHERRY_PICK } action;
|
||||||
static int no_commit;
|
|
||||||
static struct commit *commit;
|
static struct commit *commit;
|
||||||
static int needed_deref;
|
|
||||||
|
|
||||||
static const char *me;
|
static const char *me;
|
||||||
|
|
||||||
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
|
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
|
||||||
|
|
||||||
static void parse_options(int argc, const char **argv)
|
static void parse_args(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
const char *usage_str = action == REVERT ?
|
const char * const * usage_str =
|
||||||
revert_usage : cherry_pick_usage;
|
action == REVERT ? revert_usage : cherry_pick_usage;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
const char *arg;
|
const char *arg;
|
||||||
int i;
|
int noop;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
|
||||||
|
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
|
||||||
|
OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
|
||||||
|
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
if (argc < 2)
|
if (parse_options(argc, argv, options, usage_str, 0) != 1)
|
||||||
usage(usage_str);
|
usage_with_options(usage_str, options);
|
||||||
|
arg = argv[0];
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
arg = argv[i];
|
|
||||||
if (arg[0] != '-')
|
|
||||||
break;
|
|
||||||
if (!strcmp(arg, "-n") || !strcmp(arg, "--no-commit"))
|
|
||||||
no_commit = 1;
|
|
||||||
else if (!strcmp(arg, "-e") || !strcmp(arg, "--edit"))
|
|
||||||
edit = 1;
|
|
||||||
else if (!strcmp(arg, "--no-edit"))
|
|
||||||
edit = 0;
|
|
||||||
else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-"
|
|
||||||
"to-expose-my-private-commit-object-name"))
|
|
||||||
replay = 0;
|
|
||||||
else if (strcmp(arg, "-r"))
|
|
||||||
usage(usage_str);
|
|
||||||
}
|
|
||||||
if (i != argc - 1)
|
|
||||||
usage(usage_str);
|
|
||||||
arg = argv[argc - 1];
|
|
||||||
if (get_sha1(arg, sha1))
|
if (get_sha1(arg, sha1))
|
||||||
die ("Cannot find '%s'", arg);
|
die ("Cannot find '%s'", arg);
|
||||||
commit = (struct commit *)parse_object(sha1);
|
commit = (struct commit *)parse_object(sha1);
|
||||||
@ -243,10 +235,10 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
|||||||
git_config(git_default_config);
|
git_config(git_default_config);
|
||||||
me = action == REVERT ? "revert" : "cherry-pick";
|
me = action == REVERT ? "revert" : "cherry-pick";
|
||||||
setenv(GIT_REFLOG_ACTION, me, 0);
|
setenv(GIT_REFLOG_ACTION, me, 0);
|
||||||
parse_options(argc, argv);
|
parse_args(argc, argv);
|
||||||
|
|
||||||
/* this is copied from the shell script, but it's never triggered... */
|
/* this is copied from the shell script, but it's never triggered... */
|
||||||
if (action == REVERT && replay)
|
if (action == REVERT && !no_replay)
|
||||||
die("revert is incompatible with replay");
|
die("revert is incompatible with replay");
|
||||||
|
|
||||||
if (no_commit) {
|
if (no_commit) {
|
||||||
@ -310,7 +302,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
|||||||
next = commit;
|
next = commit;
|
||||||
set_author_ident_env(message);
|
set_author_ident_env(message);
|
||||||
add_message_to_msg(message);
|
add_message_to_msg(message);
|
||||||
if (!replay) {
|
if (no_replay) {
|
||||||
add_to_msg("(cherry picked from commit ");
|
add_to_msg("(cherry picked from commit ");
|
||||||
add_to_msg(sha1_to_hex(commit->object.sha1));
|
add_to_msg(sha1_to_hex(commit->object.sha1));
|
||||||
add_to_msg(")\n");
|
add_to_msg(")\n");
|
||||||
@ -388,13 +380,14 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
|
|||||||
{
|
{
|
||||||
if (isatty(0))
|
if (isatty(0))
|
||||||
edit = 1;
|
edit = 1;
|
||||||
|
no_replay = 1;
|
||||||
action = REVERT;
|
action = REVERT;
|
||||||
return revert_or_cherry_pick(argc, argv);
|
return revert_or_cherry_pick(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
|
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
replay = 1;
|
no_replay = 0;
|
||||||
action = CHERRY_PICK;
|
action = CHERRY_PICK;
|
||||||
return revert_or_cherry_pick(argc, argv);
|
return revert_or_cherry_pick(argc, argv);
|
||||||
}
|
}
|
||||||
|
54
builtin-rm.c
54
builtin-rm.c
@ -8,9 +8,12 @@
|
|||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
#include "tree-walk.h"
|
#include "tree-walk.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static const char builtin_rm_usage[] =
|
static const char * const builtin_rm_usage[] = {
|
||||||
"git-rm [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...";
|
"git-rm [options] [--] <file>...",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
int nr, alloc;
|
int nr, alloc;
|
||||||
@ -121,11 +124,23 @@ static int check_local_mod(unsigned char *head, int index_only)
|
|||||||
|
|
||||||
static struct lock_file lock_file;
|
static struct lock_file lock_file;
|
||||||
|
|
||||||
|
static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
|
||||||
|
static int ignore_unmatch = 0;
|
||||||
|
|
||||||
|
static struct option builtin_rm_options[] = {
|
||||||
|
OPT__DRY_RUN(&show_only),
|
||||||
|
OPT__QUIET(&quiet),
|
||||||
|
OPT_BOOLEAN( 0 , "cached", &index_only, "only remove from the index"),
|
||||||
|
OPT_BOOLEAN('f', NULL, &force, "override the up-to-date check"),
|
||||||
|
OPT_BOOLEAN('r', NULL, &recursive, "allow recursive removal"),
|
||||||
|
OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
|
||||||
|
"exit with a zero status even if nothing matched"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
int cmd_rm(int argc, const char **argv, const char *prefix)
|
int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, newfd;
|
int i, newfd;
|
||||||
int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
|
|
||||||
int ignore_unmatch = 0;
|
|
||||||
const char **pathspec;
|
const char **pathspec;
|
||||||
char *seen;
|
char *seen;
|
||||||
|
|
||||||
@ -136,34 +151,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
|||||||
if (read_cache() < 0)
|
if (read_cache() < 0)
|
||||||
die("index file corrupt");
|
die("index file corrupt");
|
||||||
|
|
||||||
for (i = 1 ; i < argc ; i++) {
|
argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
|
||||||
const char *arg = argv[i];
|
if (!argc)
|
||||||
|
usage_with_options(builtin_rm_usage, builtin_rm_options);
|
||||||
|
|
||||||
if (*arg != '-')
|
pathspec = get_pathspec(prefix, argv);
|
||||||
break;
|
|
||||||
else if (!strcmp(arg, "--")) {
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!strcmp(arg, "-n"))
|
|
||||||
show_only = 1;
|
|
||||||
else if (!strcmp(arg, "--cached"))
|
|
||||||
index_only = 1;
|
|
||||||
else if (!strcmp(arg, "-f"))
|
|
||||||
force = 1;
|
|
||||||
else if (!strcmp(arg, "-r"))
|
|
||||||
recursive = 1;
|
|
||||||
else if (!strcmp(arg, "--quiet"))
|
|
||||||
quiet = 1;
|
|
||||||
else if (!strcmp(arg, "--ignore-unmatch"))
|
|
||||||
ignore_unmatch = 1;
|
|
||||||
else
|
|
||||||
usage(builtin_rm_usage);
|
|
||||||
}
|
|
||||||
if (argc <= i)
|
|
||||||
usage(builtin_rm_usage);
|
|
||||||
|
|
||||||
pathspec = get_pathspec(prefix, argv + i);
|
|
||||||
seen = NULL;
|
seen = NULL;
|
||||||
for (i = 0; pathspec[i] ; i++)
|
for (i = 0; pathspec[i] ; i++)
|
||||||
/* nothing */;
|
/* nothing */;
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static const char git_symbolic_ref_usage[] =
|
static const char * const git_symbolic_ref_usage[] = {
|
||||||
"git-symbolic-ref [-q] [-m <reason>] name [ref]";
|
"git-symbolic-ref [options] name [ref]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void check_symref(const char *HEAD, int quiet)
|
static void check_symref(const char *HEAD, int quiet)
|
||||||
{
|
{
|
||||||
@ -26,44 +29,25 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
|
|||||||
{
|
{
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT__QUIET(&quiet),
|
||||||
|
OPT_STRING('m', NULL, &msg, "reason", "reason of the update"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
git_config(git_default_config);
|
git_config(git_default_config);
|
||||||
|
argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
|
||||||
while (1 < argc) {
|
if (msg &&!*msg)
|
||||||
const char *arg = argv[1];
|
die("Refusing to perform update with empty message");
|
||||||
if (arg[0] != '-')
|
|
||||||
break;
|
|
||||||
else if (!strcmp("-q", arg))
|
|
||||||
quiet = 1;
|
|
||||||
else if (!strcmp("-m", arg)) {
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
if (argc <= 1)
|
|
||||||
break;
|
|
||||||
msg = argv[1];
|
|
||||||
if (!*msg)
|
|
||||||
die("Refusing to perform update with empty message");
|
|
||||||
}
|
|
||||||
else if (!strcmp("--", arg)) {
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
die("unknown option %s", arg);
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 2:
|
case 1:
|
||||||
check_symref(argv[1], quiet);
|
check_symref(argv[0], quiet);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 2:
|
||||||
create_symref(argv[1], argv[2], msg);
|
create_symref(argv[0], argv[1], msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage(git_symbolic_ref_usage);
|
usage_with_options(git_symbolic_ref_usage, options);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,59 +1,44 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static const char git_update_ref_usage[] =
|
static const char * const git_update_ref_usage[] = {
|
||||||
"git-update-ref [-m <reason>] (-d <refname> <value> | [--no-deref] <refname> <value> [<oldval>])";
|
"git-update-ref [options] -d <refname> <oldval>",
|
||||||
|
"git-update-ref [options] <refname> <newval> [<oldval>]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
int cmd_update_ref(int argc, const char **argv, const char *prefix)
|
int cmd_update_ref(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL;
|
const char *refname, *value, *oldval, *msg=NULL;
|
||||||
unsigned char sha1[20], oldsha1[20];
|
unsigned char sha1[20], oldsha1[20];
|
||||||
int i, delete, ref_flags;
|
int delete = 0, no_deref = 0;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_STRING( 'm', NULL, &msg, "reason", "reason of the update"),
|
||||||
|
OPT_BOOLEAN('d', NULL, &delete, "deletes the reference"),
|
||||||
|
OPT_BOOLEAN( 0 , "no-deref", &no_deref,
|
||||||
|
"update <refname> not the one it points to"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
delete = 0;
|
|
||||||
ref_flags = 0;
|
|
||||||
git_config(git_default_config);
|
git_config(git_default_config);
|
||||||
|
argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
|
||||||
|
if (msg && !*msg)
|
||||||
|
die("Refusing to perform update with empty message.");
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
if (argc < 2 || argc > 3)
|
||||||
if (!strcmp("-m", argv[i])) {
|
usage_with_options(git_update_ref_usage, options);
|
||||||
if (i+1 >= argc)
|
refname = argv[0];
|
||||||
usage(git_update_ref_usage);
|
value = argv[1];
|
||||||
msg = argv[++i];
|
oldval = argv[2];
|
||||||
if (!*msg)
|
|
||||||
die("Refusing to perform update with empty message.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp("-d", argv[i])) {
|
|
||||||
delete = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcmp("--no-deref", argv[i])) {
|
|
||||||
ref_flags |= REF_NODEREF;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!refname) {
|
|
||||||
refname = argv[i];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!value) {
|
|
||||||
value = argv[i];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!oldval) {
|
|
||||||
oldval = argv[i];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!refname || !value)
|
|
||||||
usage(git_update_ref_usage);
|
|
||||||
|
|
||||||
if (get_sha1(value, sha1))
|
if (get_sha1(value, sha1))
|
||||||
die("%s: not a valid SHA1", value);
|
die("%s: not a valid SHA1", value);
|
||||||
|
|
||||||
if (delete) {
|
if (delete) {
|
||||||
if (oldval)
|
if (oldval)
|
||||||
usage(git_update_ref_usage);
|
usage_with_options(git_update_ref_usage, options);
|
||||||
return delete_ref(refname, sha1);
|
return delete_ref(refname, sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,5 +47,5 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
|
|||||||
die("%s: not a valid old SHA1", oldval);
|
die("%s: not a valid old SHA1", oldval);
|
||||||
|
|
||||||
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
|
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
|
||||||
ref_flags, DIE_ON_ERR);
|
no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
|
||||||
}
|
}
|
||||||
|
322
parse-options.c
Normal file
322
parse-options.c
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
#include "git-compat-util.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
|
#define OPT_SHORT 1
|
||||||
|
#define OPT_UNSET 2
|
||||||
|
|
||||||
|
struct optparse_t {
|
||||||
|
const char **argv;
|
||||||
|
int argc;
|
||||||
|
const char *opt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline const char *get_arg(struct optparse_t *p)
|
||||||
|
{
|
||||||
|
if (p->opt) {
|
||||||
|
const char *res = p->opt;
|
||||||
|
p->opt = NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
p->argc--;
|
||||||
|
return *++p->argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *skip_prefix(const char *str, const char *prefix)
|
||||||
|
{
|
||||||
|
size_t len = strlen(prefix);
|
||||||
|
return strncmp(str, prefix, len) ? NULL : str + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int opterror(const struct option *opt, const char *reason, int flags)
|
||||||
|
{
|
||||||
|
if (flags & OPT_SHORT)
|
||||||
|
return error("switch `%c' %s", opt->short_name, reason);
|
||||||
|
if (flags & OPT_UNSET)
|
||||||
|
return error("option `no-%s' %s", opt->long_name, reason);
|
||||||
|
return error("option `%s' %s", opt->long_name, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_value(struct optparse_t *p,
|
||||||
|
const struct option *opt, int flags)
|
||||||
|
{
|
||||||
|
const char *s, *arg;
|
||||||
|
arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
|
||||||
|
|
||||||
|
if (p->opt && (flags & OPT_UNSET))
|
||||||
|
return opterror(opt, "takes no value", flags);
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case OPTION_BOOLEAN:
|
||||||
|
if (!(flags & OPT_SHORT) && p->opt)
|
||||||
|
return opterror(opt, "takes no value", flags);
|
||||||
|
if (flags & OPT_UNSET)
|
||||||
|
*(int *)opt->value = 0;
|
||||||
|
else
|
||||||
|
(*(int *)opt->value)++;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case OPTION_STRING:
|
||||||
|
if (flags & OPT_UNSET) {
|
||||||
|
*(const char **)opt->value = (const char *)NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) {
|
||||||
|
*(const char **)opt->value = (const char *)opt->defval;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!arg)
|
||||||
|
return opterror(opt, "requires a value", flags);
|
||||||
|
*(const char **)opt->value = get_arg(p);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case OPTION_CALLBACK:
|
||||||
|
if (flags & OPT_UNSET)
|
||||||
|
return (*opt->callback)(opt, NULL, 1);
|
||||||
|
if (opt->flags & PARSE_OPT_NOARG) {
|
||||||
|
if (p->opt && !(flags & OPT_SHORT))
|
||||||
|
return opterror(opt, "takes no value", flags);
|
||||||
|
return (*opt->callback)(opt, NULL, 0);
|
||||||
|
}
|
||||||
|
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-'))
|
||||||
|
return (*opt->callback)(opt, NULL, 0);
|
||||||
|
if (!arg)
|
||||||
|
return opterror(opt, "requires a value", flags);
|
||||||
|
return (*opt->callback)(opt, get_arg(p), 0);
|
||||||
|
|
||||||
|
case OPTION_INTEGER:
|
||||||
|
if (flags & OPT_UNSET) {
|
||||||
|
*(int *)opt->value = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (opt->flags & PARSE_OPT_OPTARG && (!arg || !isdigit(*arg))) {
|
||||||
|
*(int *)opt->value = opt->defval;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!arg)
|
||||||
|
return opterror(opt, "requires a value", flags);
|
||||||
|
*(int *)opt->value = strtol(get_arg(p), (char **)&s, 10);
|
||||||
|
if (*s)
|
||||||
|
return opterror(opt, "expects a numerical value", flags);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
die("should not happen, someone must be hit on the forehead");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_short_opt(struct optparse_t *p, const struct option *options)
|
||||||
|
{
|
||||||
|
for (; options->type != OPTION_END; options++) {
|
||||||
|
if (options->short_name == *p->opt) {
|
||||||
|
p->opt = p->opt[1] ? p->opt + 1 : NULL;
|
||||||
|
return get_value(p, options, OPT_SHORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error("unknown switch `%c'", *p->opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_long_opt(struct optparse_t *p, const char *arg,
|
||||||
|
const struct option *options)
|
||||||
|
{
|
||||||
|
const char *arg_end = strchr(arg, '=');
|
||||||
|
const struct option *abbrev_option = NULL;
|
||||||
|
int abbrev_flags = 0;
|
||||||
|
|
||||||
|
if (!arg_end)
|
||||||
|
arg_end = arg + strlen(arg);
|
||||||
|
|
||||||
|
for (; options->type != OPTION_END; options++) {
|
||||||
|
const char *rest;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (!options->long_name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rest = skip_prefix(arg, options->long_name);
|
||||||
|
if (!rest) {
|
||||||
|
/* abbreviated? */
|
||||||
|
if (!strncmp(options->long_name, arg, arg_end - arg)) {
|
||||||
|
is_abbreviated:
|
||||||
|
if (abbrev_option)
|
||||||
|
return error("Ambiguous option: %s "
|
||||||
|
"(could be --%s%s or --%s%s)",
|
||||||
|
arg,
|
||||||
|
(flags & OPT_UNSET) ?
|
||||||
|
"no-" : "",
|
||||||
|
options->long_name,
|
||||||
|
(abbrev_flags & OPT_UNSET) ?
|
||||||
|
"no-" : "",
|
||||||
|
abbrev_option->long_name);
|
||||||
|
if (!(flags & OPT_UNSET) && *arg_end)
|
||||||
|
p->opt = arg_end + 1;
|
||||||
|
abbrev_option = options;
|
||||||
|
abbrev_flags = flags;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* negated and abbreviated very much? */
|
||||||
|
if (!prefixcmp("no-", arg)) {
|
||||||
|
flags |= OPT_UNSET;
|
||||||
|
goto is_abbreviated;
|
||||||
|
}
|
||||||
|
/* negated? */
|
||||||
|
if (strncmp(arg, "no-", 3))
|
||||||
|
continue;
|
||||||
|
flags |= OPT_UNSET;
|
||||||
|
rest = skip_prefix(arg + 3, options->long_name);
|
||||||
|
/* abbreviated and negated? */
|
||||||
|
if (!rest && !prefixcmp(options->long_name, arg + 3))
|
||||||
|
goto is_abbreviated;
|
||||||
|
if (!rest)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*rest) {
|
||||||
|
if (*rest != '=')
|
||||||
|
continue;
|
||||||
|
p->opt = rest + 1;
|
||||||
|
}
|
||||||
|
return get_value(p, options, flags);
|
||||||
|
}
|
||||||
|
if (abbrev_option)
|
||||||
|
return get_value(p, abbrev_option, abbrev_flags);
|
||||||
|
return error("unknown option `%s'", arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_options(int argc, const char **argv, const struct option *options,
|
||||||
|
const char * const usagestr[], int flags)
|
||||||
|
{
|
||||||
|
struct optparse_t args = { argv + 1, argc - 1, NULL };
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
for (; args.argc; args.argc--, args.argv++) {
|
||||||
|
const char *arg = args.argv[0];
|
||||||
|
|
||||||
|
if (*arg != '-' || !arg[1]) {
|
||||||
|
argv[j++] = args.argv[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[1] != '-') {
|
||||||
|
args.opt = arg + 1;
|
||||||
|
do {
|
||||||
|
if (*args.opt == 'h')
|
||||||
|
usage_with_options(usagestr, options);
|
||||||
|
if (parse_short_opt(&args, options) < 0)
|
||||||
|
usage_with_options(usagestr, options);
|
||||||
|
} while (args.opt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arg[2]) { /* "--" */
|
||||||
|
if (!(flags & PARSE_OPT_KEEP_DASHDASH)) {
|
||||||
|
args.argc--;
|
||||||
|
args.argv++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(arg + 2, "help"))
|
||||||
|
usage_with_options(usagestr, options);
|
||||||
|
if (parse_long_opt(&args, arg + 2, options))
|
||||||
|
usage_with_options(usagestr, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(argv + j, args.argv, args.argc * sizeof(*argv));
|
||||||
|
argv[j + args.argc] = NULL;
|
||||||
|
return j + args.argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define USAGE_OPTS_WIDTH 24
|
||||||
|
#define USAGE_GAP 2
|
||||||
|
|
||||||
|
void usage_with_options(const char * const *usagestr,
|
||||||
|
const struct option *opts)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s\n", *usagestr++);
|
||||||
|
while (*usagestr && **usagestr)
|
||||||
|
fprintf(stderr, " or: %s\n", *usagestr++);
|
||||||
|
while (*usagestr)
|
||||||
|
fprintf(stderr, " %s\n", *usagestr++);
|
||||||
|
|
||||||
|
if (opts->type != OPTION_GROUP)
|
||||||
|
fputc('\n', stderr);
|
||||||
|
|
||||||
|
for (; opts->type != OPTION_END; opts++) {
|
||||||
|
size_t pos;
|
||||||
|
int pad;
|
||||||
|
|
||||||
|
if (opts->type == OPTION_GROUP) {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
if (*opts->help)
|
||||||
|
fprintf(stderr, "%s\n", opts->help);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = fprintf(stderr, " ");
|
||||||
|
if (opts->short_name)
|
||||||
|
pos += fprintf(stderr, "-%c", opts->short_name);
|
||||||
|
if (opts->long_name && opts->short_name)
|
||||||
|
pos += fprintf(stderr, ", ");
|
||||||
|
if (opts->long_name)
|
||||||
|
pos += fprintf(stderr, "--%s", opts->long_name);
|
||||||
|
|
||||||
|
switch (opts->type) {
|
||||||
|
case OPTION_INTEGER:
|
||||||
|
if (opts->flags & PARSE_OPT_OPTARG)
|
||||||
|
pos += fprintf(stderr, " [<n>]");
|
||||||
|
else
|
||||||
|
pos += fprintf(stderr, " <n>");
|
||||||
|
break;
|
||||||
|
case OPTION_CALLBACK:
|
||||||
|
if (opts->flags & PARSE_OPT_NOARG)
|
||||||
|
break;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case OPTION_STRING:
|
||||||
|
if (opts->argh) {
|
||||||
|
if (opts->flags & PARSE_OPT_OPTARG)
|
||||||
|
pos += fprintf(stderr, " [<%s>]", opts->argh);
|
||||||
|
else
|
||||||
|
pos += fprintf(stderr, " <%s>", opts->argh);
|
||||||
|
} else {
|
||||||
|
if (opts->flags & PARSE_OPT_OPTARG)
|
||||||
|
pos += fprintf(stderr, " [...]");
|
||||||
|
else
|
||||||
|
pos += fprintf(stderr, " ...");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos <= USAGE_OPTS_WIDTH)
|
||||||
|
pad = USAGE_OPTS_WIDTH - pos;
|
||||||
|
else {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
pad = USAGE_OPTS_WIDTH;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
|
||||||
|
}
|
||||||
|
fputc('\n', stderr);
|
||||||
|
|
||||||
|
exit(129);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----- some often used options -----*/
|
||||||
|
#include "cache.h"
|
||||||
|
int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
if (!arg) {
|
||||||
|
v = unset ? 0 : DEFAULT_ABBREV;
|
||||||
|
} else {
|
||||||
|
v = strtol(arg, (char **)&arg, 10);
|
||||||
|
if (*arg)
|
||||||
|
return opterror(opt, "expects a numerical value", 0);
|
||||||
|
if (v && v < MINIMUM_ABBREV)
|
||||||
|
v = MINIMUM_ABBREV;
|
||||||
|
else if (v > 40)
|
||||||
|
v = 40;
|
||||||
|
}
|
||||||
|
*(int *)(opt->value) = v;
|
||||||
|
return 0;
|
||||||
|
}
|
70
parse-options.h
Normal file
70
parse-options.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef PARSE_OPTIONS_H
|
||||||
|
#define PARSE_OPTIONS_H
|
||||||
|
|
||||||
|
enum parse_opt_type {
|
||||||
|
OPTION_END,
|
||||||
|
OPTION_GROUP,
|
||||||
|
OPTION_BOOLEAN,
|
||||||
|
OPTION_STRING,
|
||||||
|
OPTION_INTEGER,
|
||||||
|
OPTION_CALLBACK,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum parse_opt_flags {
|
||||||
|
PARSE_OPT_KEEP_DASHDASH = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum parse_opt_option_flags {
|
||||||
|
PARSE_OPT_OPTARG = 1,
|
||||||
|
PARSE_OPT_NOARG = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct option;
|
||||||
|
typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
|
||||||
|
|
||||||
|
struct option {
|
||||||
|
enum parse_opt_type type;
|
||||||
|
int short_name;
|
||||||
|
const char *long_name;
|
||||||
|
void *value;
|
||||||
|
const char *argh;
|
||||||
|
const char *help;
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
parse_opt_cb *callback;
|
||||||
|
/* holds default value for PARSE_OPT_OPTARG,
|
||||||
|
though callbacks can use it like they want */
|
||||||
|
intptr_t defval;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define OPT_END() { OPTION_END }
|
||||||
|
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
|
||||||
|
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
|
||||||
|
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
|
||||||
|
#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
|
||||||
|
#define OPT_CALLBACK(s, l, v, a, h, f) \
|
||||||
|
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
|
||||||
|
|
||||||
|
/* parse_options() will filter out the processed options and leave the
|
||||||
|
* non-option argments in argv[].
|
||||||
|
* Returns the number of arguments left in argv[].
|
||||||
|
*/
|
||||||
|
extern int parse_options(int argc, const char **argv,
|
||||||
|
const struct option *options,
|
||||||
|
const char * const usagestr[], int flags);
|
||||||
|
|
||||||
|
extern NORETURN void usage_with_options(const char * const *usagestr,
|
||||||
|
const struct option *options);
|
||||||
|
|
||||||
|
/*----- some often used options -----*/
|
||||||
|
extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
|
||||||
|
|
||||||
|
#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
|
||||||
|
#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
|
||||||
|
#define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run")
|
||||||
|
#define OPT__ABBREV(var) \
|
||||||
|
{ OPTION_CALLBACK, 0, "abbrev", (var), "n", \
|
||||||
|
"use <n> digits to display SHA-1s", \
|
||||||
|
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
|
||||||
|
|
||||||
|
#endif
|
93
t/t0040-parse-options.sh
Executable file
93
t/t0040-parse-options.sh
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 Johannes Schindelin
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='our own option parser'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
cat > expect.err << EOF
|
||||||
|
usage: test-parse-options <options>
|
||||||
|
|
||||||
|
-b, --boolean get a boolean
|
||||||
|
-i, --integer <n> get a integer
|
||||||
|
-j <n> get a integer, too
|
||||||
|
|
||||||
|
string options
|
||||||
|
-s, --string <string>
|
||||||
|
get a string
|
||||||
|
--string2 <str> get another string
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'test help' '
|
||||||
|
! test-parse-options -h > output 2> output.err &&
|
||||||
|
test ! -s output &&
|
||||||
|
git diff expect.err output.err
|
||||||
|
'
|
||||||
|
|
||||||
|
cat > expect << EOF
|
||||||
|
boolean: 2
|
||||||
|
integer: 1729
|
||||||
|
string: 123
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'short options' '
|
||||||
|
test-parse-options -s123 -b -i 1729 -b > output 2> output.err &&
|
||||||
|
git diff expect output &&
|
||||||
|
test ! -s output.err
|
||||||
|
'
|
||||||
|
cat > expect << EOF
|
||||||
|
boolean: 2
|
||||||
|
integer: 1729
|
||||||
|
string: 321
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'long options' '
|
||||||
|
test-parse-options --boolean --integer 1729 --boolean --string2=321 \
|
||||||
|
> output 2> output.err &&
|
||||||
|
test ! -s output.err &&
|
||||||
|
git diff expect output
|
||||||
|
'
|
||||||
|
|
||||||
|
cat > expect << EOF
|
||||||
|
boolean: 1
|
||||||
|
integer: 13
|
||||||
|
string: 123
|
||||||
|
arg 00: a1
|
||||||
|
arg 01: b1
|
||||||
|
arg 02: --boolean
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'intermingled arguments' '
|
||||||
|
test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
|
||||||
|
> output 2> output.err &&
|
||||||
|
test ! -s output.err &&
|
||||||
|
git diff expect output
|
||||||
|
'
|
||||||
|
|
||||||
|
cat > expect << EOF
|
||||||
|
boolean: 0
|
||||||
|
integer: 2
|
||||||
|
string: (not set)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'unambiguously abbreviated option' '
|
||||||
|
test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
|
||||||
|
test ! -s output.err &&
|
||||||
|
git diff expect output
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'unambiguously abbreviated option with "="' '
|
||||||
|
test-parse-options --int=2 > output 2> output.err &&
|
||||||
|
test ! -s output.err &&
|
||||||
|
git diff expect output
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_failure 'ambiguously abbreviated option' '
|
||||||
|
test-parse-options --strin 123;
|
||||||
|
test $? != 129
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
0
t/t6300-for-each-ref.sh
Normal file → Executable file
0
t/t6300-for-each-ref.sh
Normal file → Executable file
35
test-parse-options.c
Normal file
35
test-parse-options.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "cache.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
|
static int boolean = 0;
|
||||||
|
static int integer = 0;
|
||||||
|
static char *string = NULL;
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
const char *usage[] = {
|
||||||
|
"test-parse-options <options>",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"),
|
||||||
|
OPT_INTEGER('i', "integer", &integer, "get a integer"),
|
||||||
|
OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
|
||||||
|
OPT_GROUP("string options"),
|
||||||
|
OPT_STRING('s', "string", &string, "string", "get a string"),
|
||||||
|
OPT_STRING(0, "string2", &string, "str", "get another string"),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
argc = parse_options(argc, argv, options, usage, 0);
|
||||||
|
|
||||||
|
printf("boolean: %d\n", boolean);
|
||||||
|
printf("integer: %d\n", integer);
|
||||||
|
printf("string: %s\n", string ? string : "(not set)");
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
printf("arg %02d: %s\n", i, argv[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user