summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/add.c6
-rw-r--r--builtin/apply.c71
-rw-r--r--builtin/blame.c61
-rw-r--r--builtin/branch.c5
-rw-r--r--builtin/cat-file.c2
-rw-r--r--builtin/checkout-index.c6
-rw-r--r--builtin/checkout.c10
-rw-r--r--builtin/clean.c14
-rw-r--r--builtin/commit-tree.c12
-rw-r--r--builtin/commit.c6
-rw-r--r--builtin/count-objects.c2
-rw-r--r--builtin/fetch.c9
-rw-r--r--builtin/fmt-merge-msg.c66
-rw-r--r--builtin/fsck.c2
-rw-r--r--builtin/gc.c2
-rw-r--r--builtin/grep.c4
-rw-r--r--builtin/log.c9
-rw-r--r--builtin/merge-file.c9
-rw-r--r--builtin/merge-recursive.c15
-rw-r--r--builtin/merge.c74
-rw-r--r--builtin/mv.c4
-rw-r--r--builtin/notes.c9
-rw-r--r--builtin/pack-objects.c16
-rw-r--r--builtin/prune.c5
-rw-r--r--builtin/read-tree.c12
-rw-r--r--builtin/remote.c10
-rw-r--r--builtin/reset.c2
-rw-r--r--builtin/rev-list.c6
-rw-r--r--builtin/revert.c2
-rw-r--r--builtin/rm.c6
-rw-r--r--builtin/send-pack.c5
-rw-r--r--builtin/show-ref.c3
-rw-r--r--builtin/symbolic-ref.c3
-rw-r--r--builtin/tag.c2
-rw-r--r--builtin/update-server-info.c3
-rw-r--r--builtin/verify-tag.c2
36 files changed, 280 insertions, 195 deletions
diff --git a/builtin/add.c b/builtin/add.c
index 56a4e0af6b..71f9b04fef 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -313,13 +313,13 @@ static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
static struct option builtin_add_options[] = {
- OPT__DRY_RUN(&show_only),
- OPT__VERBOSE(&verbose),
+ OPT__DRY_RUN(&show_only, "dry run"),
+ OPT__VERBOSE(&verbose, "be verbose"),
OPT_GROUP(""),
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
- OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
+ OPT__FORCE(&ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
diff --git a/builtin/apply.c b/builtin/apply.c
index 23c18c573b..14951daedf 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -449,7 +449,7 @@ static char *find_name_gnu(const char *line, char *def, int p_value)
return squash_slash(strbuf_detach(&name, NULL));
}
-static size_t tz_len(const char *line, size_t len)
+static size_t sane_tz_len(const char *line, size_t len)
{
const char *tz, *p;
@@ -467,6 +467,24 @@ static size_t tz_len(const char *line, size_t len)
return line + len - tz;
}
+static size_t tz_with_colon_len(const char *line, size_t len)
+{
+ const char *tz, *p;
+
+ if (len < strlen(" +08:00") || line[len - strlen(":00")] != ':')
+ return 0;
+ tz = line + len - strlen(" +08:00");
+
+ if (tz[0] != ' ' || (tz[1] != '+' && tz[1] != '-'))
+ return 0;
+ p = tz + 2;
+ if (!isdigit(*p++) || !isdigit(*p++) || *p++ != ':' ||
+ !isdigit(*p++) || !isdigit(*p++))
+ return 0;
+
+ return line + len - tz;
+}
+
static size_t date_len(const char *line, size_t len)
{
const char *date, *p;
@@ -561,7 +579,9 @@ static size_t diff_timestamp_len(const char *line, size_t len)
if (!isdigit(end[-1]))
return 0;
- n = tz_len(line, end - line);
+ n = sane_tz_len(line, end - line);
+ if (!n)
+ n = tz_with_colon_len(line, end - line);
end -= n;
n = short_time_len(line, end - line);
@@ -733,8 +753,8 @@ static int has_epoch_timestamp(const char *nameline)
" "
"[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
" "
- "([-+][0-2][0-9][0-5][0-9])\n";
- const char *timestamp = NULL, *cp;
+ "([-+][0-2][0-9]:?[0-5][0-9])\n";
+ const char *timestamp = NULL, *cp, *colon;
static regex_t *stamp;
regmatch_t m[10];
int zoneoffset;
@@ -764,8 +784,11 @@ static int has_epoch_timestamp(const char *nameline)
return 0;
}
- zoneoffset = strtol(timestamp + m[3].rm_so + 1, NULL, 10);
- zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100);
+ zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10);
+ if (*colon == ':')
+ zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10);
+ else
+ zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100);
if (timestamp[m[3].rm_so] == '-')
zoneoffset = -zoneoffset;
@@ -919,28 +942,28 @@ static int gitdiff_newfile(const char *line, struct patch *patch)
static int gitdiff_copysrc(const char *line, struct patch *patch)
{
patch->is_copy = 1;
- patch->old_name = find_name(line, NULL, 0, 0);
+ patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
static int gitdiff_copydst(const char *line, struct patch *patch)
{
patch->is_copy = 1;
- patch->new_name = find_name(line, NULL, 0, 0);
+ patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
static int gitdiff_renamesrc(const char *line, struct patch *patch)
{
patch->is_rename = 1;
- patch->old_name = find_name(line, NULL, 0, 0);
+ patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
static int gitdiff_renamedst(const char *line, struct patch *patch)
{
patch->is_rename = 1;
- patch->new_name = find_name(line, NULL, 0, 0);
+ patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
@@ -1025,7 +1048,7 @@ static char *git_header_name(char *line, int llen)
{
const char *name;
const char *second = NULL;
- size_t len;
+ size_t len, line_len;
line += strlen("diff --git ");
llen -= strlen("diff --git ");
@@ -1125,6 +1148,10 @@ static char *git_header_name(char *line, int llen)
* Accept a name only if it shows up twice, exactly the same
* form.
*/
+ second = strchr(name, '\n');
+ if (!second)
+ return NULL;
+ line_len = second - name;
for (len = 0 ; ; len++) {
switch (name[len]) {
default:
@@ -1132,15 +1159,11 @@ static char *git_header_name(char *line, int llen)
case '\n':
return NULL;
case '\t': case ' ':
- second = name+len;
- for (;;) {
- char c = *second++;
- if (c == '\n')
- return NULL;
- if (c == '/')
- break;
- }
- if (second[len] == '\n' && !memcmp(name, second, len)) {
+ second = stop_at_slash(name + len, line_len - len);
+ if (!second)
+ return NULL;
+ second++;
+ if (second[len] == '\n' && !strncmp(name, second, len)) {
return xmemdupz(name, len);
}
}
@@ -2645,6 +2668,12 @@ static int apply_binary_fragment(struct image *img, struct patch *patch)
unsigned long len;
void *dst;
+ if (!fragment)
+ return error("missing binary patch data for '%s'",
+ patch->new_name ?
+ patch->new_name :
+ patch->old_name);
+
/* Binary patch is irreversible without the optional second hunk */
if (apply_in_reverse) {
if (!fragment->next)
@@ -3843,7 +3872,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
"don't expect at least one line of context"),
OPT_BOOLEAN(0, "reject", &apply_with_reject,
"leave the rejected hunks in corresponding *.rej files"),
- OPT__VERBOSE(&apply_verbosely),
+ OPT__VERBOSE(&apply_verbosely, "be verbose"),
OPT_BIT(0, "inaccurate-eof", &options,
"tolerate incorrectly detected missing new-line at the end of file",
INACCURATE_EOF),
diff --git a/builtin/blame.c b/builtin/blame.c
index 101535448f..cb25ec9ce8 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -83,6 +83,7 @@ struct origin {
struct commit *commit;
mmfile_t file;
unsigned char blob_sha1[20];
+ unsigned mode;
char path[FLEX_ARRAY];
};
@@ -92,6 +93,7 @@ struct origin {
* Return 1 if the conversion succeeds, 0 otherwise.
*/
int textconv_object(const char *path,
+ unsigned mode,
const unsigned char *sha1,
char **buf,
unsigned long *buf_size)
@@ -100,7 +102,7 @@ int textconv_object(const char *path,
struct userdiff_driver *textconv;
df = alloc_filespec(path);
- fill_filespec(df, sha1, S_IFREG | 0664);
+ fill_filespec(df, sha1, mode);
textconv = get_textconv(df);
if (!textconv) {
free_filespec(df);
@@ -125,7 +127,7 @@ static void fill_origin_blob(struct diff_options *opt,
num_read_blob++;
if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
- textconv_object(o->path, o->blob_sha1, &file->ptr, &file_size))
+ textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size))
;
else
file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size);
@@ -313,21 +315,23 @@ static struct origin *get_origin(struct scoreboard *sb,
* for an origin is also used to pass the blame for the entire file to
* the parent to detect the case where a child's blob is identical to
* that of its parent's.
+ *
+ * This also fills origin->mode for corresponding tree path.
*/
-static int fill_blob_sha1(struct origin *origin)
+static int fill_blob_sha1_and_mode(struct origin *origin)
{
- unsigned mode;
if (!is_null_sha1(origin->blob_sha1))
return 0;
if (get_tree_entry(origin->commit->object.sha1,
origin->path,
- origin->blob_sha1, &mode))
+ origin->blob_sha1, &origin->mode))
goto error_out;
if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)
goto error_out;
return 0;
error_out:
hashclr(origin->blob_sha1);
+ origin->mode = S_IFINVALID;
return -1;
}
@@ -360,12 +364,14 @@ static struct origin *find_origin(struct scoreboard *sb,
/*
* If the origin was newly created (i.e. get_origin
* would call make_origin if none is found in the
- * scoreboard), it does not know the blob_sha1,
+ * scoreboard), it does not know the blob_sha1/mode,
* so copy it. Otherwise porigin was in the
- * scoreboard and already knows blob_sha1.
+ * scoreboard and already knows blob_sha1/mode.
*/
- if (porigin->refcnt == 1)
+ if (porigin->refcnt == 1) {
hashcpy(porigin->blob_sha1, cached->blob_sha1);
+ porigin->mode = cached->mode;
+ }
return porigin;
}
/* otherwise it was not very useful; free it */
@@ -400,6 +406,7 @@ static struct origin *find_origin(struct scoreboard *sb,
/* The path is the same as parent */
porigin = get_origin(sb, parent, origin->path);
hashcpy(porigin->blob_sha1, origin->blob_sha1);
+ porigin->mode = origin->mode;
} else {
/*
* Since origin->path is a pathspec, if the parent
@@ -425,6 +432,7 @@ static struct origin *find_origin(struct scoreboard *sb,
case 'M':
porigin = get_origin(sb, parent, origin->path);
hashcpy(porigin->blob_sha1, p->one->sha1);
+ porigin->mode = p->one->mode;
break;
case 'A':
case 'T':
@@ -444,6 +452,7 @@ static struct origin *find_origin(struct scoreboard *sb,
cached = make_origin(porigin->commit, porigin->path);
hashcpy(cached->blob_sha1, porigin->blob_sha1);
+ cached->mode = porigin->mode;
parent->util = cached;
}
return porigin;
@@ -486,6 +495,7 @@ static struct origin *find_rename(struct scoreboard *sb,
!strcmp(p->two->path, origin->path)) {
porigin = get_origin(sb, parent, p->one->path);
hashcpy(porigin->blob_sha1, p->one->sha1);
+ porigin->mode = p->one->mode;
break;
}
}
@@ -1099,6 +1109,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
norigin = get_origin(sb, parent, p->one->path);
hashcpy(norigin->blob_sha1, p->one->sha1);
+ norigin->mode = p->one->mode;
fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
if (!file_p.ptr)
continue;
@@ -1606,6 +1617,7 @@ static const char *format_time(unsigned long time, const char *tz_str,
#define OUTPUT_SHOW_NUMBER 040
#define OUTPUT_SHOW_SCORE 0100
#define OUTPUT_NO_AUTHOR 0200
+#define OUTPUT_SHOW_EMAIL 0400
static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent)
{
@@ -1671,12 +1683,17 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
}
printf("%.*s", length, hex);
- if (opt & OUTPUT_ANNOTATE_COMPAT)
- printf("\t(%10s\t%10s\t%d)", ci.author,
+ if (opt & OUTPUT_ANNOTATE_COMPAT) {
+ const char *name;
+ if (opt & OUTPUT_SHOW_EMAIL)
+ name = ci.author_mail;
+ else
+ name = ci.author;
+ printf("\t(%10s\t%10s\t%d)", name,
format_time(ci.author_time, ci.author_tz,
show_raw_time),
ent->lno + 1 + cnt);
- else {
+ } else {
if (opt & OUTPUT_SHOW_SCORE)
printf(" %*d %02d",
max_score_digits, ent->score,
@@ -1689,9 +1706,15 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
ent->s_lno + 1 + cnt);
if (!(opt & OUTPUT_NO_AUTHOR)) {
- int pad = longest_author - utf8_strwidth(ci.author);
+ const char *name;
+ int pad;
+ if (opt & OUTPUT_SHOW_EMAIL)
+ name = ci.author_mail;
+ else
+ name = ci.author;
+ pad = longest_author - utf8_strwidth(name);
printf(" (%s%*s %10s",
- ci.author, pad, "",
+ name, pad, "",
format_time(ci.author_time,
ci.author_tz,
show_raw_time));
@@ -1829,7 +1852,10 @@ static void find_alignment(struct scoreboard *sb, int *option)
if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
suspect->commit->object.flags |= METAINFO_SHOWN;
get_commit_info(suspect->commit, &ci, 1);
- num = utf8_strwidth(ci.author);
+ if (*option & OUTPUT_SHOW_EMAIL)
+ num = utf8_strwidth(ci.author_mail);
+ else
+ num = utf8_strwidth(ci.author);
if (longest_author < num)
longest_author = num;
}
@@ -2075,7 +2101,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
switch (st.st_mode & S_IFMT) {
case S_IFREG:
if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
- textconv_object(read_from, null_sha1, &buf.buf, &buf_len))
+ textconv_object(read_from, mode, null_sha1, &buf.buf, &buf_len))
buf.len = buf_len;
else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
die_errno("cannot open or read '%s'", read_from);
@@ -2278,6 +2304,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP),
OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME),
OPT_BIT('s', NULL, &output_option, "Suppress author name and timestamp (Default: off)", OUTPUT_NO_AUTHOR),
+ OPT_BIT('e', "show-email", &output_option, "Show author email instead of name (Default: off)", OUTPUT_SHOW_EMAIL),
OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE),
OPT_STRING('S', NULL, &revs_file, "file", "Use revisions from <file> instead of calling git-rev-list"),
OPT_STRING(0, "contents", &contents_from, "file", "Use <file>'s contents as the final image"),
@@ -2455,11 +2482,11 @@ parse_done:
}
else {
o = get_origin(&sb, sb.final, path);
- if (fill_blob_sha1(o))
+ if (fill_blob_sha1_and_mode(o))
die("no such path %s in %s", path, final_commit_name);
if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
- textconv_object(path, o->blob_sha1, (char **) &sb.final_buf,
+ textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf,
&sb.final_buf_size))
;
else
diff --git a/builtin/branch.c b/builtin/branch.c
index 87976f0921..807355a198 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -621,7 +621,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_GROUP("Generic options"),
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose,
+ "show hash and subject, give twice for upstream branch"),
OPT_SET_INT('t', "track", &track, "set up tracking mode (see git-pull(1))",
BRANCH_TRACK_EXPLICIT),
OPT_SET_INT( 0, "set-upstream", &track, "change upstream info",
@@ -651,7 +652,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_BIT('m', NULL, &rename, "move/rename a branch and its reflog", 1),
OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
- OPT_BOOLEAN('f', "force", &force_create, "force creation (when already exists)"),
+ OPT__FORCE(&force_create, "force creation (when already exists)"),
{
OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
"commit", "print only not merged branches",
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 76ec3fec92..94632dbdb4 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -143,7 +143,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
die("git cat-file --textconv %s: <object> must be <sha1:path>",
obj_name);
- if (!textconv_object(obj_context.path, sha1, &buf, &size))
+ if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size))
die("git cat-file --textconv: unable to run textconv on %s",
obj_name);
break;
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index 65cbee0552..1ee3044307 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -217,9 +217,9 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
struct option builtin_checkout_index_options[] = {
OPT_BOOLEAN('a', "all", &all,
"checks out all files in the index"),
- OPT_BOOLEAN('f', "force", &force,
- "forces overwrite of existing files"),
- OPT__QUIET(&quiet),
+ OPT__FORCE(&force, "forces overwrite of existing files"),
+ OPT__QUIET(&quiet,
+ "no warning for existing files and files not in index"),
OPT_BOOLEAN('n', "no-create", &not_new,
"don't checkout new files"),
{ OPTION_CALLBACK, 'u', "index", &newfd, NULL,
diff --git a/builtin/checkout.c b/builtin/checkout.c
index a54583b3a4..757f9a08dd 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -161,7 +161,7 @@ static int checkout_merged(int pos, struct checkout *state)
* merge.renormalize set, too
*/
status = ll_merge(&result_buf, path, &ancestor, "base",
- &ours, "ours", &theirs, "theirs", 0);
+ &ours, "ours", &theirs, "theirs", NULL);
free(ancestor.ptr);
free(ours.ptr);
free(theirs.ptr);
@@ -686,7 +686,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
int patch_mode = 0;
int dwim_new_local_branch = 1;
struct option options[] = {
- OPT__QUIET(&opts.quiet),
+ OPT__QUIET(&opts.quiet, "suppress progress reporting"),
OPT_STRING('b', NULL, &opts.new_branch, "branch",
"create and checkout a new branch"),
OPT_STRING('B', NULL, &opts.new_branch_force, "branch",
@@ -699,7 +699,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
2),
OPT_SET_INT('3', "theirs", &opts.writeout_stage, "checkout their version for unmerged files",
3),
- OPT_BOOLEAN('f', "force", &opts.force, "force checkout (throw away local modifications)"),
+ OPT__FORCE(&opts.force, "force checkout (throw away local modifications)"),
OPT_BOOLEAN('m', "merge", &opts.merge, "perform a 3-way merge with the new branch"),
OPT_STRING(0, "conflict", &conflict_style, "style",
"conflict style (merge or diff3)"),
@@ -784,9 +784,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
* between A and B, A...B names that merge base.
*
* With no paths, if <something> is _not_ a commit, no -t nor -b
- * was given, and there is a tracking branch whose name is
+ * was given, and there is a remote-tracking branch whose name is
* <something> in one and only one remote, then this is a short-hand
- * to fork local <something> from that remote tracking branch.
+ * to fork local <something> from that remote-tracking branch.
*
* Otherwise <something> shall not be ambiguous.
* - If it's *only* a reference, treat it like case (1).
diff --git a/builtin/clean.c b/builtin/clean.c
index c8798f549e..4a312abc6b 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -38,7 +38,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
{
int i;
int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0;
- int ignored_only = 0, baselen = 0, config_set = 0, errors = 0;
+ int ignored_only = 0, config_set = 0, errors = 0;
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
struct strbuf directory = STRBUF_INIT;
struct dir_struct dir;
@@ -48,9 +48,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
const char *qname;
char *seen = NULL;
struct option options[] = {
- OPT__QUIET(&quiet),
- OPT__DRY_RUN(&show_only),
- OPT_BOOLEAN('f', "force", &force, "force"),
+ OPT__QUIET(&quiet, "do not print names of files removed"),
+ OPT__DRY_RUN(&show_only, "dry run"),
+ OPT__FORCE(&force, "force"),
OPT_BOOLEAN('d', NULL, &remove_directories,
"remove whole directories"),
{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, "pattern",
@@ -138,7 +138,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (pathspec) {
memset(seen, 0, argc > 0 ? argc : 1);
matches = match_pathspec(pathspec, ent->name, len,
- baselen, seen);
+ 0, seen);
}
if (S_ISDIR(st.st_mode)) {
@@ -153,7 +153,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
printf("Removing %s\n", qname);
if (remove_dir_recursively(&directory,
rm_flags) != 0) {
- warning("failed to remove '%s'", qname);
+ warning("failed to remove %s", qname);
errors++;
}
} else if (show_only) {
@@ -173,7 +173,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
printf("Removing %s\n", qname);
}
if (unlink(ent->name) != 0) {
- warning("failed to remove '%s'", qname);
+ warning("failed to remove %s", qname);
errors++;
}
}
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index e06573920f..d083795e26 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -56,10 +56,12 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (strbuf_read(&buffer, 0, 0) < 0)
die_errno("git commit-tree: failed to read");
- if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
- printf("%s\n", sha1_to_hex(commit_sha1));
- return 0;
- }
- else
+ if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
+ strbuf_release(&buffer);
return 1;
+ }
+
+ printf("%s\n", sha1_to_hex(commit_sha1));
+ strbuf_release(&buffer);
+ return 0;
}
diff --git a/builtin/commit.c b/builtin/commit.c
index 66fdd22024..4fd1a1692f 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -114,8 +114,8 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
}
static struct option builtin_commit_options[] = {
- OPT__QUIET(&quiet),
- OPT__VERBOSE(&verbose),
+ OPT__QUIET(&quiet, "suppress summary after successful commit"),
+ OPT__VERBOSE(&verbose, "show diff in commit message template"),
OPT_GROUP("Commit message options"),
OPT_FILENAME('F', "file", &logfile, "read log from file"),
@@ -1048,7 +1048,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
int fd;
unsigned char sha1[20];
static struct option builtin_status_options[] = {
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose, "be verbose"),
OPT_SET_INT('s', "short", &status_format,
"show status concisely", STATUS_FORMAT_SHORT),
OPT_BOOLEAN('b', "branch", &status_show_branch,
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 2bdd8ebde1..c37cb98c31 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -79,7 +79,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
off_t loose_size = 0;
struct option opts[] = {
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose, "be verbose"),
OPT_END(),
};
diff --git a/builtin/fetch.c b/builtin/fetch.c
index d35f000c03..6bcce55c0c 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -43,8 +43,7 @@ static struct option builtin_fetch_options[] = {
"append to .git/FETCH_HEAD instead of overwriting"),
OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
"path to upload pack on remote end"),
- OPT_BOOLEAN('f', "force", &force,
- "force overwrite of local branch"),
+ OPT__FORCE(&force, "force overwrite of local branch"),
OPT_BOOLEAN('m', "multiple", &multiple,
"fetch from multiple remotes"),
OPT_SET_INT('t', "tags", &tags,
@@ -52,7 +51,7 @@ static struct option builtin_fetch_options[] = {
OPT_SET_INT('n', NULL, &tags,
"do not fetch all tags (--no-tags)", TAGS_UNSET),
OPT_BOOLEAN('p', "prune", &prune,
- "prune tracking branches no longer on remote"),
+ "prune remote-tracking branches no longer on remote"),
OPT_BOOLEAN(0, "dry-run", &dry_run,
"dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
@@ -98,7 +97,7 @@ static void add_merge_config(struct ref **head,
continue;
/*
- * Not fetched to a tracking branch? We need to fetch
+ * Not fetched to a remote-tracking branch? We need to fetch
* it anyway to allow this branch's "branch.$name.merge"
* to be honored by 'git pull', but we do not have to
* fail if branch.$name.merge is misconfigured to point
@@ -359,7 +358,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
what = rm->name + 10;
}
else if (!prefixcmp(rm->name, "refs/remotes/")) {
- kind = "remote branch";
+ kind = "remote-tracking branch";
what = rm->name + 13;
}
else {
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index e7e12eea25..5189b16c9e 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -7,21 +7,22 @@
#include "string-list.h"
static const char * const fmt_merge_msg_usage[] = {
- "git fmt-merge-msg [-m <message>] [--log|--no-log] [--file <file>]",
+ "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]",
NULL
};
-static int merge_summary;
+static int shortlog_len;
static int fmt_merge_msg_config(const char *key, const char *value, void *cb)
{
- static int found_merge_log = 0;
- if (!strcmp("merge.log", key)) {
- found_merge_log = 1;
- merge_summary = git_config_bool(key, value);
+ if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
+ int is_bool;
+ shortlog_len = git_config_bool_or_int(key, value, &is_bool);
+ if (!is_bool && shortlog_len < 0)
+ return error("%s: negative length %s", key, value);
+ if (is_bool && shortlog_len)
+ shortlog_len = DEFAULT_MERGE_LOG_LEN;
}
- if (!found_merge_log && !strcmp("merge.summary", key))
- merge_summary = git_config_bool(key, value);
return 0;
}
@@ -99,8 +100,8 @@ static int handle_line(char *line)
origin = line;
string_list_append(&src_data->tag, origin + 4);
src_data->head_status |= 2;
- } else if (!prefixcmp(line, "remote branch ")) {
- origin = line + 14;
+ } else if (!prefixcmp(line, "remote-tracking branch ")) {
+ origin = line + strlen("remote-tracking branch ");
string_list_append(&src_data->r_branch, origin);
src_data->head_status |= 2;
} else {
@@ -232,7 +233,7 @@ static void do_fmt_merge_msg_title(struct strbuf *out,
if (src_data->r_branch.nr) {
strbuf_addstr(out, subsep);
subsep = ", ";
- print_joined("remote branch ", "remote branches ",
+ print_joined("remote-tracking branch ", "remote-tracking branches ",
&src_data->r_branch, out);
}
if (src_data->tag.nr) {
@@ -255,9 +256,9 @@ static void do_fmt_merge_msg_title(struct strbuf *out,
strbuf_addf(out, " into %s\n", current_branch);
}
-static int do_fmt_merge_msg(int merge_title, int merge_summary,
- struct strbuf *in, struct strbuf *out) {
- int limit = 20, i = 0, pos = 0;
+static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
+ struct strbuf *out, int shortlog_len) {
+ int i = 0, pos = 0;
unsigned char head_sha1[20];
const char *current_branch;
@@ -288,7 +289,7 @@ static int do_fmt_merge_msg(int merge_title, int merge_summary,
if (merge_title)
do_fmt_merge_msg_title(out, current_branch);
- if (merge_summary) {
+ if (shortlog_len) {
struct commit *head;
struct rev_info rev;
@@ -303,17 +304,14 @@ static int do_fmt_merge_msg(int merge_title, int merge_summary,
for (i = 0; i < origins.nr; i++)
shortlog(origins.items[i].string, origins.items[i].util,
- head, &rev, limit, out);
+ head, &rev, shortlog_len, out);
}
return 0;
}
-int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
- return do_fmt_merge_msg(1, merge_summary, in, out);
-}
-
-int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out) {
- return do_fmt_merge_msg(0, 1, in, out);
+int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
+ int merge_title, int shortlog_len) {
+ return do_fmt_merge_msg(merge_title, in, out, shortlog_len);
}
int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
@@ -321,10 +319,13 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
const char *inpath = NULL;
const char *message = NULL;
struct option options[] = {
- OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"),
- { OPTION_BOOLEAN, 0, "summary", &merge_summary, NULL,
+ { OPTION_INTEGER, 0, "log", &shortlog_len, "n",
+ "populate log with at most <n> entries from shortlog",
+ PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
+ { OPTION_INTEGER, 0, "summary", &shortlog_len, "n",
"alias for --log (deprecated)",
- PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
+ PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL,
+ DEFAULT_MERGE_LOG_LEN },
OPT_STRING('m', "message", &message, "text",
"use <text> as start of message"),
OPT_FILENAME('F', "file", &inpath, "file to read from"),
@@ -340,12 +341,14 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
0);
if (argc > 0)
usage_with_options(fmt_merge_msg_usage, options);
- if (message && !merge_summary) {
+ if (message && !shortlog_len) {
char nl = '\n';
write_in_full(STDOUT_FILENO, message, strlen(message));
write_in_full(STDOUT_FILENO, &nl, 1);
return 0;
}
+ if (shortlog_len < 0)
+ die("Negative --log=%d", shortlog_len);
if (inpath && strcmp(inpath, "-")) {
in = fopen(inpath, "r");
@@ -355,12 +358,13 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
if (strbuf_read(&input, fileno(in), 0) < 0)
die_errno("could not read input file");
- if (message) {
+
+ if (message)
strbuf_addstr(&output, message);
- ret = fmt_merge_msg_shortlog(&input, &output);
- } else {
- ret = fmt_merge_msg(merge_summary, &input, &output);
- }
+ ret = fmt_merge_msg(&input, &output,
+ message ? 0 : 1,
+ shortlog_len);
+
if (ret)
return ret;
write_in_full(STDOUT_FILENO, output.buf, output.len);
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 0929c7f245..6d5ebca7a9 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -572,7 +572,7 @@ static char const * const fsck_usage[] = {
};
static struct option fsck_opts[] = {
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose, "be 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"),
diff --git a/builtin/gc.c b/builtin/gc.c
index c304638b78..397a1e6eb3 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -180,7 +180,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
char buf[80];
struct option builtin_gc_options[] = {
- OPT__QUIET(&quiet),
+ OPT__QUIET(&quiet, "suppress progress reporting"),
{ OPTION_STRING, 0, "prune", &prune_expire, "date",
"prune unreferenced objects",
PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
diff --git a/builtin/grep.c b/builtin/grep.c
index 3d5f6ace97..adb542494d 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -915,8 +915,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
{ OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
close_callback },
- OPT_BOOLEAN('q', "quiet", &opt.status_only,
- "indicate hit with exit status without output"),
+ OPT__QUIET(&opt.status_only,
+ "indicate hit with exit status without output"),
OPT_BOOLEAN(0, "all-match", &opt.all_match,
"show only matches from files that match all patterns"),
OPT_GROUP(""),
diff --git a/builtin/log.c b/builtin/log.c
index eaa1ee0fa7..d0297a1c5e 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1056,8 +1056,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.commit_format = CMIT_FMT_EMAIL;
rev.verbose_header = 1;
rev.diff = 1;
- rev.combine_merges = 0;
- rev.ignore_merges = 1;
+ rev.no_merges = 1;
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
rev.subject_prefix = fmt_patch_subject_prefix;
memset(&s_r_opt, 0, sizeof(s_r_opt));
@@ -1228,10 +1227,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
continue;
}
- /* ignore merges */
- if (commit->parents && commit->parents->next)
- continue;
-
if (ignore_if_in_upstream &&
has_commit_patch_id(commit, &ids))
continue;
@@ -1370,7 +1365,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT__ABBREV(&abbrev),
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose, "be verbose"),
OPT_END()
};
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index b6664d49be..237abd3c0b 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -28,6 +28,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
xmparam_t xmp = {{0}};
int ret = 0, i = 0, to_stdout = 0;
int quiet = 0;
+ int prefixlen = 0;
struct option options[] = {
OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"),
OPT_SET_INT(0, "diff3", &xmp.style, "use a diff3 based merge", XDL_MERGE_DIFF3),
@@ -39,7 +40,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
XDL_MERGE_FAVOR_UNION),
OPT_INTEGER(0, "marker-size", &xmp.marker_size,
"for conflicts, use this marker size"),
- OPT__QUIET(&quiet),
+ OPT__QUIET(&quiet, "do not warn about conflicts"),
OPT_CALLBACK('L', NULL, names, "name",
"set labels for file1/orig_file/file2", &label_cb),
OPT_END(),
@@ -65,10 +66,14 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
"%s\n", strerror(errno));
}
+ if (prefix)
+ prefixlen = strlen(prefix);
+
for (i = 0; i < 3; i++) {
+ const char *fname = prefix_filename(prefix, prefixlen, argv[i]);
if (!names[i])
names[i] = argv[i];
- if (read_mmfile(mmfs + i, argv[i]))
+ if (read_mmfile(mmfs + i, fname))
return -1;
if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
return error("Cannot merge binary files: %s\n",
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index 78b9db76a0..c33091b3ed 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -2,6 +2,7 @@
#include "commit.h"
#include "tag.h"
#include "merge-recursive.h"
+#include "xdiff-interface.h"
static const char builtin_merge_recursive_usage[] =
"git %s <base>... -- <head> <remote> ...";
@@ -40,19 +41,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
if (!prefixcmp(arg, "--")) {
if (!arg[2])
break;
- if (!strcmp(arg+2, "ours"))
- o.recursive_variant = MERGE_RECURSIVE_OURS;
- else if (!strcmp(arg+2, "theirs"))
- o.recursive_variant = MERGE_RECURSIVE_THEIRS;
- else if (!strcmp(arg+2, "subtree"))
- o.subtree_shift = "";
- else if (!prefixcmp(arg+2, "subtree="))
- o.subtree_shift = arg + 10;
- else if (!strcmp(arg+2, "renormalize"))
- o.renormalize = 1;
- else if (!strcmp(arg+2, "no-renormalize"))
- o.renormalize = 0;
- else
+ if (parse_merge_opt(&o, arg + 2))
die("Unknown option %s", arg);
continue;
}
diff --git a/builtin/merge.c b/builtin/merge.c
index 5f65c0c8a6..c24a7be020 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -42,7 +42,7 @@ static const char * const builtin_merge_usage[] = {
NULL
};
-static int show_diffstat = 1, option_log, squash;
+static int show_diffstat = 1, shortlog_len, squash;
static int option_commit = 1, allow_fast_forward = 1;
static int fast_forward_only;
static int allow_trivial = 1, have_message;
@@ -177,8 +177,9 @@ static struct option builtin_merge_options[] = {
OPT_BOOLEAN(0, "stat", &show_diffstat,
"show a diffstat at the end of the merge"),
OPT_BOOLEAN(0, "summary", &show_diffstat, "(synonym to --stat)"),
- OPT_BOOLEAN(0, "log", &option_log,
- "add list of one-line log to merge commit message"),
+ { OPTION_INTEGER, 0, "log", &shortlog_len, "n",
+ "add (at most <n>) entries from shortlog to merge commit message",
+ PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
OPT_BOOLEAN(0, "squash", &squash,
"create a single commit instead of doing a merge"),
OPT_BOOLEAN(0, "commit", &option_commit,
@@ -233,6 +234,24 @@ static void save_state(void)
die("not a valid object: %s", buffer.buf);
}
+static void read_empty(unsigned const char *sha1, int verbose)
+{
+ int i = 0;
+ const char *args[7];
+
+ args[i++] = "read-tree";
+ if (verbose)
+ args[i++] = "-v";
+ args[i++] = "-m";
+ args[i++] = "-u";
+ args[i++] = EMPTY_TREE_SHA1_HEX;
+ args[i++] = sha1_to_hex(sha1);
+ args[i] = NULL;
+
+ if (run_command_v_opt(args, RUN_GIT_CMD))
+ die("read-tree failed");
+}
+
static void reset_hard(unsigned const char *sha1, int verbose)
{
int i = 0;
@@ -402,7 +421,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
goto cleanup;
}
if (!prefixcmp(found_ref, "refs/remotes/")) {
- strbuf_addf(msg, "%s\t\tremote branch '%s' of .\n",
+ strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n",
sha1_to_hex(branch_head), remote);
goto cleanup;
}
@@ -504,10 +523,17 @@ static int git_merge_config(const char *k, const char *v, void *cb)
return git_config_string(&pull_twohead, k, v);
else if (!strcmp(k, "pull.octopus"))
return git_config_string(&pull_octopus, k, v);
- else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary"))
- option_log = git_config_bool(k, v);
else if (!strcmp(k, "merge.renormalize"))
option_renormalize = git_config_bool(k, v);
+ else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) {
+ int is_bool;
+ shortlog_len = git_config_bool_or_int(k, v, &is_bool);
+ if (!is_bool && shortlog_len < 0)
+ return error("%s: negative length %s", k, v);
+ if (is_bool && shortlog_len)
+ shortlog_len = DEFAULT_MERGE_LOG_LEN;
+ return 0;
+ }
return git_diff_ui_config(k, v, cb);
}
@@ -631,25 +657,9 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
o.renormalize = option_renormalize;
- /*
- * NEEDSWORK: merge with table in builtin/merge-recursive
- */
- for (x = 0; x < xopts_nr; x++) {
- if (!strcmp(xopts[x], "ours"))
- o.recursive_variant = MERGE_RECURSIVE_OURS;
- else if (!strcmp(xopts[x], "theirs"))
- o.recursive_variant = MERGE_RECURSIVE_THEIRS;
- else if (!strcmp(xopts[x], "subtree"))
- o.subtree_shift = "";
- else if (!prefixcmp(xopts[x], "subtree="))
- o.subtree_shift = xopts[x]+8;
- else if (!strcmp(xopts[x], "renormalize"))
- o.renormalize = 1;
- else if (!strcmp(xopts[x], "no-renormalize"))
- o.renormalize = 0;
- else
+ for (x = 0; x < xopts_nr; x++)
+ if (parse_merge_opt(&o, xopts[x]))
die("Unknown option for merge-recursive: -X%s", xopts[x]);
- }
o.branch1 = head_arg;
o.branch2 = remoteheads->item->util;
@@ -993,7 +1003,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
die("%s - not something we can merge", argv[0]);
update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0,
DIE_ON_ERR);
- reset_hard(remote_head->sha1, 0);
+ read_empty(remote_head->sha1, 0);
return 0;
} else {
struct strbuf merge_names = STRBUF_INIT;
@@ -1012,14 +1022,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
for (i = 0; i < argc; i++)
merge_name(argv[i], &merge_names);
- if (have_message && option_log)
- fmt_merge_msg_shortlog(&merge_names, &merge_msg);
- else if (!have_message)
- fmt_merge_msg(option_log, &merge_names, &merge_msg);
-
-
- if (!(have_message && !option_log) && merge_msg.len)
- strbuf_setlen(&merge_msg, merge_msg.len-1);
+ if (!have_message || shortlog_len) {
+ fmt_merge_msg(&merge_names, &merge_msg, !have_message,
+ shortlog_len);
+ if (merge_msg.len)
+ strbuf_setlen(&merge_msg, merge_msg.len - 1);
+ }
}
if (head_invalid || !argc)
diff --git a/builtin/mv.c b/builtin/mv.c
index cdbb09473c..93e8995d9e 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -55,8 +55,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
int i, newfd;
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
struct option builtin_mv_options[] = {
- OPT__DRY_RUN(&show_only),
- OPT_BOOLEAN('f', "force", &force, "force move/rename even if target exists"),
+ OPT__DRY_RUN(&show_only, "dry run"),
+ OPT__FORCE(&force, "force move/rename even if target exists"),
OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"),
OPT_END(),
};
diff --git a/builtin/notes.c b/builtin/notes.c
index 6d07aac80c..c85cbf5a47 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -538,7 +538,7 @@ static int add(int argc, const char **argv, const char *prefix)
{ OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
"reuse specified note object", PARSE_OPT_NONEG,
parse_reuse_arg},
- OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
+ OPT__FORCE(&force, "replace existing notes"),
OPT_END()
};
@@ -594,7 +594,7 @@ static int copy(int argc, const char **argv, const char *prefix)
struct notes_tree *t;
const char *rewrite_cmd = NULL;
struct option options[] = {
- OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
+ OPT__FORCE(&force, "replace existing notes"),
OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"),
OPT_STRING(0, "for-rewrite", &rewrite_cmd, "command",
"load rewriting config for <command> (implies "
@@ -804,9 +804,8 @@ static int prune(int argc, const char **argv, const char *prefix)
struct notes_tree *t;
int show_only = 0, verbose = 0;
struct option options[] = {
- OPT_BOOLEAN('n', "dry-run", &show_only,
- "do not remove, show only"),
- OPT_BOOLEAN('v', "verbose", &verbose, "report pruned notes"),
+ OPT__DRY_RUN(&show_only, "do not remove, show only"),
+ OPT__VERBOSE(&verbose, "report pruned notes"),
OPT_END()
};
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f8eba53c82..3cbeb299d1 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1298,9 +1298,23 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
read_lock();
src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz);
read_unlock();
- if (!src->data)
+ if (!src->data) {
+ if (src_entry->preferred_base) {
+ static int warned = 0;
+ if (!warned++)
+ warning("object %s cannot be read",
+ sha1_to_hex(src_entry->idx.sha1));
+ /*
+ * Those objects are not included in the
+ * resulting pack. Be resilient and ignore
+ * them if they can't be read, in case the
+ * pack could be created nevertheless.
+ */
+ return 0;
+ }
die("object %s cannot be read",
sha1_to_hex(src_entry->idx.sha1));
+ }
if (sz != src_size)
die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(src_entry->idx.sha1), sz, src_size);
diff --git a/builtin/prune.c b/builtin/prune.c
index 99218ba49e..e65690ba37 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -125,9 +125,8 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
const struct option options[] = {
- OPT_BOOLEAN('n', "dry-run", &show_only,
- "do not remove, show only"),
- OPT_BOOLEAN('v', "verbose", &verbose, "report pruned objects"),
+ OPT__DRY_RUN(&show_only, "do not remove, show only"),
+ OPT__VERBOSE(&verbose, "report pruned objects"),
OPT_DATE(0, "expire", &expire,
"expire objects older than <time>"),
OPT_END()
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 9ad1e66916..73c89ed15b 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -16,6 +16,7 @@
#include "resolve-undo.h"
static int nr_trees;
+static int read_empty;
static struct tree *trees[MAX_UNPACK_TREES];
static int list_tree(unsigned char *sha1)
@@ -32,7 +33,7 @@ static int list_tree(unsigned char *sha1)
}
static const char * const read_tree_usage[] = {
- "git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]]",
+ "git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])",
NULL
};
@@ -106,7 +107,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
{ OPTION_CALLBACK, 0, "index-output", NULL, "FILE",
"write resulting index to <FILE>",
PARSE_OPT_NONEG, index_output_cb },
- OPT__VERBOSE(&opts.verbose_update),
+ OPT_SET_INT(0, "empty", &read_empty,
+ "only empty the index", 1),
+ OPT__VERBOSE(&opts.verbose_update, "be verbose"),
OPT_GROUP("Merging"),
OPT_SET_INT('m', NULL, &opts.merge,
"perform a merge in addition to a read", 1),
@@ -166,6 +169,11 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
die("failed to unpack tree object %s", arg);
stage++;
}
+ if (nr_trees == 0 && !read_empty)
+ warning("read-tree: emptying the index with no arguments is deprecated; use --empty");
+ else if (nr_trees > 0 && read_empty)
+ die("passing trees as arguments contradicts --empty");
+
if (1 < opts.index_only + opts.update)
die("-u and -i at the same time makes no sense");
if ((opts.update||opts.index_only) && !opts.merge)
diff --git a/builtin/remote.c b/builtin/remote.c
index e9a6e09257..cb26080956 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -507,7 +507,7 @@ static int add_branch_for_removal(const char *refname,
return 0;
}
- /* don't delete non-remote refs */
+ /* don't delete non-remote-tracking refs */
if (prefixcmp(refname, "refs/remotes")) {
/* advise user how to delete local branches */
if (!prefixcmp(refname, "refs/heads/"))
@@ -791,9 +791,9 @@ static int rm(int argc, const char **argv)
if (skipped.nr) {
fprintf(stderr, skipped.nr == 1 ?
- "Note: A non-remote branch was not removed; "
+ "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
"to delete it, use:\n" :
- "Note: Non-remote branches were not removed; "
+ "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
"to delete them, use:\n");
for (i = 0; i < skipped.nr; i++)
fprintf(stderr, " git branch -d %s\n",
@@ -1200,7 +1200,7 @@ static int prune(int argc, const char **argv)
{
int dry_run = 0, result = 0;
struct option options[] = {
- OPT__DRY_RUN(&dry_run),
+ OPT__DRY_RUN(&dry_run, "dry run"),
OPT_END()
};
@@ -1512,7 +1512,7 @@ static int show_all(void)
int cmd_remote(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
- OPT_BOOLEAN('v', "verbose", &verbose, "be verbose; must be placed before a subcommand"),
+ OPT__VERBOSE(&verbose, "be verbose; must be placed before a subcommand"),
OPT_END()
};
int result;
diff --git a/builtin/reset.c b/builtin/reset.c
index 0037be4693..5de2bceeec 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -243,7 +243,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
struct commit *commit;
char *reflog_action, msg[1024];
const struct option options[] = {
- OPT__QUIET(&quiet),
+ OPT__QUIET(&quiet, "be quiet, only report errors"),
OPT_SET_INT(0, "mixed", &reset_type,
"reset HEAD and index", MIXED),
OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 158ce1111a..ba27d39f97 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -147,8 +147,10 @@ static void show_commit(struct commit *commit, void *data)
}
} else {
if (revs->commit_format != CMIT_FMT_USERFORMAT ||
- buf.len)
- printf("%s%c", buf.buf, info->hdr_termination);
+ buf.len) {
+ fwrite(buf.buf, 1, buf.len, stdout);
+ putchar(info->hdr_termination);
+ }
}
strbuf_release(&buf);
} else {
diff --git a/builtin/revert.c b/builtin/revert.c
index d849f40fcc..bb6e9e83b7 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -442,7 +442,7 @@ static int do_pick_commit(void)
else
parent = commit->parents->item;
- if (allow_ff && !hashcmp(parent->object.sha1, head))
+ if (allow_ff && parent && !hashcmp(parent->object.sha1, head))
return fast_forward_to(commit->object.sha1, head);
if (parent && parse_commit(parent) < 0)
diff --git a/builtin/rm.c b/builtin/rm.c
index f3772c84de..c7b7bb37a2 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -139,10 +139,10 @@ 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__DRY_RUN(&show_only, "dry run"),
+ OPT__QUIET(&quiet, "do not list removed files"),
OPT_BOOLEAN( 0 , "cached", &index_only, "only remove from the index"),
- OPT_BOOLEAN('f', "force", &force, "override the up-to-date check"),
+ OPT__FORCE(&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"),
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 481602d8ae..2cd1c40b70 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -48,6 +48,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
NULL,
NULL,
NULL,
+ NULL,
};
struct child_process po;
int i;
@@ -59,6 +60,8 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
argv[i++] = "--delta-base-offset";
if (args->quiet)
argv[i++] = "-q";
+ if (args->progress)
+ argv[i++] = "--progress";
memset(&po, 0, sizeof(po));
po.argv = argv;
po.in = -1;
@@ -101,7 +104,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
}
if (finish_command(&po))
- return error("pack-objects died with strange error");
+ return -1;
return 0;
}
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index be9b512eeb..45f0340c3e 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -193,7 +193,8 @@ static const struct option show_ref_options[] = {
"only show SHA1 hash using <n> digits",
PARSE_OPT_OPTARG, &hash_callback },
OPT__ABBREV(&abbrev),
- OPT__QUIET(&quiet),
+ OPT__QUIET(&quiet,
+ "do not print results to stdout (useful with --verify)"),
{ OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg,
"pattern", "show refs from stdin that aren't in local repository",
PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback },
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index ca855a5eb2..dea849c3c5 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -30,7 +30,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
int quiet = 0;
const char *msg = NULL;
struct option options[] = {
- OPT__QUIET(&quiet),
+ OPT__QUIET(&quiet,
+ "suppress error message for non-symbolic (detached) refs"),
OPT_STRING('m', NULL, &msg, "reason", "reason of the update"),
OPT_END(),
};
diff --git a/builtin/tag.c b/builtin/tag.c
index d311491e49..d1d7d8701d 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -390,7 +390,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
OPT_STRING('u', NULL, &keyid, "key-id",
"use another key to sign the tag"),
- OPT_BOOLEAN('f', "force", &force, "replace the tag if exists"),
+ OPT__FORCE(&force, "replace the tag if exists"),
OPT_GROUP("Tag listing options"),
{
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 2b3fddcc69..b90dce6358 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -11,8 +11,7 @@ int cmd_update_server_info(int argc, const char **argv, const char *prefix)
{
int force = 0;
struct option options[] = {
- OPT_BOOLEAN('f', "force", &force,
- "update the info files from scratch"),
+ OPT__FORCE(&force, "update the info files from scratch"),
OPT_END()
};
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index 9f482c29f5..8136dba7a1 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -93,7 +93,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
{
int i = 1, verbose = 0, had_error = 0;
const struct option verify_tag_options[] = {
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose, "print tag contents"),
OPT_END()
};