diff options
| -rw-r--r-- | Documentation/RelNotes/2.26.0.txt | 53 | ||||
| -rw-r--r-- | Documentation/gitcore-tutorial.txt | 2 | ||||
| -rwxr-xr-x | GIT-VERSION-GEN | 2 | ||||
| l--------- | RelNotes | 2 | ||||
| -rw-r--r-- | builtin/checkout.c | 2 | ||||
| -rw-r--r-- | builtin/commit.c | 1 | ||||
| -rw-r--r-- | contrib/credential/netrc/.gitignore | 1 | ||||
| -rw-r--r-- | contrib/credential/netrc/Makefile | 26 | ||||
| -rwxr-xr-x | contrib/credential/netrc/git-credential-netrc.perl (renamed from contrib/credential/netrc/git-credential-netrc) | 2 | ||||
| -rw-r--r-- | object-store.h | 2 | ||||
| -rw-r--r-- | run-command.c | 3 | ||||
| -rw-r--r-- | sha1-file.c | 38 | ||||
| -rw-r--r-- | string-list.h | 6 | ||||
| -rwxr-xr-x | t/t2070-restore.sh | 17 | ||||
| -rwxr-xr-x | t/t5702-protocol-v2.sh | 12 | ||||
| -rwxr-xr-x | t/t7500-commit-template-squash-signoff.sh | 9 | ||||
| -rw-r--r-- | transport.c | 2 | ||||
| -rw-r--r-- | unpack-trees.c | 32 |
18 files changed, 166 insertions, 46 deletions
diff --git a/Documentation/RelNotes/2.26.0.txt b/Documentation/RelNotes/2.26.0.txt new file mode 100644 index 0000000000..5553c1f4e6 --- /dev/null +++ b/Documentation/RelNotes/2.26.0.txt @@ -0,0 +1,53 @@ +Git 2.26 Release Notes +====================== + +Updates since v2.25 +------------------- + +UI, Workflows & Features + + * Sample credential helper for using .netrc has been updated to work + out of the box. + + +Performance, Internal Implementation, Development Support etc. + + +Fixes since v2.25 +----------------- + + * "git commit" gives output similar to "git status" when there is + nothing to commit, but without honoring the advise.statusHints + configuration variable, which has been corrected. + (merge 5c4f55f1f6 hw/commit-advise-while-rejecting later to maint). + + * has_object_file() said "no" given an object registered to the + system via pretend_object_file(), making it inconsistent with + read_object_file(), causing lazy fetch to attempt fetching an + empty tree from promisor remotes. + (merge 9c8a294a1a jt/sha1-file-remove-oi-skip-cached later to maint). + + * Complete an update to tutorial that encourages "git switch" over + "git checkout" that was done only half-way. + (merge 1a7e454dd6 hw/tutorial-favor-switch-over-checkout later to maint). + + * C pedantry ;-) fix. + (merge 63ab08fb99 bc/run-command-nullness-after-free-fix later to maint). + + * The code that tries to skip over the entries for the paths in a + single directory using the cache-tree was not careful enough + against corrupt index file. + (merge 573117dfa5 es/unpack-trees-oob-fix later to maint). + + * Reduce unnecessary round-trip when running "ls-remote" over the + stateless RPC mechanism. + (merge 4d8cab95cc jk/no-flush-upon-disconnecting-slrpc-transport later to maint). + + * "git restore --staged" did not correctly update the cache-tree + structure, resulting in bogus trees to be written afterwards, which + has been corrected. + (merge e701bab3e9 nd/switch-and-restore later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge 26f924d50e en/simplify-check-updates-in-unpack-trees later to maint). + (merge 065027ee1a en/string-list-can-be-custom-sorted later to maint). diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt index f880d21dfb..c0b95256cc 100644 --- a/Documentation/gitcore-tutorial.txt +++ b/Documentation/gitcore-tutorial.txt @@ -751,7 +751,7 @@ to it. ================================================ If you make the decision to start your new branch at some other point in the history than the current `HEAD`, you can do so by -just telling 'git checkout' what the base of the checkout would be. +just telling 'git switch' what the base of the checkout would be. In other words, if you have an earlier tag or branch, you'd just do ------------ diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 2b7f62b8bf..616d5a6404 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.25.0 +DEF_VER=v2.25.GIT LF=' ' @@ -1 +1 @@ -Documentation/RelNotes/2.25.0.txt
\ No newline at end of file +Documentation/RelNotes/2.26.0.txt
\ No newline at end of file diff --git a/builtin/checkout.c b/builtin/checkout.c index b52c490c8f..18ef5fb975 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -524,6 +524,8 @@ static int checkout_paths(const struct checkout_opts *opts, /* Now we are committed to check them out */ if (opts->checkout_worktree) errs |= checkout_worktree(opts); + else + remove_marked_cache_entries(&the_index, 1); /* * Allow updating the index when checking out from the index. diff --git a/builtin/commit.c b/builtin/commit.c index aa1332308a..646e84547d 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -964,6 +964,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, */ if (!committable && whence != FROM_MERGE && !allow_empty && !(amend && is_a_merge(current_head))) { + s->hints = advice_status_hints; s->display_comment_prefix = old_display_comment_prefix; run_status(stdout, index_file, prefix, 0, s); if (amend) diff --git a/contrib/credential/netrc/.gitignore b/contrib/credential/netrc/.gitignore new file mode 100644 index 0000000000..d41cdde84b --- /dev/null +++ b/contrib/credential/netrc/.gitignore @@ -0,0 +1 @@ +git-credential-netrc diff --git a/contrib/credential/netrc/Makefile b/contrib/credential/netrc/Makefile index 6174e3bb83..c284fb8ac4 100644 --- a/contrib/credential/netrc/Makefile +++ b/contrib/credential/netrc/Makefile @@ -1,8 +1,30 @@ # The default target of this Makefile is... all:: -test: +SCRIPT_PERL = git-credential-netrc.perl +GIT_ROOT_DIR = ../../.. +HERE = contrib/credential/netrc + +SCRIPT_PERL_FULL = $(patsubst %,$(HERE)/%,$(SCRIPT_PERL)) + +all:: build + +build: + $(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \ + build-perl-script + +install: build + $(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \ + install-perl-script + +clean: + $(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \ + clean-perl-script + +test: build ./t-git-credential-netrc.sh -testverbose: +testverbose: build ./t-git-credential-netrc.sh -d -v + +.PHONY: all build install clean test testverbose diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc.perl index ebfc123ec6..bc57cc6588 100755 --- a/contrib/credential/netrc/git-credential-netrc +++ b/contrib/credential/netrc/git-credential-netrc.perl @@ -423,7 +423,7 @@ sub load_config { # load settings from git config my $options = shift; # set from command argument, gpg.program option, or default to gpg - $options->{'gpg'} //= Git->repository()->config('gpg.program') + $options->{'gpg'} //= Git::config('gpg.program') // 'gpg'; log_verbose("using $options{'gpg'} for GPG operations"); } diff --git a/object-store.h b/object-store.h index 55ee639350..61b8b13e3b 100644 --- a/object-store.h +++ b/object-store.h @@ -292,8 +292,6 @@ struct object_info { #define OBJECT_INFO_LOOKUP_REPLACE 1 /* Allow reading from a loose object file of unknown/bogus type */ #define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2 -/* Do not check cached storage */ -#define OBJECT_INFO_SKIP_CACHED 4 /* Do not retry packed storage after checking packed and loose storage */ #define OBJECT_INFO_QUICK 8 /* Do not check loose object */ diff --git a/run-command.c b/run-command.c index 9942f120a9..f5e1149f9b 100644 --- a/run-command.c +++ b/run-command.c @@ -213,8 +213,9 @@ static char *locate_in_PATH(const char *file) static int exists_in_PATH(const char *file) { char *r = locate_in_PATH(file); + int found = r != NULL; free(r); - return r != NULL; + return found; } int sane_execvp(const char *file, char * const argv[]) diff --git a/sha1-file.c b/sha1-file.c index 188de57634..03ae9ae93a 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -1417,6 +1417,7 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid, struct object_info *oi, unsigned flags) { static struct object_info blank_oi = OBJECT_INFO_INIT; + struct cached_object *co; struct pack_entry e; int rtype; const struct object_id *real = oid; @@ -1431,24 +1432,22 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid, if (!oi) oi = &blank_oi; - if (!(flags & OBJECT_INFO_SKIP_CACHED)) { - struct cached_object *co = find_cached_object(real); - if (co) { - if (oi->typep) - *(oi->typep) = co->type; - if (oi->sizep) - *(oi->sizep) = co->size; - if (oi->disk_sizep) - *(oi->disk_sizep) = 0; - if (oi->delta_base_sha1) - hashclr(oi->delta_base_sha1); - if (oi->type_name) - strbuf_addstr(oi->type_name, type_name(co->type)); - if (oi->contentp) - *oi->contentp = xmemdupz(co->buf, co->size); - oi->whence = OI_CACHED; - return 0; - } + co = find_cached_object(real); + if (co) { + if (oi->typep) + *(oi->typep) = co->type; + if (oi->sizep) + *(oi->sizep) = co->size; + if (oi->disk_sizep) + *(oi->disk_sizep) = 0; + if (oi->delta_base_sha1) + hashclr(oi->delta_base_sha1); + if (oi->type_name) + strbuf_addstr(oi->type_name, type_name(co->type)); + if (oi->contentp) + *oi->contentp = xmemdupz(co->buf, co->size); + oi->whence = OI_CACHED; + return 0; } while (1) { @@ -1932,8 +1931,7 @@ int repo_has_object_file_with_flags(struct repository *r, { if (!startup_info->have_repository) return 0; - return oid_object_info_extended(r, oid, NULL, - flags | OBJECT_INFO_SKIP_CACHED) >= 0; + return oid_object_info_extended(r, oid, NULL, flags) >= 0; } int repo_has_object_file(struct repository *r, diff --git a/string-list.h b/string-list.h index 7bb0ad07e6..6c5d274126 100644 --- a/string-list.h +++ b/string-list.h @@ -4,7 +4,8 @@ /** * The string_list API offers a data structure and functions to handle * sorted and unsorted arrays of strings. A "sorted" list is one whose - * entries are sorted by string value in `strcmp()` order. + * entries are sorted by string value in the order specified by the `cmp` + * member (`strcmp()` by default). * * The caller: * @@ -209,7 +210,8 @@ struct string_list_item *string_list_append(struct string_list *list, const char struct string_list_item *string_list_append_nodup(struct string_list *list, char *string); /** - * Sort the list's entries by string value in `strcmp()` order. + * Sort the list's entries by string value in order specified by list->cmp + * (strcmp() if list->cmp is NULL). */ void string_list_sort(struct string_list *list); diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh index 21c3f84459..076d0df7fc 100755 --- a/t/t2070-restore.sh +++ b/t/t2070-restore.sh @@ -106,4 +106,21 @@ test_expect_success 'restore --staged adds deleted intent-to-add file back to in git diff --cached --exit-code ' +test_expect_success 'restore --staged invalidates cache tree for deletions' ' + test_when_finished git reset --hard && + >new1 && + >new2 && + git add new1 new2 && + + # It is important to commit and then reset here, so that the index + # contains a valid cache-tree for the "both" tree. + git commit -m both && + git reset --soft HEAD^ && + + git restore --staged new1 && + git commit -m "just new2" && + git rev-parse HEAD:new2 && + test_must_fail git rev-parse HEAD:new1 +' + test_done diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index e73067d23f..7fd7102c87 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -665,6 +665,18 @@ test_expect_success 'fetch from namespaced repo respects namespaces' ' test_cmp expect actual ' +test_expect_success 'ls-remote with v2 http sends only one POST' ' + test_when_finished "rm -f log" && + + git ls-remote "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" >expect && + GIT_TRACE_CURL="$(pwd)/log" git -c protocol.version=2 \ + ls-remote "$HTTPD_URL/smart/http_parent" >actual && + test_cmp expect actual && + + grep "Send header: POST" log >posts && + test_line_count = 1 posts +' + test_expect_success 'push with http:// and a config of v2 does not request v2' ' test_when_finished "rm -f log" && # Till v2 for push is designed, make sure that if a client has diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh index 46a5cd4b73..6d19ece05d 100755 --- a/t/t7500-commit-template-squash-signoff.sh +++ b/t/t7500-commit-template-squash-signoff.sh @@ -382,4 +382,13 @@ test_expect_success 'check commit with unstaged rename and copy' ' ) ' +test_expect_success 'commit without staging files fails and displays hints' ' + echo "initial" >file && + git add file && + git commit -m initial && + echo "changes" >>file && + test_must_fail git commit -m update >actual && + test_i18ngrep "no changes added to commit (use \"git add\" and/or \"git commit -a\")" actual +' + test_done diff --git a/transport.c b/transport.c index 83379a037d..1fdc7dac1a 100644 --- a/transport.c +++ b/transport.c @@ -737,7 +737,7 @@ static int disconnect_git(struct transport *transport) { struct git_transport_data *data = transport->data; if (data->conn) { - if (data->got_remote_heads) + if (data->got_remote_heads && !transport->stateless_rpc) packet_flush(data->fd[1]); close(data->fd[0]); close(data->fd[1]); diff --git a/unpack-trees.c b/unpack-trees.c index 2399b6818b..d5f4d997da 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -372,15 +372,20 @@ static int check_updates(struct unpack_trees_options *o) state.refresh_cache = 1; state.istate = index; + if (!o->update || o->dry_run) { + remove_marked_cache_entries(index, 0); + trace_performance_leave("check_updates"); + return 0; + } + if (o->clone) setup_collided_checkout_detection(&state, index); progress = get_progress(o); - if (o->update) - git_attr_set_direction(GIT_ATTR_CHECKOUT); + git_attr_set_direction(GIT_ATTR_CHECKOUT); - if (should_update_submodules() && o->update && !o->dry_run) + if (should_update_submodules()) load_gitmodules_file(index, NULL); for (i = 0; i < index->cache_nr; i++) { @@ -388,18 +393,18 @@ static int check_updates(struct unpack_trees_options *o) if (ce->ce_flags & CE_WT_REMOVE) { display_progress(progress, ++cnt); - if (o->update && !o->dry_run) - unlink_entry(ce); + unlink_entry(ce); } } + remove_marked_cache_entries(index, 0); remove_scheduled_dirs(); - if (should_update_submodules() && o->update && !o->dry_run) + if (should_update_submodules()) load_gitmodules_file(index, &state); enable_delayed_checkout(&state); - if (has_promisor_remote() && o->update && !o->dry_run) { + if (has_promisor_remote()) { /* * Prefetch the objects that are to be checked out in the loop * below. @@ -431,15 +436,12 @@ static int check_updates(struct unpack_trees_options *o) ce->name); display_progress(progress, ++cnt); ce->ce_flags &= ~CE_UPDATE; - if (o->update && !o->dry_run) { - errs |= checkout_entry(ce, &state, NULL, NULL); - } + errs |= checkout_entry(ce, &state, NULL, NULL); } } stop_progress(&progress); errs |= finish_delayed_checkout(&state, NULL); - if (o->update) - git_attr_set_direction(GIT_ATTR_CHECKIN); + git_attr_set_direction(GIT_ATTR_CHECKIN); if (o->clone) report_collided_checkout(index); @@ -694,9 +696,11 @@ static int index_pos_by_traverse_info(struct name_entry *names, if (pos >= 0) BUG("This is a directory and should not exist in index"); pos = -pos - 1; - if (!starts_with(o->src_index->cache[pos]->name, name.buf) || + if (pos >= o->src_index->cache_nr || + !starts_with(o->src_index->cache[pos]->name, name.buf) || (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name.buf))) - BUG("pos must point at the first entry in this directory"); + BUG("pos %d doesn't point to the first entry of %s in index", + pos, name.buf); strbuf_release(&name); return pos; } |
