aboutsummaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/am.c1
-rw-r--r--builtin/blame.c39
-rw-r--r--builtin/checkout.c3
-rw-r--r--builtin/clone.c11
-rw-r--r--builtin/commit.c2
-rw-r--r--builtin/fast-export.c2
-rw-r--r--builtin/fetch.c10
-rw-r--r--builtin/grep.c60
-rw-r--r--builtin/interpret-trailers.c13
-rw-r--r--builtin/log.c6
-rw-r--r--builtin/merge.c1
-rw-r--r--builtin/notes.c29
-rw-r--r--builtin/pull.c15
-rw-r--r--builtin/push.c2
-rw-r--r--builtin/receive-pack.c3
-rw-r--r--builtin/remote.c10
-rw-r--r--builtin/rm.c2
-rw-r--r--builtin/shortlog.c186
-rw-r--r--builtin/tag.c4
19 files changed, 248 insertions, 151 deletions
diff --git a/builtin/am.c b/builtin/am.c
index 7b8351ded..b55f903f0 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1924,6 +1924,7 @@ next:
*/
if (!state->rebasing) {
am_destroy(state);
+ close_all_packs();
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
}
diff --git a/builtin/blame.c b/builtin/blame.c
index 1df13cf7f..55bf5fae9 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -28,6 +28,7 @@
#include "line-range.h"
#include "line-log.h"
#include "dir.h"
+#include "progress.h"
static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
@@ -50,6 +51,7 @@ static int incremental;
static int xdl_opts;
static int abbrev = -1;
static int no_whole_file_rename;
+static int show_progress;
static struct date_mode blame_date_mode = { DATE_ISO8601 };
static size_t blame_date_width;
@@ -127,6 +129,11 @@ struct origin {
char path[FLEX_ARRAY];
};
+struct progress_info {
+ struct progress *progress;
+ int blamed_lines;
+};
+
static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen,
xdl_emit_hunk_consume_func_t hunk_func, void *cb_data)
{
@@ -1746,7 +1753,8 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
* The blame_entry is found to be guilty for the range.
* Show it in incremental output.
*/
-static void found_guilty_entry(struct blame_entry *ent)
+static void found_guilty_entry(struct blame_entry *ent,
+ struct progress_info *pi)
{
if (incremental) {
struct origin *suspect = ent->suspect;
@@ -1758,6 +1766,8 @@ static void found_guilty_entry(struct blame_entry *ent)
write_filename_info(suspect->path);
maybe_flush_or_die(stdout, "stdout");
}
+ pi->blamed_lines += ent->num_lines;
+ display_progress(pi->progress, pi->blamed_lines);
}
/*
@@ -1768,6 +1778,11 @@ static void assign_blame(struct scoreboard *sb, int opt)
{
struct rev_info *revs = sb->revs;
struct commit *commit = prio_queue_get(&sb->commits);
+ struct progress_info pi = { NULL, 0 };
+
+ if (show_progress)
+ pi.progress = start_progress_delay(_("Blaming lines"),
+ sb->num_lines, 50, 1);
while (commit) {
struct blame_entry *ent;
@@ -1809,7 +1824,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
suspect->guilty = 1;
for (;;) {
struct blame_entry *next = ent->next;
- found_guilty_entry(ent);
+ found_guilty_entry(ent, &pi);
if (next) {
ent = next;
continue;
@@ -1825,6 +1840,8 @@ static void assign_blame(struct scoreboard *sb, int opt)
if (DEBUG) /* sanity */
sanity_check_refcnt(sb);
}
+
+ stop_progress(&pi.progress);
}
static const char *format_time(unsigned long time, const char *tz_str,
@@ -2392,11 +2409,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
ce->ce_mode = create_ce_mode(mode);
add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
- /*
- * We are not going to write this out, so this does not matter
- * right now, but someday we might optimize diff-index --cached
- * with cache-tree information.
- */
cache_tree_invalidate_path(&the_index, path);
return commit;
@@ -2520,6 +2532,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
+ OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")),
OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
@@ -2555,6 +2568,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
dashdash_pos = 0;
+ show_progress = -1;
parse_options_start(&ctx, argc, argv, prefix, options,
PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
@@ -2579,6 +2593,13 @@ parse_done:
DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES);
argc = parse_options_end(&ctx);
+ if (incremental || (output_option & OUTPUT_PORCELAIN)) {
+ if (show_progress > 0)
+ die("--progress can't be used with --incremental or porcelain formats");
+ show_progress = 0;
+ } else if (show_progress < 0)
+ show_progress = isatty(2);
+
if (0 < abbrev)
/* one more abbrev length is needed for the boundary commit */
abbrev++;
@@ -2828,11 +2849,11 @@ parse_done:
read_mailmap(&mailmap, NULL);
+ assign_blame(&sb, opt);
+
if (!incremental)
setup_pager();
- assign_blame(&sb, opt);
-
free(final_commit_name);
if (incremental)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index e8110a924..5af84a311 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -661,7 +661,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
describe_detached_head(_("HEAD is now at"), new->commit);
}
} else if (new->path) { /* Switch branches. */
- create_symref("HEAD", new->path, msg.buf);
+ if (create_symref("HEAD", new->path, msg.buf) < 0)
+ die("unable to update HEAD");
if (!opts->quiet) {
if (old->path && !strcmp(new->path, old->path)) {
if (opts->new_branch_force)
diff --git a/builtin/clone.c b/builtin/clone.c
index 43b4c99b6..bcba0805e 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -636,9 +636,11 @@ static void update_remote_refs(const struct ref *refs,
struct strbuf head_ref = STRBUF_INIT;
strbuf_addstr(&head_ref, branch_top);
strbuf_addstr(&head_ref, "HEAD");
- create_symref(head_ref.buf,
- remote_head_points_at->peer_ref->name,
- msg);
+ if (create_symref(head_ref.buf,
+ remote_head_points_at->peer_ref->name,
+ msg) < 0)
+ die("unable to update %s", head_ref.buf);
+ strbuf_release(&head_ref);
}
}
@@ -648,7 +650,8 @@ static void update_head(const struct ref *our, const struct ref *remote,
const char *head;
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
- create_symref("HEAD", our->name, NULL);
+ 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_REFS_DIE_ON_ERR);
diff --git a/builtin/commit.c b/builtin/commit.c
index d9db59e1d..b3bd2d418 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -761,7 +761,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
hook_arg2 = "";
}
- s->fp = fopen(git_path(commit_editmsg), "w");
+ s->fp = fopen_for_writing(git_path(commit_editmsg));
if (s->fp == NULL)
die_errno(_("could not open '%s'"), git_path(commit_editmsg));
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d9ac5d841..2471297f7 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -880,7 +880,7 @@ static void export_marks(char *file)
FILE *f;
int e = 0;
- f = fopen(file, "w");
+ f = fopen_for_writing(file);
if (!f)
die_errno("Unable to open marks file %s for writing.", file);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c85f3471d..8e742135f 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -37,6 +37,7 @@ static int prune = -1; /* unspecified */
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int tags = TAGS_DEFAULT, unshallow, update_shallow;
+static int max_children = 1;
static const char *depth;
static const char *upload_pack;
static struct strbuf default_rla = STRBUF_INIT;
@@ -99,6 +100,8 @@ static struct option builtin_fetch_options[] = {
N_("fetch all tags and associated objects"), TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
+ OPT_INTEGER('j', "jobs", &max_children,
+ N_("number of submodules fetched in parallel")),
OPT_BOOL('p', "prune", &prune,
N_("prune remote-tracking branches no longer on remote")),
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
@@ -837,7 +840,7 @@ static void check_not_current_branch(struct ref *ref_map)
static int truncate_fetch_head(void)
{
const char *filename = git_path_fetch_head();
- FILE *fp = fopen(filename, "w");
+ FILE *fp = fopen_for_writing(filename);
if (!fp)
return error(_("cannot open %s: %s\n"), filename, strerror(errno));
@@ -1213,7 +1216,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
result = fetch_populated_submodules(&options,
submodule_prefix,
recurse_submodules,
- verbosity < 0);
+ verbosity < 0,
+ max_children);
argv_array_clear(&options);
}
@@ -1221,6 +1225,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
list.strdup_strings = 1;
string_list_clear(&list, 0);
+ close_all_packs();
+
argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
if (verbosity < 0)
argv_array_push(&argv_gc_auto, "--quiet");
diff --git a/builtin/grep.c b/builtin/grep.c
index 801ce60e4..8c516a954 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -24,11 +24,11 @@ static char const * const grep_usage[] = {
NULL
};
-static int use_threads = 1;
+#define GREP_NUM_THREADS_DEFAULT 8
+static int num_threads;
#ifndef NO_PTHREADS
-#define THREADS 8
-static pthread_t threads[THREADS];
+static pthread_t *threads;
/* We use one producer thread and THREADS consumer
* threads. The producer adds struct work_items to 'todo' and the
@@ -63,13 +63,13 @@ static pthread_mutex_t grep_mutex;
static inline void grep_lock(void)
{
- if (use_threads)
+ if (num_threads)
pthread_mutex_lock(&grep_mutex);
}
static inline void grep_unlock(void)
{
- if (use_threads)
+ if (num_threads)
pthread_mutex_unlock(&grep_mutex);
}
@@ -206,7 +206,8 @@ static void start_threads(struct grep_opt *opt)
strbuf_init(&todo[i].out, 0);
}
- for (i = 0; i < ARRAY_SIZE(threads); i++) {
+ threads = xcalloc(num_threads, sizeof(*threads));
+ for (i = 0; i < num_threads; i++) {
int err;
struct grep_opt *o = grep_opt_dup(opt);
o->output = strbuf_out;
@@ -238,12 +239,14 @@ static int wait_all(void)
pthread_cond_broadcast(&cond_add);
grep_unlock();
- for (i = 0; i < ARRAY_SIZE(threads); i++) {
+ for (i = 0; i < num_threads; i++) {
void *h;
pthread_join(threads[i], &h);
hit |= (int) (intptr_t) h;
}
+ free(threads);
+
pthread_mutex_destroy(&grep_mutex);
pthread_mutex_destroy(&grep_read_mutex);
pthread_mutex_destroy(&grep_attr_mutex);
@@ -267,6 +270,14 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
int st = grep_config(var, value, cb);
if (git_color_default_config(var, value, cb) < 0)
st = -1;
+
+ if (!strcmp(var, "grep.threads")) {
+ num_threads = git_config_int(var, value);
+ if (num_threads < 0)
+ die(_("invalid number of threads specified (%d) for %s"),
+ num_threads, var);
+ }
+
return st;
}
@@ -294,7 +305,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
}
#ifndef NO_PTHREADS
- if (use_threads) {
+ if (num_threads) {
add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
strbuf_release(&pathbuf);
return 0;
@@ -323,7 +334,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
strbuf_addstr(&buf, filename);
#ifndef NO_PTHREADS
- if (use_threads) {
+ if (num_threads) {
add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
strbuf_release(&buf);
return 0;
@@ -375,7 +386,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
for (nr = 0; nr < active_nr; nr++) {
const struct cache_entry *ce = active_cache[nr];
- if (!S_ISREG(ce->ce_mode))
+ if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce))
continue;
if (!ce_path_match(ce, pathspec, NULL))
continue;
@@ -697,6 +708,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
N_("show <n> context lines before matches")),
OPT_INTEGER('A', "after-context", &opt.post_context,
N_("show <n> context lines after matches")),
+ OPT_INTEGER(0, "threads", &num_threads,
+ N_("use <n> worker threads")),
OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
context_callback),
OPT_BOOL('p', "show-function", &opt.funcname,
@@ -755,9 +768,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
PARSE_OPT_STOP_AT_NON_OPTION);
grep_commit_pattern_type(pattern_type_arg, &opt);
- if (use_index && !startup_info->have_repository)
- /* die the same way as if we did it at the beginning */
- setup_git_directory();
+ if (use_index && !startup_info->have_repository) {
+ int fallback = 0;
+ git_config_get_bool("grep.fallbacktonoindex", &fallback);
+ if (fallback)
+ use_index = 0;
+ else
+ /* die the same way as if we did it at the beginning */
+ setup_git_directory();
+ }
/*
* skip a -- separator; we know it cannot be
@@ -786,7 +805,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.output_priv = &path_list;
opt.output = append_path;
string_list_append(&path_list, show_in_pager);
- use_threads = 0;
}
if (!opt.pattern_list)
@@ -817,14 +835,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
#ifndef NO_PTHREADS
- if (list.nr || cached || online_cpus() == 1)
- use_threads = 0;
+ if (list.nr || cached || show_in_pager)
+ num_threads = 0;
+ else if (num_threads == 0)
+ num_threads = GREP_NUM_THREADS_DEFAULT;
+ else if (num_threads < 0)
+ die(_("invalid number of threads specified (%d)"), num_threads);
#else
- use_threads = 0;
+ num_threads = 0;
#endif
#ifndef NO_PTHREADS
- if (use_threads) {
+ if (num_threads) {
if (!(opt.name_only || opt.unmatch_name_only || opt.count)
&& (opt.pre_context || opt.post_context ||
opt.file_break || opt.funcbody))
@@ -894,7 +916,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
hit = grep_objects(&opt, &pathspec, &list);
}
- if (use_threads)
+ if (num_threads)
hit |= wait_all();
if (hit && show_in_pager)
run_pager(&opt, prefix);
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 46838d24a..b99ae4be8 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -12,16 +12,18 @@
#include "trailer.h"
static const char * const git_interpret_trailers_usage[] = {
- N_("git interpret-trailers [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"),
+ N_("git interpret-trailers [--in-place] [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"),
NULL
};
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_DUP;
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")),
@@ -34,9 +36,12 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
if (argc) {
int i;
for (i = 0; i < argc; i++)
- process_trailers(argv[i], trim_empty, &trailers);
- } else
- process_trailers(NULL, trim_empty, &trailers);
+ process_trailers(argv[i], in_place, trim_empty, &trailers);
+ } else {
+ if (in_place)
+ die(_("no input file given for in-place editing"));
+ process_trailers(NULL, in_place, trim_empty, &trailers);
+ }
string_list_clear(&trailers, 0);
diff --git a/builtin/log.c b/builtin/log.c
index e00cea75c..0d738d6dd 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -699,6 +699,7 @@ static int do_signoff;
static const char *signature = git_version_string;
static const char *signature_file;
static int config_cover_letter;
+static const char *config_output_directory;
enum {
COVER_UNSET,
@@ -777,6 +778,8 @@ static int git_format_config(const char *var, const char *value, void *cb)
config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
return 0;
}
+ if (!strcmp(var, "format.outputdirectory"))
+ return git_config_string(&config_output_directory, var, value);
return git_log_config(var, value, cb);
}
@@ -1391,6 +1394,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (rev.show_notes)
init_display_notes(&rev.notes_opt);
+ if (!output_directory && !use_stdout)
+ output_directory = config_output_directory;
+
if (!use_stdout)
output_directory = set_outdir(prefix, output_directory);
else
diff --git a/builtin/merge.c b/builtin/merge.c
index 15bf95b3a..b98a3489b 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -404,6 +404,7 @@ static void finish(struct commit *head_commit,
* We ignore errors in 'gc --auto', since the
* user should see them.
*/
+ close_all_packs();
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
}
diff --git a/builtin/notes.c b/builtin/notes.c
index 3775e3896..9d54934d6 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -286,7 +286,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
if (!c)
return 0;
} else {
- init_notes(NULL, NULL, NULL, 0);
+ init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE);
t = &default_notes_tree;
}
@@ -329,15 +329,18 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
return ret;
}
-static struct notes_tree *init_notes_check(const char *subcommand)
+static struct notes_tree *init_notes_check(const char *subcommand,
+ int flags)
{
struct notes_tree *t;
- init_notes(NULL, NULL, NULL, 0);
+ const char *ref;
+ init_notes(NULL, NULL, NULL, flags);
t = &default_notes_tree;
- if (!starts_with(t->ref, "refs/notes/"))
+ ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref;
+ if (!starts_with(ref, "refs/notes/"))
die("Refusing to %s notes in %s (outside of refs/notes/)",
- subcommand, t->ref);
+ subcommand, ref);
return t;
}
@@ -360,7 +363,7 @@ static int list(int argc, const char **argv, const char *prefix)
usage_with_options(git_notes_list_usage, options);
}
- t = init_notes_check("list");
+ t = init_notes_check("list", 0);
if (argc) {
if (get_sha1(argv[0], object))
die(_("Failed to resolve '%s' as a valid ref."), argv[0]);
@@ -420,7 +423,7 @@ static int add(int argc, const char **argv, const char *prefix)
if (get_sha1(object_ref, object))
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
- t = init_notes_check("add");
+ t = init_notes_check("add", NOTES_INIT_WRITABLE);
note = get_note(t, object);
if (note) {
@@ -511,7 +514,7 @@ static int copy(int argc, const char **argv, const char *prefix)
if (get_sha1(object_ref, object))
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
- t = init_notes_check("copy");
+ t = init_notes_check("copy", NOTES_INIT_WRITABLE);
note = get_note(t, object);
if (note) {
@@ -589,7 +592,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
if (get_sha1(object_ref, object))
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
- t = init_notes_check(argv[0]);
+ t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
note = get_note(t, object);
prepare_note_data(object, &d, edit ? note : NULL);
@@ -652,7 +655,7 @@ static int show(int argc, const char **argv, const char *prefix)
if (get_sha1(object_ref, object))
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
- t = init_notes_check("show");
+ t = init_notes_check("show", 0);
note = get_note(t, object);
if (!note)
@@ -809,7 +812,7 @@ static int merge(int argc, const char **argv, const char *prefix)
expand_notes_ref(&remote_ref);
o.remote_ref = remote_ref.buf;
- t = init_notes_check("merge");
+ t = init_notes_check("merge", NOTES_INIT_WRITABLE);
if (strategy) {
if (parse_notes_merge_strategy(strategy, &o.strategy)) {
@@ -901,7 +904,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options,
git_notes_remove_usage, 0);
- t = init_notes_check("remove");
+ t = init_notes_check("remove", NOTES_INIT_WRITABLE);
if (!argc && !from_stdin) {
retval = remove_one_note(t, "HEAD", flag);
@@ -943,7 +946,7 @@ static int prune(int argc, const char **argv, const char *prefix)
usage_with_options(git_notes_prune_usage, options);
}
- t = init_notes_check("prune");
+ t = init_notes_check("prune", NOTES_INIT_WRITABLE);
prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) |
(show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) );
diff --git a/builtin/pull.c b/builtin/pull.c
index 52606a84c..10eff0396 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -22,7 +22,8 @@ enum rebase_type {
REBASE_INVALID = -1,
REBASE_FALSE = 0,
REBASE_TRUE,
- REBASE_PRESERVE
+ REBASE_PRESERVE,
+ REBASE_INTERACTIVE
};
/**
@@ -42,6 +43,8 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
return REBASE_TRUE;
else if (!strcmp(value, "preserve"))
return REBASE_PRESERVE;
+ else if (!strcmp(value, "interactive"))
+ return REBASE_INTERACTIVE;
if (fatal)
die(_("Invalid value for %s: %s"), key, value);
@@ -95,6 +98,7 @@ static int opt_force;
static char *opt_tags;
static char *opt_prune;
static char *opt_recurse_submodules;
+static char *max_children;
static int opt_dry_run;
static char *opt_keep;
static char *opt_depth;
@@ -112,7 +116,7 @@ static struct option pull_options[] = {
/* Options passed to git-merge or git-rebase */
OPT_GROUP(N_("Options related to merging")),
{ OPTION_CALLBACK, 'r', "rebase", &opt_rebase,
- "false|true|preserve",
+ "false|true|preserve|interactive",
N_("incorporate changes by rebasing rather than merging"),
PARSE_OPT_OPTARG, parse_opt_rebase },
OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
@@ -178,6 +182,9 @@ static struct option pull_options[] = {
N_("on-demand"),
N_("control recursive fetching of submodules"),
PARSE_OPT_OPTARG),
+ OPT_PASSTHRU('j', "jobs", &max_children, N_("n"),
+ N_("number of submodules pulled in parallel"),
+ PARSE_OPT_OPTARG),
OPT_BOOL(0, "dry-run", &opt_dry_run,
N_("dry run")),
OPT_PASSTHRU('k', "keep", &opt_keep, NULL,
@@ -525,6 +532,8 @@ static int run_fetch(const char *repo, const char **refspecs)
argv_array_push(&args, opt_prune);
if (opt_recurse_submodules)
argv_array_push(&args, opt_recurse_submodules);
+ if (max_children)
+ argv_array_push(&args, max_children);
if (opt_dry_run)
argv_array_push(&args, "--dry-run");
if (opt_keep)
@@ -772,6 +781,8 @@ static int run_rebase(const unsigned char *curr_head,
/* Options passed to git-rebase */
if (opt_rebase == REBASE_PRESERVE)
argv_array_push(&args, "--preserve-merges");
+ else if (opt_rebase == REBASE_INTERACTIVE)
+ argv_array_push(&args, "--interactive");
if (opt_diffstat)
argv_array_push(&args, opt_diffstat);
argv_array_pushv(&args, opt_strategies.argv);
diff --git a/builtin/push.c b/builtin/push.c
index 8963dbdf3..960ffc31e 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -538,7 +538,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
- OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
+ OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ca3813187..f2d6761af 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1618,7 +1618,7 @@ static void prepare_shallow_update(struct command *commands,
continue;
si->need_reachability_test[i]++;
for (k = 0; k < 32; k++)
- if (si->used_shallow[i][j] & (1 << k))
+ if (si->used_shallow[i][j] & (1U << k))
si->shallow_ref[j * 32 + k]++;
}
@@ -1796,6 +1796,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
"gc", "--auto", "--quiet", NULL,
};
int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR;
+ close_all_packs();
run_command_v_opt(argv_gc_auto, opt);
}
if (auto_update_server_info)
diff --git a/builtin/remote.c b/builtin/remote.c
index 6694cf20e..2b2ff9b7d 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -251,7 +251,7 @@ static int add(int argc, const char **argv)
struct branch_info {
char *remote_name;
struct string_list merge;
- int rebase;
+ enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase;
};
static struct string_list branch_list;
@@ -311,7 +311,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
if (v >= 0)
info->rebase = v;
else if (!strcmp(value, "preserve"))
- info->rebase = 1;
+ info->rebase = NORMAL_REBASE;
+ else if (!strcmp(value, "interactive"))
+ info->rebase = INTERACTIVE_REBASE;
}
}
return 0;
@@ -980,7 +982,9 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
printf(" %-*s ", show_info->width, item->string);
if (branch_info->rebase) {
- printf_ln(_("rebases onto remote %s"), merge->items[0].string);
+ printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ?
+ "rebases interactively onto remote %s" :
+ "rebases onto remote %s"), merge->items[0].string);
return 0;
} else if (show_info->any_rebase) {
printf_ln(_(" merges with remote %s"), merge->items[0].string);
diff --git a/builtin/rm.c b/builtin/rm.c
index 80b972f92..8829b09d0 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -211,7 +211,7 @@ static int check_local_mod(unsigned char *head, int index_only)
* "intent to add" entry.
*/
if (local_changes && staged_changes) {
- if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
+ if (!index_only || !ce_intent_to_add(ce))
string_list_append(&files_staged, name);
}
else if (!index_only) {
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 35ebd17f8..bfc082e58 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -14,7 +14,26 @@ static char const * const shortlog_usage[] = {
NULL
};
-static int compare_by_number(const void *a1, const void *a2)
+/*
+ * The util field of our string_list_items will contain one of two things:
+ *
+ * - if --summary is not in use, it will point to a string list of the
+ * oneline subjects assigned to this author
+ *
+ * - if --summary is in use, we don't need that list; we only need to know
+ * its size. So we abuse the pointer slot to store our integer counter.
+ *
+ * This macro accesses the latter.
+ */
+#define UTIL_TO_INT(x) ((intptr_t)(x)->util)
+
+static int compare_by_counter(const void *a1, const void *a2)
+{
+ const struct string_list_item *i1 = a1, *i2 = a2;
+ return UTIL_TO_INT(i2) - UTIL_TO_INT(i1);
+}
+
+static int compare_by_list(const void *a1, const void *a2)
{
const struct string_list_item *i1 = a1, *i2 = a2;
const struct string_list *l1 = i1->util, *l2 = i2->util;
@@ -31,13 +50,9 @@ static void insert_one_record(struct shortlog *log,
const char *author,
const char *oneline)
{
- const char *dot3 = log->common_repo_prefix;
- char *buffer, *p;
struct string_list_item *item;
const char *mailbuf, *namebuf;
size_t namelen, maillen;
- const char *eol;
- struct strbuf subject = STRBUF_INIT;
struct strbuf namemailbuf = STRBUF_INIT;
struct ident_split ident;
@@ -56,98 +71,95 @@ static void insert_one_record(struct shortlog *log,
strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
item = string_list_insert(&log->list, namemailbuf.buf);
- if (item->util == NULL)
- item->util = xcalloc(1, sizeof(struct string_list));
-
- /* Skip any leading whitespace, including any blank lines. */
- while (*oneline && isspace(*oneline))
- oneline++;
- eol = strchr(oneline, '\n');
- if (!eol)
- eol = oneline + strlen(oneline);
- if (starts_with(oneline, "[PATCH")) {
- char *eob = strchr(oneline, ']');
- if (eob && (!eol || eob < eol))
- oneline = eob + 1;
- }
- while (*oneline && isspace(*oneline) && *oneline != '\n')
- oneline++;
- format_subject(&subject, oneline, " ");
- buffer = strbuf_detach(&subject, NULL);
-
- if (dot3) {
- int dot3len = strlen(dot3);
- if (dot3len > 5) {
- while ((p = strstr(buffer, dot3)) != NULL) {
- int taillen = strlen(p) - dot3len;
- memcpy(p, "/.../", 5);
- memmove(p + 5, p + dot3len, taillen + 1);
+
+ if (log->summary)
+ item->util = (void *)(UTIL_TO_INT(item) + 1);
+ else {
+ const char *dot3 = log->common_repo_prefix;
+ char *buffer, *p;
+ struct strbuf subject = STRBUF_INIT;
+ const char *eol;
+
+ /* Skip any leading whitespace, including any blank lines. */
+ while (*oneline && isspace(*oneline))
+ oneline++;
+ eol = strchr(oneline, '\n');
+ if (!eol)
+ eol = oneline + strlen(oneline);
+ if (starts_with(oneline, "[PATCH")) {
+ char *eob = strchr(oneline, ']');
+ if (eob && (!eol || eob < eol))
+ oneline = eob + 1;
+ }
+ while (*oneline && isspace(*oneline) && *oneline != '\n')
+ oneline++;
+ format_subject(&subject, oneline, " ");
+ buffer = strbuf_detach(&subject, NULL);
+
+ if (dot3) {
+ int dot3len = strlen(dot3);
+ if (dot3len > 5) {
+ while ((p = strstr(buffer, dot3)) != NULL) {
+ int taillen = strlen(p) - dot3len;
+ memcpy(p, "/.../", 5);
+ memmove(p + 5, p + dot3len, taillen + 1);
+ }
}
}
- }
- string_list_append(item->util, buffer);
+ if (item->util == NULL)
+ item->util = xcalloc(1, sizeof(struct string_list));
+ string_list_append(item->util, buffer);
+ }
}
static void read_from_stdin(struct shortlog *log)
{
- char author[1024], oneline[1024];
+ struct strbuf author = STRBUF_INIT;
+ struct strbuf oneline = STRBUF_INIT;
- while (fgets(author, sizeof(author), stdin) != NULL) {
- if (!(author[0] == 'A' || author[0] == 'a') ||
- !starts_with(author + 1, "uthor: "))
+ while (strbuf_getline_lf(&author, stdin) != EOF) {
+ const char *v;
+ if (!skip_prefix(author.buf, "Author: ", &v) &&
+ !skip_prefix(author.buf, "author ", &v))
continue;
- while (fgets(oneline, sizeof(oneline), stdin) &&
- oneline[0] != '\n')
+ while (strbuf_getline_lf(&oneline, stdin) != EOF &&
+ oneline.len)
; /* discard headers */
- while (fgets(oneline, sizeof(oneline), stdin) &&
- oneline[0] == '\n')
+ while (strbuf_getline_lf(&oneline, stdin) != EOF &&
+ !oneline.len)
; /* discard blanks */
- insert_one_record(log, author + 8, oneline);
+ insert_one_record(log, v, oneline.buf);
}
+ strbuf_release(&author);
+ strbuf_release(&oneline);
}
void shortlog_add_commit(struct shortlog *log, struct commit *commit)
{
- const char *author = NULL, *buffer;
- struct strbuf buf = STRBUF_INIT;
- struct strbuf ufbuf = STRBUF_INIT;
-
- pp_commit_easy(CMIT_FMT_RAW, commit, &buf);
- buffer = buf.buf;
- while (*buffer && *buffer != '\n') {
- const char *eol = strchr(buffer, '\n');
-
- if (eol == NULL)
- eol = buffer + strlen(buffer);
+ struct strbuf author = STRBUF_INIT;
+ struct strbuf oneline = STRBUF_INIT;
+ struct pretty_print_context ctx = {0};
+
+ ctx.fmt = CMIT_FMT_USERFORMAT;
+ ctx.abbrev = log->abbrev;
+ ctx.subject = "";
+ ctx.after_subject = "";
+ ctx.date_mode.type = DATE_NORMAL;
+ ctx.output_encoding = get_log_output_encoding();
+
+ format_commit_message(commit, "%an <%ae>", &author, &ctx);
+ if (!log->summary) {
+ if (log->user_format)
+ pretty_print_commit(&ctx, commit, &oneline);
else
- eol++;
-
- if (starts_with(buffer, "author "))
- author = buffer + 7;
- buffer = eol;
- }
- if (!author) {
- warning(_("Missing author: %s"),
- oid_to_hex(&commit->object.oid));
- return;
+ format_commit_message(commit, "%s", &oneline, &ctx);
}
- if (log->user_format) {
- struct pretty_print_context ctx = {0};
- ctx.fmt = CMIT_FMT_USERFORMAT;
- ctx.abbrev = log->abbrev;
- ctx.subject = "";
- ctx.after_subject = "";
- ctx.date_mode.type = DATE_NORMAL;
- ctx.output_encoding = get_log_output_encoding();
- pretty_print_commit(&ctx, commit, &ufbuf);
- buffer = ufbuf.buf;
- } else if (*buffer) {
- buffer++;
- }
- insert_one_record(log, author, !*buffer ? "<none>" : buffer);
- strbuf_release(&ufbuf);
- strbuf_release(&buf);
+
+ insert_one_record(log, author.buf, oneline.len ? oneline.buf : "<none>");
+
+ strbuf_release(&author);
+ strbuf_release(&oneline);
}
static void get_from_rev(struct rev_info *rev, struct shortlog *log)
@@ -294,14 +306,14 @@ void shortlog_output(struct shortlog *log)
if (log->sort_by_number)
qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
- compare_by_number);
+ log->summary ? compare_by_counter : compare_by_list);
for (i = 0; i < log->list.nr; i++) {
- struct string_list *onelines = log->list.items[i].util;
-
+ const struct string_list_item *item = &log->list.items[i];
if (log->summary) {
- printf("%6d\t%s\n", onelines->nr, log->list.items[i].string);
+ printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
} else {
- printf("%s (%d):\n", log->list.items[i].string, onelines->nr);
+ struct string_list *onelines = item->util;
+ printf("%s (%d):\n", item->string, onelines->nr);
for (j = onelines->nr - 1; j >= 0; j--) {
const char *msg = onelines->items[j].string;
@@ -314,11 +326,11 @@ void shortlog_output(struct shortlog *log)
printf(" %s\n", msg);
}
putchar('\n');
+ onelines->strdup_strings = 1;
+ string_list_clear(onelines, 0);
+ free(onelines);
}
- onelines->strdup_strings = 1;
- string_list_clear(onelines, 0);
- free(onelines);
log->list.items[i].util = NULL;
}
diff --git a/builtin/tag.c b/builtin/tag.c
index 8db8c87e5..1705c9466 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -44,11 +44,11 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con
if (!format) {
if (filter->lines) {
to_free = xstrfmt("%s %%(contents:lines=%d)",
- "%(align:15)%(refname:short)%(end)",
+ "%(align:15)%(refname:strip=2)%(end)",
filter->lines);
format = to_free;
} else
- format = "%(refname:short)";
+ format = "%(refname:strip=2)";
}
verify_ref_format(format);