diff options
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/add.c | 2 | ||||
-rw-r--r-- | builtin/apply.c | 4 | ||||
-rw-r--r-- | builtin/branch.c | 13 | ||||
-rw-r--r-- | builtin/checkout.c | 8 | ||||
-rw-r--r-- | builtin/commit.c | 28 | ||||
-rw-r--r-- | builtin/config.c | 34 | ||||
-rw-r--r-- | builtin/for-each-ref.c | 2 | ||||
-rw-r--r-- | builtin/help.c | 9 | ||||
-rw-r--r-- | builtin/index-pack.c | 4 | ||||
-rw-r--r-- | builtin/init-db.c | 17 | ||||
-rw-r--r-- | builtin/log.c | 2 | ||||
-rw-r--r-- | builtin/ls-tree.c | 20 | ||||
-rw-r--r-- | builtin/mailinfo.c | 22 | ||||
-rw-r--r-- | builtin/merge.c | 22 | ||||
-rw-r--r-- | builtin/push.c | 10 | ||||
-rw-r--r-- | builtin/receive-pack.c | 95 | ||||
-rw-r--r-- | builtin/remote.c | 69 | ||||
-rw-r--r-- | builtin/repack.c | 2 | ||||
-rw-r--r-- | builtin/unpack-objects.c | 2 |
19 files changed, 229 insertions, 136 deletions
diff --git a/builtin/add.c b/builtin/add.c index ae6d3e262b..1074e32349 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -284,7 +284,7 @@ static int add_files(struct dir_struct *dir, int flags) for (i = 0; i < dir->ignored_nr; i++) fprintf(stderr, "%s\n", dir->ignored[i]->name); fprintf(stderr, _("Use -f if you really want to add them.\n")); - die(_("no files added")); + exit_status = 1; } for (i = 0; i < dir->nr; i++) diff --git a/builtin/apply.c b/builtin/apply.c index 6696ea4c3f..0aad912839 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -3728,7 +3728,7 @@ static void build_fake_ancestor(struct patch *list, const char *filename) if (!preimage_sha1_in_gitlink_patch(patch, sha1)) ; /* ok, the textual part looks sane */ else - die("sha1 information is lacking or useless for submoule %s", + die("sha1 information is lacking or useless for submodule %s", name); } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) { ; /* ok */ @@ -4180,7 +4180,7 @@ static int write_out_results(struct patch *list) if (cpath.nr) { struct string_list_item *item; - sort_string_list(&cpath); + string_list_sort(&cpath); for_each_string_list_item(item, &cpath) fprintf(stderr, "U %s\n", item->string); string_list_clear(&cpath, 0); diff --git a/builtin/branch.c b/builtin/branch.c index 3b79c5087f..dc6f0b266c 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -800,7 +800,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_create = 0, list = 0; + int delete = 0, rename = 0, force = 0, list = 0; int verbose = 0, abbrev = -1, detached = 0; int reflog = 0, edit_description = 0; int quiet = 0, unset_upstream = 0; @@ -848,7 +848,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")), OPT_BOOL(0, "edit-description", &edit_description, N_("edit the description for the branch")), - OPT__FORCE(&force_create, N_("force creation (when already exists)")), + OPT__FORCE(&force, N_("force creation, move/rename, deletion")), { OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref, N_("commit"), N_("print only not merged branches"), @@ -891,7 +891,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (with_commit || merge_filter != NO_FILTER) list = 1; - if (!!delete + !!rename + !!force_create + !!new_upstream + + if (!!delete + !!rename + !!new_upstream + list + unset_upstream > 1) usage_with_options(builtin_branch_usage, options); @@ -904,6 +904,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix) colopts = 0; } + if (force) { + delete *= 2; + rename *= 2; + } + if (delete) { if (!argc) die(_("branch name required")); @@ -1020,7 +1025,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) branch_existed = ref_exists(branch->refname); create_branch(head, argv[0], (argc == 2) ? argv[1] : head, - force_create, reflog, 0, quiet, track); + force, reflog, 0, quiet, track); /* * We only show the instructions if the user gave us diff --git a/builtin/checkout.c b/builtin/checkout.c index 5a78758036..52d6cbb0a8 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -62,7 +62,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new, } -static int update_some(const unsigned char *sha1, const char *base, int baselen, +static int update_some(const unsigned char *sha1, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { int len; @@ -72,11 +72,11 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen, if (S_ISDIR(mode)) return READ_TREE_RECURSIVE; - len = baselen + strlen(pathname); + len = base->len + strlen(pathname); ce = xcalloc(1, cache_entry_size(len)); hashcpy(ce->sha1, sha1); - memcpy(ce->name, base, baselen); - memcpy(ce->name + baselen, pathname, len - baselen); + memcpy(ce->name, base->buf, base->len); + memcpy(ce->name + base->len, pathname, len - base->len); ce->ce_flags = create_ce_flags(0) | CE_UPDATE; ce->ce_namelen = len; ce->ce_mode = create_ce_mode(mode); diff --git a/builtin/commit.c b/builtin/commit.c index e108c53015..cda74e9a68 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -800,32 +800,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (clean_message_contents) stripspace(&sb, 0); - if (signoff) { - /* - * See if we have a Conflicts: block at the end. If yes, count - * its size, so we can ignore it. - */ - int ignore_footer = 0; - int i, eol, previous = 0; - const char *nl; - - for (i = 0; i < sb.len; i++) { - nl = memchr(sb.buf + i, '\n', sb.len - i); - if (nl) - eol = nl - sb.buf; - else - eol = sb.len; - if (starts_with(sb.buf + previous, "\nConflicts:\n")) { - ignore_footer = sb.len - previous; - break; - } - while (i < eol) - i++; - previous = eol; - } - - append_signoff(&sb, ignore_footer, 0); - } + if (signoff) + append_signoff(&sb, ignore_non_trailer(&sb), 0); if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len) die_errno(_("could not write commit template")); diff --git a/builtin/config.c b/builtin/config.c index 8cc2604069..15a7bea936 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -69,8 +69,8 @@ static struct option builtin_config_options[] = { OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION), OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST), OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT), - OPT_STRING(0, "get-color", &get_color_slot, N_("slot"), N_("find the color configured: [default]")), - OPT_STRING(0, "get-colorbool", &get_colorbool_slot, N_("slot"), N_("find the color setting: [stdout-is-tty]")), + OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR), + OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL), OPT_GROUP(N_("Type")), OPT_BIT(0, "bool", &types, N_("value is \"true\" or \"false\""), TYPE_BOOL), OPT_BIT(0, "int", &types, N_("value is decimal number"), TYPE_INT), @@ -303,8 +303,9 @@ static int git_get_color_config(const char *var, const char *value, void *cb) return 0; } -static void get_color(const char *def_color) +static void get_color(const char *var, const char *def_color) { + get_color_slot = var; get_color_found = 0; parsed_color[0] = '\0'; git_config_with_options(git_get_color_config, NULL, @@ -333,8 +334,9 @@ static int git_get_colorbool_config(const char *var, const char *value, return 0; } -static int get_colorbool(int print) +static int get_colorbool(const char *var, int print) { + get_colorbool_slot = var; get_colorbool_found = -1; get_diff_color_found = -1; get_color_ui_found = -1; @@ -532,12 +534,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) usage_with_options(builtin_config_usage, builtin_config_options); } - if (get_color_slot) - actions |= ACTION_GET_COLOR; - if (get_colorbool_slot) - actions |= ACTION_GET_COLORBOOL; - - if ((get_color_slot || get_colorbool_slot) && types) { + if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && types) { error("--get-color and variable type are incoherent"); usage_with_options(builtin_config_usage, builtin_config_options); } @@ -568,8 +565,8 @@ int cmd_config(int argc, const char **argv, const char *prefix) } } else if (actions == ACTION_EDIT) { - const char *config_file = given_config_source.file ? - given_config_source.file : git_path("config"); + char *config_file; + check_argc(argc, 0, 0); if (!given_config_source.file && nongit) die("not in a git directory"); @@ -578,6 +575,8 @@ int cmd_config(int argc, const char **argv, const char *prefix) if (given_config_source.blob) die("editing blobs is not supported"); git_config(git_default_config, NULL); + config_file = xstrdup(given_config_source.file ? + given_config_source.file : git_path("config")); if (use_global_config) { int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd) { @@ -590,6 +589,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) die_errno(_("cannot create configuration file %s"), config_file); } launch_editor(config_file, NULL, NULL); + free(config_file); } else if (actions == ACTION_SET) { int ret; @@ -683,12 +683,14 @@ int cmd_config(int argc, const char **argv, const char *prefix) die("No such section!"); } else if (actions == ACTION_GET_COLOR) { - get_color(argv[0]); + check_argc(argc, 1, 2); + get_color(argv[0], argv[1]); } else if (actions == ACTION_GET_COLORBOOL) { - if (argc == 1) - color_stdout_is_tty = git_config_bool("command line", argv[0]); - return get_colorbool(argc != 0); + check_argc(argc, 1, 2); + if (argc == 2) + color_stdout_is_tty = git_config_bool("command line", argv[1]); + return get_colorbool(argv[0], argc == 2); } return 0; diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 603a90e29b..f3ce004d53 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1075,7 +1075,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) OPT_BIT(0 , "python", "e_style, N_("quote placeholders suitably for python"), QUOTE_PYTHON), OPT_BIT(0 , "tcl", "e_style, - N_("quote placeholders suitably for tcl"), QUOTE_TCL), + N_("quote placeholders suitably for Tcl"), QUOTE_TCL), OPT_GROUP(""), OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")), diff --git a/builtin/help.c b/builtin/help.c index b3c818ee01..e78c135e01 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -321,16 +321,18 @@ static void setup_man_path(void) { struct strbuf new_path = STRBUF_INIT; const char *old_path = getenv("MANPATH"); + char *git_man_path = system_path(GIT_MAN_PATH); /* We should always put ':' after our path. If there is no * old_path, the ':' at the end will let 'man' to try * system-wide paths after ours to find the manual page. If * there is old_path, we need ':' as delimiter. */ - strbuf_addstr(&new_path, system_path(GIT_MAN_PATH)); + strbuf_addstr(&new_path, git_man_path); strbuf_addch(&new_path, ':'); if (old_path) strbuf_addstr(&new_path, old_path); + free(git_man_path); setenv("MANPATH", new_path.buf, 1); strbuf_release(&new_path); @@ -380,8 +382,10 @@ static void show_info_page(const char *git_cmd) static void get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; + char *to_free = NULL; + if (!html_path) - html_path = system_path(GIT_HTML_PATH); + html_path = to_free = system_path(GIT_HTML_PATH); /* Check that we have a git documentation directory. */ if (!strstr(html_path, "://")) { @@ -392,6 +396,7 @@ static void get_html_page_path(struct strbuf *page_path, const char *page) strbuf_init(page_path, 0); strbuf_addf(page_path, "%s/%s.html", html_path, page); + free(to_free); } /* diff --git a/builtin/index-pack.c b/builtin/index-pack.c index a369f55353..4632117671 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -447,7 +447,7 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size, if (type == OBJ_BLOB && size > big_file_threshold) buf = fixed_buf; else - buf = xmalloc(size); + buf = xmallocz(size); memset(&stream, 0, sizeof(stream)); git_inflate_init(&stream); @@ -552,7 +552,7 @@ static void *unpack_data(struct object_entry *obj, git_zstream stream; int status; - data = xmalloc(consume ? 64*1024 : obj->size); + data = xmallocz(consume ? 64*1024 : obj->size); inbuf = xmalloc((len < 64*1024) ? len : 64*1024); memset(&stream, 0, sizeof(stream)); diff --git a/builtin/init-db.c b/builtin/init-db.c index aab44d2e45..9966522b4a 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -119,15 +119,18 @@ static void copy_templates(const char *template_dir) DIR *dir; const char *git_dir = get_git_dir(); int len = strlen(git_dir); + char *to_free = NULL; if (!template_dir) template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT); if (!template_dir) template_dir = init_db_template_dir; if (!template_dir) - template_dir = system_path(DEFAULT_GIT_TEMPLATE_DIR); - if (!template_dir[0]) + template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR); + if (!template_dir[0]) { + free(to_free); return; + } template_len = strlen(template_dir); if (PATH_MAX <= (template_len+strlen("/config"))) die(_("insanely long template path %s"), template_dir); @@ -139,7 +142,7 @@ static void copy_templates(const char *template_dir) dir = opendir(template_path); if (!dir) { warning(_("templates not found %s"), template_dir); - return; + goto free_return; } /* Make sure that template is from the correct vintage */ @@ -155,8 +158,7 @@ static void copy_templates(const char *template_dir) "a wrong format version %d from '%s'"), repository_format_version, template_dir); - closedir(dir); - return; + goto close_free_return; } memcpy(path, git_dir, len); @@ -166,7 +168,10 @@ static void copy_templates(const char *template_dir) copy_templates_1(path, len, template_path, template_len, dir); +close_free_return: closedir(dir); +free_return: + free(to_free); } static int git_init_db_config(const char *k, const char *v, void *cb) @@ -256,6 +261,8 @@ static int create_default_files(const char *template_path) !lstat(path, &st2) && st1.st_mode != st2.st_mode && !chmod(path, st1.st_mode)); + if (filemode && !reinit && (st1.st_mode & S_IXUSR)) + filemode = 0; } git_config_set("core.filemode", filemode ? "true" : "false"); diff --git a/builtin/log.c b/builtin/log.c index 734aab3a73..f2a9f0156d 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -489,7 +489,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev) } static int show_tree_object(const unsigned char *sha1, - const char *base, int baselen, + struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : ""); diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 51184dfa2e..3b04a0f082 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -61,10 +61,11 @@ static int show_recursive(const char *base, int baselen, const char *pathname) } } -static int show_tree(const unsigned char *sha1, const char *base, int baselen, +static int show_tree(const unsigned char *sha1, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { int retval = 0; + int baselen; const char *type = blob_type; if (S_ISGITLINK(mode)) { @@ -79,7 +80,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, */ type = commit_type; } else if (S_ISDIR(mode)) { - if (show_recursive(base, baselen, pathname)) { + if (show_recursive(base->buf, base->len, pathname)) { retval = READ_TREE_RECURSIVE; if (!(ls_options & LS_SHOW_TREES)) return retval; @@ -89,10 +90,6 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, else if (ls_options & LS_TREE_ONLY) return 0; - if (chomp_prefix && - (baselen < chomp_prefix || memcmp(ls_tree_prefix, base, chomp_prefix))) - return 0; - if (!(ls_options & LS_NAME_ONLY)) { if (ls_options & LS_SHOW_SIZE) { char size_text[24]; @@ -112,8 +109,12 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, printf("%06o %s %s\t", mode, type, find_unique_abbrev(sha1, abbrev)); } - write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix, - pathname, stdout, line_termination); + baselen = base->len; + strbuf_addstr(base, pathname); + write_name_quoted_relative(base->buf, + chomp_prefix ? ls_tree_prefix : NULL, + stdout, line_termination); + strbuf_setlen(base, baselen); return retval; } @@ -173,7 +174,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) * cannot be lifted until it is converted to use * match_pathspec() or tree_entry_interesting() */ - parse_pathspec(&pathspec, PATHSPEC_GLOB | PATHSPEC_ICASE, + parse_pathspec(&pathspec, PATHSPEC_GLOB | PATHSPEC_ICASE | + PATHSPEC_EXCLUDE, PATHSPEC_PREFER_CWD, prefix, argv + 1); for (i = 0; i < pathspec.nr; i++) diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 6a14d2985d..c8a47c173d 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -15,6 +15,7 @@ static const char *metainfo_charset; static struct strbuf line = STRBUF_INIT; static struct strbuf name = STRBUF_INIT; static struct strbuf email = STRBUF_INIT; +static char *message_id; static enum { TE_DONTCARE, TE_QP, TE_BASE64 @@ -24,6 +25,7 @@ static struct strbuf charset = STRBUF_INIT; static int patch_lines; static struct strbuf **p_hdr_data, **s_hdr_data; static int use_scissors; +static int add_message_id; static int use_inbody_headers = 1; #define MAX_HDR_PARSED 10 @@ -198,6 +200,12 @@ static void handle_content_type(struct strbuf *line) } } +static void handle_message_id(const struct strbuf *line) +{ + if (add_message_id) + message_id = strdup(line->buf); +} + static void handle_content_transfer_encoding(const struct strbuf *line) { if (strcasestr(line->buf, "base64")) @@ -342,6 +350,14 @@ static int check_header(const struct strbuf *line, ret = 1; goto check_header_out; } + if (cmp_header(line, "Message-Id")) { + len = strlen("Message-Id: "); + strbuf_add(&sb, line->buf + len, line->len - len); + decode_header(&sb); + handle_message_id(&sb); + ret = 1; + goto check_header_out; + } /* for inbody stuff */ if (starts_with(line->buf, ">From") && isspace(line->buf[5])) { @@ -816,6 +832,8 @@ static int handle_commit_msg(struct strbuf *line) } if (patchbreak(line)) { + if (message_id) + fprintf(cmitmsg, "Message-Id: %s\n", message_id); fclose(cmitmsg); cmitmsg = NULL; return 1; @@ -1013,7 +1031,7 @@ static int git_mailinfo_config(const char *var, const char *value, void *unused) } static const char mailinfo_usage[] = - "git mailinfo [-k|-b] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] msg patch < mail >info"; + "git mailinfo [-k|-b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] msg patch < mail >info"; int cmd_mailinfo(int argc, const char **argv, const char *prefix) { @@ -1032,6 +1050,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix) keep_subject = 1; else if (!strcmp(argv[1], "-b")) keep_non_patch_brackets_in_subject = 1; + else if (!strcmp(argv[1], "-m") || !strcmp(argv[1], "--message-id")) + add_message_id = 1; else if (!strcmp(argv[1], "-u")) metainfo_charset = def_charset; else if (!strcmp(argv[1], "-n")) diff --git a/builtin/merge.c b/builtin/merge.c index bebbe5b308..215d4856e5 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -29,6 +29,7 @@ #include "remote.h" #include "fmt-merge-msg.h" #include "gpg-interface.h" +#include "sequencer.h" #define DEFAULT_TWOHEAD (1<<0) #define DEFAULT_OCTOPUS (1<<1) @@ -880,28 +881,19 @@ static int finish_automerge(struct commit *head, return 0; } -static int suggest_conflicts(int renormalizing) +static int suggest_conflicts(void) { const char *filename; FILE *fp; - int pos; + struct strbuf msgbuf = STRBUF_INIT; filename = git_path("MERGE_MSG"); fp = fopen(filename, "a"); if (!fp) die_errno(_("Could not open '%s' for writing"), filename); - fprintf(fp, "\nConflicts:\n"); - for (pos = 0; pos < active_nr; pos++) { - const struct cache_entry *ce = active_cache[pos]; - - if (ce_stage(ce)) { - fprintf(fp, "\t%s\n", ce->name); - while (pos + 1 < active_nr && - !strcmp(ce->name, - active_cache[pos + 1]->name)) - pos++; - } - } + + append_conflicts_hint(&msgbuf); + fputs(msgbuf.buf, fp); fclose(fp); rerere(allow_rerere_auto); printf(_("Automatic merge failed; " @@ -1550,7 +1542,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) fprintf(stderr, _("Automatic merge went well; " "stopped before committing as requested\n")); else - ret = suggest_conflicts(option_renormalize); + ret = suggest_conflicts(); done: free(branch_to_free); diff --git a/builtin/push.c b/builtin/push.c index a076b1964d..12f5e69393 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -161,7 +161,7 @@ static const char message_detached_head_die[] = " git push %s HEAD:<name-of-remote-branch>\n"); static void setup_push_upstream(struct remote *remote, struct branch *branch, - int triangular) + int triangular, int simple) { struct strbuf refspec = STRBUF_INIT; @@ -184,7 +184,7 @@ static void setup_push_upstream(struct remote *remote, struct branch *branch, "to update which remote branch."), remote->name, branch->name); - if (push_default == PUSH_DEFAULT_SIMPLE) { + if (simple) { /* Additional safety */ if (strcmp(branch->refname, branch->merge[0]->src)) die_push_simple(branch, remote); @@ -257,11 +257,11 @@ static void setup_default_push_refspecs(struct remote *remote) if (triangular) setup_push_current(remote, branch); else - setup_push_upstream(remote, branch, triangular); + setup_push_upstream(remote, branch, triangular, 1); break; case PUSH_DEFAULT_UPSTREAM: - setup_push_upstream(remote, branch, triangular); + setup_push_upstream(remote, branch, triangular, 0); break; case PUSH_DEFAULT_CURRENT: @@ -503,7 +503,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"), N_("require old value of ref to be at this value"), PARSE_OPT_OPTARG, parseopt_push_cas_option }, - { OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"), + { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check|on-demand", N_("control recursive pushing of submodules"), PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")), diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index e908d079ba..8266c1fccf 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -26,7 +26,8 @@ enum deny_action { DENY_UNCONFIGURED, DENY_IGNORE, DENY_WARN, - DENY_REFUSE + DENY_REFUSE, + DENY_UPDATE_INSTEAD }; static int deny_deletes; @@ -76,6 +77,8 @@ static enum deny_action parse_deny_action(const char *var, const char *value) return DENY_WARN; if (!strcasecmp(value, "refuse")) return DENY_REFUSE; + if (!strcasecmp(value, "updateinstead")) + return DENY_UPDATE_INSTEAD; } if (git_config_bool(var, value)) return DENY_REFUSE; @@ -730,11 +733,89 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) return 0; } +static const char *update_worktree(unsigned char *sha1) +{ + const char *update_refresh[] = { + "update-index", "-q", "--ignore-submodules", "--refresh", NULL + }; + const char *diff_files[] = { + "diff-files", "--quiet", "--ignore-submodules", "--", NULL + }; + const char *diff_index[] = { + "diff-index", "--quiet", "--cached", "--ignore-submodules", + "HEAD", "--", NULL + }; + const char *read_tree[] = { + "read-tree", "-u", "-m", NULL, NULL + }; + const char *work_tree = git_work_tree_cfg ? git_work_tree_cfg : ".."; + struct argv_array env = ARGV_ARRAY_INIT; + struct child_process child = CHILD_PROCESS_INIT; + + if (is_bare_repository()) + return "denyCurrentBranch = updateInstead needs a worktree"; + + argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(get_git_dir())); + + child.argv = update_refresh; + child.env = env.argv; + child.dir = work_tree; + child.no_stdin = 1; + child.stdout_to_stderr = 1; + child.git_cmd = 1; + if (run_command(&child)) { + argv_array_clear(&env); + return "Up-to-date check failed"; + } + + /* run_command() does not clean up completely; reinitialize */ + child_process_init(&child); + child.argv = diff_files; + child.env = env.argv; + child.dir = work_tree; + child.no_stdin = 1; + child.stdout_to_stderr = 1; + child.git_cmd = 1; + if (run_command(&child)) { + argv_array_clear(&env); + return "Working directory has unstaged changes"; + } + + child_process_init(&child); + child.argv = diff_index; + child.env = env.argv; + child.no_stdin = 1; + child.no_stdout = 1; + child.stdout_to_stderr = 0; + child.git_cmd = 1; + if (run_command(&child)) { + argv_array_clear(&env); + return "Working directory has staged changes"; + } + + read_tree[3] = sha1_to_hex(sha1); + child_process_init(&child); + child.argv = read_tree; + child.env = env.argv; + child.dir = work_tree; + child.no_stdin = 1; + child.no_stdout = 1; + child.stdout_to_stderr = 0; + child.git_cmd = 1; + if (run_command(&child)) { + argv_array_clear(&env); + return "Could not update working tree to new HEAD"; + } + + argv_array_clear(&env); + return NULL; +} + static const char *update(struct command *cmd, struct shallow_info *si) { const char *name = cmd->ref_name; struct strbuf namespaced_name_buf = STRBUF_INIT; - const char *namespaced_name; + const char *namespaced_name, *ret; unsigned char *old_sha1 = cmd->old_sha1; unsigned char *new_sha1 = cmd->new_sha1; @@ -760,6 +841,11 @@ static const char *update(struct command *cmd, struct shallow_info *si) if (deny_current_branch == DENY_UNCONFIGURED) refuse_unconfigured_deny(); return "branch is currently checked out"; + case DENY_UPDATE_INSTEAD: + ret = update_worktree(new_sha1); + if (ret) + return ret; + break; } } @@ -784,10 +870,13 @@ static const char *update(struct command *cmd, struct shallow_info *si) break; case DENY_REFUSE: case DENY_UNCONFIGURED: + case DENY_UPDATE_INSTEAD: if (deny_delete_current == DENY_UNCONFIGURED) refuse_unconfigured_deny_delete_current(); rp_error("refusing to delete the current branch: %s", name); return "deletion of the current branch prohibited"; + default: + return "Invalid denyDeleteCurrent setting"; } } } @@ -964,7 +1053,7 @@ static void check_aliased_updates(struct command *commands) string_list_append(&ref_list, cmd->ref_name); item->util = (void *)cmd; } - sort_string_list(&ref_list); + string_list_sort(&ref_list); for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) diff --git a/builtin/remote.c b/builtin/remote.c index 7f28f92a37..46ecfd9f7b 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -352,9 +352,9 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat free_refs(stale_refs); free_refs(fetch_map); - sort_string_list(&states->new); - sort_string_list(&states->tracked); - sort_string_list(&states->stale); + string_list_sort(&states->new); + string_list_sort(&states->tracked); + string_list_sort(&states->stale); return 0; } @@ -750,16 +750,11 @@ static int mv(int argc, const char **argv) static int remove_branches(struct string_list *branches) { struct strbuf err = STRBUF_INIT; - const char **branch_names; int i, result = 0; - branch_names = xmalloc(branches->nr * sizeof(*branch_names)); - for (i = 0; i < branches->nr; i++) - branch_names[i] = branches->items[i].string; - if (repack_without_refs(branch_names, branches->nr, &err)) + if (repack_without_refs(branches, &err)) result |= error("%s", err.buf); strbuf_release(&err); - free(branch_names); for (i = 0; i < branches->nr; i++) { struct string_list_item *item = branches->items + i; @@ -914,7 +909,7 @@ static int get_remote_ref_states(const char *name, get_push_ref_states(remote_refs, states); } else { for_each_ref(append_ref_to_tracked_list, states); - sort_string_list(&states->tracked); + string_list_sort(&states->tracked); get_push_ref_states_noquery(states); } @@ -1133,7 +1128,7 @@ static int show_all(void) if (!result) { int i; - sort_string_list(&list); + string_list_sort(&list); for (i = 0; i < list.nr; i++) { struct string_list_item *item = list.items + i; if (verbose) @@ -1314,10 +1309,10 @@ static int set_head(int argc, const char **argv) static int prune_remote(const char *remote, int dry_run) { - int result = 0, i; + int result = 0; struct ref_states states; - struct string_list delete_refs_list = STRING_LIST_INIT_NODUP; - const char **delete_refs; + struct string_list refs_to_prune = STRING_LIST_INIT_NODUP; + struct string_list_item *item; const char *dangling_msg = dry_run ? _(" %s will become dangling!") : _(" %s has become dangling!"); @@ -1325,30 +1320,30 @@ static int prune_remote(const char *remote, int dry_run) memset(&states, 0, sizeof(states)); get_remote_ref_states(remote, &states, GET_REF_STATES); - if (states.stale.nr) { - printf_ln(_("Pruning %s"), remote); - printf_ln(_("URL: %s"), - states.remote->url_nr - ? states.remote->url[0] - : _("(no URL)")); - - delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs)); - for (i = 0; i < states.stale.nr; i++) - delete_refs[i] = states.stale.items[i].util; - if (!dry_run) { - struct strbuf err = STRBUF_INIT; - if (repack_without_refs(delete_refs, states.stale.nr, - &err)) - result |= error("%s", err.buf); - strbuf_release(&err); - } - free(delete_refs); + if (!states.stale.nr) { + free_remote_ref_states(&states); + return 0; } - for (i = 0; i < states.stale.nr; i++) { - const char *refname = states.stale.items[i].util; + printf_ln(_("Pruning %s"), remote); + printf_ln(_("URL: %s"), + states.remote->url_nr + ? states.remote->url[0] + : _("(no URL)")); + + for_each_string_list_item(item, &states.stale) + string_list_append(&refs_to_prune, item->util); + string_list_sort(&refs_to_prune); + + if (!dry_run) { + struct strbuf err = STRBUF_INIT; + if (repack_without_refs(&refs_to_prune, &err)) + result |= error("%s", err.buf); + strbuf_release(&err); + } - string_list_insert(&delete_refs_list, refname); + for_each_string_list_item(item, &states.stale) { + const char *refname = item->util; if (!dry_run) result |= delete_ref(refname, NULL, 0); @@ -1361,9 +1356,9 @@ static int prune_remote(const char *remote, int dry_run) abbrev_ref(refname, "refs/remotes/")); } - warn_dangling_symrefs(stdout, dangling_msg, &delete_refs_list); - string_list_clear(&delete_refs_list, 0); + warn_dangling_symrefs(stdout, dangling_msg, &refs_to_prune); + string_list_clear(&refs_to_prune, 0); free_remote_ref_states(&states); return result; } diff --git a/builtin/repack.c b/builtin/repack.c index 83e91c7382..3f852f35d1 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -376,7 +376,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (delete_redundant) { int opts = 0; - sort_string_list(&names); + string_list_sort(&names); for_each_string_list_item(item, &existing_packs) { char *sha1; size_t len = strlen(item->string); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 855d94b90b..ac6667242c 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -91,7 +91,7 @@ static void use(int bytes) static void *get_data(unsigned long size) { git_zstream stream; - void *buf = xmalloc(size); + void *buf = xmallocz(size); memset(&stream, 0, sizeof(stream)); |