diff options
| -rw-r--r-- | Documentation/RelNotes/2.36.1.txt | 33 | ||||
| -rw-r--r-- | Documentation/SubmittingPatches | 5 | ||||
| -rwxr-xr-x | GIT-VERSION-GEN | 2 | ||||
| l--------- | RelNotes | 2 | ||||
| -rw-r--r-- | archive.c | 2 | ||||
| -rw-r--r-- | builtin/diff-tree.c | 3 | ||||
| -rw-r--r-- | builtin/fast-export.c | 1 | ||||
| -rw-r--r-- | builtin/log.c | 32 | ||||
| -rw-r--r-- | builtin/name-rev.c | 21 | ||||
| -rw-r--r-- | builtin/show-branch.c | 4 | ||||
| -rw-r--r-- | builtin/submodule--helper.c | 1 | ||||
| -rwxr-xr-x | ci/lib.sh | 2 | ||||
| -rw-r--r-- | compat/nedmalloc/nedmalloc.c | 1 | ||||
| -rw-r--r-- | compat/win32/syslog.c | 2 | ||||
| -rw-r--r-- | contrib/coccinelle/xstrdup_or_null.cocci | 8 | ||||
| -rw-r--r-- | dir.c | 9 | ||||
| -rw-r--r-- | http.c | 26 | ||||
| -rw-r--r-- | log-tree.c | 1 | ||||
| -rwxr-xr-x | t/t3202-show-branch.sh | 14 | ||||
| -rwxr-xr-x | t/t4013-diff-various.sh | 33 | ||||
| -rwxr-xr-x | t/t4014-format-patch.sh | 33 | ||||
| -rwxr-xr-x | t/t7406-submodule-update.sh | 33 | ||||
| -rwxr-xr-x | t/t9350-fast-export.sh | 7 |
23 files changed, 230 insertions, 45 deletions
diff --git a/Documentation/RelNotes/2.36.1.txt b/Documentation/RelNotes/2.36.1.txt new file mode 100644 index 0000000000..a9617095db --- /dev/null +++ b/Documentation/RelNotes/2.36.1.txt @@ -0,0 +1,33 @@ +Git v2.36.1 Release Notes +========================= + +Fixes since v2.36 +----------------- + + * "git submodule update" without pathspec should silently skip an + uninitialized submodule, but it started to become noisy by mistake. + + * "diff-tree --stdin" has been broken for about a year, but 2.36 + release broke it even worse by breaking running the command with + <pathspec>, which in turn broke "gitk" and got noticed. This has + been corrected by aligning its behaviour to that of "log". + + * Regression fix for 2.36 where "git name-rev" started to sometimes + reference strings after they are freed. + + * "git show <commit1> <commit2>... -- <pathspec>" lost the pathspec + when showing the second and subsequent commits, which has been + corrected. + + * "git fast-export -- <pathspec>" lost the pathspec when showing the + second and subsequent commits, which has been corrected. + + * "git format-patch <args> -- <pathspec>" lost the pathspec when + showing the second and subsequent commits, which has been + corrected. + + * Get rid of a bogus and over-eager coccinelle rule. + + * Correct choices of C compilers used in various CI jobs. + +Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index a6121d1d42..5bd795e5db 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -452,7 +452,10 @@ repositories. - `gitk-git/` comes from Paul Mackerras's gitk project: - git://ozlabs.org/~paulus/gitk + git://git.ozlabs.org/~paulus/gitk + + Those who are interested in improve gitk can volunteer to help Paul + in maintaining it cf. <YntxL/fTplFm8lr6@cleo>. - `po/` comes from the localization coordinator, Jiang Xin: diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index fdcebd2c58..c1e8552d27 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.36.0 +DEF_VER=v2.36.1 LF=' ' @@ -1 +1 @@ -Documentation/RelNotes/2.36.0.txt
\ No newline at end of file +Documentation/RelNotes/2.36.1.txt
\ No newline at end of file @@ -342,7 +342,7 @@ int write_archive_entries(struct archiver_args *args, else err = write_entry(args, &fake_oid, path_in_archive.buf, path_in_archive.len, - info->stat.st_mode, + canon_mode(info->stat.st_mode), content.buf, content.len); if (err) break; diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 0e0ac1f167..116097a404 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -195,6 +195,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) int saved_dcctc = 0; opt->diffopt.rotate_to_strict = 0; + opt->diffopt.no_free = 1; if (opt->diffopt.detect_rename) { if (!the_index.cache) repo_read_index(the_repository); @@ -217,6 +218,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) } opt->diffopt.degraded_cc_to_c = saved_dcctc; opt->diffopt.needed_rename_limit = saved_nrl; + opt->diffopt.no_free = 0; + diff_free(&opt->diffopt); } return diff_result_code(&opt->diffopt, 0); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index a7d72697fb..1355b5a96d 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -1261,6 +1261,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) revs.diffopt.format_callback = show_filemodify; revs.diffopt.format_callback_data = &paths_of_changed_objects; revs.diffopt.flags.recursive = 1; + revs.diffopt.no_free = 1; while ((commit = get_revision(&revs))) handle_commit(commit, &revs, &paths_of_changed_objects); diff --git a/builtin/log.c b/builtin/log.c index c211d66d1d..3ac479bec3 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -417,7 +417,7 @@ static void finish_early_output(struct rev_info *rev) show_early_header(rev, "done", n); } -static int cmd_log_walk(struct rev_info *rev) +static int cmd_log_walk_no_free(struct rev_info *rev) { struct commit *commit; int saved_nrl = 0; @@ -444,7 +444,6 @@ static int cmd_log_walk(struct rev_info *rev) * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to * retain that state information if replacing rev->diffopt in this loop */ - rev->diffopt.no_free = 1; while ((commit = get_revision(rev)) != NULL) { if (!log_tree_commit(rev, commit) && rev->max_count >= 0) /* @@ -469,8 +468,6 @@ static int cmd_log_walk(struct rev_info *rev) } rev->diffopt.degraded_cc_to_c = saved_dcctc; rev->diffopt.needed_rename_limit = saved_nrl; - rev->diffopt.no_free = 0; - diff_free(&rev->diffopt); if (rev->remerge_diff) { tmp_objdir_destroy(rev->remerge_objdir); @@ -484,6 +481,17 @@ static int cmd_log_walk(struct rev_info *rev) return diff_result_code(&rev->diffopt, 0); } +static int cmd_log_walk(struct rev_info *rev) +{ + int retval; + + rev->diffopt.no_free = 1; + retval = cmd_log_walk_no_free(rev); + rev->diffopt.no_free = 0; + diff_free(&rev->diffopt); + return retval; +} + static int git_log_config(const char *var, const char *value, void *cb) { const char *slot_name; @@ -680,6 +688,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) count = rev.pending.nr; objects = rev.pending.objects; + rev.diffopt.no_free = 1; for (i = 0; i < count && !ret; i++) { struct object *o = objects[i].item; const char *name = objects[i].name; @@ -725,12 +734,16 @@ int cmd_show(int argc, const char **argv, const char *prefix) rev.pending.nr = rev.pending.alloc = 0; rev.pending.objects = NULL; add_object_array(o, name, &rev.pending); - ret = cmd_log_walk(&rev); + ret = cmd_log_walk_no_free(&rev); break; default: ret = error(_("unknown type: %d"), o->type); } } + + rev.diffopt.no_free = 0; + diff_free(&rev.diffopt); + free(objects); return ret; } @@ -1883,6 +1896,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diff = 1; rev.max_parents = 1; rev.diffopt.flags.recursive = 1; + rev.diffopt.no_free = 1; rev.subject_prefix = fmt_patch_subject_prefix; memset(&s_r_opt, 0, sizeof(s_r_opt)); s_r_opt.def = "HEAD"; @@ -2008,13 +2022,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (use_stdout) { setup_pager(); - } else if (rev.diffopt.close_file) { - /* - * The diff code parsed --output; it has already opened the - * file, but we must instruct it not to close after each diff. - */ - rev.diffopt.no_free = 1; - } else { + } else if (!rev.diffopt.close_file) { int saved; if (!output_directory) diff --git a/builtin/name-rev.c b/builtin/name-rev.c index c59b5699fe..02ea9d1633 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -18,7 +18,7 @@ #define CUTOFF_DATE_SLOP 86400 struct rev_name { - char *tip_name; + const char *tip_name; timestamp_t taggerdate; int generation; int distance; @@ -84,7 +84,7 @@ static int commit_is_before_cutoff(struct commit *commit) static int is_valid_rev_name(const struct rev_name *name) { - return name && (name->generation || name->tip_name); + return name && name->tip_name; } static struct rev_name *get_commit_rev_name(const struct commit *commit) @@ -146,20 +146,9 @@ static struct rev_name *create_or_update_name(struct commit *commit, { struct rev_name *name = commit_rev_name_at(&rev_names, commit); - if (is_valid_rev_name(name)) { - if (!is_better_name(name, taggerdate, generation, distance, from_tag)) - return NULL; - - /* - * This string might still be shared with ancestors - * (generation > 0). We can release it here regardless, - * because the new name that has just won will be better - * for them as well, so name_rev() will replace these - * stale pointers when it processes the parents. - */ - if (!name->generation) - free(name->tip_name); - } + if (is_valid_rev_name(name) && + !is_better_name(name, taggerdate, generation, distance, from_tag)) + return NULL; name->taggerdate = taggerdate; name->generation = generation; diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 330b0553b9..64c649c6a2 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -712,6 +712,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) "--all/--remotes/--independent/--merge-base"); } + if (with_current_branch && reflog) + die(_("options '%s' and '%s' cannot be used together"), + "--reflog", "--current"); + /* If nothing is specified, show all branches by default */ if (ac <= topics && all_heads + all_remotes == 0) all_heads = 1; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 2c87ef9364..1a8e5d0621 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -2026,7 +2026,6 @@ struct update_data { .references = STRING_LIST_INIT_DUP, \ .single_branch = -1, \ .max_jobs = 1, \ - .warn_if_uninitialized = 1, \ } static void next_submodule_warn_missing(struct submodule_update_clone *suc, @@ -122,7 +122,7 @@ then test macos != "$CI_OS_NAME" || CI_OS_NAME=osx CI_REPO_SLUG="$GITHUB_REPOSITORY" CI_JOB_ID="$GITHUB_RUN_ID" - CC="${CC:-gcc}" + CC="${CC_PACKAGE:-${CC:-gcc}}" DONT_SKIP_TAGS=t cache_dir="$HOME/none" diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c index edb438a777..2c0ace7075 100644 --- a/compat/nedmalloc/nedmalloc.c +++ b/compat/nedmalloc/nedmalloc.c @@ -323,7 +323,6 @@ static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned in } static void DestroyCaches(nedpool *p) THROWSPEC { - if(p->caches) { threadcache *tc; int n; diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c index 161978d720..1f8d8934cc 100644 --- a/compat/win32/syslog.c +++ b/compat/win32/syslog.c @@ -43,6 +43,7 @@ void syslog(int priority, const char *fmt, ...) va_end(ap); while ((pos = strstr(str, "%1")) != NULL) { + size_t offset = pos - str; char *oldstr = str; str = realloc(str, st_add(++str_len, 1)); if (!str) { @@ -50,6 +51,7 @@ void syslog(int priority, const char *fmt, ...) warning_errno("realloc failed"); return; } + pos = str + offset; memmove(pos + 2, pos + 1, strlen(pos)); pos[1] = ' '; } diff --git a/contrib/coccinelle/xstrdup_or_null.cocci b/contrib/coccinelle/xstrdup_or_null.cocci index 8e05d1ca4b..9c1d2939b6 100644 --- a/contrib/coccinelle/xstrdup_or_null.cocci +++ b/contrib/coccinelle/xstrdup_or_null.cocci @@ -1,13 +1,5 @@ @@ expression E; -expression V; -@@ -- if (E) -- V = xstrdup(E); -+ V = xstrdup_or_null(E); - -@@ -expression E; @@ - xstrdup(absolute_path(E)) + absolute_pathdup(E) @@ -3082,6 +3082,15 @@ char *git_url_basename(const char *repo, int is_bundle, int is_bare) } /* + * It should not be possible to overflow `ptrdiff_t` by passing in an + * insanely long URL, but GCC does not know that and will complain + * without this check. + */ + if (end - start < 0) + die(_("No directory name could be guessed.\n" + "Please specify a directory on the command line")); + + /* * Strip trailing port number if we've got only a * hostname (that is, there is no dir separator but a * colon). This check is required such that we do not @@ -1367,6 +1367,32 @@ void run_active_slot(struct active_request_slot *slot) select(max_fd+1, &readfds, &writefds, &excfds, &select_timeout); } } + + /* + * The value of slot->finished we set before the loop was used + * to set our "finished" variable when our request completed. + * + * 1. The slot may not have been reused for another requst + * yet, in which case it still has &finished. + * + * 2. The slot may already be in-use to serve another request, + * which can further be divided into two cases: + * + * (a) If call run_active_slot() hasn't been called for that + * other request, slot->finished would have been cleared + * by get_active_slot() and has NULL. + * + * (b) If the request did call run_active_slot(), then the + * call would have updated slot->finished at the beginning + * of this function, and with the clearing of the member + * below, we would find that slot->finished is now NULL. + * + * In all cases, slot->finished has no useful information to + * anybody at this point. Some compilers warn us for + * attempting to smuggle a pointer that is about to become + * invalid, i.e. &finished. We clear it here to assure them. + */ + slot->finished = NULL; } static void release_active_slot(struct active_request_slot *slot) diff --git a/log-tree.c b/log-tree.c index 38e5cccc1a..3a03e34c30 100644 --- a/log-tree.c +++ b/log-tree.c @@ -1098,6 +1098,7 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit) opt->loginfo = &log; opt->diffopt.no_free = 1; + /* NEEDSWORK: no restoring of no_free? Why? */ if (opt->line_level_traverse) return line_log_print(opt, commit); diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh index 7a1be73ce8..f2b9199007 100755 --- a/t/t3202-show-branch.sh +++ b/t/t3202-show-branch.sh @@ -161,4 +161,18 @@ test_expect_success 'show branch --reflog=2' ' test_cmp actual expect ' +# incompatible options +while read combo +do + test_expect_success "show-branch $combo (should fail)" ' + test_must_fail git show-branch $combo 2>error && + grep -e "cannot be used together" -e "usage:" error + ' +done <<\EOF +--all --reflog +--merge-base --reflog +--list --merge-base +--reflog --current +EOF + test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 750aee17ea..056e922164 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -542,6 +542,39 @@ test_expect_success 'diff-tree --stdin with log formatting' ' test_cmp expect actual ' +test_expect_success 'diff-tree --stdin with pathspec' ' + cat >expect <<-EOF && + Third + + dir/sub + Second + + dir/sub + EOF + git rev-list master^ | + git diff-tree -r --stdin --name-only --format=%s dir >actual && + test_cmp expect actual +' + +test_expect_success 'show A B ... -- <pathspec>' ' + # side touches dir/sub, file0, and file3 + # master^ touches dir/sub, and file1 + # master^^ touches dir/sub, file0, and file2 + git show --name-only --format="<%s>" side master^ master^^ -- dir >actual && + cat >expect <<-\EOF && + <Side> + + dir/sub + <Third> + + dir/sub + <Second> + + dir/sub + EOF + test_cmp expect actual +' + test_expect_success 'diff -I<regex>: setup' ' git checkout master && test_seq 50 >file0 && diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 7dc5a5c736..fbec8ad2ef 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -926,11 +926,40 @@ test_expect_success 'format-patch --numstat should produce a patch' ' ' test_expect_success 'format-patch -- <path>' ' - git format-patch main..side -- file 2>error && - ! grep "Use .--" error + rm -f *.patch && + git checkout -b pathspec main && + + echo file_a 1 >file_a && + echo file_b 1 >file_b && + git add file_a file_b && + git commit -m pathspec_initial && + + echo file_a 2 >>file_a && + git add file_a && + git commit -m pathspec_a && + + echo file_b 2 >>file_b && + git add file_b && + git commit -m pathspec_b && + + echo file_a 3 >>file_a && + echo file_b 3 >>file_b && + git add file_a file_b && + git commit -m pathspec_ab && + + cat >expect <<-\EOF && + 0001-pathspec_initial.patch + 0002-pathspec_a.patch + 0003-pathspec_ab.patch + EOF + + git format-patch main..pathspec -- file_a >output && + test_cmp expect output && + ! grep file_b *.patch ' test_expect_success 'format-patch --ignore-if-in-upstream HEAD' ' + git checkout side && git format-patch --ignore-if-in-upstream HEAD ' diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 000e055811..43f779d751 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -670,6 +670,39 @@ test_expect_success 'submodule update --init skips submodule with update=none' ' ) ' +test_expect_success 'submodule update with pathspec warns against uninitialized ones' ' + test_when_finished "rm -fr selective" && + git clone super selective && + ( + cd selective && + git submodule init submodule && + + git submodule update submodule 2>err && + ! grep "Submodule path .* not initialized" err && + + git submodule update rebasing 2>err && + grep "Submodule path .rebasing. not initialized" err && + + test_path_exists submodule/.git && + test_path_is_missing rebasing/.git + ) + +' + +test_expect_success 'submodule update without pathspec updates only initialized ones' ' + test_when_finished "rm -fr selective" && + git clone super selective && + ( + cd selective && + git submodule init submodule && + git submodule update 2>err && + test_path_exists submodule/.git && + test_path_is_missing rebasing/.git && + ! grep "Submodule path .* not initialized" err + ) + +' + test_expect_success 'submodule update continues after checkout error' ' (cd super && git reset --hard HEAD && diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 7b7a18dd2c..fc99703fc5 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -500,6 +500,13 @@ test_expect_success 'path limiting with import-marks does not lose unmodified fi grep file0 actual ' +test_expect_success 'path limiting works' ' + git fast-export simple -- file >actual && + sed -ne "s/^M .* //p" <actual | sort -u >actual.files && + echo file >expect && + test_cmp expect actual.files +' + test_expect_success 'avoid corrupt stream with non-existent mark' ' test_create_repo avoid_non_existent_mark && ( |
