aboutsummaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/add.c40
-rw-r--r--builtin/am.c134
-rw-r--r--builtin/apply.c4
-rw-r--r--builtin/bisect--helper.c137
-rw-r--r--builtin/blame.c15
-rw-r--r--builtin/branch.c143
-rw-r--r--builtin/cat-file.c14
-rw-r--r--builtin/check-ref-format.c7
-rw-r--r--builtin/checkout-index.c8
-rw-r--r--builtin/checkout.c56
-rw-r--r--builtin/clean.c26
-rw-r--r--builtin/clone.c35
-rw-r--r--builtin/commit-tree.c5
-rw-r--r--builtin/commit.c116
-rw-r--r--builtin/config.c11
-rw-r--r--builtin/count-objects.c1
-rw-r--r--builtin/describe.c64
-rw-r--r--builtin/diff-files.c1
-rw-r--r--builtin/diff-index.c2
-rw-r--r--builtin/diff-tree.c1
-rw-r--r--builtin/diff.c20
-rw-r--r--builtin/difftool.c40
-rw-r--r--builtin/fast-export.c53
-rw-r--r--builtin/fetch.c40
-rw-r--r--builtin/fmt-merge-msg.c7
-rw-r--r--builtin/for-each-ref.c28
-rw-r--r--builtin/fsck.c84
-rw-r--r--builtin/gc.c11
-rw-r--r--builtin/get-tar-commit-id.c9
-rw-r--r--builtin/grep.c408
-rw-r--r--builtin/hash-object.c12
-rw-r--r--builtin/help.c5
-rw-r--r--builtin/index-pack.c5
-rw-r--r--builtin/init-db.c2
-rw-r--r--builtin/interpret-trailers.c107
-rw-r--r--builtin/log.c65
-rw-r--r--builtin/ls-files.c20
-rw-r--r--builtin/merge-base.c42
-rw-r--r--builtin/merge-ours.c16
-rw-r--r--builtin/merge-tree.c16
-rw-r--r--builtin/merge.c69
-rw-r--r--builtin/mv.c3
-rw-r--r--builtin/name-rev.c3
-rw-r--r--builtin/notes.c25
-rw-r--r--builtin/pack-objects.c163
-rw-r--r--builtin/pack-redundant.c1
-rw-r--r--builtin/prune-packed.c4
-rw-r--r--builtin/prune.c2
-rw-r--r--builtin/pull.c37
-rw-r--r--builtin/push.c28
-rw-r--r--builtin/read-tree.c2
-rw-r--r--builtin/rebase--helper.c29
-rw-r--r--builtin/receive-pack.c27
-rw-r--r--builtin/reflog.c24
-rw-r--r--builtin/remote-ext.c2
-rw-r--r--builtin/remote.c23
-rw-r--r--builtin/replace.c14
-rw-r--r--builtin/rerere.c2
-rw-r--r--builtin/reset.c47
-rw-r--r--builtin/rev-list.c18
-rw-r--r--builtin/rev-parse.c37
-rw-r--r--builtin/revert.c2
-rw-r--r--builtin/rm.c3
-rw-r--r--builtin/send-pack.c2
-rw-r--r--builtin/shortlog.c56
-rw-r--r--builtin/show-branch.c20
-rw-r--r--builtin/show-ref.c4
-rw-r--r--builtin/submodule--helper.c407
-rw-r--r--builtin/symbolic-ref.c5
-rw-r--r--builtin/tag.c86
-rw-r--r--builtin/unpack-file.c14
-rw-r--r--builtin/unpack-objects.c2
-rw-r--r--builtin/update-index.c65
-rw-r--r--builtin/update-ref.c73
-rw-r--r--builtin/verify-tag.c21
-rw-r--r--builtin/worktree.c32
76 files changed, 1888 insertions, 1274 deletions
diff --git a/builtin/add.c b/builtin/add.c
index e888fb8c5..bf01d89e2 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -26,13 +26,14 @@ static const char * const builtin_add_usage[] = {
};
static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
+static int add_renormalize;
struct update_callback_data {
int flags;
int add_errors;
};
-static void chmod_pathspec(struct pathspec *pathspec, int force_mode)
+static void chmod_pathspec(struct pathspec *pathspec, char flip)
{
int i;
@@ -42,8 +43,8 @@ static void chmod_pathspec(struct pathspec *pathspec, int force_mode)
if (pathspec && !ce_path_match(ce, pathspec, NULL))
continue;
- if (chmod_cache_entry(ce, force_mode) < 0)
- fprintf(stderr, "cannot chmod '%s'", ce->name);
+ if (chmod_cache_entry(ce, flip) < 0)
+ fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
}
}
@@ -116,11 +117,32 @@ int add_files_to_cache(const char *prefix,
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = update_callback;
rev.diffopt.format_callback_data = &data;
+ rev.diffopt.flags.override_submodule_config = 1;
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
+ clear_pathspec(&rev.prune_data);
return !!data.add_errors;
}
+static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
+{
+ int i, retval = 0;
+
+ for (i = 0; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+
+ if (ce_stage(ce))
+ continue; /* do not touch unmerged paths */
+ if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
+ continue; /* do not touch non blobs */
+ if (pathspec && !ce_path_match(ce, pathspec, NULL))
+ continue;
+ retval |= add_file_to_cache(ce->name, flags | HASH_RENORMALIZE);
+ }
+
+ return retval;
+}
+
static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
{
char *seen;
@@ -216,7 +238,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
argc = setup_revisions(argc, argv, &rev, NULL);
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
rev.diffopt.use_color = 0;
- DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
+ rev.diffopt.flags.ignore_dirty_submodules = 1;
out = open(file, O_CREAT | O_WRONLY, 0666);
if (out < 0)
die(_("Could not open '%s' for writing."), file);
@@ -274,6 +296,7 @@ static struct option builtin_add_options[] = {
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
+ OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
{ OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
@@ -404,7 +427,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
chmod_arg[1] != 'x' || chmod_arg[2]))
die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
- add_new_files = !take_worktree_changes && !refresh_only;
+ add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
@@ -498,7 +521,10 @@ int cmd_add(int argc, const char **argv, const char *prefix)
plug_bulk_checkin();
- exit_status |= add_files_to_cache(prefix, &pathspec, flags);
+ if (add_renormalize)
+ exit_status |= renormalize_tracked_files(&pathspec, flags);
+ else
+ exit_status |= add_files_to_cache(prefix, &pathspec, flags);
if (add_new_files)
exit_status |= add_files(&dir, flags);
@@ -513,5 +539,7 @@ finish:
die(_("Unable to write new index file"));
}
+ UNLEAK(pathspec);
+ UNLEAK(dir);
return exit_status;
}
diff --git a/builtin/am.c b/builtin/am.c
index c973bd96d..02853b3e0 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -31,6 +31,7 @@
#include "mailinfo.h"
#include "apply.h"
#include "string-list.h"
+#include "packfile.h"
/**
* Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -431,6 +432,14 @@ static void am_load(struct am_state *state)
read_state_file(&sb, state, "utf8", 1);
state->utf8 = !strcmp(sb.buf, "t");
+ if (file_exists(am_path(state, "rerere-autoupdate"))) {
+ read_state_file(&sb, state, "rerere-autoupdate", 1);
+ state->allow_rerere_autoupdate = strcmp(sb.buf, "t") ?
+ RERERE_NOAUTOUPDATE : RERERE_AUTOUPDATE;
+ } else {
+ state->allow_rerere_autoupdate = 0;
+ }
+
read_state_file(&sb, state, "keep", 1);
if (!strcmp(sb.buf, "t"))
state->keep = KEEP_TRUE;
@@ -662,9 +671,7 @@ static int detect_patch_format(const char **paths)
goto done;
}
- strbuf_reset(&l2);
strbuf_getline(&l2, fp);
- strbuf_reset(&l3);
strbuf_getline(&l3, fp);
/*
@@ -687,6 +694,8 @@ static int detect_patch_format(const char **paths)
done:
fclose(fp);
strbuf_release(&l1);
+ strbuf_release(&l2);
+ strbuf_release(&l3);
return ret;
}
@@ -872,6 +881,7 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
{
struct strbuf sb = STRBUF_INIT;
+ int rc = 0;
while (!strbuf_getline_lf(&sb, in)) {
const char *str;
@@ -885,19 +895,27 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
errno = 0;
timestamp = parse_timestamp(str, &end, 10);
- if (errno)
- return error(_("invalid timestamp"));
+ if (errno) {
+ rc = error(_("invalid timestamp"));
+ goto exit;
+ }
- if (!skip_prefix(end, " ", &str))
- return error(_("invalid Date line"));
+ if (!skip_prefix(end, " ", &str)) {
+ rc = error(_("invalid Date line"));
+ goto exit;
+ }
errno = 0;
tz = strtol(str, &end, 10);
- if (errno)
- return error(_("invalid timezone offset"));
+ if (errno) {
+ rc = error(_("invalid timezone offset"));
+ goto exit;
+ }
- if (*end)
- return error(_("invalid Date line"));
+ if (*end) {
+ rc = error(_("invalid Date line"));
+ goto exit;
+ }
/*
* mercurial's timezone is in seconds west of UTC,
@@ -922,9 +940,9 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
fwrite(sb.buf, 1, sb.len, out);
strbuf_reset(&sb);
}
-
+exit:
strbuf_release(&sb);
- return 0;
+ return rc;
}
/**
@@ -1003,6 +1021,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
write_state_bool(state, "sign", state->signoff);
write_state_bool(state, "utf8", state->utf8);
+ if (state->allow_rerere_autoupdate)
+ write_state_bool(state, "rerere-autoupdate",
+ state->allow_rerere_autoupdate == RERERE_AUTOUPDATE);
+
switch (state->keep) {
case KEEP_FALSE:
str = "f";
@@ -1046,8 +1068,8 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
if (!get_oid("HEAD", &curr_head)) {
write_state_text(state, "abort-safety", oid_to_hex(&curr_head));
if (!state->rebasing)
- update_ref_oid("am", "ORIG_HEAD", &curr_head, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref("am", "ORIG_HEAD", &curr_head, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
} else {
write_state_text(state, "abort-safety", "");
if (!state->rebasing)
@@ -1112,11 +1134,11 @@ static const char *msgnum(const struct am_state *state)
*/
static void refresh_and_write_cache(void)
{
- struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+ struct lock_file lock_file = LOCK_INIT;
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
refresh_cache(REFRESH_QUIET);
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write index file"));
}
@@ -1131,13 +1153,13 @@ static int index_has_changes(struct strbuf *sb)
struct object_id head;
int i;
- if (!get_sha1_tree("HEAD", head.hash)) {
+ if (!get_oid_tree("HEAD", &head)) {
struct diff_options opt;
diff_setup(&opt);
- DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);
+ opt.flags.exit_with_status = 1;
if (!sb)
- DIFF_OPT_SET(&opt, QUICK);
+ opt.flags.quick = 1;
do_diff_cache(&head, &opt);
diffcore_std(&opt);
for (i = 0; sb && i < diff_queued_diff.nr; i++) {
@@ -1146,7 +1168,7 @@ static int index_has_changes(struct strbuf *sb)
strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);
}
diff_flush(&opt);
- return DIFF_OPT_TST(&opt, HAS_CHANGES) != 0;
+ return opt.flags.has_changes != 0;
} else {
for (i = 0; sb && i < active_nr; i++) {
if (i)
@@ -1181,34 +1203,10 @@ static void NORETURN die_user_resolve(const struct am_state *state)
*/
static void am_append_signoff(struct am_state *state)
{
- char *cp;
- struct strbuf mine = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
-
- /* our sign-off */
- strbuf_addf(&mine, "\n%s%s\n",
- sign_off_header,
- fmt_name(getenv("GIT_COMMITTER_NAME"),
- getenv("GIT_COMMITTER_EMAIL")));
-
- /* Does sb end with it already? */
- if (mine.len < sb.len &&
- !strcmp(mine.buf, sb.buf + sb.len - mine.len))
- goto exit; /* no need to duplicate */
-
- /* Does it have any Signed-off-by: in the text */
- for (cp = sb.buf;
- cp && *cp && (cp = strstr(cp, sign_off_header)) != NULL;
- cp = strchr(cp, '\n')) {
- if (sb.buf == cp || cp[-1] == '\n')
- break;
- }
-
- strbuf_addstr(&sb, mine.buf + !!cp);
-exit:
- strbuf_release(&mine);
+ append_signoff(&sb, 0, 0);
state->msg = strbuf_detach(&sb, &state->msg_len);
}
@@ -1411,8 +1409,8 @@ static void write_commit_patch(const struct am_state *state, struct commit *comm
rev_info.show_root_diff = 1;
rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
rev_info.no_commit_id = 1;
- DIFF_OPT_SET(&rev_info.diffopt, BINARY);
- DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);
+ rev_info.diffopt.flags.binary = 1;
+ rev_info.diffopt.flags.full_index = 1;
rev_info.diffopt.use_color = 0;
rev_info.diffopt.file = fp;
rev_info.diffopt.close_file = 1;
@@ -1432,7 +1430,7 @@ static void write_index_patch(const struct am_state *state)
struct rev_info rev_info;
FILE *fp;
- if (!get_sha1_tree("HEAD", head.hash))
+ if (!get_oid_tree("HEAD", &head))
tree = lookup_tree(&head);
else
tree = lookup_tree(&empty_tree_oid);
@@ -1490,11 +1488,10 @@ static int run_apply(const struct am_state *state, const char *index_file)
struct argv_array apply_opts = ARGV_ARRAY_INIT;
struct apply_state apply_state;
int res, opts_left;
- static struct lock_file lock_file;
int force_apply = 0;
int options = 0;
- if (init_apply_state(&apply_state, NULL, &lock_file))
+ if (init_apply_state(&apply_state, NULL))
die("BUG: init_apply_state() failed");
argv_array_push(&apply_opts, "apply");
@@ -1661,7 +1658,7 @@ static void do_commit(const struct am_state *state)
if (write_cache_as_tree(tree.hash, 0, NULL))
die(_("git write-tree failed to write a tree"));
- if (!get_sha1_commit("HEAD", parent.hash)) {
+ if (!get_oid_commit("HEAD", &parent)) {
old_oid = &parent;
commit_list_insert(lookup_commit(&parent), &parents);
} else {
@@ -1688,8 +1685,8 @@ static void do_commit(const struct am_state *state)
strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg),
state->msg);
- update_ref_oid(sb.buf, "HEAD", &commit, old_oid, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref(sb.buf, "HEAD", &commit, old_oid, 0,
+ UPDATE_REFS_DIE_ON_ERR);
if (state->rebasing) {
FILE *fp = xfopen(am_path(state, "rewritten"), "a");
@@ -1948,15 +1945,14 @@ next:
*/
static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
{
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
struct unpack_trees_options opts;
struct tree_desc t[2];
if (parse_tree(head) || parse_tree(remote))
return -1;
- lock_file = xcalloc(1, sizeof(struct lock_file));
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
refresh_cache(REFRESH_QUIET);
@@ -1972,11 +1968,11 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
init_tree_desc(&t[1], remote->buffer, remote->size);
if (unpack_trees(2, t, &opts)) {
- rollback_lock_file(lock_file);
+ rollback_lock_file(&lock_file);
return -1;
}
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
@@ -1988,15 +1984,14 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
*/
static int merge_tree(struct tree *tree)
{
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
struct unpack_trees_options opts;
struct tree_desc t[1];
if (parse_tree(tree))
return -1;
- lock_file = xcalloc(1, sizeof(struct lock_file));
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
@@ -2007,11 +2002,11 @@ static int merge_tree(struct tree *tree)
init_tree_desc(&t[0], tree->buffer, tree->size);
if (unpack_trees(1, t, &opts)) {
- rollback_lock_file(lock_file);
+ rollback_lock_file(&lock_file);
return -1;
}
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
@@ -2107,6 +2102,7 @@ static int safe_to_abort(const struct am_state *state)
die(_("could not parse %s"), am_path(state, "abort-safety"));
} else
oidclr(&abort_safety);
+ strbuf_release(&sb);
if (get_oid("HEAD", &head))
oidclr(&head);
@@ -2136,7 +2132,7 @@ static void am_abort(struct am_state *state)
am_rerere_clear();
- curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL);
+ curr_branch = resolve_refdup("HEAD", 0, &curr_head, NULL);
has_curr_head = curr_branch && !is_null_oid(&curr_head);
if (!has_curr_head)
hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN);
@@ -2148,11 +2144,11 @@ static void am_abort(struct am_state *state)
clean_index(&curr_head, &orig_head);
if (has_orig_head)
- update_ref_oid("am --abort", "HEAD", &orig_head,
- has_curr_head ? &curr_head : NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref("am --abort", "HEAD", &orig_head,
+ has_curr_head ? &curr_head : NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
else if (curr_branch)
- delete_ref(NULL, curr_branch, NULL, REF_NODEREF);
+ delete_ref(NULL, curr_branch, NULL, REF_NO_DEREF);
free(curr_branch);
am_destroy(state);
diff --git a/builtin/apply.c b/builtin/apply.c
index 81b9a61c3..48d398933 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -9,8 +9,6 @@ static const char * const apply_usage[] = {
NULL
};
-static struct lock_file lock_file;
-
int cmd_apply(int argc, const char **argv, const char *prefix)
{
int force_apply = 0;
@@ -18,7 +16,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
int ret;
struct apply_state state;
- if (init_apply_state(&state, prefix, &lock_file))
+ if (init_apply_state(&state, prefix))
exit(128);
argc = apply_parse_options(argc, argv,
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 332422902..4b5fadcbe 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -2,19 +2,128 @@
#include "cache.h"
#include "parse-options.h"
#include "bisect.h"
+#include "refs.h"
+
+static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
+static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
+static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
static const char * const git_bisect_helper_usage[] = {
N_("git bisect--helper --next-all [--no-checkout]"),
+ N_("git bisect--helper --write-terms <bad_term> <good_term>"),
+ N_("git bisect--helper --bisect-clean-state"),
NULL
};
+/*
+ * Check whether the string `term` belongs to the set of strings
+ * included in the variable arguments.
+ */
+LAST_ARG_MUST_BE_NULL
+static int one_of(const char *term, ...)
+{
+ int res = 0;
+ va_list matches;
+ const char *match;
+
+ va_start(matches, term);
+ while (!res && (match = va_arg(matches, const char *)))
+ res = !strcmp(term, match);
+ va_end(matches);
+
+ return res;
+}
+
+static int check_term_format(const char *term, const char *orig_term)
+{
+ int res;
+ char *new_term = xstrfmt("refs/bisect/%s", term);
+
+ res = check_refname_format(new_term, 0);
+ free(new_term);
+
+ if (res)
+ return error(_("'%s' is not a valid term"), term);
+
+ if (one_of(term, "help", "start", "skip", "next", "reset",
+ "visualize", "view", "replay", "log", "run", "terms", NULL))
+ return error(_("can't use the builtin command '%s' as a term"), term);
+
+ /*
+ * In theory, nothing prevents swapping completely good and bad,
+ * but this situation could be confusing and hasn't been tested
+ * enough. Forbid it for now.
+ */
+
+ if ((strcmp(orig_term, "bad") && one_of(term, "bad", "new", NULL)) ||
+ (strcmp(orig_term, "good") && one_of(term, "good", "old", NULL)))
+ return error(_("can't change the meaning of the term '%s'"), term);
+
+ return 0;
+}
+
+static int write_terms(const char *bad, const char *good)
+{
+ FILE *fp = NULL;
+ int res;
+
+ if (!strcmp(bad, good))
+ return error(_("please use two different terms"));
+
+ if (check_term_format(bad, "bad") || check_term_format(good, "good"))
+ return -1;
+
+ fp = fopen(git_path_bisect_terms(), "w");
+ if (!fp)
+ return error_errno(_("could not open the file BISECT_TERMS"));
+
+ res = fprintf(fp, "%s\n%s\n", bad, good);
+ res |= fclose(fp);
+ return (res < 0) ? -1 : 0;
+}
+
+static int is_expected_rev(const char *expected_hex)
+{
+ struct strbuf actual_hex = STRBUF_INIT;
+ int res = 0;
+ if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {
+ strbuf_trim(&actual_hex);
+ res = !strcmp(actual_hex.buf, expected_hex);
+ }
+ strbuf_release(&actual_hex);
+ return res;
+}
+
+static void check_expected_revs(const char **revs, int rev_nr)
+{
+ int i;
+
+ for (i = 0; i < rev_nr; i++) {
+ if (!is_expected_rev(revs[i])) {
+ unlink_or_warn(git_path_bisect_ancestors_ok());
+ unlink_or_warn(git_path_bisect_expected_rev());
+ }
+ }
+}
+
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
{
- int next_all = 0;
+ enum {
+ NEXT_ALL = 1,
+ WRITE_TERMS,
+ BISECT_CLEAN_STATE,
+ CHECK_EXPECTED_REVS
+ } cmdmode = 0;
int no_checkout = 0;
struct option options[] = {
- OPT_BOOL(0, "next-all", &next_all,
- N_("perform 'git bisect next'")),
+ OPT_CMDMODE(0, "next-all", &cmdmode,
+ N_("perform 'git bisect next'"), NEXT_ALL),
+ OPT_CMDMODE(0, "write-terms", &cmdmode,
+ N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS),
+ OPT_CMDMODE(0, "bisect-clean-state", &cmdmode,
+ N_("cleanup the bisection state"), BISECT_CLEAN_STATE),
+ OPT_CMDMODE(0, "check-expected-revs", &cmdmode,
+ N_("check for expected revs"), CHECK_EXPECTED_REVS),
OPT_BOOL(0, "no-checkout", &no_checkout,
N_("update BISECT_HEAD instead of checking out the current commit")),
OPT_END()
@@ -23,9 +132,25 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options,
git_bisect_helper_usage, 0);
- if (!next_all)
+ if (!cmdmode)
usage_with_options(git_bisect_helper_usage, options);
- /* next-all */
- return bisect_next_all(prefix, no_checkout);
+ switch (cmdmode) {
+ case NEXT_ALL:
+ return bisect_next_all(prefix, no_checkout);
+ case WRITE_TERMS:
+ if (argc != 2)
+ return error(_("--write-terms requires two arguments"));
+ return write_terms(argv[0], argv[1]);
+ case BISECT_CLEAN_STATE:
+ if (argc != 0)
+ return error(_("--bisect-clean-state requires no arguments"));
+ return bisect_clean_state();
+ case CHECK_EXPECTED_REVS:
+ check_expected_revs(argv, argc);
+ return 0;
+ default:
+ return error("BUG: unknown subcommand '%d'", cmdmode);
+ }
+ return 0;
}
diff --git a/builtin/blame.c b/builtin/blame.c
index bda1a7872..005f55aaa 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -488,7 +488,7 @@ static int read_ancestry(const char *graft_file)
return -1;
while (!strbuf_getwholeline(&buf, fp, '\n')) {
/* The format is just "Commit Parent1 Parent2 ...\n" */
- struct commit_graft *graft = read_graft_line(buf.buf, buf.len);
+ struct commit_graft *graft = read_graft_line(&buf);
if (graft)
register_commit_graft(graft, 0);
}
@@ -708,8 +708,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
git_config(git_blame_config, &output_option);
init_revisions(&revs, NULL);
revs.date_mode = blame_date_mode;
- DIFF_OPT_SET(&revs.diffopt, ALLOW_TEXTCONV);
- DIFF_OPT_SET(&revs.diffopt, FOLLOW_RENAMES);
+ revs.diffopt.flags.allow_textconv = 1;
+ revs.diffopt.flags.follow_renames = 1;
save_commit_buffer = 0;
dashdash_pos = 0;
@@ -734,9 +734,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
}
parse_done:
- no_whole_file_rename = !DIFF_OPT_TST(&revs.diffopt, FOLLOW_RENAMES);
+ no_whole_file_rename = !revs.diffopt.flags.follow_renames;
xdl_opts |= revs.diffopt.xdl_opts & XDF_INDENT_HEURISTIC;
- DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES);
+ revs.diffopt.flags.follow_renames = 0;
argc = parse_options_end(&ctx);
if (incremental || (output_option & OUTPUT_PORCELAIN)) {
@@ -803,7 +803,7 @@ parse_done:
}
blame_date_width -= 1; /* strip the null */
- if (DIFF_OPT_TST(&revs.diffopt, FIND_COPIES_HARDER))
+ if (revs.diffopt.flags.find_copies_harder)
opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE |
PICKAXE_BLAME_COPY_HARDER);
@@ -925,8 +925,7 @@ parse_done:
sb.found_guilty_entry = &found_guilty_entry;
sb.found_guilty_entry_data = &pi;
if (show_progress)
- pi.progress = start_progress_delay(_("Blaming lines"),
- sb.num_lines, 50, 1);
+ pi.progress = start_delayed_progress(_("Blaming lines"), sb.num_lines);
assign_blame(&sb, opt);
diff --git a/builtin/branch.c b/builtin/branch.c
index 8a0595e11..af95ad219 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -28,6 +28,7 @@ static const char * const builtin_branch_usage[] = {
N_("git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"),
N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
+ N_("git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"),
N_("git branch [<options>] [-r | -a] [--points-at]"),
N_("git branch [<options>] [-r | -a] [--format]"),
NULL
@@ -124,7 +125,7 @@ static int branch_merged(int kind, const char *name,
if (upstream &&
(reference_name = reference_name_to_free =
resolve_refdup(upstream, RESOLVE_REF_READING,
- oid.hash, NULL)) != NULL)
+ &oid, NULL)) != NULL)
reference_rev = lookup_commit_reference(&oid);
}
if (!reference_rev)
@@ -216,7 +217,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
if (!head_rev)
die(_("Couldn't look up commit object for HEAD"));
}
- for (i = 0; i < argc; i++, strbuf_release(&bname)) {
+ for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
char *target = NULL;
int flags = 0;
@@ -240,7 +241,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
RESOLVE_REF_READING
| RESOLVE_REF_NO_RECURSE
| RESOLVE_REF_ALLOW_BAD_NAME,
- oid.hash, &flags);
+ &oid, &flags);
if (!target) {
error(remote_branch
? _("remote-tracking branch '%s' not found.")
@@ -256,8 +257,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
goto next;
}
- if (delete_ref(NULL, name, is_null_oid(&oid) ? NULL : oid.hash,
- REF_NODEREF)) {
+ if (delete_ref(NULL, name, is_null_oid(&oid) ? NULL : &oid,
+ REF_NO_DEREF)) {
error(remote_branch
? _("Error deleting remote-tracking branch '%s'")
: _("Error deleting branch '%s'"),
@@ -281,8 +282,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
}
free(name);
+ strbuf_release(&bname);
- return(ret);
+ return ret;
}
static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
@@ -352,7 +354,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r
strbuf_addf(&obname, "%%(objectname:short=%d)", filter->abbrev);
strbuf_addf(&local, "%%(align:%d,left)%%(refname:lstrip=2)%%(end)", maxwidth);
- strbuf_addf(&local, "%s", branch_get_color(BRANCH_COLOR_RESET));
+ strbuf_addstr(&local, branch_get_color(BRANCH_COLOR_RESET));
strbuf_addf(&local, " %s ", obname.buf);
if (filter->verbose > 1)
@@ -383,7 +385,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r
return strbuf_detach(&fmt, NULL);
}
-static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, const char *format)
+static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format)
{
int i;
struct ref_array array;
@@ -407,14 +409,17 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
if (filter->verbose)
maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
- if (!format)
- format = to_free = build_format(filter, maxwidth, remote_prefix);
- verify_ref_format(format);
+ if (!format->format)
+ format->format = to_free = build_format(filter, maxwidth, remote_prefix);
+ format->use_color = branch_use_color;
+
+ if (verify_ref_format(format))
+ die(_("unable to parse format string"));
ref_array_sort(sorting, &array);
for (i = 0; i < array.nr; i++) {
- format_ref_array_item(array.items[i], format, 0, &out);
+ format_ref_array_item(array.items[i], format, &out);
if (column_active(colopts)) {
assert(!filter->verbose && "--column and --verbose are incompatible");
/* format to a string_list to let print_columns() do its job */
@@ -453,15 +458,18 @@ static void reject_rebase_or_bisect_branch(const char *target)
free_worktrees(worktrees);
}
-static void rename_branch(const char *oldname, const char *newname, int force)
+static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
{
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
int recovery = 0;
- int clobber_head_ok;
- if (!oldname)
- die(_("cannot rename the current branch while not on any."));
+ if (!oldname) {
+ if (copy)
+ die(_("cannot copy the current branch while not on any."));
+ else
+ die(_("cannot rename the current branch while not on any."));
+ }
if (strbuf_check_branch_ref(&oldref, oldname)) {
/*
@@ -478,22 +486,36 @@ static void rename_branch(const char *oldname, const char *newname, int force)
* A command like "git branch -M currentbranch currentbranch" cannot
* cause the worktree to become inconsistent with HEAD, so allow it.
*/
- clobber_head_ok = !strcmp(oldname, newname);
-
- validate_new_branchname(newname, &newref, force, clobber_head_ok);
+ if (!strcmp(oldname, newname))
+ validate_branchname(newname, &newref);
+ else
+ validate_new_branchname(newname, &newref, force);
reject_rebase_or_bisect_branch(oldref.buf);
- strbuf_addf(&logmsg, "Branch: renamed %s to %s",
- oldref.buf, newref.buf);
+ if (copy)
+ strbuf_addf(&logmsg, "Branch: copied %s to %s",
+ oldref.buf, newref.buf);
+ else
+ strbuf_addf(&logmsg, "Branch: renamed %s to %s",
+ oldref.buf, newref.buf);
- if (rename_ref(oldref.buf, newref.buf, logmsg.buf))
+ if (!copy && rename_ref(oldref.buf, newref.buf, logmsg.buf))
die(_("Branch rename failed"));
+ if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
+ die(_("Branch copy failed"));
- if (recovery)
- warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11);
+ if (recovery) {
+ if (copy)
+ warning(_("Copied a misnamed branch '%s' away"),
+ oldref.buf + 11);
+ else
+ warning(_("Renamed a misnamed branch '%s' away"),
+ oldref.buf + 11);
+ }
- if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
+ if (!copy &&
+ replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
strbuf_release(&logmsg);
@@ -502,8 +524,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)
strbuf_release(&oldref);
strbuf_addf(&newsection, "branch.%s", newref.buf + 11);
strbuf_release(&newref);
- if (git_config_rename_section(oldsection.buf, newsection.buf) < 0)
+ if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
die(_("Branch is renamed, but update of config-file failed"));
+ if (copy && strcmp(oldname, newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
+ die(_("Branch is copied, but update of config-file failed"));
strbuf_release(&oldsection);
strbuf_release(&newsection);
}
@@ -541,7 +565,7 @@ static int edit_branch_description(const char *branch_name)
int cmd_branch(int argc, const char **argv, const char *prefix)
{
- int delete = 0, rename = 0, force = 0, list = 0;
+ int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
int reflog = 0, edit_description = 0;
int quiet = 0, unset_upstream = 0;
const char *new_upstream = NULL;
@@ -549,7 +573,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
struct ref_filter filter;
int icase = 0;
static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
- const char *format = NULL;
+ struct ref_format format = REF_FORMAT_INIT;
struct option options[] = {
OPT_GROUP(N_("Generic options")),
@@ -558,8 +582,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT__QUIET(&quiet, N_("suppress informational messages")),
OPT_SET_INT('t', "track", &track, N_("set up tracking mode (see git-pull(1))"),
BRANCH_TRACK_EXPLICIT),
- OPT_SET_INT( 0, "set-upstream", &track, N_("change upstream info"),
- BRANCH_TRACK_OVERRIDE),
+ { OPTION_SET_INT, 0, "set-upstream", &track, NULL, N_("do not use"),
+ PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, BRANCH_TRACK_OVERRIDE },
OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")),
OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("Unset the upstream info")),
OPT__COLOR(&branch_use_color, N_("use colored output")),
@@ -578,6 +602,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
+ OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
+ OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
OPT_BOOL(0, "list", &list, N_("list branch names")),
OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
OPT_BOOL(0, "edit-description", &edit_description,
@@ -593,7 +619,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
N_("print only branches of the object"), 0, parse_opt_object_name
},
OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
- OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
+ OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
OPT_END(),
};
@@ -610,7 +636,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
track = git_branch_track;
- head = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
+ head = resolve_refdup("HEAD", 0, &head_oid, NULL);
if (!head)
die(_("Failed to resolve HEAD as a valid ref."));
if (!strcmp(head, "HEAD"))
@@ -621,14 +647,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
0);
- if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
+ if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0)
list = 1;
if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr ||
filter.no_commit)
list = 1;
- if (!!delete + !!rename + !!new_upstream +
+ if (!!delete + !!rename + !!copy + !!new_upstream +
list + unset_upstream > 1)
usage_with_options(builtin_branch_usage, options);
@@ -646,8 +672,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (force) {
delete *= 2;
rename *= 2;
+ copy *= 2;
}
+ if (list)
+ setup_auto_pager("branch", 1);
+
if (delete) {
if (!argc)
die(_("branch name required"));
@@ -667,7 +697,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!sorting)
sorting = ref_default_sorting();
sorting->ignore_case = icase;
- print_ref_list(&filter, sorting, format);
+ print_ref_list(&filter, sorting, &format);
print_columns(&output, colopts, NULL);
string_list_clear(&output, 0);
return 0;
@@ -700,20 +730,29 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (edit_branch_description(branch_name))
return 1;
+ } else if (copy) {
+ if (!argc)
+ die(_("branch name required"));
+ else if (argc == 1)
+ copy_or_rename_branch(head, argv[0], 1, copy > 1);
+ else if (argc == 2)
+ copy_or_rename_branch(argv[0], argv[1], 1, copy > 1);
+ else
+ die(_("too many branches for a copy operation"));
} else if (rename) {
if (!argc)
die(_("branch name required"));
else if (argc == 1)
- rename_branch(head, argv[0], rename > 1);
+ copy_or_rename_branch(head, argv[0], 0, rename > 1);
else if (argc == 2)
- rename_branch(argv[0], argv[1], rename > 1);
+ copy_or_rename_branch(argv[0], argv[1], 0, rename > 1);
else
- die(_("too many branches for a rename operation"));
+ die(_("too many arguments for a rename operation"));
} else if (new_upstream) {
struct branch *branch = branch_get(argv[0]);
if (argc > 1)
- die(_("too many branches to set new upstream"));
+ die(_("too many arguments to set new upstream"));
if (!branch) {
if (!argc || !strcmp(argv[0], "HEAD"))
@@ -736,7 +775,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
struct strbuf buf = STRBUF_INIT;
if (argc > 1)
- die(_("too many branches to unset upstream"));
+ die(_("too many arguments to unset upstream"));
if (!branch) {
if (!argc || !strcmp(argv[0], "HEAD"))
@@ -756,11 +795,6 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
strbuf_release(&buf);
} else if (argc > 0 && argc <= 2) {
struct branch *branch = branch_get(argv[0]);
- int branch_existed = 0, remote_tracking = 0;
- struct strbuf buf = STRBUF_INIT;
-
- if (!strcmp(argv[0], "HEAD"))
- die(_("it does not make sense to create 'HEAD' manually"));
if (!branch)
die(_("no such branch '%s'"), argv[0]);
@@ -769,28 +803,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
if (track == BRANCH_TRACK_OVERRIDE)
- fprintf(stderr, _("The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to\n"));
-
- strbuf_addf(&buf, "refs/remotes/%s", branch->name);
- remote_tracking = ref_exists(buf.buf);
- strbuf_release(&buf);
+ die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead."));
- branch_existed = ref_exists(branch->refname);
create_branch(argv[0], (argc == 2) ? argv[1] : head,
force, reflog, 0, quiet, track);
- /*
- * We only show the instructions if the user gave us
- * one branch which doesn't exist locally, but is the
- * name of a remote-tracking branch.
- */
- if (argc == 1 && track == BRANCH_TRACK_OVERRIDE &&
- !branch_existed && remote_tracking) {
- fprintf(stderr, _("\nIf you wanted to make '%s' track '%s', do this:\n\n"), head, branch->name);
- fprintf(stderr, " git branch -d %s\n", branch->name);
- fprintf(stderr, " git branch --set-upstream-to %s\n", branch->name);
- }
-
} else
usage_with_options(builtin_branch_usage, options);
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 96b786e48..f5fa4fd75 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -12,6 +12,7 @@
#include "streaming.h"
#include "tree-walk.h"
#include "sha1-array.h"
+#include "packfile.h"
struct batch_options {
int enabled;
@@ -63,8 +64,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
if (unknown_type)
flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
- if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
- oid.hash, &obj_context))
+ if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH,
+ &oid, &obj_context))
die("Not a valid object name %s", obj_name);
if (!path)
@@ -96,7 +97,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
return !has_object_file(&oid);
case 'w':
- if (!path[0])
+ if (!path)
die("git cat-file --filters %s: <object> must be "
"<sha1:path>", obj_name);
@@ -106,12 +107,13 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
break;
case 'c':
- if (!path[0])
+ if (!path)
die("git cat-file --textconv %s: <object> must be <sha1:path>",
obj_name);
if (textconv_object(path, obj_context.mode, &oid, 1, &buf, &size))
break;
+ /* else fallthrough */
case 'p':
type = sha1_object_info(oid.hash, NULL);
@@ -361,10 +363,10 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt,
struct expand_data *data)
{
struct object_context ctx;
- int flags = opt->follow_symlinks ? GET_SHA1_FOLLOW_SYMLINKS : 0;
+ int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
enum follow_symlinks_result result;
- result = get_sha1_with_context(obj_name, flags, data->oid.hash, &ctx);
+ result = get_oid_with_context(obj_name, flags, &data->oid, &ctx);
if (result != FOUND) {
switch (result) {
case MISSING_OBJECT:
diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c
index eac499450..bc67d3f0a 100644
--- a/builtin/check-ref-format.c
+++ b/builtin/check-ref-format.c
@@ -39,12 +39,15 @@ static char *collapse_slashes(const char *refname)
static int check_ref_format_branch(const char *arg)
{
struct strbuf sb = STRBUF_INIT;
+ const char *name;
int nongit;
setup_git_directory_gently(&nongit);
- if (strbuf_check_branch_ref(&sb, arg))
+ if (strbuf_check_branch_ref(&sb, arg) ||
+ !skip_prefix(sb.buf, "refs/heads/", &name))
die("'%s' is not a valid branch name", arg);
- printf("%s\n", sb.buf + 11);
+ printf("%s\n", name);
+ strbuf_release(&sb);
return 0;
}
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index 39c8be05d..b0e78b819 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -129,8 +129,6 @@ static const char * const builtin_checkout_index_usage[] = {
NULL
};
-static struct lock_file lock_file;
-
static int option_parse_stage(const struct option *opt,
const char *arg, int unset)
{
@@ -150,7 +148,7 @@ static int option_parse_stage(const struct option *opt,
int cmd_checkout_index(int argc, const char **argv, const char *prefix)
{
int i;
- int newfd = -1;
+ struct lock_file lock_file = LOCK_INIT;
int all = 0;
int read_from_stdin = 0;
int prefix_length;
@@ -206,7 +204,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
if (index_opt && !state.base_dir_len && !to_tempfile) {
state.refresh_cache = 1;
state.istate = &the_index;
- newfd = hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
}
/* Check out named files first */
@@ -251,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
if (all)
checkout_all(prefix, prefix_length);
- if (0 <= newfd &&
+ if (is_lock_file_locked(&lock_file) &&
write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die("Unable to write new index file");
return 0;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 9661e1bcb..3faae382d 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -247,7 +247,7 @@ static int checkout_paths(const struct checkout_opts *opts,
struct object_id rev;
struct commit *head;
int errs = 0;
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
if (opts->track != BRANCH_TRACK_UNSPECIFIED)
die(_("'%s' cannot be used with updating paths"), "--track");
@@ -275,9 +275,7 @@ static int checkout_paths(const struct checkout_opts *opts,
return run_add_interactive(revision, "--patch=checkout",
&opts->pathspec);
- lock_file = xcalloc(1, sizeof(struct lock_file));
-
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
if (read_cache_preload(&opts->pathspec) < 0)
return error(_("index file corrupt"));
@@ -358,6 +356,8 @@ static int checkout_paths(const struct checkout_opts *opts,
state.force = 1;
state.refresh_cache = 1;
state.istate = &the_index;
+
+ enable_delayed_checkout(&state);
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
if (ce->ce_flags & CE_MATCHED) {
@@ -372,11 +372,12 @@ static int checkout_paths(const struct checkout_opts *opts,
pos = skip_same_name(ce, pos) - 1;
}
}
+ errs |= finish_delayed_checkout(&state);
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
- read_ref_full("HEAD", 0, rev.hash, NULL);
+ read_ref_full("HEAD", 0, &rev, NULL);
head = lookup_commit_reference_gently(&rev, 1);
errs |= post_checkout_hook(head, head, 0);
@@ -433,6 +434,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
* update paths in the work tree, and we cannot revert
* them.
*/
+ /* fallthrough */
case 0:
return 0;
default:
@@ -468,9 +470,9 @@ static int merge_working_tree(const struct checkout_opts *opts,
int *writeout_error)
{
int ret;
- struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+ struct lock_file lock_file = LOCK_INIT;
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
if (read_cache_preload(NULL) < 0)
return error(_("index file corrupt"));
@@ -587,7 +589,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
if (!cache_tree_fully_valid(active_cache_tree))
cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
if (!opts->force && !opts->quiet)
@@ -660,8 +662,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) {
/* Nothing to do. */
} else if (opts->force_detach || !new->path) { /* No longer on any branch. */
- update_ref(msg.buf, "HEAD", new->commit->object.oid.hash, NULL,
- REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+ update_ref(msg.buf, "HEAD", &new->commit->object.oid, NULL,
+ REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
if (!opts->quiet) {
if (old->path &&
advice_detached_head && !opts->force_detach)
@@ -793,9 +795,14 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
for_each_ref(add_pending_uninteresting_ref, &revs);
add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING);
+ /* Save pending objects, so they can be cleaned up later. */
refs = revs.pending;
revs.leak_pending = 1;
+ /*
+ * prepare_revision_walk (together with .leak_pending = 1) makes us
+ * the sole owner of the list of pending objects.
+ */
if (prepare_revision_walk(&revs))
die(_("internal error in revision walk"));
if (!(old->object.flags & UNINTERESTING))
@@ -803,8 +810,10 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
else
describe_detached_head(_("Previous HEAD position was"), old);
+ /* Clean up objects used, as they will be reused. */
clear_commit_marks_for_object_array(&refs, ALL_REV_FLAGS);
- free(refs.objects);
+
+ object_array_clear(&refs);
}
static int switch_branches(const struct checkout_opts *opts,
@@ -816,7 +825,7 @@ static int switch_branches(const struct checkout_opts *opts,
struct object_id rev;
int flag, writeout_error = 0;
memset(&old, 0, sizeof(old));
- old.path = path_to_free = resolve_refdup("HEAD", 0, rev.hash, &flag);
+ old.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag);
if (old.path)
old.commit = lookup_commit_reference_gently(&rev, 1);
if (!(flag & REF_ISSYMREF))
@@ -858,7 +867,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
}
if (starts_with(var, "submodule."))
- return submodule_config(var, value, NULL);
+ return git_default_submodule_config(var, value, NULL);
return git_xmerge_config(var, value, NULL);
}
@@ -1027,7 +1036,7 @@ static int parse_branchname_arg(int argc, const char **argv,
setup_branch_path(new);
if (!check_refname_format(new->path, 0) &&
- !read_ref(new->path, branch_rev.hash))
+ !read_ref(new->path, &branch_rev))
oidcpy(rev, &branch_rev);
else
new->path = NULL; /* not an existing branch */
@@ -1113,9 +1122,8 @@ static int checkout_branch(struct checkout_opts *opts,
if (new->path && !opts->force_detach && !opts->new_branch &&
!opts->ignore_other_worktrees) {
- struct object_id oid;
int flag;
- char *head_ref = resolve_refdup("HEAD", 0, oid.hash, &flag);
+ char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag);
if (head_ref &&
(!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)))
die_if_checked_out(new->path, 1);
@@ -1126,7 +1134,7 @@ static int checkout_branch(struct checkout_opts *opts,
struct object_id rev;
int flag;
- if (!read_ref_full("HEAD", 0, rev.hash, &flag) &&
+ if (!read_ref_full("HEAD", 0, &rev, &flag) &&
(flag & REF_ISSYMREF) && is_null_oid(&rev))
return switch_unborn_to_new_branch(opts);
}
@@ -1179,7 +1187,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.prefix = prefix;
opts.show_progress = -1;
- gitmodules_config();
git_config(git_checkout_config, &opts);
opts.track = BRANCH_TRACK_UNSPECIFIED;
@@ -1280,14 +1287,15 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
if (opts.new_branch) {
struct strbuf buf = STRBUF_INIT;
- opts.branch_exists =
- validate_new_branchname(opts.new_branch, &buf,
- !!opts.new_branch_force,
- !!opts.new_branch_force);
-
+ if (opts.new_branch_force)
+ opts.branch_exists = validate_branchname(opts.new_branch, &buf);
+ else
+ opts.branch_exists =
+ validate_new_branchname(opts.new_branch, &buf, 0);
strbuf_release(&buf);
}
+ UNLEAK(opts);
if (opts.patch_mode || opts.pathspec.nr)
return checkout_paths(&opts, new.name);
else
diff --git a/builtin/clean.c b/builtin/clean.c
index 057fc97fe..189e20628 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -33,15 +33,6 @@ static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
static const char *msg_warn_remove_failed = N_("failed to remove %s");
-static int clean_use_color = -1;
-static char clean_colors[][COLOR_MAXLEN] = {
- GIT_COLOR_RESET,
- GIT_COLOR_NORMAL, /* PLAIN */
- GIT_COLOR_BOLD_BLUE, /* PROMPT */
- GIT_COLOR_BOLD, /* HEADER */
- GIT_COLOR_BOLD_RED, /* HELP */
- GIT_COLOR_BOLD_RED, /* ERROR */
-};
enum color_clean {
CLEAN_COLOR_RESET = 0,
CLEAN_COLOR_PLAIN = 1,
@@ -51,6 +42,16 @@ enum color_clean {
CLEAN_COLOR_ERROR = 5
};
+static int clean_use_color = -1;
+static char clean_colors[][COLOR_MAXLEN] = {
+ [CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED,
+ [CLEAN_COLOR_HEADER] = GIT_COLOR_BOLD,
+ [CLEAN_COLOR_HELP] = GIT_COLOR_BOLD_RED,
+ [CLEAN_COLOR_PLAIN] = GIT_COLOR_NORMAL,
+ [CLEAN_COLOR_PROMPT] = GIT_COLOR_BOLD_BLUE,
+ [CLEAN_COLOR_RESET] = GIT_COLOR_RESET,
+};
+
#define MENU_OPTS_SINGLETON 01
#define MENU_OPTS_IMMEDIATE 02
#define MENU_OPTS_LIST_ONLY 04
@@ -167,7 +168,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
}
*dir_gone = 0;
- return 0;
+ goto out;
}
dir = opendir(path->buf);
@@ -181,7 +182,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
warning_errno(_(msg_warn_remove_failed), quoted.buf);
*dir_gone = 0;
}
- return res;
+ ret = res;
+ goto out;
}
strbuf_complete(path, '/');
@@ -249,6 +251,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
for (i = 0; i < dels.nr; i++)
printf(dry_run ? _(msg_would_remove) : _(msg_remove), dels.items[i].string);
}
+out:
+ strbuf_release(&quoted);
string_list_clear(&dels, 0);
return ret;
}
diff --git a/builtin/clone.c b/builtin/clone.c
index 08b5cc433..b22845738 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -25,6 +25,7 @@
#include "remote.h"
#include "run-command.h"
#include "connected.h"
+#include "packfile.h"
/*
* Overall FIXMEs:
@@ -506,8 +507,8 @@ static void remove_junk(void)
if (junk_work_tree) {
strbuf_addstr(&sb, junk_work_tree);
remove_dir_recursively(&sb, 0);
- strbuf_reset(&sb);
}
+ strbuf_release(&sb);
}
static void remove_junk_on_signal(int signo)
@@ -587,7 +588,7 @@ static void write_remote_refs(const struct ref *local_refs)
for (r = local_refs; r; r = r->next) {
if (!r->peer_ref)
continue;
- if (ref_transaction_create(t, r->peer_ref->name, r->old_oid.hash,
+ if (ref_transaction_create(t, r->peer_ref->name, &r->old_oid,
0, NULL, &err))
die("%s", err.buf);
}
@@ -609,12 +610,12 @@ static void write_followtags(const struct ref *refs, const char *msg)
continue;
if (!has_object_file(&ref->old_oid))
continue;
- update_ref(msg, ref->name, ref->old_oid.hash,
- NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+ update_ref(msg, ref->name, &ref->old_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
}
}
-static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
+static int iterate_ref_map(void *cb_data, struct object_id *oid)
{
struct ref **rm = cb_data;
struct ref *ref = *rm;
@@ -629,7 +630,7 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
if (!ref)
return -1;
- hashcpy(sha1, ref->old_oid.hash);
+ oidcpy(oid, &ref->old_oid);
*rm = ref->next;
return 0;
}
@@ -681,23 +682,23 @@ static void update_head(const struct ref *our, const struct ref *remote,
if (create_symref("HEAD", our->name, NULL) < 0)
die(_("unable to update HEAD"));
if (!option_bare) {
- update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
+ update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
UPDATE_REFS_DIE_ON_ERR);
install_branch_config(0, head, option_origin, our->name);
}
} else if (our) {
struct commit *c = lookup_commit_reference(&our->old_oid);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
- update_ref(msg, "HEAD", c->object.oid.hash,
- NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+ update_ref(msg, "HEAD", &c->object.oid, NULL, REF_NO_DEREF,
+ UPDATE_REFS_DIE_ON_ERR);
} else if (remote) {
/*
* We know remote HEAD points to a non-branch, or
* HEAD points to a branch but we don't know which one.
* Detach HEAD in all these cases.
*/
- update_ref(msg, "HEAD", remote->old_oid.hash,
- NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+ update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NO_DEREF,
+ UPDATE_REFS_DIE_ON_ERR);
}
}
@@ -705,7 +706,7 @@ static int checkout(int submodule_progress)
{
struct object_id oid;
char *head;
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
struct unpack_trees_options opts;
struct tree *tree;
struct tree_desc t;
@@ -714,7 +715,7 @@ static int checkout(int submodule_progress)
if (option_no_checkout)
return 0;
- head = resolve_refdup("HEAD", RESOLVE_REF_READING, oid.hash, NULL);
+ head = resolve_refdup("HEAD", RESOLVE_REF_READING, &oid, NULL);
if (!head) {
warning(_("remote HEAD refers to nonexistent ref, "
"unable to checkout.\n"));
@@ -732,8 +733,7 @@ static int checkout(int submodule_progress)
/* We need to be in the new work tree for the checkout */
setup_work_tree();
- lock_file = xcalloc(1, sizeof(struct lock_file));
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
memset(&opts, 0, sizeof opts);
opts.update = 1;
@@ -749,7 +749,7 @@ static int checkout(int submodule_progress)
if (unpack_trees(1, &t, &opts) < 0)
die(_("unable to checkout working tree"));
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
@@ -768,6 +768,9 @@ static int checkout(int submodule_progress)
if (submodule_progress)
argv_array_push(&args, "--progress");
+ if (option_verbosity < 0)
+ argv_array_push(&args, "--quiet");
+
err = run_command_v_opt(args.argv, RUN_GIT_CMD);
argv_array_clear(&args);
}
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index a4a923d7c..2177251e2 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -56,7 +56,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
struct object_id oid;
if (argc <= ++i)
usage(commit_tree_usage);
- if (get_sha1_commit(argv[i], oid.hash))
+ if (get_oid_commit(argv[i], &oid))
die("Not a valid object name %s", argv[i]);
assert_sha1_type(oid.hash, OBJ_COMMIT);
new_parent(lookup_commit(&oid), &parents);
@@ -102,11 +102,10 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (fd && close(fd))
die_errno("git commit-tree: failed to close '%s'",
argv[i]);
- strbuf_complete_line(&buffer);
continue;
}
- if (get_sha1_tree(arg, tree_oid.hash))
+ if (get_oid_tree(arg, &tree_oid))
die("Not a valid object name %s", arg);
if (got_tree)
die("Cannot give more than one trees");
diff --git a/builtin/commit.c b/builtin/commit.c
index 8e9380251..8a8770141 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static int config_commit_verbose = -1; /* unspecified */
static int no_post_rewrite, allow_empty_message;
-static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
+static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
static char *sign_commit;
/*
@@ -139,7 +139,7 @@ static const char *cleanup_arg;
static enum commit_whence whence;
static int sequencer_in_use;
static int use_editor = 1, include_status = 1;
-static int show_ignored_in_status, have_option_m;
+static int have_option_m;
static struct strbuf message = STRBUF_INIT;
static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
@@ -195,7 +195,6 @@ static void determine_whence(struct wt_status *s)
static void status_init_config(struct wt_status *s, config_fn_t fn)
{
wt_status_prepare(s);
- gitmodules_config();
git_config(fn, s);
determine_whence(s);
init_diff_ui_defaults();
@@ -336,7 +335,7 @@ static void refresh_cache_or_die(int refresh_flags)
static const char *prepare_index(int argc, const char **argv, const char *prefix,
const struct commit *current_head, int is_status)
{
- struct string_list partial;
+ struct string_list partial = STRING_LIST_INIT_DUP;
struct pathspec pathspec;
int refresh_flags = REFRESH_QUIET;
const char *ret;
@@ -356,7 +355,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
refresh_cache_or_die(refresh_flags);
- if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
+ if (write_locked_index(&the_index, &index_lock, 0))
die(_("unable to create temporary index"));
old_index_env = getenv(INDEX_ENVIRONMENT);
@@ -375,13 +374,14 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
if (reopen_lock_file(&index_lock) < 0)
die(_("unable to write index file"));
- if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
+ if (write_locked_index(&the_index, &index_lock, 0))
die(_("unable to update temporary index"));
} else
warning(_("Failed to update main cache tree"));
commit_style = COMMIT_NORMAL;
- return get_lock_file_path(&index_lock);
+ ret = get_lock_file_path(&index_lock);
+ goto out;
}
/*
@@ -401,10 +401,11 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
add_files_to_cache(also ? prefix : NULL, &pathspec, 0);
refresh_cache_or_die(refresh_flags);
update_main_cache_tree(WRITE_TREE_SILENT);
- if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
+ if (write_locked_index(&the_index, &index_lock, 0))
die(_("unable to write new_index file"));
commit_style = COMMIT_NORMAL;
- return get_lock_file_path(&index_lock);
+ ret = get_lock_file_path(&index_lock);
+ goto out;
}
/*
@@ -430,7 +431,8 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
rollback_lock_file(&index_lock);
}
commit_style = COMMIT_AS_IS;
- return get_index_file();
+ ret = get_index_file();
+ goto out;
}
/*
@@ -461,7 +463,6 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
die(_("cannot do a partial commit during a cherry-pick."));
}
- string_list_init(&partial, 1);
if (list_paths(&partial, !current_head ? NULL : "HEAD", prefix, &pathspec))
exit(1);
@@ -473,7 +474,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
add_remove_files(&partial);
refresh_cache(REFRESH_QUIET);
update_main_cache_tree(WRITE_TREE_SILENT);
- if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
+ if (write_locked_index(&the_index, &index_lock, 0))
die(_("unable to write new_index file"));
hold_lock_file_for_update(&false_lock,
@@ -485,12 +486,15 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
add_remove_files(&partial);
refresh_cache(REFRESH_QUIET);
- if (write_locked_index(&the_index, &false_lock, CLOSE_LOCK))
+ if (write_locked_index(&the_index, &false_lock, 0))
die(_("unable to write temporary index file"));
discard_cache();
ret = get_lock_file_path(&false_lock);
read_cache_from(ret);
+out:
+ string_list_clear(&partial, 0);
+ clear_pathspec(&pathspec);
return ret;
}
@@ -510,7 +514,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
s->index_file = index_file;
s->fp = fp;
s->nowarn = nowarn;
- s->is_initial = get_sha1(s->reference, oid.hash) ? 1 : 0;
+ s->is_initial = get_oid(s->reference, &oid) ? 1 : 0;
if (!s->is_initial)
hashcpy(s->sha1_commit, oid.hash);
s->status_format = status_format;
@@ -891,7 +895,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
if (amend)
parent = "HEAD^1";
- if (get_sha1(parent, oid.hash)) {
+ if (get_oid(parent, &oid)) {
int i, ita_nr = 0;
for (i = 0; i < active_nr; i++)
@@ -908,11 +912,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
* submodules which were manually staged, which would
* be really confusing.
*/
- int diff_flags = DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
+ struct diff_flags flags = DIFF_FLAGS_INIT;
+ flags.override_submodule_config = 1;
if (ignore_submodule_arg &&
!strcmp(ignore_submodule_arg, "all"))
- diff_flags |= DIFF_OPT_IGNORE_SUBMODULES;
- commitable = index_differs_from(parent, diff_flags, 1);
+ flags.ignore_submodules = 1;
+ commitable = index_differs_from(parent, &flags, 1);
}
}
strbuf_release(&committer_ident);
@@ -940,13 +945,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
return 0;
}
- /*
- * Re-read the index as pre-commit hook could have updated it,
- * and write it out as a tree. We must do this before we invoke
- * the editor and after we invoke run_status above.
- */
- discard_cache();
+ if (!no_verify && find_hook("pre-commit")) {
+ /*
+ * Re-read the index as pre-commit hook could have updated it,
+ * and write it out as a tree. We must do this before we invoke
+ * the editor and after we invoke run_status above.
+ */
+ discard_cache();
+ }
read_cache_from(index_file);
+
if (update_main_cache_tree(0)) {
error(_("Error building trees"));
return 0;
@@ -1068,6 +1076,19 @@ static const char *find_author_by_nickname(const char *name)
die(_("--author '%s' is not 'Name <email>' and matches no existing author"), name);
}
+static void handle_ignored_arg(struct wt_status *s)
+{
+ if (!ignored_arg)
+ ; /* default already initialized */
+ else if (!strcmp(ignored_arg, "traditional"))
+ s->show_ignored_mode = SHOW_TRADITIONAL_IGNORED;
+ else if (!strcmp(ignored_arg, "no"))
+ s->show_ignored_mode = SHOW_NO_IGNORED;
+ else if (!strcmp(ignored_arg, "matching"))
+ s->show_ignored_mode = SHOW_MATCHING_IGNORED;
+ else
+ die(_("Invalid ignored mode '%s'"), ignored_arg);
+}
static void handle_untracked_files_arg(struct wt_status *s)
{
@@ -1356,8 +1377,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)
N_("mode"),
N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
- OPT_BOOL(0, "ignored", &show_ignored_in_status,
- N_("show ignored files")),
+ { OPTION_STRING, 0, "ignored", &ignored_arg,
+ N_("mode"),
+ N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
+ PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" },
{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1376,8 +1399,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
finalize_deferred_config(&s);
handle_untracked_files_arg(&s);
- if (show_ignored_in_status)
- s.show_ignored_files = 1;
+ handle_ignored_arg(&s);
+
+ if (s.show_ignored_mode == SHOW_MATCHING_IGNORED &&
+ s.show_untracked_files == SHOW_NO_UNTRACKED_FILES)
+ die(_("Unsupported combination of ignored and untracked-files arguments"));
+
parse_pathspec(&s.pathspec, 0,
PATHSPEC_PREFER_FULL,
prefix, argv);
@@ -1385,9 +1412,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
read_cache_preload(&s.pathspec);
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &s.pathspec, NULL, NULL);
- fd = hold_locked_index(&index_lock, 0);
+ if (use_optional_locks())
+ fd = hold_locked_index(&index_lock, 0);
+ else
+ fd = -1;
- s.is_initial = get_sha1(s.reference, oid.hash) ? 1 : 0;
+ s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
if (!s.is_initial)
hashcpy(s.sha1_commit, oid.hash);
@@ -1429,7 +1459,6 @@ static void print_summary(const char *prefix, const struct object_id *oid,
struct rev_info rev;
struct commit *commit;
struct strbuf format = STRBUF_INIT;
- struct object_id junk_oid;
const char *head;
struct pretty_print_context pctx = {0};
struct strbuf author_ident = STRBUF_INIT;
@@ -1482,7 +1511,9 @@ static void print_summary(const char *prefix, const struct object_id *oid,
rev.diffopt.break_opt = 0;
diff_setup_done(&rev.diffopt);
- head = resolve_ref_unsafe("HEAD", 0, junk_oid.hash, NULL);
+ head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
+ if (!head)
+ die_errno(_("unable to resolve HEAD after creating commit"));
if (!strcmp(head, "HEAD"))
head = _("detached HEAD");
else
@@ -1657,7 +1688,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
s.colopts = 0;
- if (get_sha1("HEAD", oid.hash))
+ if (get_oid("HEAD", &oid))
current_head = NULL;
else {
current_head = lookup_commit_or_die(&oid, "HEAD");
@@ -1719,7 +1750,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
allow_fast_forward = 0;
}
if (allow_fast_forward)
- parents = reduce_heads(parents);
+ reduce_heads_replace(&parents);
} else {
if (!reflog_msg)
reflog_msg = (whence == FROM_CHERRY_PICK)
@@ -1739,17 +1770,17 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (verbose || /* Truncate the message just before the diff, if any. */
cleanup_mode == CLEANUP_SCISSORS)
strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len));
-
if (cleanup_mode != CLEANUP_NONE)
strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL);
- if (template_untouched(&sb) && !allow_empty_message) {
+
+ if (message_is_empty(&sb) && !allow_empty_message) {
rollback_index_files();
- fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
+ fprintf(stderr, _("Aborting commit due to empty commit message.\n"));
exit(1);
}
- if (message_is_empty(&sb) && !allow_empty_message) {
+ if (template_untouched(&sb) && !allow_empty_message) {
rollback_index_files();
- fprintf(stderr, _("Aborting commit due to empty commit message.\n"));
+ fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
exit(1);
}
@@ -1779,9 +1810,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
transaction = ref_transaction_begin(&err);
if (!transaction ||
- ref_transaction_update(transaction, "HEAD", oid.hash,
+ ref_transaction_update(transaction, "HEAD", &oid,
current_head
- ? current_head->object.oid.hash : null_sha1,
+ ? &current_head->object.oid : &null_oid,
0, sb.buf, &err) ||
ref_transaction_commit(transaction, &err)) {
rollback_index_files();
@@ -1816,6 +1847,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (!quiet)
print_summary(prefix, &oid, !current_head);
- strbuf_release(&err);
+ UNLEAK(err);
+ UNLEAK(sb);
return 0;
}
diff --git a/builtin/config.c b/builtin/config.c
index 70ff231e9..d13daeeb5 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -518,10 +518,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
die("$HOME not set");
if (access_or_warn(user_config, R_OK, 0) &&
- xdg_config && !access_or_warn(xdg_config, R_OK, 0))
+ xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
given_config_source.file = xdg_config;
- else
+ free(user_config);
+ } else {
given_config_source.file = user_config;
+ free(xdg_config);
+ }
}
else if (use_system_config)
given_config_source.file = git_etc_gitconfig();
@@ -628,6 +631,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
+ UNLEAK(value);
ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
if (ret == CONFIG_NOTHING_SET)
error(_("cannot overwrite multiple values with a single value\n"
@@ -638,6 +642,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
+ UNLEAK(value);
return git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, argv[2], 0);
}
@@ -645,6 +650,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
+ UNLEAK(value);
return git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value,
CONFIG_REGEX_NONE, 0);
@@ -653,6 +659,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
+ UNLEAK(value);
return git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, argv[2], 1);
}
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 1d82e61f2..33343818c 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -10,6 +10,7 @@
#include "builtin.h"
#include "parse-options.h"
#include "quote.h"
+#include "packfile.h"
static unsigned long garbage;
static off_t size_garbage;
diff --git a/builtin/describe.c b/builtin/describe.c
index 89ea1cdd6..e14e162ef 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -7,12 +7,12 @@
#include "builtin.h"
#include "exec_cmd.h"
#include "parse-options.h"
+#include "revision.h"
#include "diff.h"
#include "hashmap.h"
#include "argv-array.h"
#include "run-command.h"
-#define SEEN (1u << 0)
#define MAX_TAGS (FLAG_BITS - 1)
static const char * const describe_usage[] = {
@@ -55,10 +55,13 @@ static const char *prio_names[] = {
};
static int commit_name_cmp(const void *unused_cmp_data,
- const struct commit_name *cn1,
- const struct commit_name *cn2,
+ const void *entry,
+ const void *entry_or_key,
const void *peeled)
{
+ const struct commit_name *cn1 = entry;
+ const struct commit_name *cn2 = entry_or_key;
+
return oidcmp(&cn1->peeled, peeled ? peeled : &cn2->peeled);
}
@@ -126,13 +129,24 @@ static void add_to_known_names(const char *path,
static int get_name(const char *path, const struct object_id *oid, int flag, void *cb_data)
{
- int is_tag = starts_with(path, "refs/tags/");
+ int is_tag = 0;
struct object_id peeled;
int is_annotated, prio;
-
- /* Reject anything outside refs/tags/ unless --all */
- if (!all && !is_tag)
+ const char *path_to_match = NULL;
+
+ if (skip_prefix(path, "refs/tags/", &path_to_match)) {
+ is_tag = 1;
+ } else if (all) {
+ if ((exclude_patterns.nr || patterns.nr) &&
+ !skip_prefix(path, "refs/heads/", &path_to_match) &&
+ !skip_prefix(path, "refs/remotes/", &path_to_match)) {
+ /* Only accept reference of known type if there are match/exclude patterns */
+ return 0;
+ }
+ } else {
+ /* Reject anything outside refs/tags/ unless --all */
return 0;
+ }
/*
* If we're given exclude patterns, first exclude any tag which match
@@ -141,11 +155,8 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
if (exclude_patterns.nr) {
struct string_list_item *item;
- if (!is_tag)
- return 0;
-
for_each_string_list_item(item, &exclude_patterns) {
- if (!wildmatch(item->string, path + 10, 0))
+ if (!wildmatch(item->string, path_to_match, 0))
return 0;
}
}
@@ -155,22 +166,22 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
* pattern.
*/
if (patterns.nr) {
+ int found = 0;
struct string_list_item *item;
- if (!is_tag)
- return 0;
-
for_each_string_list_item(item, &patterns) {
- if (!wildmatch(item->string, path + 10, 0))
+ if (!wildmatch(item->string, path_to_match, 0)) {
+ found = 1;
break;
+ }
+ }
- /* If we get here, no pattern matched. */
+ if (!found)
return 0;
- }
}
/* Is it annotated? */
- if (!peel_ref(path, peeled.hash)) {
+ if (!peel_ref(path, &peeled)) {
is_annotated = !!oidcmp(oid, &peeled);
} else {
oidcpy(&peeled, oid);
@@ -503,9 +514,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
return cmd_name_rev(args.argc, args.argv, prefix);
}
- hashmap_init(&names, (hashmap_cmp_fn) commit_name_cmp, NULL, 0);
+ hashmap_init(&names, commit_name_cmp, NULL, 0);
for_each_rawref(get_name, NULL);
- if (!names.size && !always)
+ if (!hashmap_get_size(&names) && !always)
die(_("No names found, cannot describe anything."));
if (argc == 0) {
@@ -532,7 +543,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
}
} else if (dirty) {
static struct lock_file index_lock;
- int fd;
+ struct rev_info revs;
+ struct argv_array args = ARGV_ARRAY_INIT;
+ int fd, result;
read_cache_preload(NULL);
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED,
@@ -541,8 +554,13 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
if (0 <= fd)
update_index_if_able(&the_index, &index_lock);
- if (!cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1,
- diff_index_args, prefix))
+ init_revisions(&revs, prefix);
+ argv_array_pushv(&args, diff_index_args);
+ if (setup_revisions(args.argc, args.argv, &revs, NULL) != 1)
+ BUG("malformed internal diff-index command line");
+ result = run_diff_index(&revs, 0);
+
+ if (!diff_result_code(&revs.diffopt, result))
suffix = NULL;
else
suffix = dirty;
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 17bf84d18..e88493ffe 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -26,7 +26,6 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
init_revisions(&rev, prefix);
- gitmodules_config();
rev.abbrev = 0;
precompose_argv(argc, argv);
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index 185e6f9b5..522f4fdff 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -23,7 +23,6 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
init_revisions(&rev, prefix);
- gitmodules_config();
rev.abbrev = 0;
precompose_argv(argc, argv);
@@ -57,5 +56,6 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
return -1;
}
result = run_diff_index(&rev, cached);
+ UNLEAK(rev);
return diff_result_code(&rev.diffopt, result);
}
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index 31d2cb410..d66499909 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -110,7 +110,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
init_revisions(opt, prefix);
- gitmodules_config();
opt->abbrev = 0;
opt->diff = 1;
opt->disable_stdin = 1;
diff --git a/builtin/diff.c b/builtin/diff.c
index 7cde6abbc..9808d062a 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -44,7 +44,7 @@ static void stuff_change(struct diff_options *opt,
!oidcmp(old_oid, new_oid) && (old_mode == new_mode))
return;
- if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
+ if (opt->flags.reverse_diff) {
SWAP(old_mode, new_mode);
SWAP(old_oid, new_oid);
SWAP(old_path, new_path);
@@ -203,17 +203,16 @@ static int builtin_diff_combined(struct rev_info *revs,
static void refresh_index_quietly(void)
{
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
int fd;
- lock_file = xcalloc(1, sizeof(struct lock_file));
- fd = hold_locked_index(lock_file, 0);
+ fd = hold_locked_index(&lock_file, 0);
if (fd < 0)
return;
discard_cache();
read_cache();
refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
- update_index_if_able(&the_index, lock_file);
+ update_index_if_able(&the_index, &lock_file);
}
static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
@@ -315,8 +314,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
no_index = DIFF_NO_INDEX_IMPLICIT;
}
- if (!no_index)
- gitmodules_config();
init_diff_ui_defaults();
git_config(git_diff_ui_config, NULL);
precompose_argv(argc, argv);
@@ -352,8 +349,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
rev.diffopt.stat_graph_width = -1;
/* Default to let external and textconv be used */
- DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
- DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
+ rev.diffopt.flags.allow_external = 1;
+ rev.diffopt.flags.allow_textconv = 1;
if (nongit)
die(_("Not a git repository"));
@@ -363,7 +360,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
diff_setup_done(&rev.diffopt);
}
- DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
+ rev.diffopt.flags.recursive = 1;
setup_diff_pager(&rev.diffopt);
@@ -466,5 +463,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
result = diff_result_code(&rev.diffopt, result);
if (1 < rev.diffopt.skip_stat_unmatch)
refresh_index_quietly();
+ UNLEAK(rev);
+ UNLEAK(ent);
+ UNLEAK(blob);
return result;
}
diff --git a/builtin/difftool.c b/builtin/difftool.c
index a1a26ba89..bcc79d188 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -111,7 +111,7 @@ static int use_wt_file(const char *workdir, const char *name,
int fd = open(buf.buf, O_RDONLY);
if (fd >= 0 &&
- !index_fd(wt_oid.hash, fd, &st, OBJ_BLOB, name, 0)) {
+ !index_fd(&wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
if (is_null_oid(oid)) {
oidcpy(oid, &wt_oid);
use = 1;
@@ -131,10 +131,12 @@ struct working_tree_entry {
};
static int working_tree_entry_cmp(const void *unused_cmp_data,
- struct working_tree_entry *a,
- struct working_tree_entry *b,
- void *unused_keydata)
+ const void *entry,
+ const void *entry_or_key,
+ const void *unused_keydata)
{
+ const struct working_tree_entry *a = entry;
+ const struct working_tree_entry *b = entry_or_key;
return strcmp(a->path, b->path);
}
@@ -149,9 +151,13 @@ struct pair_entry {
};
static int pair_cmp(const void *unused_cmp_data,
- struct pair_entry *a, struct pair_entry *b,
- void *unused_keydata)
+ const void *entry,
+ const void *entry_or_key,
+ const void *unused_keydata)
{
+ const struct pair_entry *a = entry;
+ const struct pair_entry *b = entry_or_key;
+
return strcmp(a->path, b->path);
}
@@ -179,9 +185,13 @@ struct path_entry {
};
static int path_entry_cmp(const void *unused_cmp_data,
- struct path_entry *a, struct path_entry *b,
- void *key)
+ const void *entry,
+ const void *entry_or_key,
+ const void *key)
{
+ const struct path_entry *a = entry;
+ const struct path_entry *b = entry_or_key;
+
return strcmp(a->path, key ? key : b->path);
}
@@ -372,10 +382,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
rdir_len = rdir.len;
wtdir_len = wtdir.len;
- hashmap_init(&working_tree_dups,
- (hashmap_cmp_fn)working_tree_entry_cmp, NULL, 0);
- hashmap_init(&submodules, (hashmap_cmp_fn)pair_cmp, NULL, 0);
- hashmap_init(&symlinks2, (hashmap_cmp_fn)pair_cmp, NULL, 0);
+ hashmap_init(&working_tree_dups, working_tree_entry_cmp, NULL, 0);
+ hashmap_init(&submodules, pair_cmp, NULL, 0);
+ hashmap_init(&symlinks2, pair_cmp, NULL, 0);
child.no_stdin = 1;
child.git_cmd = 1;
@@ -585,10 +594,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
* in the common case of --symlinks and the difftool updating
* files through the symlink.
*/
- hashmap_init(&wt_modified, (hashmap_cmp_fn)path_entry_cmp,
- NULL, wtindex.cache_nr);
- hashmap_init(&tmp_modified, (hashmap_cmp_fn)path_entry_cmp,
- NULL, wtindex.cache_nr);
+ hashmap_init(&wt_modified, path_entry_cmp, NULL, wtindex.cache_nr);
+ hashmap_init(&tmp_modified, path_entry_cmp, NULL, wtindex.cache_nr);
for (i = 0; i < wtindex.cache_nr; i++) {
struct hashmap_entry dummy;
@@ -609,7 +616,6 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
if (hold_lock_file_for_update(&lock, buf.buf, 0) < 0 ||
write_locked_index(&wtindex, &lock, COMMIT_LOCK)) {
ret = error("could not write %s", buf.buf);
- rollback_lock_file(&lock);
goto finish;
}
changed_files(&wt_modified, buf.buf, workdir);
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d412c0a8f..f8fe04ca5 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -344,6 +344,7 @@ static void show_filemodify(struct diff_queue_struct *q,
struct diff_options *options, void *data)
{
int i;
+ struct string_list *changed = data;
/*
* Handle files below a directory first, in case they are all deleted
@@ -359,20 +360,31 @@ static void show_filemodify(struct diff_queue_struct *q,
case DIFF_STATUS_DELETED:
printf("D ");
print_path(spec->path);
+ string_list_insert(changed, spec->path);
putchar('\n');
break;
case DIFF_STATUS_COPIED:
case DIFF_STATUS_RENAMED:
- printf("%c ", q->queue[i]->status);
- print_path(ospec->path);
- putchar(' ');
- print_path(spec->path);
- putchar('\n');
-
- if (!oidcmp(&ospec->oid, &spec->oid) &&
- ospec->mode == spec->mode)
- break;
+ /*
+ * If a change in the file corresponding to ospec->path
+ * has been observed, we cannot trust its contents
+ * because the diff is calculated based on the prior
+ * contents, not the current contents. So, declare a
+ * copy or rename only if there was no change observed.
+ */
+ if (!string_list_has_string(changed, ospec->path)) {
+ printf("%c ", q->queue[i]->status);
+ print_path(ospec->path);
+ putchar(' ');
+ print_path(spec->path);
+ string_list_insert(changed, spec->path);
+ putchar('\n');
+
+ if (!oidcmp(&ospec->oid, &spec->oid) &&
+ ospec->mode == spec->mode)
+ break;
+ }
/* fallthrough */
case DIFF_STATUS_TYPE_CHANGED:
@@ -393,6 +405,7 @@ static void show_filemodify(struct diff_queue_struct *q,
get_object_mark(object));
}
print_path(spec->path);
+ string_list_insert(changed, spec->path);
putchar('\n');
break;
@@ -528,7 +541,8 @@ static void anonymize_ident_line(const char **beg, const char **end)
*end = out->buf + out->len;
}
-static void handle_commit(struct commit *commit, struct rev_info *rev)
+static void handle_commit(struct commit *commit, struct rev_info *rev,
+ struct string_list *paths_of_changed_objects)
{
int saved_output_format = rev->diffopt.output_format;
const char *commit_buffer;
@@ -615,6 +629,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
if (full_tree)
printf("deleteall\n");
log_tree_diff_flush(rev);
+ string_list_clear(paths_of_changed_objects, 0);
rev->diffopt.output_format = saved_output_format;
printf("\n");
@@ -630,15 +645,15 @@ static void *anonymize_tag(const void *old, size_t *len)
return strbuf_detach(&out, len);
}
-static void handle_tail(struct object_array *commits, struct rev_info *revs)
+static void handle_tail(struct object_array *commits, struct rev_info *revs,
+ struct string_list *paths_of_changed_objects)
{
struct commit *commit;
while (commits->nr) {
- commit = (struct commit *)commits->objects[commits->nr - 1].item;
+ commit = (struct commit *)object_array_pop(commits);
if (has_unshown_parent(commit))
return;
- handle_commit(commit, revs);
- commits->nr--;
+ handle_commit(commit, revs, paths_of_changed_objects);
}
}
@@ -808,7 +823,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
if (e->flags & UNINTERESTING)
continue;
- if (dwim_ref(e->name, strlen(e->name), oid.hash, &full_name) != 1)
+ if (dwim_ref(e->name, strlen(e->name), &oid, &full_name) != 1)
continue;
if (refspecs) {
@@ -977,6 +992,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
char *export_filename = NULL, *import_filename = NULL;
uint32_t lastimportid;
struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
+ struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
struct option options[] = {
OPT_INTEGER(0, "progress", &progress,
N_("show progress after <n> objects")),
@@ -1049,14 +1065,15 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
revs.diffopt.format_callback = show_filemodify;
- DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
+ revs.diffopt.format_callback_data = &paths_of_changed_objects;
+ revs.diffopt.flags.recursive = 1;
while ((commit = get_revision(&revs))) {
if (has_unshown_parent(commit)) {
add_object_array(&commit->object, NULL, &commits);
}
else {
- handle_commit(commit, &revs);
- handle_tail(&commits, &revs);
+ handle_commit(commit, &revs, &paths_of_changed_objects);
+ handle_tail(&commits, &revs, &paths_of_changed_objects);
}
}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c87e59f3b..e705237fa 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -17,6 +17,7 @@
#include "connected.h"
#include "argv-array.h"
#include "utf8.h"
+#include "packfile.h"
static const char * const builtin_fetch_usage[] = {
N_("git fetch [<options>] [<repository> [<refspec>...]]"),
@@ -39,7 +40,7 @@ static int prune = -1; /* unspecified */
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative;
static int progress = -1;
static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
-static int max_children = -1;
+static int max_children = 1;
static enum transport_family family;
static const char *depth;
static const char *deepen_since;
@@ -68,9 +69,30 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
recurse_submodules = r;
}
+ if (!strcmp(k, "submodule.fetchjobs")) {
+ max_children = parse_submodule_fetchjobs(k, v);
+ return 0;
+ } else if (!strcmp(k, "fetch.recursesubmodules")) {
+ recurse_submodules = parse_fetch_recurse_submodules_arg(k, v);
+ return 0;
+ }
+
return git_default_config(k, v, cb);
}
+static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
+{
+ if (!strcmp(var, "submodule.fetchjobs")) {
+ max_children = parse_submodule_fetchjobs(var, value);
+ return 0;
+ } else if (!strcmp(var, "fetch.recursesubmodules")) {
+ recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
+ return 0;
+ }
+
+ return 0;
+}
+
static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
{
ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
@@ -435,8 +457,8 @@ static int s_update_ref(const char *action,
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, ref->name,
- ref->new_oid.hash,
- check_old ? ref->old_oid.hash : NULL,
+ &ref->new_oid,
+ check_old ? &ref->old_oid : NULL,
0, msg, &err))
goto fail;
@@ -705,7 +727,7 @@ static int update_local_ref(struct ref *ref,
}
}
-static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
+static int iterate_ref_map(void *cb_data, struct object_id *oid)
{
struct ref **rm = cb_data;
struct ref *ref = *rm;
@@ -715,7 +737,7 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
if (!ref)
return -1; /* end of the list */
*rm = ref->next;
- hashcpy(sha1, ref->old_oid.hash);
+ oidcpy(oid, &ref->old_oid);
return 0;
}
@@ -1311,6 +1333,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++)
strbuf_addf(&default_rla, " %s", argv[i]);
+ config_from_gitmodules(gitmodules_fetch_config, NULL);
git_config(git_fetch_config, NULL);
argc = parse_options(argc, argv, prefix,
@@ -1338,12 +1361,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (depth || deepen_since || deepen_not.nr)
deepen = 1;
- if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
- set_config_fetch_recurse_submodules(recurse_submodules_default);
- gitmodules_config();
- git_config(submodule_config, NULL);
- }
-
if (all) {
if (argc == 1)
die(_("fetch --all does not take a repository argument"));
@@ -1383,6 +1400,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
result = fetch_populated_submodules(&options,
submodule_prefix,
recurse_submodules,
+ recurse_submodules_default,
verbosity < 0,
max_children);
argv_array_clear(&options);
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 10cbb4341..22034f87e 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -408,7 +408,8 @@ static void shortlog(const char *name,
}
static void fmt_merge_msg_title(struct strbuf *out,
- const char *current_branch) {
+ const char *current_branch)
+{
int i = 0;
char *sep = "";
@@ -570,7 +571,7 @@ static void find_merge_parents(struct merge_parents *result,
head_commit = lookup_commit(head);
if (head_commit)
commit_list_insert(head_commit, &parents);
- parents = reduce_heads(parents);
+ reduce_heads_replace(&parents);
while (parents) {
struct commit *cmit = pop_commit(&parents);
@@ -602,7 +603,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
/* get current branch */
current_branch = current_branch_to_free =
- resolve_refdup("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL);
+ resolve_refdup("HEAD", RESOLVE_REF_READING, &head_oid, NULL);
if (!current_branch)
die("No current branch");
if (starts_with(current_branch, "refs/heads/"))
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 52be99cba..e931be9ce 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -17,25 +17,26 @@ static char const * const for_each_ref_usage[] = {
int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
{
int i;
- const char *format = "%(objectname) %(objecttype)\t%(refname)";
struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
- int maxcount = 0, quote_style = 0, icase = 0;
+ int maxcount = 0, icase = 0;
struct ref_array array;
struct ref_filter filter;
+ struct ref_format format = REF_FORMAT_INIT;
struct option opts[] = {
- OPT_BIT('s', "shell", &quote_style,
+ OPT_BIT('s', "shell", &format.quote_style,
N_("quote placeholders suitably for shells"), QUOTE_SHELL),
- OPT_BIT('p', "perl", &quote_style,
+ OPT_BIT('p', "perl", &format.quote_style,
N_("quote placeholders suitably for perl"), QUOTE_PERL),
- OPT_BIT(0 , "python", &quote_style,
+ OPT_BIT(0 , "python", &format.quote_style,
N_("quote placeholders suitably for python"), QUOTE_PYTHON),
- OPT_BIT(0 , "tcl", &quote_style,
+ OPT_BIT(0 , "tcl", &format.quote_style,
N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
OPT_GROUP(""),
OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
- OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
+ OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
+ OPT__COLOR(&format.use_color, N_("respect format colors")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
N_("field name to sort on"), &parse_opt_ref_sorting),
OPT_CALLBACK(0, "points-at", &filter.points_at,
@@ -52,16 +53,20 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
memset(&array, 0, sizeof(array));
memset(&filter, 0, sizeof(filter));
+ format.format = "%(objectname) %(objecttype)\t%(refname)";
+
+ git_config(git_default_config, NULL);
+
parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
usage_with_options(for_each_ref_usage, opts);
}
- if (HAS_MULTI_BITS(quote_style)) {
+ if (HAS_MULTI_BITS(format.quote_style)) {
error("more than one quoting style?");
usage_with_options(for_each_ref_usage, opts);
}
- if (verify_ref_format(format))
+ if (verify_ref_format(&format))
usage_with_options(for_each_ref_usage, opts);
if (!sorting)
@@ -69,9 +74,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
sorting->ignore_case = icase;
filter.ignore_case = icase;
- /* for warn_ambiguous_refs */
- git_config(git_default_config, NULL);
-
filter.name_patterns = argv;
filter.match_as_path = 1;
filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);
@@ -80,7 +82,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
if (!maxcount || array.nr < maxcount)
maxcount = array.nr;
for (i = 0; i < maxcount; i++)
- show_ref_array_item(array.items[i], format, quote_style);
+ show_ref_array_item(array.items[i], &format);
ref_array_clear(&array);
return 0;
}
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 99dea7adf..04846d46f 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -15,10 +15,13 @@
#include "progress.h"
#include "streaming.h"
#include "decorate.h"
+#include "packfile.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
#define HAS_OBJ 0x0004
+/* This flag is set if something points to this object. */
+#define USED 0x0008
static int show_root;
static int show_tags;
@@ -168,18 +171,7 @@ static void mark_object_reachable(struct object *obj)
static int traverse_one_object(struct object *obj)
{
- int result;
- struct tree *tree = NULL;
-
- if (obj->type == OBJ_TREE) {
- tree = (struct tree *)obj;
- if (parse_tree(tree) < 0)
- return 1; /* error already displayed */
- }
- result = fsck_walk(obj, obj, &fsck_walk_options);
- if (tree)
- free_tree_buffer(tree);
- return result;
+ return fsck_walk(obj, obj, &fsck_walk_options);
}
static int traverse_reachable(void)
@@ -188,14 +180,9 @@ static int traverse_reachable(void)
unsigned int nr = 0;
int result = 0;
if (show_progress)
- progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2);
+ progress = start_delayed_progress(_("Checking connectivity"), 0);
while (pending.nr) {
- struct object_array_entry *entry;
- struct object *obj;
-
- entry = pending.objects + --pending.nr;
- obj = entry->item;
- result |= traverse_one_object(obj);
+ result |= traverse_one_object(object_array_pop(&pending));
display_progress(progress, ++nr);
}
stop_progress(&progress);
@@ -206,7 +193,7 @@ static int mark_used(struct object *obj, int type, void *data, struct fsck_optio
{
if (!obj)
return 1;
- obj->used = 1;
+ obj->flags |= USED;
return 0;
}
@@ -255,7 +242,7 @@ static void check_unreachable_object(struct object *obj)
}
/*
- * "!used" means that nothing at all points to it, including
+ * "!USED" means that nothing at all points to it, including
* other unreachable objects. In other words, it's the "tip"
* of some set of unreachable objects, usually a commit that
* got dropped.
@@ -266,7 +253,7 @@ static void check_unreachable_object(struct object *obj)
* deleted a branch by mistake, this is a prime candidate to
* start looking at, for example.
*/
- if (!obj->used) {
+ if (!(obj->flags & USED)) {
if (show_dangling)
printf("dangling %s %s\n", printable_type(obj),
describe_object(obj));
@@ -335,6 +322,8 @@ static void check_connectivity(void)
static int fsck_obj(struct object *obj)
{
+ int err;
+
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
@@ -345,20 +334,13 @@ static int fsck_obj(struct object *obj)
if (fsck_walk(obj, NULL, &fsck_obj_options))
objerror(obj, "broken links");
- if (fsck_object(obj, NULL, 0, &fsck_obj_options))
- return -1;
-
- if (obj->type == OBJ_TREE) {
- struct tree *item = (struct tree *) obj;
-
- free_tree_buffer(item);
- }
+ err = fsck_object(obj, NULL, 0, &fsck_obj_options);
+ if (err)
+ goto out;
if (obj->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *) obj;
- free_commit_buffer(commit);
-
if (!commit->parents && show_root)
printf("root %s\n", describe_object(&commit->object));
}
@@ -374,7 +356,12 @@ static int fsck_obj(struct object *obj)
}
}
- return 0;
+out:
+ if (obj->type == OBJ_TREE)
+ free_tree_buffer((struct tree *)obj);
+ if (obj->type == OBJ_COMMIT)
+ free_commit_buffer((struct commit *)obj);
+ return err;
}
static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
@@ -390,7 +377,8 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
errors_found |= ERROR_OBJECT;
return error("%s: object corrupt or missing", oid_to_hex(oid));
}
- obj->flags = HAS_OBJ;
+ obj->flags &= ~(REACHABLE | SEEN);
+ obj->flags |= HAS_OBJ;
return fsck_obj(obj);
}
@@ -408,7 +396,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
add_decoration(fsck_walk_options.object_names,
obj,
xstrfmt("%s@{%"PRItime"}", refname, timestamp));
- obj->used = 1;
+ obj->flags |= USED;
mark_object_reachable(obj);
} else {
error("%s: invalid reflog entry %s", refname, oid_to_hex(oid));
@@ -456,7 +444,7 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
errors_found |= ERROR_REFS;
}
default_refs++;
- obj->used = 1;
+ obj->flags |= USED;
if (name_objects)
add_decoration(fsck_walk_options.object_names,
obj, xstrdup(refname));
@@ -524,7 +512,8 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
return 0; /* keep checking other objects */
}
- obj->flags = HAS_OBJ;
+ obj->flags &= ~(REACHABLE | SEEN);
+ obj->flags |= HAS_OBJ;
if (fsck_obj(obj))
errors_found |= ERROR_OBJECT;
return 0;
@@ -566,7 +555,7 @@ static int fsck_head_link(void)
if (verbose)
fprintf(stderr, "Checking HEAD link\n");
- head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid.hash, NULL);
+ head_points_at = resolve_ref_unsafe("HEAD", 0, &head_oid, NULL);
if (!head_points_at) {
errors_found |= ERROR_REFS;
return error("Invalid HEAD");
@@ -606,7 +595,7 @@ static int fsck_cache_tree(struct cache_tree *it)
errors_found |= ERROR_REFS;
return 1;
}
- obj->used = 1;
+ obj->flags |= USED;
if (name_objects)
add_decoration(fsck_walk_options.object_names,
obj, xstrdup(":"));
@@ -667,7 +656,7 @@ static struct option fsck_opts[] = {
int cmd_fsck(int argc, const char **argv, const char *prefix)
{
- int i, heads;
+ int i;
struct alternate_object_database *alt;
errors_found = 0;
@@ -735,25 +724,23 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
}
- heads = 0;
for (i = 0; i < argc; i++) {
const char *arg = argv[i];
- unsigned char sha1[20];
- if (!get_sha1(arg, sha1)) {
- struct object *obj = lookup_object(sha1);
+ struct object_id oid;
+ if (!get_oid(arg, &oid)) {
+ struct object *obj = lookup_object(oid.hash);
if (!obj || !(obj->flags & HAS_OBJ)) {
- error("%s: object missing", sha1_to_hex(sha1));
+ error("%s: object missing", oid_to_hex(&oid));
errors_found |= ERROR_OBJECT;
continue;
}
- obj->used = 1;
+ obj->flags |= USED;
if (name_objects)
add_decoration(fsck_walk_options.object_names,
obj, xstrdup(arg));
mark_object_reachable(obj);
- heads++;
continue;
}
error("invalid parameter: expected sha1, got '%s'", arg);
@@ -772,6 +759,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
if (keep_cache_objects) {
verify_index_checksum = 1;
+ verify_ce_order = 1;
read_cache();
for (i = 0; i < active_nr; i++) {
unsigned int mode;
@@ -785,7 +773,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
if (!blob)
continue;
obj = &blob->object;
- obj->used = 1;
+ obj->flags |= USED;
if (name_objects)
add_decoration(fsck_walk_options.object_names,
obj,
diff --git a/builtin/gc.c b/builtin/gc.c
index e6b84475a..3c5eae0ed 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -19,6 +19,7 @@
#include "sigchain.h"
#include "argv-array.h"
#include "commit.h"
+#include "packfile.h"
#define FAILED_RUN "failed to run %s"
@@ -46,7 +47,7 @@ static struct argv_array prune = ARGV_ARRAY_INIT;
static struct argv_array prune_worktrees = ARGV_ARRAY_INIT;
static struct argv_array rerere = ARGV_ARRAY_INIT;
-static struct tempfile pidfile;
+static struct tempfile *pidfile;
static struct lock_file log_lock;
static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
@@ -77,7 +78,7 @@ static void process_log_file(void)
*/
int saved_errno = errno;
fprintf(stderr, _("Failed to fstat %s: %s"),
- get_tempfile_path(&log_lock.tempfile),
+ get_tempfile_path(log_lock.tempfile),
strerror(saved_errno));
fflush(stderr);
commit_lock_file(&log_lock);
@@ -241,7 +242,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
int fd;
char *pidfile_path;
- if (is_tempfile_active(&pidfile))
+ if (is_tempfile_active(pidfile))
/* already locked */
return NULL;
@@ -257,7 +258,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
int should_exit;
if (!scan_fmt)
- scan_fmt = xstrfmt("%s %%%dc", "%"SCNuMAX, HOST_NAME_MAX);
+ scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX);
fp = fopen(pidfile_path, "r");
memset(locking_host, 0, sizeof(locking_host));
should_exit =
@@ -292,7 +293,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
write_in_full(fd, sb.buf, sb.len);
strbuf_release(&sb);
commit_lock_file(&lock);
- register_tempfile(&pidfile, pidfile_path);
+ pidfile = register_tempfile(pidfile_path);
free(pidfile_path);
return NULL;
}
diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c
index e21c5416c..2706fcfaf 100644
--- a/builtin/get-tar-commit-id.c
+++ b/builtin/get-tar-commit-id.c
@@ -26,15 +26,16 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
usage(builtin_get_tar_commit_id_usage);
n = read_in_full(0, buffer, HEADERSIZE);
- if (n < HEADERSIZE)
- die("git get-tar-commit-id: read error");
+ if (n < 0)
+ die_errno("git get-tar-commit-id: read error");
+ if (n != HEADERSIZE)
+ die_errno("git get-tar-commit-id: EOF before reading tar header");
if (header->typeflag[0] != 'g')
return 1;
if (!skip_prefix(content, "52 comment=", &comment))
return 1;
- n = write_in_full(1, comment, 41);
- if (n < 41)
+ if (write_in_full(1, comment, 41) < 0)
die_errno("git get-tar-commit-id: write error");
return 0;
diff --git a/builtin/grep.c b/builtin/grep.c
index 7e79eb1a7..5a6cfe6b4 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -28,13 +28,7 @@ static char const * const grep_usage[] = {
NULL
};
-static const char *super_prefix;
static int recurse_submodules;
-static struct argv_array submodule_options = ARGV_ARRAY_INIT;
-static const char *parent_basename;
-
-static int grep_submodule_launch(struct grep_opt *opt,
- const struct grep_source *gs);
#define GREP_NUM_THREADS_DEFAULT 8
static int num_threads;
@@ -186,10 +180,7 @@ static void *run(void *arg)
break;
opt->output_priv = w;
- if (w->source.type == GREP_SOURCE_SUBMODULE)
- hit |= grep_submodule_launch(opt, &w->source);
- else
- hit |= grep_source(opt, &w->source);
+ hit |= grep_source(opt, &w->source);
grep_source_clear_data(&w->source);
work_done(w);
}
@@ -327,21 +318,13 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
{
struct strbuf pathbuf = STRBUF_INIT;
- if (super_prefix) {
- strbuf_add(&pathbuf, filename, tree_name_len);
- strbuf_addstr(&pathbuf, super_prefix);
- strbuf_addstr(&pathbuf, filename + tree_name_len);
+ if (opt->relative && opt->prefix_length) {
+ quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
+ strbuf_insert(&pathbuf, 0, filename, tree_name_len);
} else {
strbuf_addstr(&pathbuf, filename);
}
- if (opt->relative && opt->prefix_length) {
- char *name = strbuf_detach(&pathbuf, NULL);
- quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf);
- strbuf_insert(&pathbuf, 0, name, tree_name_len);
- free(name);
- }
-
#ifndef NO_PTHREADS
if (num_threads) {
add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
@@ -366,15 +349,10 @@ static int grep_file(struct grep_opt *opt, const char *filename)
{
struct strbuf buf = STRBUF_INIT;
- if (super_prefix)
- strbuf_addstr(&buf, super_prefix);
- strbuf_addstr(&buf, filename);
-
- if (opt->relative && opt->prefix_length) {
- char *name = strbuf_detach(&buf, NULL);
- quote_path_relative(name, opt->prefix, &buf);
- free(name);
- }
+ if (opt->relative && opt->prefix_length)
+ quote_path_relative(filename, opt->prefix, &buf);
+ else
+ strbuf_addstr(&buf, filename);
#ifndef NO_PTHREADS
if (num_threads) {
@@ -421,284 +399,91 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
exit(status);
}
-static void compile_submodule_options(const struct grep_opt *opt,
- const char **argv,
- int cached, int untracked,
- int opt_exclude, int use_index,
- int pattern_type_arg)
-{
- struct grep_pat *pattern;
-
- if (recurse_submodules)
- argv_array_push(&submodule_options, "--recurse-submodules");
-
- if (cached)
- argv_array_push(&submodule_options, "--cached");
- if (!use_index)
- argv_array_push(&submodule_options, "--no-index");
- if (untracked)
- argv_array_push(&submodule_options, "--untracked");
- if (opt_exclude > 0)
- argv_array_push(&submodule_options, "--exclude-standard");
-
- if (opt->invert)
- argv_array_push(&submodule_options, "-v");
- if (opt->ignore_case)
- argv_array_push(&submodule_options, "-i");
- if (opt->word_regexp)
- argv_array_push(&submodule_options, "-w");
- switch (opt->binary) {
- case GREP_BINARY_NOMATCH:
- argv_array_push(&submodule_options, "-I");
- break;
- case GREP_BINARY_TEXT:
- argv_array_push(&submodule_options, "-a");
- break;
- default:
- break;
- }
- if (opt->allow_textconv)
- argv_array_push(&submodule_options, "--textconv");
- if (opt->max_depth != -1)
- argv_array_pushf(&submodule_options, "--max-depth=%d",
- opt->max_depth);
- if (opt->linenum)
- argv_array_push(&submodule_options, "-n");
- if (!opt->pathname)
- argv_array_push(&submodule_options, "-h");
- if (!opt->relative)
- argv_array_push(&submodule_options, "--full-name");
- if (opt->name_only)
- argv_array_push(&submodule_options, "-l");
- if (opt->unmatch_name_only)
- argv_array_push(&submodule_options, "-L");
- if (opt->null_following_name)
- argv_array_push(&submodule_options, "-z");
- if (opt->count)
- argv_array_push(&submodule_options, "-c");
- if (opt->file_break)
- argv_array_push(&submodule_options, "--break");
- if (opt->heading)
- argv_array_push(&submodule_options, "--heading");
- if (opt->pre_context)
- argv_array_pushf(&submodule_options, "--before-context=%d",
- opt->pre_context);
- if (opt->post_context)
- argv_array_pushf(&submodule_options, "--after-context=%d",
- opt->post_context);
- if (opt->funcname)
- argv_array_push(&submodule_options, "-p");
- if (opt->funcbody)
- argv_array_push(&submodule_options, "-W");
- if (opt->all_match)
- argv_array_push(&submodule_options, "--all-match");
- if (opt->debug)
- argv_array_push(&submodule_options, "--debug");
- if (opt->status_only)
- argv_array_push(&submodule_options, "-q");
-
- switch (pattern_type_arg) {
- case GREP_PATTERN_TYPE_BRE:
- argv_array_push(&submodule_options, "-G");
- break;
- case GREP_PATTERN_TYPE_ERE:
- argv_array_push(&submodule_options, "-E");
- break;
- case GREP_PATTERN_TYPE_FIXED:
- argv_array_push(&submodule_options, "-F");
- break;
- case GREP_PATTERN_TYPE_PCRE:
- argv_array_push(&submodule_options, "-P");
- break;
- case GREP_PATTERN_TYPE_UNSPECIFIED:
- break;
- default:
- die("BUG: Added a new grep pattern type without updating switch statement");
- }
-
- for (pattern = opt->pattern_list; pattern != NULL;
- pattern = pattern->next) {
- switch (pattern->token) {
- case GREP_PATTERN:
- argv_array_pushf(&submodule_options, "-e%s",
- pattern->pattern);
- break;
- case GREP_AND:
- case GREP_OPEN_PAREN:
- case GREP_CLOSE_PAREN:
- case GREP_NOT:
- case GREP_OR:
- argv_array_push(&submodule_options, pattern->pattern);
- break;
- /* BODY and HEAD are not used by git-grep */
- case GREP_PATTERN_BODY:
- case GREP_PATTERN_HEAD:
- break;
- }
- }
-
- /*
- * Limit number of threads for child process to use.
- * This is to prevent potential fork-bomb behavior of git-grep as each
- * submodule process has its own thread pool.
- */
- argv_array_pushf(&submodule_options, "--threads=%d",
- DIV_ROUND_UP(num_threads, 2));
-
- /* Add Pathspecs */
- argv_array_push(&submodule_options, "--");
- for (; *argv; argv++)
- argv_array_push(&submodule_options, *argv);
-}
+static int grep_cache(struct grep_opt *opt, struct repository *repo,
+ const struct pathspec *pathspec, int cached);
+static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
+ struct tree_desc *tree, struct strbuf *base, int tn_len,
+ int check_attr, struct repository *repo);
-/*
- * Launch child process to grep contents of a submodule
- */
-static int grep_submodule_launch(struct grep_opt *opt,
- const struct grep_source *gs)
+static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
+ const struct pathspec *pathspec,
+ const struct object_id *oid,
+ const char *filename, const char *path)
{
- struct child_process cp = CHILD_PROCESS_INIT;
- int status, i;
- const char *end_of_base;
- const char *name;
- struct strbuf child_output = STRBUF_INIT;
-
- end_of_base = strchr(gs->name, ':');
- if (gs->identifier && end_of_base)
- name = end_of_base + 1;
- else
- name = gs->name;
+ struct repository submodule;
+ int hit;
- prepare_submodule_repo_env(&cp.env_array);
- argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT);
+ if (!is_submodule_active(superproject, path))
+ return 0;
- if (opt->relative && opt->prefix_length)
- argv_array_pushf(&cp.env_array, "%s=%s",
- GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
- opt->prefix);
+ if (repo_submodule_init(&submodule, superproject, path))
+ return 0;
- /* Add super prefix */
- argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
- super_prefix ? super_prefix : "",
- name);
- argv_array_push(&cp.args, "grep");
+ repo_read_gitmodules(&submodule);
/*
- * Add basename of parent project
- * When performing grep on a tree object the filename is prefixed
- * with the object's name: 'tree-name:filename'. In order to
- * provide uniformity of output we want to pass the name of the
- * parent project's object name to the submodule so the submodule can
- * prefix its output with the parent's name and not its own OID.
+ * NEEDSWORK: This adds the submodule's object directory to the list of
+ * alternates for the single in-memory object store. This has some bad
+ * consequences for memory (processed objects will never be freed) and
+ * performance (this increases the number of pack files git has to pay
+ * attention to, to the sum of the number of pack files in all the
+ * repositories processed so far). This can be removed once the object
+ * store is no longer global and instead is a member of the repository
+ * object.
*/
- if (gs->identifier && end_of_base)
- argv_array_pushf(&cp.args, "--parent-basename=%.*s",
- (int) (end_of_base - gs->name),
- gs->name);
+ grep_read_lock();
+ add_to_alternates_memory(submodule.objectdir);
+ grep_read_unlock();
- /* Add options */
- for (i = 0; i < submodule_options.argc; i++) {
- /*
- * If there is a tree identifier for the submodule, add the
- * rev after adding the submodule options but before the
- * pathspecs. To do this we listen for the '--' and insert the
- * oid before pushing the '--' onto the child process argv
- * array.
- */
- if (gs->identifier &&
- !strcmp("--", submodule_options.argv[i])) {
- argv_array_push(&cp.args, oid_to_hex(gs->identifier));
- }
+ if (oid) {
+ struct object *object;
+ struct tree_desc tree;
+ void *data;
+ unsigned long size;
+ struct strbuf base = STRBUF_INIT;
- argv_array_push(&cp.args, submodule_options.argv[i]);
- }
+ object = parse_object_or_die(oid, oid_to_hex(oid));
- cp.git_cmd = 1;
- cp.dir = gs->path;
+ grep_read_lock();
+ data = read_object_with_reference(object->oid.hash, tree_type,
+ &size, NULL);
+ grep_read_unlock();
- /*
- * Capture output to output buffer and check the return code from the
- * child process. A '0' indicates a hit, a '1' indicates no hit and
- * anything else is an error.
- */
- status = capture_command(&cp, &child_output, 0);
- if (status && (status != 1)) {
- /* flush the buffer */
- write_or_die(1, child_output.buf, child_output.len);
- die("process for submodule '%s' failed with exit code: %d",
- gs->name, status);
- }
+ if (!data)
+ die(_("unable to read tree (%s)"), oid_to_hex(&object->oid));
- opt->output(opt, child_output.buf, child_output.len);
- strbuf_release(&child_output);
- /* invert the return code to make a hit equal to 1 */
- return !status;
-}
+ strbuf_addstr(&base, filename);
+ strbuf_addch(&base, '/');
-/*
- * Prep grep structures for a submodule grep
- * oid: the oid of the submodule or NULL if using the working tree
- * filename: name of the submodule including tree name of parent
- * path: location of the submodule
- */
-static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
- const char *filename, const char *path)
-{
- if (!is_submodule_active(the_repository, path))
- return 0;
- if (!is_submodule_populated_gently(path, NULL)) {
- /*
- * If searching history, check for the presence of the
- * submodule's gitdir before skipping the submodule.
- */
- if (oid) {
- const struct submodule *sub =
- submodule_from_path(null_sha1, path);
- if (sub)
- path = git_path("modules/%s", sub->name);
-
- if (!(is_directory(path) && is_git_directory(path)))
- return 0;
- } else {
- return 0;
- }
+ init_tree_desc(&tree, data, size);
+ hit = grep_tree(opt, pathspec, &tree, &base, base.len,
+ object->type == OBJ_COMMIT, &submodule);
+ strbuf_release(&base);
+ free(data);
+ } else {
+ hit = grep_cache(opt, &submodule, pathspec, 1);
}
-#ifndef NO_PTHREADS
- if (num_threads) {
- add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid);
- return 0;
- } else
-#endif
- {
- struct grep_source gs;
- int hit;
-
- grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
- filename, path, oid);
- hit = grep_submodule_launch(opt, &gs);
-
- grep_source_clear(&gs);
- return hit;
- }
+ repo_clear(&submodule);
+ return hit;
}
-static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
- int cached)
+static int grep_cache(struct grep_opt *opt, struct repository *repo,
+ const struct pathspec *pathspec, int cached)
{
int hit = 0;
int nr;
struct strbuf name = STRBUF_INIT;
int name_base_len = 0;
- if (super_prefix) {
- name_base_len = strlen(super_prefix);
- strbuf_addstr(&name, super_prefix);
+ if (repo->submodule_prefix) {
+ name_base_len = strlen(repo->submodule_prefix);
+ strbuf_addstr(&name, repo->submodule_prefix);
}
- read_cache();
+ repo_read_index(repo);
- for (nr = 0; nr < active_nr; nr++) {
- const struct cache_entry *ce = active_cache[nr];
+ for (nr = 0; nr < repo->index->cache_nr; nr++) {
+ const struct cache_entry *ce = repo->index->cache[nr];
strbuf_setlen(&name, name_base_len);
strbuf_addstr(&name, ce->name);
@@ -715,14 +500,14 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
ce_skip_worktree(ce)) {
if (ce_stage(ce) || ce_intent_to_add(ce))
continue;
- hit |= grep_oid(opt, &ce->oid, ce->name,
- 0, ce->name);
+ hit |= grep_oid(opt, &ce->oid, name.buf,
+ 0, name.buf);
} else {
- hit |= grep_file(opt, ce->name);
+ hit |= grep_file(opt, name.buf);
}
} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
submodule_path_match(pathspec, name.buf, NULL)) {
- hit |= grep_submodule(opt, NULL, ce->name, ce->name);
+ hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name);
} else {
continue;
}
@@ -730,8 +515,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
if (ce_stage(ce)) {
do {
nr++;
- } while (nr < active_nr &&
- !strcmp(ce->name, active_cache[nr]->name));
+ } while (nr < repo->index->cache_nr &&
+ !strcmp(ce->name, repo->index->cache[nr]->name));
nr--; /* compensate for loop control */
}
if (hit && opt->status_only)
@@ -744,7 +529,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
struct tree_desc *tree, struct strbuf *base, int tn_len,
- int check_attr)
+ int check_attr, struct repository *repo)
{
int hit = 0;
enum interesting match = entry_not_interesting;
@@ -752,8 +537,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
int old_baselen = base->len;
struct strbuf name = STRBUF_INIT;
int name_base_len = 0;
- if (super_prefix) {
- strbuf_addstr(&name, super_prefix);
+ if (repo->submodule_prefix) {
+ strbuf_addstr(&name, repo->submodule_prefix);
name_base_len = name.len;
}
@@ -791,11 +576,11 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
strbuf_addch(base, '/');
init_tree_desc(&sub, data, size);
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
- check_attr);
+ check_attr, repo);
free(data);
} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
- hit |= grep_submodule(opt, entry.oid, base->buf,
- base->buf + tn_len);
+ hit |= grep_submodule(opt, repo, pathspec, entry.oid,
+ base->buf, base->buf + tn_len);
}
strbuf_setlen(base, old_baselen);
@@ -809,7 +594,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
}
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
- struct object *obj, const char *name, const char *path)
+ struct object *obj, const char *name, const char *path,
+ struct repository *repo)
{
if (obj->type == OBJ_BLOB)
return grep_oid(opt, &obj->oid, name, 0, path);
@@ -828,10 +614,6 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
if (!data)
die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
- /* Use parent's name as base when recursing submodules */
- if (recurse_submodules && parent_basename)
- name = parent_basename;
-
len = name ? strlen(name) : 0;
strbuf_init(&base, PATH_MAX + len + 1);
if (len) {
@@ -840,7 +622,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
}
init_tree_desc(&tree, data, size);
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
- obj->type == OBJ_COMMIT);
+ obj->type == OBJ_COMMIT, repo);
strbuf_release(&base);
free(data);
return hit;
@@ -849,6 +631,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
}
static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
+ struct repository *repo,
const struct object_array *list)
{
unsigned int i;
@@ -862,9 +645,10 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
/* load the gitmodules file for this rev */
if (recurse_submodules) {
submodule_free();
- gitmodules_config_sha1(real_obj->oid.hash);
+ gitmodules_config_oid(&real_obj->oid);
}
- if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) {
+ if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path,
+ repo)) {
hit = 1;
if (opt->status_only)
break;
@@ -1005,9 +789,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
N_("ignore files specified via '.gitignore'"), 1),
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
N_("recursively search in each submodule")),
- OPT_STRING(0, "parent-basename", &parent_basename,
- N_("basename"),
- N_("prepend parent project's basename to output")),
OPT_GROUP(""),
OPT_BOOL('v', "invert-match", &opt.invert,
N_("show non-matching lines")),
@@ -1112,7 +893,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
init_grep_defaults();
git_config(grep_cmd_config, NULL);
grep_init(&opt, prefix);
- super_prefix = get_super_prefix();
/*
* If there is no -- then the paths must exist in the working
@@ -1205,8 +985,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
break;
}
- if (get_sha1_with_context(arg, GET_SHA1_RECORD_PATH,
- oid.hash, &oc)) {
+ if (get_oid_with_context(arg, GET_OID_RECORD_PATH,
+ &oid, &oc)) {
if (seen_dashdash)
die(_("unable to resolve revision: %s"), arg);
break;
@@ -1270,13 +1050,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
#endif
- if (recurse_submodules) {
- gitmodules_config();
- compile_submodule_options(&opt, argv + i, cached, untracked,
- opt_exclude, use_index,
- pattern_type_arg);
- }
-
if (show_in_pager && (cached || list.nr))
die(_("--open-files-in-pager only works on the worktree"));
@@ -1318,11 +1091,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (!cached)
setup_work_tree();
- hit = grep_cache(&opt, &pathspec, cached);
+ hit = grep_cache(&opt, the_repository, &pathspec, cached);
} else {
if (cached)
die(_("both --cached and trees are given."));
- hit = grep_objects(&opt, &pathspec, &list);
+
+ hit = grep_objects(&opt, &pathspec, the_repository, &list);
}
if (num_threads)
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index d04baf999..c532ff932 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -16,7 +16,7 @@
* needs to bypass the data conversion performed by, and the type
* limitation imposed by, index_fd() and its callees.
*/
-static int hash_literally(unsigned char *sha1, int fd, const char *type, unsigned flags)
+static int hash_literally(struct object_id *oid, int fd, const char *type, unsigned flags)
{
struct strbuf buf = STRBUF_INIT;
int ret;
@@ -24,7 +24,7 @@ static int hash_literally(unsigned char *sha1, int fd, const char *type, unsigne
if (strbuf_read(&buf, fd, 4096) < 0)
ret = -1;
else
- ret = hash_sha1_file_literally(buf.buf, buf.len, type, sha1, flags);
+ ret = hash_sha1_file_literally(buf.buf, buf.len, type, oid, flags);
strbuf_release(&buf);
return ret;
}
@@ -33,16 +33,16 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
int literally)
{
struct stat st;
- unsigned char sha1[20];
+ struct object_id oid;
if (fstat(fd, &st) < 0 ||
(literally
- ? hash_literally(sha1, fd, type, flags)
- : index_fd(sha1, fd, &st, type_from_string(type), path, flags)))
+ ? hash_literally(&oid, fd, type, flags)
+ : index_fd(&oid, fd, &st, type_from_string(type), path, flags)))
die((flags & HASH_WRITE_OBJECT)
? "Unable to add %s to database"
: "Unable to hash %s", path);
- printf("%s\n", sha1_to_hex(sha1));
+ printf("%s\n", oid_to_hex(&oid));
maybe_flush_or_die(stdout, "hash to stdout");
}
diff --git a/builtin/help.c b/builtin/help.c
index 334a8494a..d3c8fc408 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -131,6 +131,7 @@ static void exec_woman_emacs(const char *path, const char *page)
strbuf_addf(&man_page, "(woman \"%s\")", page);
execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL);
warning_errno(_("failed to exec '%s'"), path);
+ strbuf_release(&man_page);
}
}
@@ -152,6 +153,7 @@ static void exec_man_konqueror(const char *path, const char *page)
strbuf_addf(&man_page, "man:%s(1)", page);
execlp(path, filename, "newTab", man_page.buf, (char *)NULL);
warning_errno(_("failed to exec '%s'"), path);
+ strbuf_release(&man_page);
}
}
@@ -169,6 +171,7 @@ static void exec_man_cmd(const char *cmd, const char *page)
strbuf_addf(&shell_cmd, "%s %s", cmd, page);
execl(SHELL_PATH, SHELL_PATH, "-c", shell_cmd.buf, (char *)NULL);
warning(_("failed to exec '%s'"), cmd);
+ strbuf_release(&shell_cmd);
}
static void add_man_viewer(const char *name)
@@ -438,7 +441,7 @@ static const char *check_git_cmd(const char* cmd)
alias = alias_lookup(cmd);
if (alias) {
- printf_ln(_("`git %s' is aliased to `%s'"), cmd, alias);
+ printf_ln(_("'%s' is aliased to '%s'"), cmd, alias);
free(alias);
exit(0);
}
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 26828c1d8..8ec459f52 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -12,6 +12,7 @@
#include "exec_cmd.h"
#include "streaming.h"
#include "thread-utils.h"
+#include "packfile.h"
static const char index_pack_usage[] =
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
@@ -632,7 +633,7 @@ static int find_ofs_delta(const off_t offset, enum object_type type)
int first = 0, last = nr_ofs_deltas;
while (first < last) {
- int next = (first + last) / 2;
+ int next = first + (last - first) / 2;
struct ofs_delta_entry *delta = &ofs_deltas[next];
int cmp;
@@ -686,7 +687,7 @@ static int find_ref_delta(const unsigned char *sha1, enum object_type type)
int first = 0, last = nr_ref_deltas;
while (first < last) {
- int next = (first + last) / 2;
+ int next = first + (last - first) / 2;
struct ref_delta_entry *delta = &ref_deltas[next];
int cmp;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 47823f9aa..c9b7946ba 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -579,6 +579,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
set_git_work_tree(work_tree);
}
+ UNLEAK(real_git_dir);
+
flags |= INIT_DB_EXIST_OK;
return init_db(git_dir, real_git_dir, template_dir, flags);
}
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 175f14797..b742539d4 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -16,34 +16,119 @@ static const char * const git_interpret_trailers_usage[] = {
NULL
};
+static enum trailer_where where;
+static enum trailer_if_exists if_exists;
+static enum trailer_if_missing if_missing;
+
+static int option_parse_where(const struct option *opt,
+ const char *arg, int unset)
+{
+ return trailer_set_where(&where, arg);
+}
+
+static int option_parse_if_exists(const struct option *opt,
+ const char *arg, int unset)
+{
+ return trailer_set_if_exists(&if_exists, arg);
+}
+
+static int option_parse_if_missing(const struct option *opt,
+ const char *arg, int unset)
+{
+ return trailer_set_if_missing(&if_missing, arg);
+}
+
+static void new_trailers_clear(struct list_head *trailers)
+{
+ struct list_head *pos, *tmp;
+ struct new_trailer_item *item;
+
+ list_for_each_safe(pos, tmp, trailers) {
+ item = list_entry(pos, struct new_trailer_item, list);
+ list_del(pos);
+ free(item);
+ }
+}
+
+static int option_parse_trailer(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct list_head *trailers = opt->value;
+ struct new_trailer_item *item;
+
+ if (unset) {
+ new_trailers_clear(trailers);
+ return 0;
+ }
+
+ if (!arg)
+ return -1;
+
+ item = xmalloc(sizeof(*item));
+ item->text = arg;
+ item->where = where;
+ item->if_exists = if_exists;
+ item->if_missing = if_missing;
+ list_add_tail(&item->list, trailers);
+ return 0;
+}
+
+static int parse_opt_parse(const struct option *opt, const char *arg,
+ int unset)
+{
+ struct process_trailer_options *v = opt->value;
+ v->only_trailers = 1;
+ v->only_input = 1;
+ v->unfold = 1;
+ return 0;
+}
+
int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
{
- int in_place = 0;
- int trim_empty = 0;
- struct string_list trailers = STRING_LIST_INIT_NODUP;
+ struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
+ LIST_HEAD(trailers);
struct option options[] = {
- OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
- OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")),
- OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
- N_("trailer(s) to add")),
+ OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
+ OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
+
+ OPT_CALLBACK(0, "where", NULL, N_("action"),
+ N_("where to place the new trailer"), option_parse_where),
+ OPT_CALLBACK(0, "if-exists", NULL, N_("action"),
+ N_("action if trailer already exists"), option_parse_if_exists),
+ OPT_CALLBACK(0, "if-missing", NULL, N_("action"),
+ N_("action if trailer is missing"), option_parse_if_missing),
+
+ OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
+ OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply config rules")),
+ OPT_BOOL(0, "unfold", &opts.unfold, N_("join whitespace-continued values")),
+ { OPTION_CALLBACK, 0, "parse", &opts, NULL, N_("set parsing options"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse },
+ OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"),
+ N_("trailer(s) to add"), option_parse_trailer),
OPT_END()
};
argc = parse_options(argc, argv, prefix, options,
git_interpret_trailers_usage, 0);
+ if (opts.only_input && !list_empty(&trailers))
+ usage_msg_opt(
+ _("--trailer with --only-input does not make sense"),
+ git_interpret_trailers_usage,
+ options);
+
if (argc) {
int i;
for (i = 0; i < argc; i++)
- process_trailers(argv[i], in_place, trim_empty, &trailers);
+ process_trailers(argv[i], &opts, &trailers);
} else {
- if (in_place)
+ if (opts.in_place)
die(_("no input file given for in-place editing"));
- process_trailers(NULL, in_place, trim_empty, &trailers);
+ process_trailers(NULL, &opts, &trailers);
}
- string_list_clear(&trailers, 0);
+ new_trailers_clear(&trailers);
return 0;
}
diff --git a/builtin/log.c b/builtin/log.c
index c6362cf92..6c1fa896a 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -27,6 +27,7 @@
#include "version.h"
#include "mailmap.h"
#include "gpg-interface.h"
+#include "progress.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -58,9 +59,9 @@ static int auto_decoration_style(void)
return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0;
}
-static int parse_decoration_style(const char *var, const char *value)
+static int parse_decoration_style(const char *value)
{
- switch (git_config_maybe_bool(var, value)) {
+ switch (git_parse_maybe_bool(value)) {
case 1:
return DECORATE_SHORT_REFS;
case 0:
@@ -82,7 +83,7 @@ static int decorate_callback(const struct option *opt, const char *arg, int unse
if (unset)
decoration_style = 0;
else if (arg)
- decoration_style = parse_decoration_style("command line", arg);
+ decoration_style = parse_decoration_style(arg);
else
decoration_style = DECORATE_SHORT_REFS;
@@ -120,20 +121,19 @@ static void cmd_log_init_defaults(struct rev_info *rev)
if (fmt_pretty)
get_commit_format(fmt_pretty, rev);
if (default_follow)
- DIFF_OPT_SET(&rev->diffopt, DEFAULT_FOLLOW_RENAMES);
+ rev->diffopt.flags.default_follow_renames = 1;
rev->verbose_header = 1;
- DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
+ rev->diffopt.flags.recursive = 1;
rev->diffopt.stat_width = -1; /* use full terminal width */
rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */
rev->abbrev_commit = default_abbrev_commit;
rev->show_root_diff = default_show_root;
rev->subject_prefix = fmt_patch_subject_prefix;
rev->show_signature = default_show_signature;
- DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
+ rev->diffopt.flags.allow_textconv = 1;
if (default_date_mode)
parse_date_format(default_date_mode, &rev->date_mode);
- rev->diffopt.touched_flags = 0;
}
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
@@ -181,7 +181,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
init_display_notes(&rev->notes_opt);
if (rev->diffopt.pickaxe || rev->diffopt.filter ||
- DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES))
+ rev->diffopt.flags.follow_renames)
rev->always_show_header = 0;
if (source)
@@ -372,11 +372,14 @@ static int cmd_log_walk(struct rev_info *rev)
*/
rev->max_count++;
if (!rev->reflog_info) {
- /* we allow cycles in reflog ancestry */
+ /*
+ * We may show a given commit multiple times when
+ * walking the reflogs.
+ */
free_commit_buffer(commit);
+ free_commit_list(commit->parents);
+ commit->parents = NULL;
}
- free_commit_list(commit->parents);
- commit->parents = NULL;
if (saved_nrl < rev->diffopt.needed_rename_limit)
saved_nrl = rev->diffopt.needed_rename_limit;
if (rev->diffopt.degraded_cc_to_c)
@@ -388,7 +391,7 @@ static int cmd_log_walk(struct rev_info *rev)
fclose(rev->diffopt.file);
if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
- DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
+ rev->diffopt.flags.check_failed) {
return 02;
}
return diff_result_code(&rev->diffopt, 0);
@@ -409,7 +412,7 @@ static int git_log_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "log.date"))
return git_config_string(&default_date_mode, var, value);
if (!strcmp(var, "log.decorate")) {
- decoration_style = parse_decoration_style(var, value);
+ decoration_style = parse_decoration_style(value);
if (decoration_style < 0)
decoration_style = 0; /* maybe warn? */
return 0;
@@ -480,12 +483,12 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
unsigned long size;
fflush(rev->diffopt.file);
- if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
- !DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
+ if (!rev->diffopt.flags.textconv_set_via_cmdline ||
+ !rev->diffopt.flags.allow_textconv)
return stream_blob_to_fd(1, oid, NULL, 0);
- if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
- oidc.hash, &obj_context))
+ if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH,
+ &oidc, &obj_context))
die(_("Not a valid object name %s"), obj_name);
if (!obj_context.path ||
!textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size)) {
@@ -663,9 +666,9 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix)
static void log_setup_revisions_tweak(struct rev_info *rev,
struct setup_revision_opt *opt)
{
- if (DIFF_OPT_TST(&rev->diffopt, DEFAULT_FOLLOW_RENAMES) &&
+ if (rev->diffopt.flags.default_follow_renames &&
rev->prune_data.nr == 1)
- DIFF_OPT_SET(&rev->diffopt, FOLLOW_RENAMES);
+ rev->diffopt.flags.follow_renames = 1;
/* Turn --cc/-c into -p --cc/-c when -p was not given */
if (!rev->diffopt.output_format && rev->combine_merges)
@@ -821,7 +824,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
return 0;
}
if (!strcmp(var, "format.from")) {
- int b = git_config_maybe_bool(var, value);
+ int b = git_parse_maybe_bool(value);
free(from);
if (b < 0)
from = xstrdup(value);
@@ -971,7 +974,7 @@ static char *find_branch_name(struct rev_info *rev)
return NULL;
ref = rev->cmdline.rev[positive].name;
tip_oid = &rev->cmdline.rev[positive].item->oid;
- if (dwim_ref(ref, strlen(ref), branch_oid.hash, &full_ref) &&
+ if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref) &&
skip_prefix(full_ref, "refs/heads/", &v) &&
!oidcmp(tip_oid, &branch_oid))
branch = xstrdup(v);
@@ -1337,7 +1340,7 @@ static void prepare_bases(struct base_tree_info *bases,
return;
diff_setup(&diffopt);
- DIFF_OPT_SET(&diffopt, RECURSIVE);
+ diffopt.flags.recursive = 1;
diff_setup_done(&diffopt);
oidcpy(&bases->base_commit, &base->object.oid);
@@ -1419,6 +1422,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
char *branch_name = NULL;
char *base_commit = NULL;
struct base_tree_info bases;
+ int show_progress = 0;
+ struct progress *progress = NULL;
const struct option builtin_format_patch_options[] = {
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
@@ -1490,6 +1495,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
OPT_FILENAME(0, "signature-file", &signature_file,
N_("add a signature from a file")),
OPT__QUIET(&quiet, N_("don't print the patch filenames")),
+ OPT_BOOL(0, "progress", &show_progress,
+ N_("show progress while generating patches")),
OPT_END()
};
@@ -1504,7 +1511,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.verbose_header = 1;
rev.diff = 1;
rev.max_parents = 1;
- DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
+ rev.diffopt.flags.recursive = 1;
rev.subject_prefix = fmt_patch_subject_prefix;
memset(&s_r_opt, 0, sizeof(s_r_opt));
s_r_opt.def = "HEAD";
@@ -1605,8 +1612,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.zero_commit = zero_commit;
- if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
- DIFF_OPT_SET(&rev.diffopt, BINARY);
+ if (!rev.diffopt.flags.text && !no_binary_diff)
+ rev.diffopt.flags.binary = 1;
if (rev.show_notes)
init_display_notes(&rev.notes_opt);
@@ -1652,10 +1659,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
check_head = 1;
if (check_head) {
- struct object_id oid;
const char *ref, *v;
ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- oid.hash, NULL);
+ NULL, NULL);
if (ref && skip_prefix(ref, "refs/heads/", &v))
branch_name = xstrdup(v);
else
@@ -1749,8 +1755,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
start_number--;
}
rev.add_signoff = do_signoff;
+
+ if (show_progress)
+ progress = start_delayed_progress(_("Generating patches"), total);
while (0 <= --nr) {
int shown;
+ display_progress(progress, total - nr);
commit = list[nr];
rev.nr = total - nr + (start_number - 1);
/* Make the second and subsequent mails replies to the first */
@@ -1815,6 +1825,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (!use_stdout)
fclose(rev.diffopt.file);
}
+ stop_progress(&progress);
free(list);
free(branch_name);
string_list_clear(&extra_to, 0);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index b8514a002..2fc836e33 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -19,6 +19,7 @@
#include "pathspec.h"
#include "run-command.h"
#include "submodule.h"
+#include "submodule-config.h"
static int abbrev;
static int show_deleted;
@@ -30,6 +31,7 @@ static int show_resolve_undo;
static int show_modified;
static int show_killed;
static int show_valid_bit;
+static int show_fsmonitor_bit;
static int line_terminator = '\n';
static int debug_mode;
static int show_eol;
@@ -85,7 +87,8 @@ static const char *get_tag(const struct cache_entry *ce, const char *tag)
{
static char alttag[4];
- if (tag && *tag && show_valid_bit && (ce->ce_flags & CE_VALID)) {
+ if (tag && *tag && ((show_valid_bit && (ce->ce_flags & CE_VALID)) ||
+ (show_fsmonitor_bit && (ce->ce_flags & CE_FSMONITOR_VALID)))) {
memcpy(alttag, tag, 3);
if (isalpha(tag[0])) {
@@ -210,8 +213,6 @@ static void show_submodule(struct repository *superproject,
if (repo_read_index(&submodule) < 0)
die("index file corrupt");
- repo_read_gitmodules(&submodule);
-
show_files(&submodule, dir);
repo_clear(&submodule);
@@ -362,7 +363,7 @@ static void prune_index(struct index_state *istate,
int pos;
unsigned int first, last;
- if (!prefix)
+ if (!prefix || !istate->cache_nr)
return;
pos = index_name_pos(istate, prefix, prefixlen);
if (pos < 0)
@@ -378,8 +379,7 @@ static void prune_index(struct index_state *istate,
}
last = next;
}
- memmove(istate->cache, istate->cache + pos,
- (last - pos) * sizeof(struct cache_entry *));
+ MOVE_ARRAY(istate->cache, istate->cache + pos, last - pos);
istate->cache_nr = last - pos;
}
@@ -517,6 +517,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
N_("identify the file status with tags")),
OPT_BOOL('v', NULL, &show_valid_bit,
N_("use lowercase letters for 'assume unchanged' files")),
+ OPT_BOOL('f', NULL, &show_fsmonitor_bit,
+ N_("use lowercase letters for 'fsmonitor clean' files")),
OPT_BOOL('c', "cached", &show_cached,
N_("show cached files in the output (default)")),
OPT_BOOL('d', "deleted", &show_deleted,
@@ -586,7 +588,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
for (i = 0; i < exclude_list.nr; i++) {
add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
}
- if (show_tag || show_valid_bit) {
+ if (show_tag || show_valid_bit || show_fsmonitor_bit) {
tag_cached = "H ";
tag_unmerged = "M ";
tag_removed = "R ";
@@ -610,9 +612,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
if (require_work_tree && !is_inside_work_tree())
setup_work_tree();
- if (recurse_submodules)
- repo_read_gitmodules(the_repository);
-
if (recurse_submodules &&
(show_stage || show_deleted || show_others || show_unmerged ||
show_killed || show_modified || show_resolve_undo || with_tree))
@@ -678,5 +677,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
return bad ? 1 : 0;
}
+ UNLEAK(dir);
return 0;
}
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 6dbd167d3..3b7600150 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -9,20 +9,20 @@
static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
{
- struct commit_list *result;
+ struct commit_list *result, *r;
result = get_merge_bases_many_dirty(rev[0], rev_nr - 1, rev + 1);
if (!result)
return 1;
- while (result) {
- printf("%s\n", oid_to_hex(&result->item->object.oid));
+ for (r = result; r; r = r->next) {
+ printf("%s\n", oid_to_hex(&r->item->object.oid));
if (!show_all)
- return 0;
- result = result->next;
+ break;
}
+ free_commit_list(result);
return 0;
}
@@ -51,45 +51,47 @@ static struct commit *get_commit_reference(const char *arg)
static int handle_independent(int count, const char **args)
{
- struct commit_list *revs = NULL;
- struct commit_list *result;
+ struct commit_list *revs = NULL, *rev;
int i;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
- result = reduce_heads(revs);
- if (!result)
+ reduce_heads_replace(&revs);
+
+ if (!revs)
return 1;
- while (result) {
- printf("%s\n", oid_to_hex(&result->item->object.oid));
- result = result->next;
- }
+ for (rev = revs; rev; rev = rev->next)
+ printf("%s\n", oid_to_hex(&rev->item->object.oid));
+
+ free_commit_list(revs);
return 0;
}
static int handle_octopus(int count, const char **args, int show_all)
{
struct commit_list *revs = NULL;
- struct commit_list *result;
+ struct commit_list *result, *rev;
int i;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
- result = reduce_heads(get_octopus_merge_bases(revs));
+ result = get_octopus_merge_bases(revs);
+ free_commit_list(revs);
+ reduce_heads_replace(&result);
if (!result)
return 1;
- while (result) {
- printf("%s\n", oid_to_hex(&result->item->object.oid));
+ for (rev = result; rev; rev = rev->next) {
+ printf("%s\n", oid_to_hex(&rev->item->object.oid));
if (!show_all)
- return 0;
- result = result->next;
+ break;
}
+ free_commit_list(result);
return 0;
}
@@ -156,7 +158,7 @@ static int handle_fork_point(int argc, const char **argv)
struct commit_list *bases;
int i, ret = 0;
- switch (dwim_ref(argv[0], strlen(argv[0]), oid.hash, &refname)) {
+ switch (dwim_ref(argv[0], strlen(argv[0]), &oid, &refname)) {
case 0:
die("No such ref: '%s'", argv[0]);
case 1:
diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c
index 684411694..c84c6e05e 100644
--- a/builtin/merge-ours.c
+++ b/builtin/merge-ours.c
@@ -9,26 +9,24 @@
*/
#include "git-compat-util.h"
#include "builtin.h"
+#include "diff.h"
static const char builtin_merge_ours_usage[] =
"git merge-ours <base>... -- HEAD <remote>...";
-static const char *diff_index_args[] = {
- "diff-index", "--quiet", "--cached", "HEAD", "--", NULL
-};
-#define NARGS (ARRAY_SIZE(diff_index_args) - 1)
-
int cmd_merge_ours(int argc, const char **argv, const char *prefix)
{
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(builtin_merge_ours_usage);
/*
- * We need to exit with 2 if the index does not match our HEAD tree,
- * because the current index is what we will be committing as the
- * merge result.
+ * The contents of the current index becomes the tree we
+ * commit. The index must match HEAD, or this merge cannot go
+ * through.
*/
- if (cmd_diff_index(NARGS, diff_index_args, prefix))
+ if (read_cache() < 0)
+ die_errno("read_cache failed");
+ if (index_differs_from("HEAD", NULL, 0))
exit(2);
exit(0);
}
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index bad6735c7..d01ddecf6 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -213,11 +213,11 @@ static void unresolved_directory(const struct traverse_info *info,
newbase = traverse_path(info, p);
-#define ENTRY_SHA1(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid->hash : NULL)
- buf0 = fill_tree_descriptor(t+0, ENTRY_SHA1(n + 0));
- buf1 = fill_tree_descriptor(t+1, ENTRY_SHA1(n + 1));
- buf2 = fill_tree_descriptor(t+2, ENTRY_SHA1(n + 2));
-#undef ENTRY_SHA1
+#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid : NULL)
+ buf0 = fill_tree_descriptor(t + 0, ENTRY_OID(n + 0));
+ buf1 = fill_tree_descriptor(t + 1, ENTRY_OID(n + 1));
+ buf2 = fill_tree_descriptor(t + 2, ENTRY_OID(n + 2));
+#undef ENTRY_OID
merge_trees(t, newbase);
@@ -347,12 +347,12 @@ static void merge_trees(struct tree_desc t[3], const char *base)
static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
{
- unsigned char sha1[20];
+ struct object_id oid;
void *buf;
- if (get_sha1(rev, sha1))
+ if (get_oid(rev, &oid))
die("unknown rev %s", rev);
- buf = fill_tree_descriptor(desc, sha1);
+ buf = fill_tree_descriptor(desc, &oid);
if (!buf)
die("%s is not a tree", rev);
return buf;
diff --git a/builtin/merge.c b/builtin/merge.c
index 900bafdb4..612dd7bfb 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -32,6 +32,7 @@
#include "gpg-interface.h"
#include "sequencer.h"
#include "string-list.h"
+#include "packfile.h"
#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
@@ -70,7 +71,9 @@ static int continue_current_merge;
static int allow_unrelated_histories;
static int show_progress = -1;
static int default_to_upstream = 1;
+static int signoff;
static const char *sign_commit;
+static int verify_msg = 1;
static struct strategy all_strategy[] = {
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -233,6 +236,8 @@ static struct option builtin_merge_options[] = {
{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
+ OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")),
+ OPT_BOOL(0, "verify", &verify_msg, N_("verify commit-msg hook")),
OPT_END()
};
@@ -250,6 +255,7 @@ static int save_state(struct object_id *stash)
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf buffer = STRBUF_INIT;
const char *argv[] = {"stash", "create", NULL};
+ int rc = -1;
cp.argv = argv;
cp.out = -1;
@@ -263,11 +269,14 @@ static int save_state(struct object_id *stash)
if (finish_command(&cp) || len < 0)
die(_("stash failed"));
else if (!len) /* no changes */
- return -1;
+ goto out;
strbuf_setlen(&buffer, buffer.len-1);
if (get_oid(buffer.buf, stash))
die(_("not a valid object: %s"), buffer.buf);
- return 0;
+ rc = 0;
+out:
+ strbuf_release(&buffer);
+ return rc;
}
static void read_empty(unsigned const char *sha1, int verbose)
@@ -396,9 +405,8 @@ static void finish(struct commit *head_commit,
printf(_("No merge message -- not updating HEAD\n"));
else {
const char *argv_gc_auto[] = { "gc", "--auto", NULL };
- update_ref(reflog_message.buf, "HEAD",
- new_head->hash, head->hash, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref(reflog_message.buf, "HEAD", new_head, head,
+ 0, UPDATE_REFS_DIE_ON_ERR);
/*
* We ignore errors in 'gc --auto', since the
* user should see them.
@@ -446,7 +454,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
if (!remote_head)
die(_("'%s' does not point to a commit"), remote);
- if (dwim_ref(remote, strlen(remote), branch_head.hash, &found_ref) > 0) {
+ if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref) > 0) {
if (starts_with(found_ref, "refs/heads/")) {
strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
oid_to_hex(&branch_head), remote);
@@ -537,7 +545,7 @@ static void parse_branch_merge_options(char *bmo)
die(_("Bad branch.%s.mergeoptions string: %s"), branch,
split_cmdline_strerror(argc));
REALLOC_ARRAY(argv, argc + 2);
- memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
+ MOVE_ARRAY(argv + 1, argv, argc + 1);
argc++;
argv[0] = "branch.*.mergeoptions";
parse_options(argc, argv, NULL, builtin_merge_options,
@@ -566,7 +574,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
else if (!strcmp(k, "merge.renormalize"))
option_renormalize = git_config_bool(k, v);
else if (!strcmp(k, "merge.ff")) {
- int boolval = git_config_maybe_bool(k, v);
+ int boolval = git_parse_maybe_bool(v);
if (0 <= boolval) {
fast_forward = boolval ? FF_ALLOW : FF_NO;
} else if (v && !strcmp(v, "only")) {
@@ -756,13 +764,19 @@ N_("Please enter a commit message to explain why this merge is necessary,\n"
"Lines starting with '%c' will be ignored, and an empty message aborts\n"
"the commit.\n");
+static void write_merge_heads(struct commit_list *);
static void prepare_to_commit(struct commit_list *remoteheads)
{
struct strbuf msg = STRBUF_INIT;
strbuf_addbuf(&msg, &merge_msg);
strbuf_addch(&msg, '\n');
+ if (squash)
+ BUG("the control must not reach here under --squash");
if (0 < option_edit)
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
+ if (signoff)
+ append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0);
+ write_merge_heads(remoteheads);
write_file_buf(git_path_merge_msg(), msg.buf, msg.len);
if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
git_path_merge_msg(), "merge", NULL))
@@ -771,6 +785,12 @@ static void prepare_to_commit(struct commit_list *remoteheads)
if (launch_editor(git_path_merge_msg(), NULL, NULL))
abort_commit(remoteheads, NULL);
}
+
+ if (verify_msg && run_commit_hook(0 < option_edit, get_index_file(),
+ "commit-msg",
+ git_path_merge_msg(), NULL))
+ abort_commit(remoteheads, NULL);
+
read_merge_msg(&msg);
strbuf_stripspace(&msg, 0 < option_edit);
if (!msg.len)
@@ -904,7 +924,7 @@ static int setup_with_upstream(const char ***argv)
return i;
}
-static void write_merge_state(struct commit_list *remoteheads)
+static void write_merge_heads(struct commit_list *remoteheads)
{
struct commit_list *j;
struct strbuf buf = STRBUF_INIT;
@@ -920,13 +940,19 @@ static void write_merge_state(struct commit_list *remoteheads)
strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
}
write_file_buf(git_path_merge_head(), buf.buf, buf.len);
- strbuf_addch(&merge_msg, '\n');
- write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len);
strbuf_reset(&buf);
if (fast_forward == FF_NO)
strbuf_addstr(&buf, "no-ff");
write_file_buf(git_path_merge_mode(), buf.buf, buf.len);
+ strbuf_release(&buf);
+}
+
+static void write_merge_state(struct commit_list *remoteheads)
+{
+ write_merge_heads(remoteheads);
+ strbuf_addch(&merge_msg, '\n');
+ write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len);
}
static int default_edit_option(void)
@@ -940,7 +966,7 @@ static int default_edit_option(void)
return 0;
if (e) {
- int v = git_config_maybe_bool(name, e);
+ int v = git_parse_maybe_bool(e);
if (v < 0)
die(_("Bad value '%s' in environment '%s'"), e, name);
return v;
@@ -972,6 +998,7 @@ static struct commit_list *reduce_parents(struct commit *head_commit,
/* Find what parents to record by checking independent ones. */
parents = reduce_heads(remoteheads);
+ free_commit_list(remoteheads);
remoteheads = NULL;
remotes = &remoteheads;
@@ -1116,9 +1143,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* Check if we are _not_ on a detached HEAD, i.e. if there is a
* current branch.
*/
- branch = branch_to_free = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
- if (branch && starts_with(branch, "refs/heads/"))
- branch += 11;
+ branch = branch_to_free = resolve_refdup("HEAD", 0, &head_oid, NULL);
+ if (branch)
+ skip_prefix(branch, "refs/heads/", &branch);
if (!branch || is_null_oid(&head_oid))
head_commit = NULL;
else
@@ -1234,8 +1261,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
die(_("Can merge only exactly one commit into empty head"));
remote_head_oid = &remoteheads->item->object.oid;
read_empty(remote_head_oid->hash, 0);
- update_ref("initial pull", "HEAD", remote_head_oid->hash,
- NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+ update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
goto done;
}
@@ -1330,8 +1357,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
free(list);
}
- update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.oid.hash,
- NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+ update_ref("updating ORIG_HEAD", "ORIG_HEAD",
+ &head_commit->object.oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
if (remoteheads && !common) {
/* No common ancestors found. */
@@ -1345,7 +1372,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* If head can reach all the merge then we are up to date.
* but first the most common case of merging one remote.
*/
- finish_up_to_date(_("Already up-to-date."));
+ finish_up_to_date(_("Already up to date."));
goto done;
} else if (fast_forward != FF_NO && !remoteheads->next &&
!common->next &&
@@ -1428,7 +1455,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
}
}
if (up_to_date) {
- finish_up_to_date(_("Already up-to-date. Yeeah!"));
+ finish_up_to_date(_("Already up to date. Yeeah!"));
goto done;
}
}
diff --git a/builtin/mv.c b/builtin/mv.c
index dcf6736b5..ffdd5f01a 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -81,7 +81,7 @@ static void prepare_move_submodule(const char *src, int first,
struct strbuf submodule_dotgit = STRBUF_INIT;
if (!S_ISGITLINK(active_cache[first]->ce_mode))
die(_("Directory %s is in index and no submodule?"), src);
- if (!is_staging_gitmodules_ok())
+ if (!is_staging_gitmodules_ok(&the_index))
die(_("Please stage your changes to .gitmodules or stash them to proceed"));
strbuf_addf(&submodule_dotgit, "%s/.git", src);
*submodule_gitfile = read_gitfile(submodule_dotgit.buf);
@@ -131,7 +131,6 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
struct stat st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
- gitmodules_config();
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_mv_options,
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index c41ea7c2a..9e088ebd1 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -253,7 +253,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
struct commit *commit = (struct commit *)o;
int from_tag = starts_with(path, "refs/tags/");
- if (taggerdate == ULONG_MAX)
+ if (taggerdate == TIME_MAX)
taggerdate = ((struct commit *)o)->date;
path = name_ref_abbrev(path, can_abbreviate_output);
name_rev(commit, xstrdup(path), taggerdate, 0, 0,
@@ -494,5 +494,6 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
always, allow_undefined, data.name_only);
}
+ UNLEAK(revs);
return 0;
}
diff --git a/builtin/notes.c b/builtin/notes.c
index 77573cf1e..a2a542f82 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -328,6 +328,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
} else {
finish_copy_notes_for_rewrite(c, msg);
}
+ strbuf_release(&buf);
return ret;
}
@@ -456,7 +457,7 @@ static int add(int argc, const char **argv, const char *prefix)
oid_to_hex(&object));
}
- prepare_note_data(&object, &d, note->hash);
+ prepare_note_data(&object, &d, note ? note->hash : NULL);
if (d.buf.len || allow_empty) {
write_note_data(&d, new_note.hash);
if (add_note(t, &object, &new_note, combine_notes_overwrite))
@@ -685,7 +686,7 @@ static int merge_abort(struct notes_merge_options *o)
if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL"));
- if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NODEREF))
+ if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NO_DEREF))
ret += error(_("failed to delete ref NOTES_MERGE_REF"));
if (notes_merge_abort(o))
ret += error(_("failed to remove 'git notes merge' worktree"));
@@ -723,7 +724,7 @@ static int merge_commit(struct notes_merge_options *o)
init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
o->local_ref = local_ref_to_free =
- resolve_refdup("NOTES_MERGE_REF", 0, oid.hash, NULL);
+ resolve_refdup("NOTES_MERGE_REF", 0, &oid, NULL);
if (!o->local_ref)
die(_("failed to resolve NOTES_MERGE_REF"));
@@ -735,8 +736,8 @@ static int merge_commit(struct notes_merge_options *o)
format_commit_message(partial, "%s", &msg, &pretty_ctx);
strbuf_trim(&msg);
strbuf_insert(&msg, 0, "notes: ", 7);
- update_ref(msg.buf, o->local_ref, oid.hash,
- is_null_oid(&parent_oid) ? NULL : parent_oid.hash,
+ update_ref(msg.buf, o->local_ref, &oid,
+ is_null_oid(&parent_oid) ? NULL : &parent_oid,
0, UPDATE_REFS_DIE_ON_ERR);
free_notes(t);
@@ -849,12 +850,12 @@ static int merge(int argc, const char **argv, const char *prefix)
if (result >= 0) /* Merge resulted (trivially) in result_oid */
/* Update default notes ref with new commit */
- update_ref(msg.buf, default_notes_ref(), result_oid.hash, NULL,
- 0, UPDATE_REFS_DIE_ON_ERR);
+ update_ref(msg.buf, default_notes_ref(), &result_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
else { /* Merge has unresolved conflicts */
const struct worktree *wt;
/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
- update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_oid.hash, NULL,
+ update_ref(msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL,
0, UPDATE_REFS_DIE_ON_ERR);
/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
@@ -864,10 +865,10 @@ static int merge(int argc, const char **argv, const char *prefix)
if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
die(_("failed to store link to current notes ref (%s)"),
default_notes_ref());
- printf(_("Automatic notes merge failed. Fix conflicts in %s and "
- "commit the result with 'git notes merge --commit', or "
- "abort the merge with 'git notes merge --abort'.\n"),
- git_path(NOTES_MERGE_WORKTREE));
+ fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
+ "and commit the result with 'git notes merge --commit', "
+ "or abort the merge with 'git notes merge --abort'.\n"),
+ git_path(NOTES_MERGE_WORKTREE));
}
free_notes(t);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f4a8441fe..631de2876 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -25,6 +25,7 @@
#include "sha1-array.h"
#include "argv-array.h"
#include "mru.h"
+#include "packfile.h"
static const char *pack_usage[] = {
N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),
@@ -150,7 +151,7 @@ static unsigned long do_compress(void **pptr, unsigned long size)
}
static unsigned long write_large_blob_data(struct git_istream *st, struct sha1file *f,
- const unsigned char *sha1)
+ const struct object_id *oid)
{
git_zstream stream;
unsigned char ibuf[1024 * 16];
@@ -164,7 +165,7 @@ static unsigned long write_large_blob_data(struct git_istream *st, struct sha1fi
int zret = Z_OK;
readlen = read_istream(st, ibuf, sizeof(ibuf));
if (readlen == -1)
- die(_("unable to read %s"), sha1_to_hex(sha1));
+ die(_("unable to read %s"), oid_to_hex(oid));
stream.next_in = ibuf;
stream.avail_in = readlen;
@@ -338,7 +339,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent
sha1write(f, header, hdrlen);
}
if (st) {
- datalen = write_large_blob_data(st, f, entry->idx.oid.hash);
+ datalen = write_large_blob_data(st, f, &entry->idx.oid);
close_istream(st);
} else {
sha1write(f, buf, datalen);
@@ -556,13 +557,13 @@ static enum write_one_status write_one(struct sha1file *f,
static int mark_tagged(const char *path, const struct object_id *oid, int flag,
void *cb_data)
{
- unsigned char peeled[20];
+ struct object_id peeled;
struct object_entry *entry = packlist_find(&to_pack, oid->hash, NULL);
if (entry)
entry->tagged = 1;
- if (!peel_ref(path, peeled)) {
- entry = packlist_find(&to_pack, peeled, NULL);
+ if (!peel_ref(path, &peeled)) {
+ entry = packlist_find(&to_pack, peeled.hash, NULL);
if (entry)
entry->tagged = 1;
}
@@ -791,7 +792,7 @@ static void write_pack_file(void)
write_order = compute_write_order();
do {
- unsigned char sha1[20];
+ struct object_id oid;
char *pack_tmp_name = NULL;
if (pack_to_stdout)
@@ -822,13 +823,13 @@ static void write_pack_file(void)
* If so, rewrite it like in fast-import
*/
if (pack_to_stdout) {
- sha1close(f, sha1, CSUM_CLOSE);
+ sha1close(f, oid.hash, CSUM_CLOSE);
} else if (nr_written == nr_remaining) {
- sha1close(f, sha1, CSUM_FSYNC);
+ sha1close(f, oid.hash, CSUM_FSYNC);
} else {
- int fd = sha1close(f, sha1, 0);
- fixup_pack_header_footer(fd, sha1, pack_tmp_name,
- nr_written, sha1, offset);
+ int fd = sha1close(f, oid.hash, 0);
+ fixup_pack_header_footer(fd, oid.hash, pack_tmp_name,
+ nr_written, oid.hash, offset);
close(fd);
if (write_bitmap_index) {
warning(_(no_split_warning));
@@ -862,16 +863,16 @@ static void write_pack_file(void)
strbuf_addf(&tmpname, "%s-", base_name);
if (write_bitmap_index) {
- bitmap_writer_set_checksum(sha1);
+ bitmap_writer_set_checksum(oid.hash);
bitmap_writer_build_type_index(written_list, nr_written);
}
finish_tmp_packfile(&tmpname, pack_tmp_name,
written_list, nr_written,
- &pack_idx_opts, sha1);
+ &pack_idx_opts, oid.hash);
if (write_bitmap_index) {
- strbuf_addf(&tmpname, "%s.bitmap", sha1_to_hex(sha1));
+ strbuf_addf(&tmpname, "%s.bitmap", oid_to_hex(&oid));
stop_progress(&progress_state);
@@ -886,7 +887,7 @@ static void write_pack_file(void)
strbuf_release(&tmpname);
free(pack_tmp_name);
- puts(sha1_to_hex(sha1));
+ puts(oid_to_hex(&oid));
}
/* mark written objects as written to previous pack */
@@ -927,13 +928,13 @@ static int no_try_delta(const char *path)
* found the item, since that saves us from having to look it up again a
* few lines later when we want to add the new entry.
*/
-static int have_duplicate_entry(const unsigned char *sha1,
+static int have_duplicate_entry(const struct object_id *oid,
int exclude,
uint32_t *index_pos)
{
struct object_entry *entry;
- entry = packlist_find(&to_pack, sha1, index_pos);
+ entry = packlist_find(&to_pack, oid->hash, index_pos);
if (!entry)
return 0;
@@ -989,7 +990,7 @@ static int want_found_object(int exclude, struct packed_git *p)
* function finds if there is any pack that has the object and returns the pack
* and its offset in these variables.
*/
-static int want_object_in_pack(const unsigned char *sha1,
+static int want_object_in_pack(const struct object_id *oid,
int exclude,
struct packed_git **found_pack,
off_t *found_offset)
@@ -997,7 +998,7 @@ static int want_object_in_pack(const unsigned char *sha1,
struct mru_entry *entry;
int want;
- if (!exclude && local && has_loose_object_nonlocal(sha1))
+ if (!exclude && local && has_loose_object_nonlocal(oid->hash))
return 0;
/*
@@ -1011,14 +1012,14 @@ static int want_object_in_pack(const unsigned char *sha1,
return want;
}
- for (entry = packed_git_mru->head; entry; entry = entry->next) {
+ for (entry = packed_git_mru.head; entry; entry = entry->next) {
struct packed_git *p = entry->item;
off_t offset;
if (p == *found_pack)
offset = *found_offset;
else
- offset = find_pack_entry_one(sha1, p);
+ offset = find_pack_entry_one(oid->hash, p);
if (offset) {
if (!*found_pack) {
@@ -1029,7 +1030,7 @@ static int want_object_in_pack(const unsigned char *sha1,
}
want = want_found_object(exclude, p);
if (!exclude && want > 0)
- mru_mark(packed_git_mru, entry);
+ mru_mark(&packed_git_mru, entry);
if (want != -1)
return want;
}
@@ -1038,7 +1039,7 @@ static int want_object_in_pack(const unsigned char *sha1,
return 1;
}
-static void create_object_entry(const unsigned char *sha1,
+static void create_object_entry(const struct object_id *oid,
enum object_type type,
uint32_t hash,
int exclude,
@@ -1049,7 +1050,7 @@ static void create_object_entry(const unsigned char *sha1,
{
struct object_entry *entry;
- entry = packlist_alloc(&to_pack, sha1, index_pos);
+ entry = packlist_alloc(&to_pack, oid->hash, index_pos);
entry->hash = hash;
if (type)
entry->type = type;
@@ -1069,17 +1070,17 @@ static const char no_closure_warning[] = N_(
"disabling bitmap writing, as some objects are not being packed"
);
-static int add_object_entry(const unsigned char *sha1, enum object_type type,
+static int add_object_entry(const struct object_id *oid, enum object_type type,
const char *name, int exclude)
{
struct packed_git *found_pack = NULL;
off_t found_offset = 0;
uint32_t index_pos;
- if (have_duplicate_entry(sha1, exclude, &index_pos))
+ if (have_duplicate_entry(oid, exclude, &index_pos))
return 0;
- if (!want_object_in_pack(sha1, exclude, &found_pack, &found_offset)) {
+ if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) {
/* The pack is missing an object, so it will not have closure */
if (write_bitmap_index) {
warning(_(no_closure_warning));
@@ -1088,7 +1089,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
return 0;
}
- create_object_entry(sha1, type, pack_name_hash(name),
+ create_object_entry(oid, type, pack_name_hash(name),
exclude, name && no_try_delta(name),
index_pos, found_pack, found_offset);
@@ -1096,27 +1097,27 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
return 1;
}
-static int add_object_entry_from_bitmap(const unsigned char *sha1,
+static int add_object_entry_from_bitmap(const struct object_id *oid,
enum object_type type,
int flags, uint32_t name_hash,
struct packed_git *pack, off_t offset)
{
uint32_t index_pos;
- if (have_duplicate_entry(sha1, 0, &index_pos))
+ if (have_duplicate_entry(oid, 0, &index_pos))
return 0;
- if (!want_object_in_pack(sha1, 0, &pack, &offset))
+ if (!want_object_in_pack(oid, 0, &pack, &offset))
return 0;
- create_object_entry(sha1, type, name_hash, 0, 0, index_pos, pack, offset);
+ create_object_entry(oid, type, name_hash, 0, 0, index_pos, pack, offset);
display_progress(progress_state, nr_result);
return 1;
}
struct pbase_tree_cache {
- unsigned char sha1[20];
+ struct object_id oid;
int ref;
int temporary;
void *tree_data;
@@ -1124,9 +1125,9 @@ struct pbase_tree_cache {
};
static struct pbase_tree_cache *(pbase_tree_cache[256]);
-static int pbase_tree_cache_ix(const unsigned char *sha1)
+static int pbase_tree_cache_ix(const struct object_id *oid)
{
- return sha1[0] % ARRAY_SIZE(pbase_tree_cache);
+ return oid->hash[0] % ARRAY_SIZE(pbase_tree_cache);
}
static int pbase_tree_cache_ix_incr(int ix)
{
@@ -1143,14 +1144,14 @@ static struct pbase_tree {
struct pbase_tree_cache pcache;
} *pbase_tree;
-static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
+static struct pbase_tree_cache *pbase_tree_get(const struct object_id *oid)
{
struct pbase_tree_cache *ent, *nent;
void *data;
unsigned long size;
enum object_type type;
int neigh;
- int my_ix = pbase_tree_cache_ix(sha1);
+ int my_ix = pbase_tree_cache_ix(oid);
int available_ix = -1;
/* pbase-tree-cache acts as a limited hashtable.
@@ -1159,7 +1160,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
*/
for (neigh = 0; neigh < 8; neigh++) {
ent = pbase_tree_cache[my_ix];
- if (ent && !hashcmp(ent->sha1, sha1)) {
+ if (ent && !oidcmp(&ent->oid, oid)) {
ent->ref++;
return ent;
}
@@ -1175,7 +1176,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
/* Did not find one. Either we got a bogus request or
* we need to read and perhaps cache.
*/
- data = read_sha1_file(sha1, &type, &size);
+ data = read_sha1_file(oid->hash, &type, &size);
if (!data)
return NULL;
if (type != OBJ_TREE) {
@@ -1201,7 +1202,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
free(ent->tree_data);
nent = ent;
}
- hashcpy(nent->sha1, sha1);
+ oidcpy(&nent->oid, oid);
nent->tree_data = data;
nent->tree_size = size;
nent->ref = 1;
@@ -1246,7 +1247,7 @@ static void add_pbase_object(struct tree_desc *tree,
if (cmp < 0)
return;
if (name[cmplen] != '/') {
- add_object_entry(entry.oid->hash,
+ add_object_entry(entry.oid,
object_type(entry.mode),
fullname, 1);
return;
@@ -1257,7 +1258,7 @@ static void add_pbase_object(struct tree_desc *tree,
const char *down = name+cmplen+1;
int downlen = name_cmp_len(down);
- tree = pbase_tree_get(entry.oid->hash);
+ tree = pbase_tree_get(entry.oid);
if (!tree)
return;
init_tree_desc(&sub, tree->tree_data, tree->tree_size);
@@ -1276,7 +1277,7 @@ static int done_pbase_path_pos(unsigned hash)
int lo = 0;
int hi = done_pbase_paths_num;
while (lo < hi) {
- int mi = (hi + lo) / 2;
+ int mi = lo + (hi - lo) / 2;
if (done_pbase_paths[mi] == hash)
return mi;
if (done_pbase_paths[mi] < hash)
@@ -1289,7 +1290,7 @@ static int done_pbase_path_pos(unsigned hash)
static int check_pbase_path(unsigned hash)
{
- int pos = (!done_pbase_paths) ? -1 : done_pbase_path_pos(hash);
+ int pos = done_pbase_path_pos(hash);
if (0 <= pos)
return 1;
pos = -pos - 1;
@@ -1298,9 +1299,8 @@ static int check_pbase_path(unsigned hash)
done_pbase_paths_alloc);
done_pbase_paths_num++;
if (pos < done_pbase_paths_num)
- memmove(done_pbase_paths + pos + 1,
- done_pbase_paths + pos,
- (done_pbase_paths_num - pos - 1) * sizeof(unsigned));
+ MOVE_ARRAY(done_pbase_paths + pos + 1, done_pbase_paths + pos,
+ done_pbase_paths_num - pos - 1);
done_pbase_paths[pos] = hash;
return 0;
}
@@ -1317,7 +1317,7 @@ static void add_preferred_base_object(const char *name)
cmplen = name_cmp_len(name);
for (it = pbase_tree; it; it = it->next) {
if (cmplen == 0) {
- add_object_entry(it->pcache.sha1, OBJ_TREE, NULL, 1);
+ add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1);
}
else {
struct tree_desc tree;
@@ -1327,22 +1327,22 @@ static void add_preferred_base_object(const char *name)
}
}
-static void add_preferred_base(unsigned char *sha1)
+static void add_preferred_base(struct object_id *oid)
{
struct pbase_tree *it;
void *data;
unsigned long size;
- unsigned char tree_sha1[20];
+ struct object_id tree_oid;
if (window <= num_preferred_base++)
return;
- data = read_object_with_reference(sha1, tree_type, &size, tree_sha1);
+ data = read_object_with_reference(oid->hash, tree_type, &size, tree_oid.hash);
if (!data)
return;
for (it = pbase_tree; it; it = it->next) {
- if (!hashcmp(it->pcache.sha1, tree_sha1)) {
+ if (!oidcmp(&it->pcache.oid, &tree_oid)) {
free(data);
return;
}
@@ -1352,7 +1352,7 @@ static void add_preferred_base(unsigned char *sha1)
it->next = pbase_tree;
pbase_tree = it;
- hashcpy(it->pcache.sha1, tree_sha1);
+ oidcpy(&it->pcache.oid, &tree_oid);
it->pcache.tree_data = data;
it->pcache.tree_size = size;
}
@@ -2171,7 +2171,10 @@ static void *threaded_find_deltas(void *arg)
{
struct thread_params *me = arg;
+ progress_lock();
while (me->remaining) {
+ progress_unlock();
+
find_deltas(me->list, &me->remaining,
me->window, me->depth, me->processed);
@@ -2193,7 +2196,10 @@ static void *threaded_find_deltas(void *arg)
pthread_cond_wait(&me->cond, &me->mutex);
me->data_ready = 0;
pthread_mutex_unlock(&me->mutex);
+
+ progress_lock();
}
+ progress_unlock();
/* leave ->working 1 so that this doesn't get more work assigned */
return NULL;
}
@@ -2351,7 +2357,7 @@ static void add_tag_chain(const struct object_id *oid)
die("unable to pack objects reachable from tag %s",
oid_to_hex(oid));
- add_object_entry(tag->object.oid.hash, OBJ_TAG, NULL, 0);
+ add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0);
if (tag->tagged->type != OBJ_TAG)
return;
@@ -2365,7 +2371,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag,
struct object_id peeled;
if (starts_with(path, "refs/tags/") && /* is a tag? */
- !peel_ref(path, peeled.hash) && /* peelable? */
+ !peel_ref(path, &peeled) && /* peelable? */
packlist_find(&to_pack, peeled.hash, NULL)) /* object packed? */
add_tag_chain(oid);
return 0;
@@ -2499,8 +2505,9 @@ static int git_pack_config(const char *k, const char *v, void *cb)
static void read_object_list_from_stdin(void)
{
- char line[40 + 1 + PATH_MAX + 2];
- unsigned char sha1[20];
+ char line[GIT_MAX_HEXSZ + 1 + PATH_MAX + 2];
+ struct object_id oid;
+ const char *p;
for (;;) {
if (!fgets(line, sizeof(line), stdin)) {
@@ -2514,17 +2521,17 @@ static void read_object_list_from_stdin(void)
continue;
}
if (line[0] == '-') {
- if (get_sha1_hex(line+1, sha1))
- die("expected edge sha1, got garbage:\n %s",
+ if (get_oid_hex(line+1, &oid))
+ die("expected edge object ID, got garbage:\n %s",
line);
- add_preferred_base(sha1);
+ add_preferred_base(&oid);
continue;
}
- if (get_sha1_hex(line, sha1))
- die("expected sha1, got garbage:\n %s", line);
+ if (parse_oid_hex(line, &oid, &p))
+ die("expected object ID, got garbage:\n %s", line);
- add_preferred_base_object(line+41);
- add_object_entry(sha1, 0, line+41, 0);
+ add_preferred_base_object(p + 1);
+ add_object_entry(&oid, 0, p + 1, 0);
}
}
@@ -2532,7 +2539,7 @@ static void read_object_list_from_stdin(void)
static void show_commit(struct commit *commit, void *data)
{
- add_object_entry(commit->object.oid.hash, OBJ_COMMIT, NULL, 0);
+ add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0);
commit->object.flags |= OBJECT_ADDED;
if (write_bitmap_index)
@@ -2542,13 +2549,13 @@ static void show_commit(struct commit *commit, void *data)
static void show_object(struct object *obj, const char *name, void *data)
{
add_preferred_base_object(name);
- add_object_entry(obj->oid.hash, obj->type, name, 0);
+ add_object_entry(&obj->oid, obj->type, name, 0);
obj->flags |= OBJECT_ADDED;
}
static void show_edge(struct commit *commit)
{
- add_preferred_base(commit->object.oid.hash);
+ add_preferred_base(&commit->object.oid);
}
struct in_pack_object {
@@ -2557,8 +2564,8 @@ struct in_pack_object {
};
struct in_pack {
- int alloc;
- int nr;
+ unsigned int alloc;
+ unsigned int nr;
struct in_pack_object *array;
};
@@ -2595,7 +2602,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
memset(&in_pack, 0, sizeof(in_pack));
for (p = packed_git; p; p = p->next) {
- const unsigned char *sha1;
+ struct object_id oid;
struct object *o;
if (!p->pack_local || p->pack_keep)
@@ -2608,8 +2615,8 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
in_pack.alloc);
for (i = 0; i < p->num_objects; i++) {
- sha1 = nth_packed_object_sha1(p, i);
- o = lookup_unknown_object(sha1);
+ nth_packed_object_oid(&oid, p, i);
+ o = lookup_unknown_object(oid.hash);
if (!(o->flags & OBJECT_ADDED))
mark_in_pack_object(o, p, &in_pack);
o->flags |= OBJECT_ADDED;
@@ -2620,7 +2627,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
QSORT(in_pack.array, in_pack.nr, ofscmp);
for (i = 0; i < in_pack.nr; i++) {
struct object *o = in_pack.array[i].object;
- add_object_entry(o->oid.hash, o->type, "", 0);
+ add_object_entry(&o->oid, o->type, "", 0);
}
}
free(in_pack.array);
@@ -2636,7 +2643,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,
return 0;
}
- add_object_entry(oid->hash, type, "", 0);
+ add_object_entry(oid, type, "", 0);
return 0;
}
@@ -2652,7 +2659,7 @@ static void add_unreachable_loose_objects(void)
NULL, NULL, NULL);
}
-static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
+static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid)
{
static struct packed_git *last_found = (void *)1;
struct packed_git *p;
@@ -2661,7 +2668,7 @@ static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
while (p) {
if ((!p->pack_local || p->pack_keep) &&
- find_pack_entry_one(sha1, p)) {
+ find_pack_entry_one(oid->hash, p)) {
last_found = p;
return 1;
}
@@ -2712,7 +2719,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
for (i = 0; i < p->num_objects; i++) {
nth_packed_object_oid(&oid, p, i);
if (!packlist_find(&to_pack, oid.hash, NULL) &&
- !has_sha1_pack_kept_or_nonlocal(oid.hash) &&
+ !has_sha1_pack_kept_or_nonlocal(&oid) &&
!loosened_object_can_be_discarded(&oid, p->mtime))
if (force_object_loose(oid.hash, p->mtime))
die("unable to force loose object");
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index cb1df1c76..aaa813632 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -7,6 +7,7 @@
*/
#include "builtin.h"
+#include "packfile.h"
#define BLKSIZE 512
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index ac978ad40..419238171 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -2,6 +2,7 @@
#include "cache.h"
#include "progress.h"
#include "parse-options.h"
+#include "packfile.h"
static const char * const prune_packed_usage[] = {
N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
@@ -37,8 +38,7 @@ static int prune_object(const struct object_id *oid, const char *path,
void prune_packed_objects(int opts)
{
if (opts & PRUNE_PACKED_VERBOSE)
- progress = start_progress_delay(_("Removing duplicate objects"),
- 256, 95, 2);
+ progress = start_delayed_progress(_("Removing duplicate objects"), 256);
for_each_loose_file_in_objdir(get_object_directory(),
prune_object, NULL, prune_subdir, &opts);
diff --git a/builtin/prune.c b/builtin/prune.c
index c37869054..cddabf26a 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -138,7 +138,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
if (show_progress == -1)
show_progress = isatty(2);
if (show_progress)
- progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2);
+ progress = start_delayed_progress(_("Checking connectivity"), 0);
mark_reachable_objects(&revs, 1, expire, progress);
stop_progress(&progress);
diff --git a/builtin/pull.c b/builtin/pull.c
index 9b86e519b..166b777ed 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -39,7 +39,7 @@ enum rebase_type {
static enum rebase_type parse_config_rebase(const char *key, const char *value,
int fatal)
{
- int v = git_config_maybe_bool("pull.rebase", value);
+ int v = git_parse_maybe_bool(value);
if (!v)
return REBASE_FALSE;
@@ -86,6 +86,7 @@ static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static enum rebase_type opt_rebase = -1;
static char *opt_diffstat;
static char *opt_log;
+static char *opt_signoff;
static char *opt_squash;
static char *opt_commit;
static char *opt_edit;
@@ -112,6 +113,8 @@ static char *opt_depth;
static char *opt_unshallow;
static char *opt_update_shallow;
static char *opt_refmap;
+static char *opt_ipv4;
+static char *opt_ipv6;
static struct option pull_options[] = {
/* Shared options */
@@ -142,6 +145,9 @@ static struct option pull_options[] = {
OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
N_("add (at most <n>) entries from shortlog to merge commit message"),
PARSE_OPT_OPTARG),
+ OPT_PASSTHRU(0, "signoff", &opt_signoff, NULL,
+ N_("add Signed-off-by:"),
+ PARSE_OPT_OPTARG),
OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
N_("create a single commit instead of doing a merge"),
PARSE_OPT_NOARG),
@@ -214,6 +220,12 @@ static struct option pull_options[] = {
OPT_PASSTHRU(0, "refmap", &opt_refmap, N_("refmap"),
N_("specify fetch refmap"),
PARSE_OPT_NONEG),
+ OPT_PASSTHRU('4', "ipv4", &opt_ipv4, NULL,
+ N_("use IPv4 addresses only"),
+ PARSE_OPT_NOARG),
+ OPT_PASSTHRU('6', "ipv6", &opt_ipv6, NULL,
+ N_("use IPv6 addresses only"),
+ PARSE_OPT_NOARG),
OPT_END()
};
@@ -274,7 +286,7 @@ static const char *config_get_ff(void)
if (git_config_get_value("pull.ff", &value))
return NULL;
- switch (git_config_maybe_bool("pull.ff", value)) {
+ switch (git_parse_maybe_bool(value)) {
case 0:
return "--no-ff";
case 1:
@@ -325,6 +337,10 @@ static int git_pull_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "rebase.autostash")) {
config_autostash = git_config_bool(var, value);
return 0;
+ } else if (!strcmp(var, "submodule.recurse")) {
+ recurse_submodules = git_config_bool(var, value) ?
+ RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
+ return 0;
}
return git_default_config(var, value, cb);
}
@@ -514,6 +530,10 @@ static int run_fetch(const char *repo, const char **refspecs)
argv_array_push(&args, opt_update_shallow);
if (opt_refmap)
argv_array_push(&args, opt_refmap);
+ if (opt_ipv4)
+ argv_array_push(&args, opt_ipv4);
+ if (opt_ipv6)
+ argv_array_push(&args, opt_ipv6);
if (repo) {
argv_array_push(&args, repo);
@@ -540,7 +560,7 @@ static int pull_into_void(const struct object_id *merge_head,
if (checkout_fast_forward(&empty_tree_oid, merge_head, 0))
return 1;
- if (update_ref("initial pull", "HEAD", merge_head->hash, curr_head->hash, 0, UPDATE_REFS_DIE_ON_ERR))
+ if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
return 1;
return 0;
@@ -590,6 +610,8 @@ static int run_merge(void)
argv_array_push(&args, opt_diffstat);
if (opt_log)
argv_array_push(&args, opt_log);
+ if (opt_signoff)
+ argv_array_push(&args, opt_signoff);
if (opt_squash)
argv_array_push(&args, opt_squash);
if (opt_commit)
@@ -741,12 +763,15 @@ static int get_octopus_merge_base(struct object_id *merge_base,
if (!is_null_oid(fork_point))
commit_list_insert(lookup_commit_reference(fork_point), &revs);
- result = reduce_heads(get_octopus_merge_bases(revs));
+ result = get_octopus_merge_bases(revs);
free_commit_list(revs);
+ reduce_heads_replace(&result);
+
if (!result)
return 1;
oidcpy(merge_base, &result->item->object.oid);
+ free_commit_list(result);
return 0;
}
@@ -815,6 +840,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
+ git_config(git_pull_config, NULL);
+
argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
parse_repo_refspecs(argc, argv, &repo, &refspecs);
@@ -825,8 +852,6 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (opt_rebase < 0)
opt_rebase = config_get_rebase();
- git_config(git_pull_config, NULL);
-
if (read_cache_unmerged())
die_resolve_conflict("pull");
diff --git a/builtin/push.c b/builtin/push.c
index 03846e837..1c28427d8 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -32,6 +32,8 @@ static const char **refspec;
static int refspec_nr;
static int refspec_alloc;
+static struct string_list push_options_config = STRING_LIST_INIT_DUP;
+
static void add_refspec(const char *ref)
{
refspec_nr++;
@@ -481,7 +483,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
} else if (!strcmp(k, "push.gpgsign")) {
const char *value;
if (!git_config_get_value("push.gpgsign", &value)) {
- switch (git_config_maybe_bool("push.gpgsign", value)) {
+ switch (git_parse_maybe_bool(value)) {
case 0:
set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_NEVER);
break;
@@ -503,6 +505,15 @@ static int git_push_config(const char *k, const char *v, void *cb)
int val = git_config_bool(k, v) ?
RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
recurse_submodules = val;
+ } else if (!strcmp(k, "push.pushoption")) {
+ if (!v)
+ return config_error_nonbool(k);
+ else
+ if (!*v)
+ string_list_clear(&push_options_config, 0);
+ else
+ string_list_append(&push_options_config, v);
+ return 0;
}
return git_default_config(k, v, NULL);
@@ -515,7 +526,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
int push_cert = -1;
int rc;
const char *repo = NULL; /* default repository */
- struct string_list push_options = STRING_LIST_INIT_DUP;
+ struct string_list push_options_cmdline = STRING_LIST_INIT_DUP;
+ struct string_list *push_options;
const struct string_list_item *item;
struct option options[] = {
@@ -551,7 +563,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
PARSE_OPT_OPTARG, option_parse_push_signed },
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
- OPT_STRING_LIST('o', "push-option", &push_options, N_("server-specific"), N_("option to transmit")),
+ OPT_STRING_LIST('o', "push-option", &push_options_cmdline, N_("server-specific"), N_("option to transmit")),
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
@@ -562,6 +574,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
packet_trace_identity("push");
git_config(git_push_config, &flags);
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
+ push_options = (push_options_cmdline.nr
+ ? &push_options_cmdline
+ : &push_options_config);
set_push_cert_flags(&flags, push_cert);
if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
@@ -584,12 +599,13 @@ int cmd_push(int argc, const char **argv, const char *prefix)
set_refspecs(argv + 1, argc - 1, repo);
}
- for_each_string_list_item(item, &push_options)
+ for_each_string_list_item(item, push_options)
if (strchr(item->string, '\n'))
die(_("push options must not have new line characters"));
- rc = do_push(repo, flags, &push_options);
- string_list_clear(&push_options, 0);
+ rc = do_push(repo, flags, push_options);
+ string_list_clear(&push_options_cmdline, 0);
+ string_list_clear(&push_options_config, 0);
if (rc == -1)
usage_with_options(push_usage, options);
else
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index d5f618d08..bf87a2710 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -164,8 +164,6 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
argc = parse_options(argc, argv, unused_prefix, read_tree_options,
read_tree_usage, 0);
- load_submodule_cache();
-
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
prefix_set = opts.prefix ? 1 : 0;
diff --git a/builtin/rebase--helper.c b/builtin/rebase--helper.c
index c82b4dce6..f8519363a 100644
--- a/builtin/rebase--helper.c
+++ b/builtin/rebase--helper.c
@@ -12,15 +12,30 @@ static const char * const builtin_rebase_helper_usage[] = {
int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
{
struct replay_opts opts = REPLAY_OPTS_INIT;
+ int keep_empty = 0;
enum {
- CONTINUE = 1, ABORT
+ CONTINUE = 1, ABORT, MAKE_SCRIPT, SHORTEN_SHA1S, EXPAND_SHA1S,
+ CHECK_TODO_LIST, SKIP_UNNECESSARY_PICKS, REARRANGE_SQUASH
} command = 0;
struct option options[] = {
OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
+ OPT_BOOL(0, "keep-empty", &keep_empty, N_("keep empty commits")),
OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
CONTINUE),
OPT_CMDMODE(0, "abort", &command, N_("abort rebase"),
ABORT),
+ OPT_CMDMODE(0, "make-script", &command,
+ N_("make rebase script"), MAKE_SCRIPT),
+ OPT_CMDMODE(0, "shorten-ids", &command,
+ N_("shorten SHA-1s in the todo list"), SHORTEN_SHA1S),
+ OPT_CMDMODE(0, "expand-ids", &command,
+ N_("expand SHA-1s in the todo list"), EXPAND_SHA1S),
+ OPT_CMDMODE(0, "check-todo-list", &command,
+ N_("check the todo list"), CHECK_TODO_LIST),
+ OPT_CMDMODE(0, "skip-unnecessary-picks", &command,
+ N_("skip unnecessary picks"), SKIP_UNNECESSARY_PICKS),
+ OPT_CMDMODE(0, "rearrange-squash", &command,
+ N_("rearrange fixup/squash lines"), REARRANGE_SQUASH),
OPT_END()
};
@@ -37,5 +52,17 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
return !!sequencer_continue(&opts);
if (command == ABORT && argc == 1)
return !!sequencer_remove_state(&opts);
+ if (command == MAKE_SCRIPT && argc > 1)
+ return !!sequencer_make_script(keep_empty, stdout, argc, argv);
+ if (command == SHORTEN_SHA1S && argc == 1)
+ return !!transform_todo_ids(1);
+ if (command == EXPAND_SHA1S && argc == 1)
+ return !!transform_todo_ids(0);
+ if (command == CHECK_TODO_LIST && argc == 1)
+ return !!check_todo_list();
+ if (command == SKIP_UNNECESSARY_PICKS && argc == 1)
+ return !!skip_unnecessary_picks();
+ if (command == REARRANGE_SQUASH && argc == 1)
+ return !!rearrange_squash();
usage_with_options(builtin_rebase_helper_usage, options);
}
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index cabdc55e0..4d37a160d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -23,6 +23,7 @@
#include "fsck.h"
#include "tmp-objdir.h"
#include "oidset.h"
+#include "packfile.h"
static const char * const receive_pack_usage[] = {
N_("git receive-pack <git-dir>"),
@@ -742,7 +743,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,
size_t n;
if (feed(feed_state, &buf, &n))
break;
- if (write_in_full(proc.in, buf, n) != n)
+ if (write_in_full(proc.in, buf, n) < 0)
break;
}
close(proc.in);
@@ -869,7 +870,7 @@ static void refuse_unconfigured_deny_delete_current(void)
rp_error("%s", _(refuse_unconfigured_deny_delete_current_msg));
}
-static int command_singleton_iterator(void *cb_data, unsigned char sha1[20]);
+static int command_singleton_iterator(void *cb_data, struct object_id *oid);
static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
{
static struct lock_file shallow_lock;
@@ -919,9 +920,9 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
*/
static int head_has_history(void)
{
- unsigned char sha1[20];
+ struct object_id oid;
- return !get_sha1("HEAD", sha1);
+ return !get_oid("HEAD", &oid);
}
static const char *push_to_deploy(unsigned char *sha1,
@@ -1138,7 +1139,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
}
if (ref_transaction_delete(transaction,
namespaced_name,
- old_oid->hash,
+ old_oid,
0, "push", &err)) {
rp_error("%s", err.buf);
strbuf_release(&err);
@@ -1155,7 +1156,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
if (ref_transaction_update(transaction,
namespaced_name,
- new_oid->hash, old_oid->hash,
+ new_oid, old_oid,
0, "push",
&err)) {
rp_error("%s", err.buf);
@@ -1206,11 +1207,10 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
const char *dst_name;
struct string_list_item *item;
struct command *dst_cmd;
- unsigned char sha1[GIT_MAX_RAWSZ];
int flag;
strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
- dst_name = resolve_ref_unsafe(buf.buf, 0, sha1, &flag);
+ dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
strbuf_release(&buf);
if (!(flag & REF_ISSYMREF))
@@ -1270,7 +1270,7 @@ static void check_aliased_updates(struct command *commands)
string_list_clear(&ref_list, 0);
}
-static int command_singleton_iterator(void *cb_data, unsigned char sha1[20])
+static int command_singleton_iterator(void *cb_data, struct object_id *oid)
{
struct command **cmd_list = cb_data;
struct command *cmd = *cmd_list;
@@ -1278,7 +1278,7 @@ static int command_singleton_iterator(void *cb_data, unsigned char sha1[20])
if (!cmd || is_null_oid(&cmd->new_oid))
return -1; /* end of list */
*cmd_list = NULL; /* this returns only one */
- hashcpy(sha1, cmd->new_oid.hash);
+ oidcpy(oid, &cmd->new_oid);
return 0;
}
@@ -1309,7 +1309,7 @@ struct iterate_data {
struct shallow_info *si;
};
-static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
+static int iterate_receive_command_list(void *cb_data, struct object_id *oid)
{
struct iterate_data *data = cb_data;
struct command **cmd_list = &data->cmds;
@@ -1320,7 +1320,7 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
/* to be checked in update_shallow_ref() */
continue;
if (!is_null_oid(&cmd->new_oid) && !cmd->skip_update) {
- hashcpy(sha1, cmd->new_oid.hash);
+ oidcpy(oid, &cmd->new_oid);
*cmd_list = cmd->next;
return 0;
}
@@ -1458,7 +1458,6 @@ static void execute_commands(struct command *commands,
{
struct check_connected_options opt = CHECK_CONNECTED_INIT;
struct command *cmd;
- struct object_id oid;
struct iterate_data data;
struct async muxer;
int err_fd = 0;
@@ -1515,7 +1514,7 @@ static void execute_commands(struct command *commands,
check_aliased_updates(commands);
free(head_name_to_free);
- head_name = head_name_to_free = resolve_refdup("HEAD", 0, oid.hash, NULL);
+ head_name = head_name_to_free = resolve_refdup("HEAD", 0, NULL, NULL);
if (use_atomic)
execute_commands_atomic(commands, si);
diff --git a/builtin/reflog.c b/builtin/reflog.c
index e237d927a..ab31a3b6a 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -42,7 +42,7 @@ struct expire_reflog_policy_cb {
};
struct collected_reflog {
- unsigned char sha1[20];
+ struct object_id oid;
char reflog[FLEX_ARRAY];
};
@@ -126,7 +126,7 @@ static int commit_is_complete(struct commit *commit)
struct commit *c;
struct commit_list *parent;
- c = (struct commit *)study.objects[--study.nr].item;
+ c = (struct commit *)object_array_pop(&study);
if (!c->object.parsed && !parse_object(&c->object.oid))
c->object.flags |= INCOMPLETE;
@@ -182,8 +182,8 @@ static int commit_is_complete(struct commit *commit)
found.objects[i].item->flags |= SEEN;
}
/* free object arrays */
- free(study.objects);
- free(found.objects);
+ object_array_clear(&study);
+ object_array_clear(&found);
return !is_incomplete;
}
@@ -385,7 +385,7 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus
struct collect_reflog_cb *cb = cb_data;
FLEX_ALLOC_STR(e, reflog, ref);
- hashcpy(e->sha1, oid->hash);
+ oidcpy(&e->oid, oid);
ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc);
cb->e[cb->nr++] = e;
return 0;
@@ -589,7 +589,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
for (i = 0; i < collected.nr; i++) {
struct collected_reflog *e = collected.e[i];
set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog);
- status |= reflog_expire(e->reflog, e->sha1, flags,
+ status |= reflog_expire(e->reflog, &e->oid, flags,
reflog_expiry_prepare,
should_expire_reflog_ent,
reflog_expiry_cleanup,
@@ -601,13 +601,13 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
for (; i < argc; i++) {
char *ref;
- unsigned char sha1[20];
- if (!dwim_log(argv[i], strlen(argv[i]), sha1, &ref)) {
+ struct object_id oid;
+ if (!dwim_log(argv[i], strlen(argv[i]), &oid, &ref)) {
status |= error("%s points nowhere!", argv[i]);
continue;
}
set_reflog_expiry_param(&cb.cmd, explicit_expiry, ref);
- status |= reflog_expire(ref, sha1, flags,
+ status |= reflog_expire(ref, &oid, flags,
reflog_expiry_prepare,
should_expire_reflog_ent,
reflog_expiry_cleanup,
@@ -659,7 +659,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
for ( ; i < argc; i++) {
const char *spec = strstr(argv[i], "@{");
- unsigned char sha1[20];
+ struct object_id oid;
char *ep, *ref;
int recno;
@@ -668,7 +668,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
continue;
}
- if (!dwim_log(argv[i], spec - argv[i], sha1, &ref)) {
+ if (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) {
status |= error("no reflog for '%s'", argv[i]);
continue;
}
@@ -683,7 +683,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
cb.cmd.expire_total = 0;
}
- status |= reflog_expire(ref, sha1, flags,
+ status |= reflog_expire(ref, &oid, flags,
reflog_expiry_prepare,
should_expire_reflog_ent,
reflog_expiry_cleanup,
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index bfb21ba7d..6a9127a33 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -57,7 +57,7 @@ static char *strip_escapes(const char *str, const char *service,
special = str[rpos];
if (rpos == 1)
break;
- /* Fall-through to error. */
+ /* fallthrough */
default:
die("Bad remote-ext placeholder '%%%c'.",
str[rpos]);
diff --git a/builtin/remote.c b/builtin/remote.c
index 6273c0c23..d95bf904c 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -301,7 +301,7 @@ static int config_read_branches(const char *key, const char *value, void *cb)
}
string_list_append(&info->merge, xstrdup(value));
} else {
- int v = git_config_maybe_bool(orig_key, value);
+ int v = git_parse_maybe_bool(value);
if (v >= 0)
info->rebase = v;
else if (!strcmp(value, "preserve"))
@@ -558,19 +558,19 @@ static int read_remote_branches(const char *refname,
struct strbuf buf = STRBUF_INIT;
struct string_list_item *item;
int flag;
- struct object_id orig_oid;
const char *symref;
strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
if (starts_with(refname, buf.buf)) {
item = string_list_append(rename->remote_branches, xstrdup(refname));
symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING,
- orig_oid.hash, &flag);
- if (flag & REF_ISSYMREF)
+ NULL, &flag);
+ if (symref && (flag & REF_ISSYMREF))
item->util = xstrdup(symref);
else
item->util = NULL;
}
+ strbuf_release(&buf);
return 0;
}
@@ -595,6 +595,7 @@ static int migrate_file(struct remote *remote)
unlink_or_warn(git_path("remotes/%s", remote->name));
else if (remote->origin == REMOTE_BRANCHES)
unlink_or_warn(git_path("branches/%s", remote->name));
+ strbuf_release(&buf);
return 0;
}
@@ -689,10 +690,10 @@ static int mv(int argc, const char **argv)
int flag = 0;
struct object_id oid;
- read_ref_full(item->string, RESOLVE_REF_READING, oid.hash, &flag);
+ read_ref_full(item->string, RESOLVE_REF_READING, &oid, &flag);
if (!(flag & REF_ISSYMREF))
continue;
- if (delete_ref(NULL, item->string, NULL, REF_NODEREF))
+ if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF))
die(_("deleting '%s' failed"), item->string);
}
for (i = 0; i < remote_branches.nr; i++) {
@@ -787,7 +788,7 @@ static int rm(int argc, const char **argv)
strbuf_release(&buf);
if (!result)
- result = delete_refs("remote: remove", &branches, REF_NODEREF);
+ result = delete_refs("remote: remove", &branches, REF_NO_DEREF);
string_list_clear(&branches, 0);
if (skipped.nr) {
@@ -1254,7 +1255,7 @@ static int set_head(int argc, const char **argv)
head_name = xstrdup(states.heads.items[0].string);
free_remote_ref_states(&states);
} else if (opt_d && !opt_a && argc == 1) {
- if (delete_ref(NULL, buf.buf, NULL, REF_NODEREF))
+ if (delete_ref(NULL, buf.buf, NULL, REF_NO_DEREF))
result |= error(_("Could not delete %s"), buf.buf);
} else
usage_with_options(builtin_remote_sethead_usage, options);
@@ -1563,9 +1564,7 @@ static int set_url(int argc, const char **argv)
"^$", 0);
else
git_config_set(name_buf.buf, newurl);
- strbuf_release(&name_buf);
-
- return 0;
+ goto out;
}
/* Old URL specified. Demand that one matches. */
@@ -1588,6 +1587,8 @@ static int set_url(int argc, const char **argv)
git_config_set_multivar(name_buf.buf, newurl, oldurl, 0);
else
git_config_set_multivar(name_buf.buf, NULL, oldurl, 1);
+out:
+ strbuf_release(&name_buf);
return 0;
}
diff --git a/builtin/replace.c b/builtin/replace.c
index fba336a68..10078ae37 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -50,7 +50,7 @@ static int show_reference(const char *refname, const struct object_id *oid,
struct object_id object;
enum object_type obj_type, repl_type;
- if (get_sha1(refname, object.hash))
+ if (get_oid(refname, &object))
return error("Failed to resolve '%s' as a valid ref.", refname);
obj_type = sha1_object_info(object.hash, NULL);
@@ -113,7 +113,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
strbuf_addstr(&ref, oid_to_hex(&oid));
full_hex = ref.buf + base_len;
- if (read_ref(ref.buf, oid.hash)) {
+ if (read_ref(ref.buf, &oid)) {
error("replace ref '%s' not found.", full_hex);
had_error = 1;
continue;
@@ -128,7 +128,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
static int delete_replace_ref(const char *name, const char *ref,
const struct object_id *oid)
{
- if (delete_ref(NULL, ref, oid->hash, 0))
+ if (delete_ref(NULL, ref, oid, 0))
return 1;
printf("Deleted replace ref '%s'\n", name);
return 0;
@@ -144,7 +144,7 @@ static void check_ref_valid(struct object_id *object,
if (check_refname_format(ref->buf, 0))
die("'%s' is not a valid ref name.", ref->buf);
- if (read_ref(ref->buf, prev->hash))
+ if (read_ref(ref->buf, prev))
oidclr(prev);
else if (!force)
die("replace ref '%s' already exists", ref->buf);
@@ -175,7 +175,7 @@ static int replace_object_oid(const char *object_ref,
transaction = ref_transaction_begin(&err);
if (!transaction ||
- ref_transaction_update(transaction, ref.buf, repl->hash, prev.hash,
+ ref_transaction_update(transaction, ref.buf, repl, &prev,
0, NULL, &err) ||
ref_transaction_commit(transaction, &err))
die("%s", err.buf);
@@ -269,7 +269,7 @@ static void import_object(struct object_id *oid, enum object_type type,
if (fstat(fd, &st) < 0)
die_errno("unable to fstat %s", filename);
- if (index_fd(oid->hash, fd, &st, type, NULL, flags) < 0)
+ if (index_fd(oid, fd, &st, type, NULL, flags) < 0)
die("unable to write object to database");
/* index_fd close()s fd for us */
}
@@ -365,7 +365,7 @@ static void check_one_mergetag(struct commit *commit,
/* iterate over new parents */
for (i = 1; i < mergetag_data->argc; i++) {
struct object_id oid;
- if (get_sha1(mergetag_data->argv[i], oid.hash) < 0)
+ if (get_oid(mergetag_data->argv[i], &oid) < 0)
die(_("Not a valid object name: '%s'"), mergetag_data->argv[i]);
if (!oidcmp(&tag->tagged->oid, &oid))
return; /* found */
diff --git a/builtin/rerere.c b/builtin/rerere.c
index ffb66e290..0bc40298c 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -18,7 +18,7 @@ static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
{
int i;
for (i = 0; i < nbuf; i++)
- if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
+ if (write_in_full(1, ptr[i].ptr, ptr[i].size) < 0)
return -1;
return 0;
}
diff --git a/builtin/reset.c b/builtin/reset.c
index 7aeaea273..906e54165 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -44,10 +44,11 @@ static inline int is_merge(void)
static int reset_index(const struct object_id *oid, int reset_type, int quiet)
{
- int nr = 1;
+ int i, nr = 0;
struct tree_desc desc[2];
struct tree *tree;
struct unpack_trees_options opts;
+ int ret = -1;
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
@@ -75,23 +76,32 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet)
struct object_id head_oid;
if (get_oid("HEAD", &head_oid))
return error(_("You do not have a valid HEAD."));
- if (!fill_tree_descriptor(desc, head_oid.hash))
+ if (!fill_tree_descriptor(desc + nr, &head_oid))
return error(_("Failed to find tree of HEAD."));
nr++;
opts.fn = twoway_merge;
}
- if (!fill_tree_descriptor(desc + nr - 1, oid->hash))
- return error(_("Failed to find tree of %s."), oid_to_hex(oid));
+ if (!fill_tree_descriptor(desc + nr, oid)) {
+ error(_("Failed to find tree of %s."), oid_to_hex(oid));
+ goto out;
+ }
+ nr++;
+
if (unpack_trees(nr, desc, &opts))
- return -1;
+ goto out;
if (reset_type == MIXED || reset_type == HARD) {
tree = parse_tree_indirect(oid);
prime_cache_tree(&the_index, tree);
}
- return 0;
+ ret = 0;
+
+out:
+ for (i = 0; i < nr; i++)
+ free((void *)desc[i].buffer);
+ return ret;
}
static void print_new_head_line(struct commit *commit)
@@ -156,6 +166,7 @@ static int read_from_tree(const struct pathspec *pathspec,
opt.output_format = DIFF_FORMAT_CALLBACK;
opt.format_callback = update_index_from_diff;
opt.format_callback_data = &intent_to_add;
+ opt.flags.override_submodule_config = 1;
if (do_diff_cache(tree_oid, &opt))
return 1;
@@ -219,8 +230,8 @@ static void parse_args(struct pathspec *pathspec,
* has to be unambiguous. If there is a single argument, it
* can not be a tree
*/
- else if ((!argv[1] && !get_sha1_committish(argv[0], unused.hash)) ||
- (argv[1] && !get_sha1_treeish(argv[0], unused.hash))) {
+ else if ((!argv[1] && !get_oid_committish(argv[0], &unused)) ||
+ (argv[1] && !get_oid_treeish(argv[0], &unused))) {
/*
* Ok, argv[0] looks like a commit/tree; it should not
* be a filename.
@@ -255,12 +266,12 @@ static int reset_refs(const char *rev, const struct object_id *oid)
if (!get_oid("HEAD", &oid_orig)) {
orig = &oid_orig;
set_reflog_message(&msg, "updating ORIG_HEAD", NULL);
- update_ref_oid(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
+ update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
UPDATE_REFS_MSG_ON_ERR);
} else if (old_orig)
- delete_ref(NULL, "ORIG_HEAD", old_orig->hash, 0);
+ delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
set_reflog_message(&msg, "updating HEAD", rev);
- update_ref_status = update_ref_oid(msg.buf, "HEAD", oid, orig, 0,
+ update_ref_status = update_ref(msg.buf, "HEAD", oid, orig, 0,
UPDATE_REFS_MSG_ON_ERR);
strbuf_release(&msg);
return update_ref_status;
@@ -308,15 +319,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_DASHDASH);
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
- load_submodule_cache();
-
- unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash);
+ unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
if (unborn) {
/* reset on unborn branch: treat as reset to empty tree */
hashcpy(oid.hash, EMPTY_TREE_SHA1_BIN);
} else if (!pathspec.nr) {
struct commit *commit;
- if (get_sha1_committish(rev, oid.hash))
+ if (get_oid_committish(rev, &oid))
die(_("Failed to resolve '%s' as a valid revision."), rev);
commit = lookup_commit_reference(&oid);
if (!commit)
@@ -324,7 +333,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
oidcpy(&oid, &commit->object.oid);
} else {
struct tree *tree;
- if (get_sha1_treeish(rev, oid.hash))
+ if (get_oid_treeish(rev, &oid))
die(_("Failed to resolve '%s' as a valid tree."), rev);
tree = parse_tree_indirect(&oid);
if (!tree)
@@ -368,8 +377,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
die_if_unmerged_cache(reset_type);
if (reset_type != SOFT) {
- struct lock_file *lock = xcalloc(1, sizeof(*lock));
- hold_locked_index(lock, LOCK_DIE_ON_ERROR);
+ struct lock_file lock = LOCK_INIT;
+ hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
if (reset_type == MIXED) {
int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
if (read_from_tree(&pathspec, &oid, intent_to_add))
@@ -385,7 +394,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
die(_("Could not reset index file to revision '%s'."), rev);
}
- if (write_locked_index(&the_index, lock, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock, COMMIT_LOCK))
die(_("Could not write new index file."));
}
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 95d84d5cd..4032eb381 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -11,6 +11,7 @@
#include "graph.h"
#include "bisect.h"
#include "progress.h"
+#include "reflog-walk.h"
static const char rev_list_usage[] =
"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@ -122,6 +123,7 @@ static void show_commit(struct commit *commit, void *data)
ctx.date_mode_explicit = revs->date_mode_explicit;
ctx.fmt = revs->commit_format;
ctx.output_encoding = get_log_output_encoding();
+ ctx.color = revs->diffopt.use_color;
pretty_print_commit(&ctx, commit, &buf);
if (buf.len) {
if (revs->commit_format != CMIT_FMT_ONELINE)
@@ -256,14 +258,14 @@ static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
}
static int show_object_fast(
- const unsigned char *sha1,
+ const struct object_id *oid,
enum object_type type,
int exclude,
uint32_t name_hash,
struct packed_git *found_pack,
off_t found_offset)
{
- fprintf(stdout, "%s\n", sha1_to_hex(sha1));
+ fprintf(stdout, "%s\n", oid_to_hex(oid));
return 1;
}
@@ -292,7 +294,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (revs.bisect)
bisect_list = 1;
- if (DIFF_OPT_TST(&revs.diffopt, QUICK))
+ if (revs.diffopt.flags.quick)
info.flags |= REV_LIST_QUIET;
for (i = 1 ; i < argc; i++) {
const char *arg = argv[i];
@@ -348,9 +350,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
/* Only --header was specified */
revs.commit_format = CMIT_FMT_RAW;
- if ((!revs.commits &&
+ if ((!revs.commits && reflog_walk_empty(revs.reflog_info) &&
(!(revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
- !revs.pending.nr)) ||
+ !revs.pending.nr) &&
+ !revs.rev_input_given) ||
revs.diff)
usage(rev_list_usage);
@@ -364,7 +367,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
revs.limited = 1;
if (show_progress)
- progress = start_progress_delay(show_progress, 0, 0, 2);
+ progress = start_delayed_progress(show_progress, 0);
if (use_bitmap_index && !revs.prune) {
if (revs.count && !revs.left_right && !revs.cherry_mark) {
@@ -394,8 +397,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (bisect_list) {
int reaches = reaches, all = all;
- revs.commits = find_bisection(revs.commits, &reaches, &all,
- bisect_find_all);
+ find_bisection(&revs.commits, &reaches, &all, bisect_find_all);
if (bisect_show_vars)
return show_bisect_vars(&info, reaches, all);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index c78b7b33d..74aa644cb 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -133,7 +133,7 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
struct object_id discard;
char *full;
- switch (dwim_ref(name, strlen(name), discard.hash, &full)) {
+ switch (dwim_ref(name, strlen(name), &discard, &full)) {
case 0:
/*
* Not found -- not a ref. We could
@@ -274,7 +274,7 @@ static int try_difference(const char *arg)
return 0;
}
- if (!get_sha1_committish(this, oid.hash) && !get_sha1_committish(next, end.hash)) {
+ if (!get_oid_committish(this, &oid) && !get_oid_committish(next, &end)) {
show_rev(NORMAL, &end, next);
show_rev(symmetric ? NORMAL : REVERSED, &oid, this);
if (symmetric) {
@@ -328,7 +328,7 @@ static int try_parent_shorthands(const char *arg)
return 0;
*dotdot = 0;
- if (get_sha1_committish(arg, oid.hash)) {
+ if (get_oid_committish(arg, &oid)) {
*dotdot = '^';
return 0;
}
@@ -387,6 +387,14 @@ static const char *skipspaces(const char *s)
return s;
}
+static char *findspace(const char *s)
+{
+ for (; *s; s++)
+ if (isspace(*s))
+ return (char*)s;
+ return NULL;
+}
+
static int cmd_parseopt(int argc, const char **argv, const char *prefix)
{
static int keep_dashdash = 0, stop_at_non_option = 0;
@@ -434,7 +442,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
while (strbuf_getline(&sb, stdin) != EOF) {
const char *s;
- const char *help;
+ char *help;
struct option *o;
if (!sb.len)
@@ -444,15 +452,17 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
memset(opts + onb, 0, sizeof(opts[onb]));
o = &opts[onb++];
- help = strchr(sb.buf, ' ');
- if (!help || *sb.buf == ' ') {
+ help = findspace(sb.buf);
+ if (!help || sb.buf == help) {
o->type = OPTION_GROUP;
o->help = xstrdup(skipspaces(sb.buf));
continue;
}
+ *help = '\0';
+
o->type = OPTION_CALLBACK;
- o->help = xstrdup(skipspaces(help));
+ o->help = xstrdup(skipspaces(help+1));
o->value = &parsed;
o->flags = PARSE_OPT_NOARG;
o->callback = &parseopt_dump;
@@ -702,7 +712,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
quiet = 1;
- flags |= GET_SHA1_QUIETLY;
+ flags |= GET_OID_QUIETLY;
continue;
}
if (opt_with_value(arg, "--short", &arg)) {
@@ -757,8 +767,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--bisect")) {
- for_each_ref_in("refs/bisect/bad", show_reference, NULL);
- for_each_ref_in("refs/bisect/good", anti_reference, NULL);
+ for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0);
+ for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0);
continue;
}
if (opt_with_value(arg, "--branches", &arg)) {
@@ -868,6 +878,11 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
: "false");
continue;
}
+ if (!strcmp(arg, "--is-shallow-repository")) {
+ printf("%s\n", is_repository_shallow() ? "true"
+ : "false");
+ continue;
+ }
if (!strcmp(arg, "--shared-index-path")) {
if (read_cache() < 0)
die(_("Could not read the index"));
@@ -911,7 +926,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
name++;
type = REVERSED;
}
- if (!get_sha1_with_context(name, flags, oid.hash, &unused)) {
+ if (!get_oid_with_context(name, flags, &oid, &unused)) {
if (verify)
revs_count++;
else
diff --git a/builtin/revert.c b/builtin/revert.c
index 16028b9ea..b9d927eb0 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -155,6 +155,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
"--strategy-option", opts->xopts ? 1 : 0,
"-x", opts->record_origin,
"--ff", opts->allow_ff,
+ "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,
+ "--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE,
NULL);
}
diff --git a/builtin/rm.c b/builtin/rm.c
index 52826d137..d91451fea 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -255,7 +255,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
struct pathspec pathspec;
char *seen;
- gitmodules_config();
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_rm_options,
@@ -286,7 +285,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
list.entry[list.nr].name = xstrdup(ce->name);
list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode);
if (list.entry[list.nr++].is_submodule &&
- !is_staging_gitmodules_ok())
+ !is_staging_gitmodules_ok(&the_index))
die (_("Please stage your changes to .gitmodules or stash them to proceed"));
}
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 633e0c3cd..fc4f0bb5f 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -105,7 +105,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
if (!strcmp(k, "push.gpgsign")) {
const char *value;
if (!git_config_get_value("push.gpgsign", &value)) {
- switch (git_config_maybe_bool("push.gpgsign", value)) {
+ switch (git_parse_maybe_bool(value)) {
case 0:
args.push_cert = SEND_PACK_PUSH_CERT_NEVER;
break;
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 43c4799ea..e29875b84 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -52,26 +52,8 @@ static void insert_one_record(struct shortlog *log,
const char *oneline)
{
struct string_list_item *item;
- const char *mailbuf, *namebuf;
- size_t namelen, maillen;
- struct strbuf namemailbuf = STRBUF_INIT;
- struct ident_split ident;
- if (split_ident_line(&ident, author, strlen(author)))
- return;
-
- namebuf = ident.name_begin;
- mailbuf = ident.mail_begin;
- namelen = ident.name_end - ident.name_begin;
- maillen = ident.mail_end - ident.mail_begin;
-
- map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
- strbuf_add(&namemailbuf, namebuf, namelen);
-
- if (log->email)
- strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
-
- item = string_list_insert(&log->list, namemailbuf.buf);
+ item = string_list_insert(&log->list, author);
if (log->summary)
item->util = (void *)(UTIL_TO_INT(item) + 1);
@@ -114,9 +96,33 @@ static void insert_one_record(struct shortlog *log,
}
}
+static int parse_stdin_author(struct shortlog *log,
+ struct strbuf *out, const char *in)
+{
+ const char *mailbuf, *namebuf;
+ size_t namelen, maillen;
+ struct ident_split ident;
+
+ if (split_ident_line(&ident, in, strlen(in)))
+ return -1;
+
+ namebuf = ident.name_begin;
+ mailbuf = ident.mail_begin;
+ namelen = ident.name_end - ident.name_begin;
+ maillen = ident.mail_end - ident.mail_begin;
+
+ map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
+ strbuf_add(out, namebuf, namelen);
+ if (log->email)
+ strbuf_addf(out, " <%.*s>", (int)maillen, mailbuf);
+
+ return 0;
+}
+
static void read_from_stdin(struct shortlog *log)
{
struct strbuf author = STRBUF_INIT;
+ struct strbuf mapped_author = STRBUF_INIT;
struct strbuf oneline = STRBUF_INIT;
static const char *author_match[2] = { "Author: ", "author " };
static const char *committer_match[2] = { "Commit: ", "committer " };
@@ -134,9 +140,15 @@ static void read_from_stdin(struct shortlog *log)
while (strbuf_getline_lf(&oneline, stdin) != EOF &&
!oneline.len)
; /* discard blanks */
- insert_one_record(log, v, oneline.buf);
+
+ strbuf_reset(&mapped_author);
+ if (parse_stdin_author(log, &mapped_author, v) < 0)
+ continue;
+
+ insert_one_record(log, mapped_author.buf, oneline.buf);
}
strbuf_release(&author);
+ strbuf_release(&mapped_author);
strbuf_release(&oneline);
}
@@ -153,7 +165,9 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
ctx.date_mode.type = DATE_NORMAL;
ctx.output_encoding = get_log_output_encoding();
- fmt = log->committer ? "%cn <%ce>" : "%an <%ae>";
+ fmt = log->committer ?
+ (log->email ? "%cN <%cE>" : "%cN") :
+ (log->email ? "%aN <%aE>" : "%aN");
format_commit_message(commit, fmt, &author, &ctx);
if (!log->summary) {
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 7073a3eb9..2e24b5c33 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -393,7 +393,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid,
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
*/
- if (get_sha1(refname + ofs, tmp.hash) || oidcmp(&tmp, oid))
+ if (get_oid(refname + ofs, &tmp) || oidcmp(&tmp, oid))
ofs = 5;
return append_ref(refname + ofs, oid, 0);
}
@@ -408,7 +408,7 @@ static int append_remote_ref(const char *refname, const struct object_id *oid,
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
*/
- if (get_sha1(refname + ofs, tmp.hash) || oidcmp(&tmp, oid))
+ if (get_oid(refname + ofs, &tmp) || oidcmp(&tmp, oid))
ofs = 5;
return append_ref(refname + ofs, oid, 0);
}
@@ -514,7 +514,7 @@ static int show_independent(struct commit **rev,
static void append_one_rev(const char *av)
{
struct object_id revkey;
- if (!get_sha1(av, revkey.hash)) {
+ if (!get_oid(av, &revkey)) {
append_ref(av, &revkey, 0);
return;
}
@@ -705,8 +705,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
static const char *fake_av[2];
fake_av[0] = resolve_refdup("HEAD",
- RESOLVE_REF_READING,
- oid.hash, NULL);
+ RESOLVE_REF_READING, &oid,
+ NULL);
fake_av[1] = NULL;
av = fake_av;
ac = 1;
@@ -720,7 +720,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
die(Q_("only %d entry can be shown at one time.",
"only %d entries can be shown at one time.",
MAX_REVS), MAX_REVS);
- if (!dwim_ref(*av, strlen(*av), oid.hash, &ref))
+ if (!dwim_ref(*av, strlen(*av), &oid, &ref))
die(_("no such ref %s"), *av);
/* Has the base been specified? */
@@ -731,7 +731,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
/* Ah, that is a date spec... */
timestamp_t at;
at = approxidate(reflog_base);
- read_ref_at(ref, flags, at, -1, oid.hash, NULL,
+ read_ref_at(ref, flags, at, -1, &oid, NULL,
NULL, NULL, &base);
}
}
@@ -743,7 +743,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
timestamp_t timestamp;
int tz;
- if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg,
+ if (read_ref_at(ref, flags, 0, base + i, &oid, &logmsg,
&timestamp, &tz, NULL)) {
reflog = i;
break;
@@ -775,7 +775,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
}
head = resolve_refdup("HEAD", RESOLVE_REF_READING,
- head_oid.hash, NULL);
+ &head_oid, NULL);
if (with_current_branch && head) {
int has_head = 0;
@@ -808,7 +808,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
die(Q_("cannot handle more than %d rev.",
"cannot handle more than %d revs.",
MAX_REVS), MAX_REVS);
- if (get_sha1(ref_name[num_rev], revkey.hash))
+ if (get_oid(ref_name[num_rev], &revkey))
die(_("'%s' is not a valid ref."), ref_name[num_rev]);
commit = lookup_commit_reference(&revkey);
if (!commit)
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 013d241ab..41e5e71ca 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -38,7 +38,7 @@ static void show_one(const char *refname, const struct object_id *oid)
if (!deref_tags)
return;
- if (!peel_ref(refname, peeled.hash)) {
+ if (!peel_ref(refname, &peeled)) {
hex = find_unique_abbrev(peeled.hash, abbrev);
printf("%s %s^{}\n", hex, refname);
}
@@ -197,7 +197,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
struct object_id oid;
if ((starts_with(*pattern, "refs/") || !strcmp(*pattern, "HEAD")) &&
- !read_ref(*pattern, oid.hash)) {
+ !read_ref(*pattern, &oid)) {
show_one(*pattern, &oid);
}
else if (!quiet)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6abdad329..2086f0eb0 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -13,13 +13,22 @@
#include "remote.h"
#include "refs.h"
#include "connect.h"
+#include "revision.h"
+#include "diffcore.h"
+#include "diff.h"
+
+#define OPT_QUIET (1 << 0)
+#define OPT_CACHED (1 << 1)
+#define OPT_RECURSIVE (1 << 2)
+
+typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
+ void *cb_data);
static char *get_default_remote(void)
{
char *dest = NULL, *ret;
- unsigned char sha1[20];
struct strbuf sb = STRBUF_INIT;
- const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+ const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
if (!refname)
die(_("No such ref: %s"), "HEAD");
@@ -220,6 +229,64 @@ static int resolve_relative_url_test(int argc, const char **argv, const char *pr
return 0;
}
+/* the result should be freed by the caller. */
+static char *get_submodule_displaypath(const char *path, const char *prefix)
+{
+ const char *super_prefix = get_super_prefix();
+
+ if (prefix && super_prefix) {
+ BUG("cannot have prefix '%s' and superprefix '%s'",
+ prefix, super_prefix);
+ } else if (prefix) {
+ struct strbuf sb = STRBUF_INIT;
+ char *displaypath = xstrdup(relative_path(path, prefix, &sb));
+ strbuf_release(&sb);
+ return displaypath;
+ } else if (super_prefix) {
+ return xstrfmt("%s%s", super_prefix, path);
+ } else {
+ return xstrdup(path);
+ }
+}
+
+static char *compute_rev_name(const char *sub_path, const char* object_id)
+{
+ struct strbuf sb = STRBUF_INIT;
+ const char ***d;
+
+ static const char *describe_bare[] = { NULL };
+
+ static const char *describe_tags[] = { "--tags", NULL };
+
+ static const char *describe_contains[] = { "--contains", NULL };
+
+ static const char *describe_all_always[] = { "--all", "--always", NULL };
+
+ static const char **describe_argv[] = { describe_bare, describe_tags,
+ describe_contains,
+ describe_all_always, NULL };
+
+ for (d = describe_argv; *d; d++) {
+ struct child_process cp = CHILD_PROCESS_INIT;
+ prepare_submodule_repo_env(&cp.env_array);
+ cp.dir = sub_path;
+ cp.git_cmd = 1;
+ cp.no_stderr = 1;
+
+ argv_array_push(&cp.args, "describe");
+ argv_array_pushv(&cp.args, *d);
+ argv_array_push(&cp.args, object_id);
+
+ if (!capture_command(&cp, &sb, 0)) {
+ strbuf_strip_suffix(&sb, "\n");
+ return strbuf_detach(&sb, NULL);
+ }
+ }
+
+ strbuf_release(&sb);
+ return NULL;
+}
+
struct module_list {
const struct cache_entry **entries;
int alloc, nr;
@@ -275,8 +342,6 @@ static void module_list_active(struct module_list *list)
int i;
struct module_list active_modules = MODULE_LIST_INIT;
- gitmodules_config();
-
for (i = 0; i < list->nr; i++) {
const struct cache_entry *ce = list->entries[i];
@@ -331,26 +396,31 @@ static int module_list(int argc, const char **argv, const char *prefix)
return 0;
}
-static void init_submodule(const char *path, const char *prefix, int quiet)
+static void for_each_listed_submodule(const struct module_list *list,
+ each_submodule_fn fn, void *cb_data)
+{
+ int i;
+ for (i = 0; i < list->nr; i++)
+ fn(list->entries[i], cb_data);
+}
+
+struct init_cb {
+ const char *prefix;
+ unsigned int flags;
+};
+
+#define INIT_CB_INIT { NULL, 0 }
+
+static void init_submodule(const char *path, const char *prefix,
+ unsigned int flags)
{
const struct submodule *sub;
struct strbuf sb = STRBUF_INIT;
char *upd = NULL, *url = NULL, *displaypath;
- /* Only loads from .gitmodules, no overlay with .git/config */
- gitmodules_config();
+ displaypath = get_submodule_displaypath(path, prefix);
- if (prefix && get_super_prefix())
- die("BUG: cannot have prefix and superprefix");
- else if (prefix)
- displaypath = xstrdup(relative_path(path, prefix, &sb));
- else if (get_super_prefix()) {
- strbuf_addf(&sb, "%s%s", get_super_prefix(), path);
- displaypath = strbuf_detach(&sb, NULL);
- } else
- displaypath = xstrdup(path);
-
- sub = submodule_from_path(null_sha1, path);
+ sub = submodule_from_path(&null_oid, path);
if (!sub)
die(_("No url found for submodule path '%s' in .gitmodules"),
@@ -363,9 +433,9 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
* Set active flag for the submodule being initialized
*/
if (!is_submodule_active(the_repository, path)) {
- strbuf_reset(&sb);
strbuf_addf(&sb, "submodule.%s.active", sub->name);
git_config_set_gently(sb.buf, "true");
+ strbuf_reset(&sb);
}
/*
@@ -373,7 +443,6 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
* To look up the url in .git/config, we must not fall back to
* .gitmodules, so look it up directly.
*/
- strbuf_reset(&sb);
strbuf_addf(&sb, "submodule.%s.url", sub->name);
if (git_config_get_string(sb.buf, &url)) {
if (!sub->url)
@@ -405,14 +474,14 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
if (git_config_set_gently(sb.buf, url))
die(_("Failed to register url for submodule path '%s'"),
displaypath);
- if (!quiet)
+ if (!(flags & OPT_QUIET))
fprintf(stderr,
_("Submodule '%s' (%s) registered for path '%s'\n"),
sub->name, url, displaypath);
}
+ strbuf_reset(&sb);
/* Copy "update" setting when it is not set yet */
- strbuf_reset(&sb);
strbuf_addf(&sb, "submodule.%s.update", sub->name);
if (git_config_get_string(sb.buf, &upd) &&
sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
@@ -432,12 +501,18 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
free(upd);
}
+static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
+{
+ struct init_cb *info = cb_data;
+ init_submodule(list_item->name, info->prefix, info->flags);
+}
+
static int module_init(int argc, const char **argv, const char *prefix)
{
+ struct init_cb info = INIT_CB_INIT;
struct pathspec pathspec;
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
- int i;
struct option module_init_options[] = {
OPT__QUIET(&quiet, N_("Suppress output for initializing a submodule")),
@@ -462,8 +537,165 @@ static int module_init(int argc, const char **argv, const char *prefix)
if (!argc && git_config_get_value_multi("submodule.active"))
module_list_active(&list);
- for (i = 0; i < list.nr; i++)
- init_submodule(list.entries[i]->name, prefix, quiet);
+ info.prefix = prefix;
+ if (quiet)
+ info.flags |= OPT_QUIET;
+
+ for_each_listed_submodule(&list, init_submodule_cb, &info);
+
+ return 0;
+}
+
+struct status_cb {
+ const char *prefix;
+ unsigned int flags;
+};
+
+#define STATUS_CB_INIT { NULL, 0 }
+
+static void print_status(unsigned int flags, char state, const char *path,
+ const struct object_id *oid, const char *displaypath)
+{
+ if (flags & OPT_QUIET)
+ return;
+
+ printf("%c%s %s", state, oid_to_hex(oid), displaypath);
+
+ if (state == ' ' || state == '+')
+ printf(" (%s)", compute_rev_name(path, oid_to_hex(oid)));
+
+ printf("\n");
+}
+
+static int handle_submodule_head_ref(const char *refname,
+ const struct object_id *oid, int flags,
+ void *cb_data)
+{
+ struct object_id *output = cb_data;
+ if (oid)
+ oidcpy(output, oid);
+
+ return 0;
+}
+
+static void status_submodule(const char *path, const struct object_id *ce_oid,
+ unsigned int ce_flags, const char *prefix,
+ unsigned int flags)
+{
+ char *displaypath;
+ struct argv_array diff_files_args = ARGV_ARRAY_INIT;
+ struct rev_info rev;
+ int diff_files_result;
+
+ if (!submodule_from_path(&null_oid, path))
+ die(_("no submodule mapping found in .gitmodules for path '%s'"),
+ path);
+
+ displaypath = get_submodule_displaypath(path, prefix);
+
+ if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
+ print_status(flags, 'U', path, &null_oid, displaypath);
+ goto cleanup;
+ }
+
+ if (!is_submodule_active(the_repository, path)) {
+ print_status(flags, '-', path, ce_oid, displaypath);
+ goto cleanup;
+ }
+
+ argv_array_pushl(&diff_files_args, "diff-files",
+ "--ignore-submodules=dirty", "--quiet", "--",
+ path, NULL);
+
+ git_config(git_diff_basic_config, NULL);
+ init_revisions(&rev, prefix);
+ rev.abbrev = 0;
+ diff_files_args.argc = setup_revisions(diff_files_args.argc,
+ diff_files_args.argv,
+ &rev, NULL);
+ diff_files_result = run_diff_files(&rev, 0);
+
+ if (!diff_result_code(&rev.diffopt, diff_files_result)) {
+ print_status(flags, ' ', path, ce_oid,
+ displaypath);
+ } else if (!(flags & OPT_CACHED)) {
+ struct object_id oid;
+
+ if (refs_head_ref(get_submodule_ref_store(path),
+ handle_submodule_head_ref, &oid))
+ die(_("could not resolve HEAD ref inside the"
+ "submodule '%s'"), path);
+
+ print_status(flags, '+', path, &oid, displaypath);
+ } else {
+ print_status(flags, '+', path, ce_oid, displaypath);
+ }
+
+ if (flags & OPT_RECURSIVE) {
+ struct child_process cpr = CHILD_PROCESS_INIT;
+
+ cpr.git_cmd = 1;
+ cpr.dir = path;
+ prepare_submodule_repo_env(&cpr.env_array);
+
+ argv_array_push(&cpr.args, "--super-prefix");
+ argv_array_pushf(&cpr.args, "%s/", displaypath);
+ argv_array_pushl(&cpr.args, "submodule--helper", "status",
+ "--recursive", NULL);
+
+ if (flags & OPT_CACHED)
+ argv_array_push(&cpr.args, "--cached");
+
+ if (flags & OPT_QUIET)
+ argv_array_push(&cpr.args, "--quiet");
+
+ if (run_command(&cpr))
+ die(_("failed to recurse into submodule '%s'"), path);
+ }
+
+cleanup:
+ argv_array_clear(&diff_files_args);
+ free(displaypath);
+}
+
+static void status_submodule_cb(const struct cache_entry *list_item,
+ void *cb_data)
+{
+ struct status_cb *info = cb_data;
+ status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
+ info->prefix, info->flags);
+}
+
+static int module_status(int argc, const char **argv, const char *prefix)
+{
+ struct status_cb info = STATUS_CB_INIT;
+ struct pathspec pathspec;
+ struct module_list list = MODULE_LIST_INIT;
+ int quiet = 0;
+
+ struct option module_status_options[] = {
+ OPT__QUIET(&quiet, N_("Suppress submodule status output")),
+ OPT_BIT(0, "cached", &info.flags, N_("Use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
+ OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
+ OPT_END()
+ };
+
+ const char *const git_submodule_helper_usage[] = {
+ N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
+ NULL
+ };
+
+ argc = parse_options(argc, argv, prefix, module_status_options,
+ git_submodule_helper_usage, 0);
+
+ if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
+ return 1;
+
+ info.prefix = prefix;
+ if (quiet)
+ info.flags |= OPT_QUIET;
+
+ for_each_listed_submodule(&list, status_submodule_cb, &info);
return 0;
}
@@ -475,8 +707,7 @@ static int module_name(int argc, const char **argv, const char *prefix)
if (argc != 2)
usage(_("git submodule--helper name <path>"));
- gitmodules_config();
- sub = submodule_from_path(null_sha1, argv[1]);
+ sub = submodule_from_path(&null_oid, argv[1]);
if (!sub)
die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@ -780,6 +1011,10 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
struct strbuf *out)
{
const struct submodule *sub = NULL;
+ const char *url = NULL;
+ const char *update_string;
+ enum submodule_update_type update_type;
+ char *key;
struct strbuf displaypath_sb = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
const char *displaypath = NULL;
@@ -795,7 +1030,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}
- sub = submodule_from_path(null_sha1, ce->name);
+ sub = submodule_from_path(&null_oid, ce->name);
if (suc->recursive_prefix)
displaypath = relative_path(suc->recursive_prefix,
@@ -808,9 +1043,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}
+ key = xstrfmt("submodule.%s.update", sub->name);
+ if (!repo_config_get_string_const(the_repository, key, &update_string)) {
+ update_type = parse_submodule_update_type(update_string);
+ } else {
+ update_type = sub->update_strategy.type;
+ }
+ free(key);
+
if (suc->update.type == SM_UPDATE_NONE
|| (suc->update.type == SM_UPDATE_UNSPECIFIED
- && sub->update_strategy.type == SM_UPDATE_NONE)) {
+ && update_type == SM_UPDATE_NONE)) {
strbuf_addf(out, _("Skipping submodule '%s'"), displaypath);
strbuf_addch(out, '\n');
goto cleanup;
@@ -823,6 +1066,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
}
strbuf_reset(&sb);
+ strbuf_addf(&sb, "submodule.%s.url", sub->name);
+ if (repo_config_get_string_const(the_repository, sb.buf, &url))
+ url = sub->url;
+
+ strbuf_reset(&sb);
strbuf_addf(&sb, "%s/.git", ce->name);
needs_cloning = !file_exists(sb.buf);
@@ -851,7 +1099,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
argv_array_push(&child->args, "--depth=1");
argv_array_pushl(&child->args, "--path", sub->path, NULL);
argv_array_pushl(&child->args, "--name", sub->name, NULL);
- argv_array_pushl(&child->args, "--url", sub->url, NULL);
+ argv_array_pushl(&child->args, "--url", url, NULL);
if (suc->references.nr) {
struct string_list_item *item;
for_each_string_list_item(item, &suc->references)
@@ -930,7 +1178,7 @@ static int update_clone_task_finished(int result,
const struct cache_entry *ce;
struct submodule_update_clone *suc = suc_cb;
- int *idxP = *(int**)idx_task_cb;
+ int *idxP = idx_task_cb;
int idx = *idxP;
free(idxP);
@@ -960,10 +1208,19 @@ static int update_clone_task_finished(int result,
return 0;
}
+static int gitmodules_update_clone_config(const char *var, const char *value,
+ void *cb)
+{
+ int *max_jobs = cb;
+ if (!strcmp(var, "submodule.fetchjobs"))
+ *max_jobs = parse_submodule_fetchjobs(var, value);
+ return 0;
+}
+
static int update_clone(int argc, const char **argv, const char *prefix)
{
const char *update = NULL;
- int max_jobs = -1;
+ int max_jobs = 1;
struct string_list_item *item;
struct pathspec pathspec;
struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
@@ -1000,6 +1257,9 @@ static int update_clone(int argc, const char **argv, const char *prefix)
};
suc.prefix = prefix;
+ config_from_gitmodules(gitmodules_update_clone_config, &max_jobs);
+ git_config(gitmodules_update_clone_config, &max_jobs);
+
argc = parse_options(argc, argv, prefix, module_update_clone_options,
git_submodule_helper_usage, 0);
@@ -1013,13 +1273,6 @@ static int update_clone(int argc, const char **argv, const char *prefix)
if (pathspec.nr)
suc.warn_if_uninitialized = 1;
- /* Overlay the parsed .gitmodules file with .git/config */
- gitmodules_config();
- git_config(submodule_config, NULL);
-
- if (max_jobs < 0)
- max_jobs = parallel_submodules();
-
run_processes_parallel(max_jobs,
update_clone_get_next_task,
update_clone_start_failure,
@@ -1057,19 +1310,23 @@ static int resolve_relative_path(int argc, const char **argv, const char *prefix
static const char *remote_submodule_branch(const char *path)
{
const struct submodule *sub;
- gitmodules_config();
- git_config(submodule_config, NULL);
+ const char *branch = NULL;
+ char *key;
- sub = submodule_from_path(null_sha1, path);
+ sub = submodule_from_path(&null_oid, path);
if (!sub)
return NULL;
- if (!sub->branch)
+ key = xstrfmt("submodule.%s.branch", sub->name);
+ if (repo_config_get_string_const(the_repository, key, &branch))
+ branch = sub->branch;
+ free(key);
+
+ if (!branch)
return "master";
- if (!strcmp(sub->branch, ".")) {
- unsigned char sha1[20];
- const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+ if (!strcmp(branch, ".")) {
+ const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
if (!refname)
die(_("No such ref: %s"), "HEAD");
@@ -1085,7 +1342,7 @@ static const char *remote_submodule_branch(const char *path)
return refname;
}
- return sub->branch;
+ return branch;
}
static int resolve_remote_submodule_branch(int argc, const char **argv,
@@ -1108,9 +1365,28 @@ static int resolve_remote_submodule_branch(int argc, const char **argv,
static int push_check(int argc, const char **argv, const char *prefix)
{
struct remote *remote;
+ const char *superproject_head;
+ char *head;
+ int detached_head = 0;
+ struct object_id head_oid;
- if (argc < 2)
- die("submodule--helper push-check requires at least 1 argument");
+ if (argc < 3)
+ die("submodule--helper push-check requires at least 2 arguments");
+
+ /*
+ * superproject's resolved head ref.
+ * if HEAD then the superproject is in a detached head state, otherwise
+ * it will be the resolved head ref.
+ */
+ superproject_head = argv[1];
+ argv++;
+ argc--;
+ /* Get the submodule's head ref and determine if it is detached */
+ head = resolve_refdup("HEAD", 0, &head_oid, NULL);
+ if (!head)
+ die(_("Failed to resolve HEAD as a valid ref."));
+ if (!strcmp(head, "HEAD"))
+ detached_head = 1;
/*
* The remote must be configured.
@@ -1133,18 +1409,31 @@ static int push_check(int argc, const char **argv, const char *prefix)
if (rs->pattern || rs->matching)
continue;
- /*
- * LHS must match a single ref
- * NEEDSWORK: add logic to special case 'HEAD' once
- * working with submodules in a detached head state
- * ceases to be the norm.
- */
- if (count_refspec_match(rs->src, local_refs, NULL) != 1)
+ /* LHS must match a single ref */
+ switch (count_refspec_match(rs->src, local_refs, NULL)) {
+ case 1:
+ break;
+ case 0:
+ /*
+ * If LHS matches 'HEAD' then we need to ensure
+ * that it matches the same named branch
+ * checked out in the superproject.
+ */
+ if (!strcmp(rs->src, "HEAD")) {
+ if (!detached_head &&
+ !strcmp(head, superproject_head))
+ break;
+ die("HEAD does not match the named branch in the superproject");
+ }
+ /* fallthrough */
+ default:
die("src refspec '%s' must name a ref",
rs->src);
+ }
}
free_refspec(refspec_nr, refspec);
}
+ free(head);
return 0;
}
@@ -1173,9 +1462,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
- gitmodules_config();
- git_config(submodule_config, NULL);
-
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
return 1;
@@ -1191,8 +1477,6 @@ static int is_active(int argc, const char **argv, const char *prefix)
if (argc != 2)
die("submodule--helper is-active takes exactly 1 argument");
- gitmodules_config();
-
return !is_submodule_active(the_repository, argv[1]);
}
@@ -1213,6 +1497,7 @@ static struct cmd_struct commands[] = {
{"resolve-relative-url", resolve_relative_url, 0},
{"resolve-relative-url-test", resolve_relative_url_test, 0},
{"init", module_init, SUPPORT_SUPER_PREFIX},
+ {"status", module_status, SUPPORT_SUPER_PREFIX},
{"remote-branch", resolve_remote_submodule_branch, 0},
{"push-check", push_check, 0},
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index df75cb9d4..80237f0df 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -12,9 +12,8 @@ static const char * const git_symbolic_ref_usage[] = {
static int check_symref(const char *HEAD, int quiet, int shorten, int print)
{
- unsigned char sha1[20];
int flag;
- const char *refname = resolve_ref_unsafe(HEAD, 0, sha1, &flag);
+ const char *refname = resolve_ref_unsafe(HEAD, 0, NULL, &flag);
if (!refname)
die("No such ref: %s", HEAD);
@@ -59,7 +58,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
die("Cannot delete %s, not a symbolic ref", argv[0]);
if (!strcmp(argv[0], "HEAD"))
die("deleting '%s' is not allowed", argv[0]);
- return delete_ref(NULL, argv[0], NULL, REF_NODEREF);
+ return delete_ref(NULL, argv[0], NULL, REF_NO_DEREF);
}
switch (argc) {
diff --git a/builtin/tag.c b/builtin/tag.c
index 01154ea8d..a7e6a5b0f 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -32,7 +32,8 @@ static const char * const git_tag_usage[] = {
static unsigned int colopts;
static int force_sign_annotate;
-static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, const char *format)
+static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
+ struct ref_format *format)
{
struct ref_array array;
char *to_free = NULL;
@@ -43,23 +44,24 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con
if (filter->lines == -1)
filter->lines = 0;
- if (!format) {
+ if (!format->format) {
if (filter->lines) {
to_free = xstrfmt("%s %%(contents:lines=%d)",
"%(align:15)%(refname:lstrip=2)%(end)",
filter->lines);
- format = to_free;
+ format->format = to_free;
} else
- format = "%(refname:lstrip=2)";
+ format->format = "%(refname:lstrip=2)";
}
- verify_ref_format(format);
+ if (verify_ref_format(format))
+ die(_("unable to parse format string"));
filter->with_commit_tag_algo = 1;
filter_refs(&array, filter, FILTER_REFS_TAGS);
ref_array_sort(sorting, &array);
for (i = 0; i < array.nr; i++)
- show_ref_array_item(array.items[i], format, 0);
+ show_ref_array_item(array.items[i], format);
ref_array_clear(&array);
free(to_free);
@@ -80,7 +82,7 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
for (p = argv; *p; p++) {
strbuf_reset(&ref);
strbuf_addf(&ref, "refs/tags/%s", *p);
- if (read_ref(ref.buf, oid.hash)) {
+ if (read_ref(ref.buf, &oid)) {
error(_("tag '%s' not found."), *p);
had_error = 1;
continue;
@@ -95,7 +97,7 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
static int delete_tag(const char *name, const char *ref,
const struct object_id *oid, const void *cb_data)
{
- if (delete_ref(NULL, ref, oid->hash, 0))
+ if (delete_ref(NULL, ref, oid, 0))
return 1;
printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
return 0;
@@ -105,17 +107,17 @@ static int verify_tag(const char *name, const char *ref,
const struct object_id *oid, const void *cb_data)
{
int flags;
- const char *fmt_pretty = cb_data;
+ const struct ref_format *format = cb_data;
flags = GPG_VERIFY_VERBOSE;
- if (fmt_pretty)
+ if (format->format)
flags = GPG_VERIFY_OMIT_STATUS;
- if (gpg_verify_tag(oid->hash, name, flags))
+ if (gpg_verify_tag(oid, name, flags))
return -1;
- if (fmt_pretty)
- pretty_print_ref(name, oid->hash, fmt_pretty);
+ if (format->format)
+ pretty_print_ref(name, oid->hash, format);
return 0;
}
@@ -134,30 +136,6 @@ static const char tag_template_nocleanup[] =
"Lines starting with '%c' will be kept; you may remove them"
" yourself if you want to.\n");
-/* Parse arg given and add it the ref_sorting array */
-static int parse_sorting_string(const char *arg, struct ref_sorting **sorting_tail)
-{
- struct ref_sorting *s;
- int len;
-
- s = xcalloc(1, sizeof(*s));
- s->next = *sorting_tail;
- *sorting_tail = s;
-
- if (*arg == '-') {
- s->reverse = 1;
- arg++;
- }
- if (skip_prefix(arg, "version:", &arg) ||
- skip_prefix(arg, "v:", &arg))
- s->version = 1;
-
- len = strlen(arg);
- s->atom = parse_ref_filter_atom(arg, arg+len);
-
- return 0;
-}
-
static int git_tag_config(const char *var, const char *value, void *cb)
{
int status;
@@ -166,7 +144,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "tag.sort")) {
if (!value)
return config_error_nonbool(var);
- parse_sorting_string(value, sorting_tail);
+ parse_ref_sorting(sorting_tail, value);
return 0;
}
@@ -180,7 +158,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)
if (starts_with(var, "column."))
return git_column_config(var, value, "tag", &colopts);
- return git_default_config(var, value, cb);
+ return git_color_default_config(var, value, cb);
}
static void write_tag_body(int fd, const struct object_id *oid)
@@ -392,7 +370,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct strbuf err = STRBUF_INIT;
struct ref_filter filter;
static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
- const char *format = NULL;
+ struct ref_format format = REF_FORMAT_INIT;
int icase = 0;
struct option options[] = {
OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
@@ -431,7 +409,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
parse_opt_object_name, (intptr_t) "HEAD"
},
- OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
+ OPT_STRING( 0 , "format", &format.format, N_("format"),
+ N_("format to use for the output")),
+ OPT__COLOR(&format.use_color, N_("respect format colors")),
OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
OPT_END()
};
@@ -461,6 +441,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
cmdmode = 'l';
}
+ if (cmdmode == 'l')
+ setup_auto_pager("tag", 1);
+
if ((create_tag_object || force) && (cmdmode != 0))
usage_with_options(git_tag_usage, options);
@@ -483,7 +466,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
run_column_filter(colopts, &copts);
}
filter.name_patterns = argv;
- ret = list_tags(&filter, sorting, format);
+ ret = list_tags(&filter, sorting, &format);
if (column_active(colopts))
stop_column_filter();
return ret;
@@ -501,9 +484,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
if (cmdmode == 'd')
return for_each_tag_name(argv, delete_tag, NULL);
if (cmdmode == 'v') {
- if (format)
- verify_ref_format(format);
- return for_each_tag_name(argv, verify_tag, format);
+ if (format.format && verify_ref_format(&format))
+ usage_with_options(git_tag_usage, options);
+ return for_each_tag_name(argv, verify_tag, &format);
}
if (msg.given || msgfile) {
@@ -535,7 +518,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
if (strbuf_check_tag_ref(&ref, tag))
die(_("'%s' is not a valid tag name."), tag);
- if (read_ref(ref.buf, prev.hash))
+ if (read_ref(ref.buf, &prev))
oidclr(&prev);
else if (!force)
die(_("tag '%s' already exists"), tag);
@@ -561,7 +544,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
transaction = ref_transaction_begin(&err);
if (!transaction ||
- ref_transaction_update(transaction, ref.buf, object.hash, prev.hash,
+ ref_transaction_update(transaction, ref.buf, &object, &prev,
create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
reflog_msg.buf, &err) ||
ref_transaction_commit(transaction, &err))
@@ -570,9 +553,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
if (force && !is_null_oid(&prev) && oidcmp(&prev, &object))
printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev.hash, DEFAULT_ABBREV));
- strbuf_release(&err);
- strbuf_release(&buf);
- strbuf_release(&ref);
- strbuf_release(&reflog_msg);
+ UNLEAK(buf);
+ UNLEAK(ref);
+ UNLEAK(reflog_msg);
+ UNLEAK(msg);
+ UNLEAK(err);
return 0;
}
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 73f133419..32e015557 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -1,7 +1,7 @@
#include "builtin.h"
#include "config.h"
-static char *create_temp_file(unsigned char *sha1)
+static char *create_temp_file(struct object_id *oid)
{
static char path[50];
void *buf;
@@ -9,13 +9,13 @@ static char *create_temp_file(unsigned char *sha1)
unsigned long size;
int fd;
- buf = read_sha1_file(sha1, &type, &size);
+ buf = read_sha1_file(oid->hash, &type, &size);
if (!buf || type != OBJ_BLOB)
- die("unable to read blob object %s", sha1_to_hex(sha1));
+ die("unable to read blob object %s", oid_to_hex(oid));
xsnprintf(path, sizeof(path), ".merge_file_XXXXXX");
fd = xmkstemp(path);
- if (write_in_full(fd, buf, size) != size)
+ if (write_in_full(fd, buf, size) < 0)
die_errno("unable to write temp-file");
close(fd);
return path;
@@ -23,15 +23,15 @@ static char *create_temp_file(unsigned char *sha1)
int cmd_unpack_file(int argc, const char **argv, const char *prefix)
{
- unsigned char sha1[20];
+ struct object_id oid;
if (argc != 2 || !strcmp(argv[1], "-h"))
usage("git unpack-file <sha1>");
- if (get_sha1(argv[1], sha1))
+ if (get_oid(argv[1], &oid))
die("Not a valid object name %s", argv[1]);
git_config(git_default_config, NULL);
- puts(create_temp_file(sha1));
+ puts(create_temp_file(&oid));
return 0;
}
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 689a29fac..62ea264c4 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -394,7 +394,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
lo = 0;
hi = nr;
while (lo < hi) {
- mid = (lo + hi)/2;
+ mid = lo + (hi - lo) / 2;
if (base_offset < obj_list[mid].offset) {
hi = mid;
} else if (base_offset > obj_list[mid].offset) {
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 56721cf03..58d1c2d28 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -16,6 +16,7 @@
#include "pathspec.h"
#include "dir.h"
#include "split-index.h"
+#include "fsmonitor.h"
/*
* Default to not allowing changes to the list of files. The
@@ -32,6 +33,7 @@ static int force_remove;
static int verbose;
static int mark_valid_only;
static int mark_skip_worktree_only;
+static int mark_fsmonitor_only;
#define MARK_FLAG 1
#define UNMARK_FLAG 2
static struct strbuf mtime_dir = STRBUF_INIT;
@@ -228,6 +230,7 @@ static int mark_ce_flags(const char *path, int flag, int mark)
int namelen = strlen(path);
int pos = cache_name_pos(path, namelen);
if (0 <= pos) {
+ mark_fsmonitor_invalid(&the_index, active_cache[pos]);
if (mark)
active_cache[pos]->ce_flags |= flag;
else
@@ -280,15 +283,17 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
fill_stat_cache_info(ce, st);
ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
- if (index_path(ce->oid.hash, path, st,
+ if (index_path(&ce->oid, path, st,
info_only ? 0 : HASH_WRITE_OBJECT)) {
free(ce);
return -1;
}
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
- if (add_cache_entry(ce, option))
+ if (add_cache_entry(ce, option)) {
+ free(ce);
return error("%s: cannot add to the index - missing --add option?", path);
+ }
return 0;
}
@@ -326,7 +331,7 @@ static int process_directory(const char *path, int len, struct stat *st)
if (S_ISGITLINK(ce->ce_mode)) {
/* Do nothing to the index if there is no HEAD! */
- if (resolve_gitlink_ref(path, "HEAD", oid.hash) < 0)
+ if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
return 0;
return add_one_path(ce, path, len, st);
@@ -352,7 +357,7 @@ static int process_directory(const char *path, int len, struct stat *st)
}
/* No match - should we add it as a gitlink? */
- if (!resolve_gitlink_ref(path, "HEAD", oid.hash))
+ if (!resolve_gitlink_ref(path, "HEAD", &oid))
return add_one_path(NULL, path, len, st);
/* Error out. */
@@ -458,6 +463,11 @@ static void update_one(const char *path)
die("Unable to mark file %s", path);
return;
}
+ if (mark_fsmonitor_only) {
+ if (mark_ce_flags(path, CE_FSMONITOR_VALID, mark_fsmonitor_only == MARK_FLAG))
+ die("Unable to mark file %s", path);
+ return;
+ }
if (force_remove) {
if (remove_file_from_cache(path))
@@ -677,9 +687,9 @@ static int unresolve_one(const char *path)
static void read_head_pointers(void)
{
- if (read_ref("HEAD", head_oid.hash))
+ if (read_ref("HEAD", &head_oid))
die("No HEAD -- no initial commit yet?");
- if (read_ref("MERGE_HEAD", merge_head_oid.hash)) {
+ if (read_ref("MERGE_HEAD", &merge_head_oid)) {
fprintf(stderr, "Not in the middle of a merge.\n");
exit(0);
}
@@ -719,7 +729,7 @@ static int do_reupdate(int ac, const char **av,
PATHSPEC_PREFER_CWD,
prefix, av + 1);
- if (read_ref("HEAD", head_oid.hash))
+ if (read_ref("HEAD", &head_oid))
/* If there is no HEAD, that means it is an initial
* commit. Update everything in the index.
*/
@@ -915,7 +925,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
struct refresh_params refresh_args = {0, &has_errors};
int lock_error = 0;
int split_index = -1;
- struct lock_file *lock_file;
+ int force_write = 0;
+ int fsmonitor = -1;
+ struct lock_file lock_file = LOCK_INIT;
struct parse_opt_ctx_t ctx;
strbuf_getline_fn getline_fn;
int parseopt_state = PARSE_OPT_UNKNOWN;
@@ -1006,6 +1018,16 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
N_("test if the filesystem supports untracked cache"), UC_TEST),
OPT_SET_INT(0, "force-untracked-cache", &untracked_cache,
N_("enable untracked cache without testing the filesystem"), UC_FORCE),
+ OPT_SET_INT(0, "force-write-index", &force_write,
+ N_("write out the index even if is not flagged as changed"), 1),
+ OPT_BOOL(0, "fsmonitor", &fsmonitor,
+ N_("enable or disable file system monitor")),
+ {OPTION_SET_INT, 0, "fsmonitor-valid", &mark_fsmonitor_only, NULL,
+ N_("mark files as fsmonitor valid"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
+ {OPTION_SET_INT, 0, "no-fsmonitor-valid", &mark_fsmonitor_only, NULL,
+ N_("clear fsmonitor valid bit"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
OPT_END()
};
@@ -1014,11 +1036,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
- /* We can't free this memory, it becomes part of a linked list parsed atexit() */
- lock_file = xcalloc(1, sizeof(struct lock_file));
-
/* we will diagnose later if it turns out that we need to update it */
- newfd = hold_locked_index(lock_file, 0);
+ newfd = hold_locked_index(&lock_file, 0);
if (newfd < 0)
lock_error = errno;
@@ -1147,17 +1166,33 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
die("BUG: bad untracked_cache value: %d", untracked_cache);
}
- if (active_cache_changed) {
+ if (fsmonitor > 0) {
+ if (git_config_get_fsmonitor() == 0)
+ warning(_("core.fsmonitor is unset; "
+ "set it if you really want to "
+ "enable fsmonitor"));
+ add_fsmonitor(&the_index);
+ report(_("fsmonitor enabled"));
+ } else if (!fsmonitor) {
+ if (git_config_get_fsmonitor() == 1)
+ warning(_("core.fsmonitor is set; "
+ "remove it if you really want to "
+ "disable fsmonitor"));
+ remove_fsmonitor(&the_index);
+ report(_("fsmonitor disabled"));
+ }
+
+ if (active_cache_changed || force_write) {
if (newfd < 0) {
if (refresh_args.flags & REFRESH_QUIET)
exit(128);
unable_to_lock_die(get_index_file(), lock_error);
}
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die("Unable to write new index file");
}
- rollback_lock_file(lock_file);
+ rollback_lock_file(&lock_file);
return has_errors ? 1 : 0;
}
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 40ccfc193..4b4714b3f 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -94,10 +94,10 @@ static char *parse_refname(struct strbuf *input, const char **next)
* provided but cannot be converted to a SHA-1, die. flags can
* include PARSE_SHA1_OLD and/or PARSE_SHA1_ALLOW_EMPTY.
*/
-static int parse_next_sha1(struct strbuf *input, const char **next,
- unsigned char *sha1,
- const char *command, const char *refname,
- int flags)
+static int parse_next_oid(struct strbuf *input, const char **next,
+ struct object_id *oid,
+ const char *command, const char *refname,
+ int flags)
{
struct strbuf arg = STRBUF_INIT;
int ret = 0;
@@ -115,11 +115,11 @@ static int parse_next_sha1(struct strbuf *input, const char **next,
(*next)++;
*next = parse_arg(*next, &arg);
if (arg.len) {
- if (get_sha1(arg.buf, sha1))
+ if (get_oid(arg.buf, oid))
goto invalid;
} else {
/* Without -z, an empty value means all zeros: */
- hashclr(sha1);
+ oidclr(oid);
}
} else {
/* With -z, read the next NUL-terminated line */
@@ -133,13 +133,13 @@ static int parse_next_sha1(struct strbuf *input, const char **next,
*next += arg.len;
if (arg.len) {
- if (get_sha1(arg.buf, sha1))
+ if (get_oid(arg.buf, oid))
goto invalid;
} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
/* With -z, treat an empty value as all zeros: */
warning("%s %s: missing <newvalue>, treating as zero",
command, refname);
- hashclr(sha1);
+ oidclr(oid);
} else {
/*
* With -z, an empty non-required value means
@@ -182,26 +182,25 @@ static const char *parse_cmd_update(struct ref_transaction *transaction,
{
struct strbuf err = STRBUF_INIT;
char *refname;
- unsigned char new_sha1[20];
- unsigned char old_sha1[20];
+ struct object_id new_oid, old_oid;
int have_old;
refname = parse_refname(input, &next);
if (!refname)
die("update: missing <ref>");
- if (parse_next_sha1(input, &next, new_sha1, "update", refname,
- PARSE_SHA1_ALLOW_EMPTY))
+ if (parse_next_oid(input, &next, &new_oid, "update", refname,
+ PARSE_SHA1_ALLOW_EMPTY))
die("update %s: missing <newvalue>", refname);
- have_old = !parse_next_sha1(input, &next, old_sha1, "update", refname,
- PARSE_SHA1_OLD);
+ have_old = !parse_next_oid(input, &next, &old_oid, "update", refname,
+ PARSE_SHA1_OLD);
if (*next != line_termination)
die("update %s: extra input: %s", refname, next);
if (ref_transaction_update(transaction, refname,
- new_sha1, have_old ? old_sha1 : NULL,
+ &new_oid, have_old ? &old_oid : NULL,
update_flags | create_reflog_flag,
msg, &err))
die("%s", err.buf);
@@ -218,22 +217,22 @@ static const char *parse_cmd_create(struct ref_transaction *transaction,
{
struct strbuf err = STRBUF_INIT;
char *refname;
- unsigned char new_sha1[20];
+ struct object_id new_oid;
refname = parse_refname(input, &next);
if (!refname)
die("create: missing <ref>");
- if (parse_next_sha1(input, &next, new_sha1, "create", refname, 0))
+ if (parse_next_oid(input, &next, &new_oid, "create", refname, 0))
die("create %s: missing <newvalue>", refname);
- if (is_null_sha1(new_sha1))
+ if (is_null_oid(&new_oid))
die("create %s: zero <newvalue>", refname);
if (*next != line_termination)
die("create %s: extra input: %s", refname, next);
- if (ref_transaction_create(transaction, refname, new_sha1,
+ if (ref_transaction_create(transaction, refname, &new_oid,
update_flags | create_reflog_flag,
msg, &err))
die("%s", err.buf);
@@ -250,18 +249,18 @@ static const char *parse_cmd_delete(struct ref_transaction *transaction,
{
struct strbuf err = STRBUF_INIT;
char *refname;
- unsigned char old_sha1[20];
+ struct object_id old_oid;
int have_old;
refname = parse_refname(input, &next);
if (!refname)
die("delete: missing <ref>");
- if (parse_next_sha1(input, &next, old_sha1, "delete", refname,
- PARSE_SHA1_OLD)) {
+ if (parse_next_oid(input, &next, &old_oid, "delete", refname,
+ PARSE_SHA1_OLD)) {
have_old = 0;
} else {
- if (is_null_sha1(old_sha1))
+ if (is_null_oid(&old_oid))
die("delete %s: zero <oldvalue>", refname);
have_old = 1;
}
@@ -270,7 +269,7 @@ static const char *parse_cmd_delete(struct ref_transaction *transaction,
die("delete %s: extra input: %s", refname, next);
if (ref_transaction_delete(transaction, refname,
- have_old ? old_sha1 : NULL,
+ have_old ? &old_oid : NULL,
update_flags, msg, &err))
die("%s", err.buf);
@@ -286,20 +285,20 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
{
struct strbuf err = STRBUF_INIT;
char *refname;
- unsigned char old_sha1[20];
+ struct object_id old_oid;
refname = parse_refname(input, &next);
if (!refname)
die("verify: missing <ref>");
- if (parse_next_sha1(input, &next, old_sha1, "verify", refname,
- PARSE_SHA1_OLD))
- hashclr(old_sha1);
+ if (parse_next_oid(input, &next, &old_oid, "verify", refname,
+ PARSE_SHA1_OLD))
+ oidclr(&old_oid);
if (*next != line_termination)
die("verify %s: extra input: %s", refname, next);
- if (ref_transaction_verify(transaction, refname, old_sha1,
+ if (ref_transaction_verify(transaction, refname, &old_oid,
update_flags, &err))
die("%s", err.buf);
@@ -313,7 +312,7 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
static const char *parse_cmd_option(struct strbuf *input, const char *next)
{
if (!strncmp(next, "no-deref", 8) && next[8] == line_termination)
- update_flags |= REF_NODEREF;
+ update_flags |= REF_NO_DEREF;
else
die("option unknown: %s", next);
return next + 8;
@@ -355,7 +354,7 @@ static void update_refs_stdin(struct ref_transaction *transaction)
int cmd_update_ref(int argc, const char **argv, const char *prefix)
{
const char *refname, *oldval;
- unsigned char sha1[20], oldsha1[20];
+ struct object_id oid, oldoid;
int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;
unsigned int flags = 0;
int create_reflog = 0;
@@ -412,7 +411,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
refname = argv[0];
value = argv[1];
oldval = argv[2];
- if (get_sha1(value, sha1))
+ if (get_oid(value, &oid))
die("%s: not a valid SHA1", value);
}
@@ -422,23 +421,23 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
* The empty string implies that the reference
* must not already exist:
*/
- hashclr(oldsha1);
- else if (get_sha1(oldval, oldsha1))
+ oidclr(&oldoid);
+ else if (get_oid(oldval, &oldoid))
die("%s: not a valid old SHA1", oldval);
}
if (no_deref)
- flags = REF_NODEREF;
+ flags = REF_NO_DEREF;
if (delete)
/*
* For purposes of backwards compatibility, we treat
* NULL_SHA1 as "don't care" here:
*/
return delete_ref(msg, refname,
- (oldval && !is_null_sha1(oldsha1)) ? oldsha1 : NULL,
+ (oldval && !is_null_oid(&oldoid)) ? &oldoid : NULL,
flags);
else
- return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
+ return update_ref(msg, refname, &oid, oldval ? &oldoid : NULL,
flags | create_reflog_flag,
UPDATE_REFS_DIE_ON_ERR);
}
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index f9a5f7535..ad7b79fa5 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -32,11 +32,11 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
{
int i = 1, verbose = 0, had_error = 0;
unsigned flags = 0;
- char *fmt_pretty = NULL;
+ struct ref_format format = REF_FORMAT_INIT;
const struct option verify_tag_options[] = {
OPT__VERBOSE(&verbose, N_("print tag contents")),
OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
- OPT_STRING( 0 , "format", &fmt_pretty, N_("format"), N_("format to use for the output")),
+ OPT_STRING(0, "format", &format.format, N_("format"), N_("format to use for the output")),
OPT_END()
};
@@ -50,26 +50,29 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
if (verbose)
flags |= GPG_VERIFY_VERBOSE;
- if (fmt_pretty) {
- verify_ref_format(fmt_pretty);
+ if (format.format) {
+ if (verify_ref_format(&format))
+ usage_with_options(verify_tag_usage,
+ verify_tag_options);
flags |= GPG_VERIFY_OMIT_STATUS;
}
while (i < argc) {
- unsigned char sha1[20];
+ struct object_id oid;
const char *name = argv[i++];
- if (get_sha1(name, sha1)) {
+
+ if (get_oid(name, &oid)) {
had_error = !!error("tag '%s' not found.", name);
continue;
}
- if (gpg_verify_tag(sha1, name, flags)) {
+ if (gpg_verify_tag(&oid, name, flags)) {
had_error = 1;
continue;
}
- if (fmt_pretty)
- pretty_print_ref(name, sha1, fmt_pretty);
+ if (format.format)
+ pretty_print_ref(name, oid.hash, &format);
}
return had_error;
}
diff --git a/builtin/worktree.c b/builtin/worktree.c
index c98e2ce5f..ed043d5f1 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -38,7 +38,9 @@ static int prune_worktree(const char *id, struct strbuf *reason)
{
struct stat st;
char *path;
- int fd, len;
+ int fd;
+ size_t len;
+ ssize_t read_result;
if (!is_directory(git_path("worktrees/%s", id))) {
strbuf_addf(reason, _("Removing worktrees/%s: not a valid directory"), id);
@@ -56,10 +58,26 @@ static int prune_worktree(const char *id, struct strbuf *reason)
id, strerror(errno));
return 1;
}
- len = st.st_size;
+ len = xsize_t(st.st_size);
path = xmallocz(len);
- read_in_full(fd, path, len);
+
+ read_result = read_in_full(fd, path, len);
+ if (read_result < 0) {
+ strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"),
+ id, strerror(errno));
+ close(fd);
+ free(path);
+ return 1;
+ }
close(fd);
+
+ if (read_result != len) {
+ strbuf_addf(reason,
+ _("Removing worktrees/%s: short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
+ id, (uintmax_t)len, (uintmax_t)read_result);
+ free(path);
+ return 1;
+ }
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
len--;
if (!len) {
@@ -381,6 +399,8 @@ static int add(int ac, const char **av, const char *prefix)
branch = opts.new_branch;
}
+ UNLEAK(path);
+ UNLEAK(opts);
return add_worktree(path, branch, &opts);
}
@@ -390,7 +410,7 @@ static void show_worktree_porcelain(struct worktree *wt)
if (wt->is_bare)
printf("bare\n");
else {
- printf("HEAD %s\n", sha1_to_hex(wt->head_sha1));
+ printf("HEAD %s\n", oid_to_hex(&wt->head_oid));
if (wt->is_detached)
printf("detached\n");
else if (wt->head_ref)
@@ -410,7 +430,7 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
strbuf_addstr(&sb, "(bare)");
else {
strbuf_addf(&sb, "%-*s ", abbrev_len,
- find_unique_abbrev(wt->head_sha1, DEFAULT_ABBREV));
+ find_unique_abbrev(wt->head_oid.hash, DEFAULT_ABBREV));
if (wt->is_detached)
strbuf_addstr(&sb, "(detached HEAD)");
else if (wt->head_ref) {
@@ -435,7 +455,7 @@ static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
if (path_len > *maxlen)
*maxlen = path_len;
- sha1_len = strlen(find_unique_abbrev(wt[i]->head_sha1, *abbrev));
+ sha1_len = strlen(find_unique_abbrev(wt[i]->head_oid.hash, *abbrev));
if (sha1_len > *abbrev)
*abbrev = sha1_len;
}