aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/apply.c16
-rw-r--r--builtin/branch.c4
-rw-r--r--builtin/checkout.c43
-rw-r--r--builtin/clone.c54
-rw-r--r--builtin/commit-tree.c2
-rw-r--r--builtin/fast-export.c11
-rw-r--r--builtin/log.c3
-rw-r--r--builtin/merge.c50
-rw-r--r--builtin/push.c2
9 files changed, 162 insertions, 23 deletions
diff --git a/builtin/apply.c b/builtin/apply.c
index 06f5320b18..5b882d01f6 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -2117,10 +2117,10 @@ static void update_pre_post_images(struct image *preimage,
/*
* Adjust the common context lines in postimage. This can be
- * done in-place when we are just doing whitespace fixing,
- * which does not make the string grow, but needs a new buffer
- * when ignoring whitespace causes the update, since in this case
- * we could have e.g. tabs converted to multiple spaces.
+ * done in-place when we are shrinking it with whitespace
+ * fixing, but needs a new buffer when ignoring whitespace or
+ * expanding leading tabs to spaces.
+ *
* We trust the caller to tell us if the update can be done
* in place (postlen==0) or not.
*/
@@ -2185,7 +2185,7 @@ static int match_fragment(struct image *img,
int i;
char *fixed_buf, *buf, *orig, *target;
struct strbuf fixed;
- size_t fixed_len;
+ size_t fixed_len, postlen;
int preimage_limit;
if (preimage->nr + try_lno <= img->nr) {
@@ -2335,6 +2335,7 @@ static int match_fragment(struct image *img,
strbuf_init(&fixed, preimage->len + 1);
orig = preimage->buf;
target = img->buf + try;
+ postlen = 0;
for (i = 0; i < preimage_limit; i++) {
size_t oldlen = preimage->line[i].len;
size_t tgtlen = img->line[try_lno + i].len;
@@ -2362,6 +2363,7 @@ static int match_fragment(struct image *img,
match = (tgtfix.len == fixed.len - fixstart &&
!memcmp(tgtfix.buf, fixed.buf + fixstart,
fixed.len - fixstart));
+ postlen += tgtfix.len;
strbuf_release(&tgtfix);
if (!match)
@@ -2399,8 +2401,10 @@ static int match_fragment(struct image *img,
* hunk match. Update the context lines in the postimage.
*/
fixed_buf = strbuf_detach(&fixed, &fixed_len);
+ if (postlen < postimage->len)
+ postlen = 0;
update_pre_post_images(preimage, postimage,
- fixed_buf, fixed_len, 0);
+ fixed_buf, fixed_len, postlen);
return 1;
unmatch_exit:
diff --git a/builtin/branch.c b/builtin/branch.c
index e09ce51c2e..3f0fbc082a 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -904,7 +904,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (edit_branch_description(branch_name))
return 1;
} else if (rename) {
- if (argc == 1)
+ if (!argc)
+ die(_("branch name required"));
+ else if (argc == 1)
rename_branch(head, argv[0], rename > 1);
else if (argc == 2)
rename_branch(argv[0], argv[1], rename > 1);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index a9c1b5a95f..f8033f446e 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -271,24 +271,55 @@ static int checkout_paths(const struct checkout_opts *opts,
;
ps_matched = xcalloc(1, pos);
+ /*
+ * Make sure all pathspecs participated in locating the paths
+ * to be checked out.
+ */
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
+ ce->ce_flags &= ~CE_MATCHED;
if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
+ /*
+ * "git checkout tree-ish -- path", but this entry
+ * is in the original index; it will not be checked
+ * out to the working tree and it does not matter
+ * if pathspec matched this entry. We will not do
+ * anything to this entry at all.
+ */
continue;
- match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
+ /*
+ * Either this entry came from the tree-ish we are
+ * checking the paths out of, or we are checking out
+ * of the index.
+ *
+ * If it comes from the tree-ish, we already know it
+ * matches the pathspec and could just stamp
+ * CE_MATCHED to it from update_some(). But we still
+ * need ps_matched and read_tree_recursive (and
+ * eventually tree_entry_interesting) cannot fill
+ * ps_matched yet. Once it can, we can avoid calling
+ * match_pathspec() for _all_ entries when
+ * opts->source_tree != NULL.
+ */
+ if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce),
+ 0, ps_matched))
+ ce->ce_flags |= CE_MATCHED;
}
- if (report_path_error(ps_matched, opts->pathspec, opts->prefix))
+ if (report_path_error(ps_matched, opts->pathspec, opts->prefix)) {
+ free(ps_matched);
return 1;
+ }
+ free(ps_matched);
/* "checkout -m path" to recreate conflicted state */
if (opts->merge)
- unmerge_cache(opts->pathspec);
+ unmerge_marked_index(&the_index);
/* Any unmerged paths? */
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
- if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
+ if (ce->ce_flags & CE_MATCHED) {
if (!ce_stage(ce))
continue;
if (opts->force) {
@@ -313,9 +344,7 @@ static int checkout_paths(const struct checkout_opts *opts,
state.refresh_cache = 1;
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
- if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
- continue;
- if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
+ if (ce->ce_flags & CE_MATCHED) {
if (!ce_stage(ce)) {
errs |= checkout_entry(ce, &state, NULL);
continue;
diff --git a/builtin/clone.c b/builtin/clone.c
index e0aaf13583..f9c380eb6c 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -23,6 +23,7 @@
#include "branch.h"
#include "remote.h"
#include "run-command.h"
+#include "connected.h"
/*
* Overall FIXMEs:
@@ -376,10 +377,32 @@ static void clone_local(const char *src_repo, const char *dest_repo)
static const char *junk_work_tree;
static const char *junk_git_dir;
static pid_t junk_pid;
+enum {
+ JUNK_LEAVE_NONE,
+ JUNK_LEAVE_REPO,
+ JUNK_LEAVE_ALL
+} junk_mode = JUNK_LEAVE_NONE;
+
+static const char junk_leave_repo_msg[] =
+N_("Clone succeeded, but checkout failed.\n"
+ "You can inspect what was checked out with 'git status'\n"
+ "and retry the checkout with 'git checkout -f HEAD'\n");
static void remove_junk(void)
{
struct strbuf sb = STRBUF_INIT;
+
+ switch (junk_mode) {
+ case JUNK_LEAVE_REPO:
+ warning("%s", _(junk_leave_repo_msg));
+ /* fall-through */
+ case JUNK_LEAVE_ALL:
+ return;
+ default:
+ /* proceed to removal */
+ break;
+ }
+
if (getpid() != junk_pid)
return;
if (junk_git_dir) {
@@ -485,12 +508,37 @@ static void write_followtags(const struct ref *refs, const char *msg)
}
}
+static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
+{
+ struct ref **rm = cb_data;
+ struct ref *ref = *rm;
+
+ /*
+ * Skip anything missing a peer_ref, which we are not
+ * actually going to write a ref for.
+ */
+ while (ref && !ref->peer_ref)
+ ref = ref->next;
+ /* Returning -1 notes "end of list" to the caller. */
+ if (!ref)
+ return -1;
+
+ hashcpy(sha1, ref->old_sha1);
+ *rm = ref->next;
+ return 0;
+}
+
static void update_remote_refs(const struct ref *refs,
const struct ref *mapped_refs,
const struct ref *remote_head_points_at,
const char *branch_top,
const char *msg)
{
+ const struct ref *rm = mapped_refs;
+
+ if (check_everything_connected(iterate_ref_map, 0, &rm))
+ die(_("remote did not send all necessary objects"));
+
if (refs) {
write_remote_refs(mapped_refs);
if (option_single_branch)
@@ -579,7 +627,8 @@ static int checkout(void)
tree = parse_tree_indirect(sha1);
parse_tree(tree);
init_tree_desc(&t, tree->buffer, tree->size);
- unpack_trees(1, &t, &opts);
+ if (unpack_trees(1, &t, &opts) < 0)
+ die(_("unable to checkout working tree"));
if (write_cache(fd, active_cache, active_nr) ||
commit_locked_index(lock_file))
@@ -898,12 +947,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
transport_unlock_pack(transport);
transport_disconnect(transport);
+ junk_mode = JUNK_LEAVE_REPO;
err = checkout();
strbuf_release(&reflog_msg);
strbuf_release(&branch_top);
strbuf_release(&key);
strbuf_release(&value);
- junk_pid = 0;
+ junk_mode = JUNK_LEAVE_ALL;
return err;
}
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index eac901a0ee..f641ff2a89 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -10,7 +10,7 @@
#include "utf8.h"
#include "gpg-interface.h"
-static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S<signer>] [-m <message>] [-F <file>] <sha1> <changelog";
+static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1> <changelog";
static void new_parent(struct commit *parent, struct commit_list **parents_p)
{
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d380155d9c..f44b76cb33 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -618,9 +618,12 @@ static void import_marks(char *input_file)
|| *mark_end != ' ' || get_sha1(mark_end + 1, sha1))
die("corrupt mark line: %s", line);
+ if (last_idnum < mark)
+ last_idnum = mark;
+
object = parse_object(sha1);
if (!object)
- die ("Could not read blob %s", sha1_to_hex(sha1));
+ continue;
if (object->flags & SHOWN)
error("Object %s already has a mark", sha1_to_hex(sha1));
@@ -630,8 +633,6 @@ static void import_marks(char *input_file)
continue;
mark_object(object, mark);
- if (last_idnum < mark)
- last_idnum = mark;
object->flags |= SHOWN;
}
@@ -645,6 +646,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
struct string_list extra_refs = STRING_LIST_INIT_NODUP;
struct commit *commit;
char *export_filename = NULL, *import_filename = NULL;
+ uint32_t lastimportid;
struct option options[] = {
OPT_INTEGER(0, "progress", &progress,
N_("show progress after <n> objects")),
@@ -688,6 +690,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
if (import_filename)
import_marks(import_filename);
+ lastimportid = last_idnum;
if (import_filename && revs.prune_data.nr)
full_tree = 1;
@@ -710,7 +713,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
handle_tags_and_duplicates(&extra_refs);
- if (export_filename)
+ if (export_filename && lastimportid != last_idnum)
export_marks(export_filename);
if (use_done_feature)
diff --git a/builtin/log.c b/builtin/log.c
index 59de484bc2..0f318107e5 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -23,6 +23,7 @@
#include "streaming.h"
#include "version.h"
#include "mailmap.h"
+#include "gpg-interface.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -367,6 +368,8 @@ static int git_log_config(const char *var, const char *value, void *cb)
if (grep_config(var, value, cb) < 0)
return -1;
+ if (git_gpg_config(var, value, cb) < 0)
+ return -1;
return git_diff_ui_config(var, value, cb);
}
diff --git a/builtin/merge.c b/builtin/merge.c
index 7c8922c8b0..3e2daa37c3 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -49,7 +49,7 @@ static const char * const builtin_merge_usage[] = {
static int show_diffstat = 1, shortlog_len = -1, squash;
static int option_commit = 1, allow_fast_forward = 1;
static int fast_forward_only, option_edit = -1;
-static int allow_trivial = 1, have_message;
+static int allow_trivial = 1, have_message, verify_signatures;
static int overwrite_ignore = 1;
static struct strbuf merge_msg = STRBUF_INIT;
static struct strategy **use_strategies;
@@ -199,6 +199,8 @@ static struct option builtin_merge_options[] = {
OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
N_("abort if fast-forward is not possible")),
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
+ OPT_BOOL(0, "verify-signatures", &verify_signatures,
+ N_("Verify that the named commit has a valid GPG signature")),
OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"),
N_("merge strategy to use"), option_parse_strategy),
OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"),
@@ -516,6 +518,19 @@ static void merge_name(const char *remote, struct strbuf *msg)
strbuf_release(&line);
goto cleanup;
}
+
+ if (remote_head->util) {
+ struct merge_remote_desc *desc;
+ desc = merge_remote_util(remote_head);
+ if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
+ strbuf_addf(msg, "%s\t\t%s '%s'\n",
+ sha1_to_hex(desc->obj->sha1),
+ typename(desc->obj->type),
+ remote);
+ goto cleanup;
+ }
+ }
+
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
sha1_to_hex(remote_head->object.sha1), remote);
cleanup:
@@ -1233,6 +1248,39 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
usage_with_options(builtin_merge_usage,
builtin_merge_options);
+ if (verify_signatures) {
+ for (p = remoteheads; p; p = p->next) {
+ struct commit *commit = p->item;
+ char hex[41];
+ struct signature_check signature_check;
+ memset(&signature_check, 0, sizeof(signature_check));
+
+ check_commit_signature(commit, &signature_check);
+
+ strcpy(hex, find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+ switch (signature_check.result) {
+ case 'G':
+ break;
+ case 'U':
+ die(_("Commit %s has an untrusted GPG signature, "
+ "allegedly by %s."), hex, signature_check.signer);
+ case 'B':
+ die(_("Commit %s has a bad GPG signature "
+ "allegedly by %s."), hex, signature_check.signer);
+ default: /* 'N' */
+ die(_("Commit %s does not have a GPG signature."), hex);
+ }
+ if (verbosity >= 0 && signature_check.result == 'G')
+ printf(_("Commit %s has a good GPG signature by %s\n"),
+ hex, signature_check.signer);
+
+ free(signature_check.gpg_output);
+ free(signature_check.gpg_status);
+ free(signature_check.signer);
+ free(signature_check.key);
+ }
+ }
+
strbuf_addstr(&buf, "merge");
for (p = remoteheads; p; p = p->next)
strbuf_addf(&buf, " %s", merge_remote_util(p->item)->name);
diff --git a/builtin/push.c b/builtin/push.c
index 5e4a0e958f..909c34dfda 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)
static int do_push(const char *repo, int flags)
{
int i, errs;
- struct remote *remote = remote_get(repo);
+ struct remote *remote = pushremote_get(repo);
const char **url;
int url_nr;