Merge branch 'master' of github.com:git/git

* 'master' of github.com:git/git:
  A few more topics after 2.41-rc1
  Git 2.41-rc1
  t/lib-httpd: make CGIPassAuth support conditional
  t9001: mark the script as no longer leak checker clean
  send-email: clear the $message_id after validation
  upload-pack: advertise capabilities when cloning empty repos
  A bit more before -rc1
  imap-send: include strbuf.h
  run-command.c: fix missing include under `NO_PTHREADS`
  test: do not negate test_path_is_* to assert absense
  t2021: do not negate test_path_is_dir
  tests: do not negate test_path_exists
  doc/git-config: add unit for http.lowSpeedLimit
  rebase -r: fix the total number shown in the progress
  rebase --update-refs: fix loops
  attr: teach "--attr-source=<tree>" global option to "git"
maint
Jiang Xin 2023-05-20 08:44:08 +08:00
commit 68a86d028b
36 changed files with 292 additions and 55 deletions

View File

@ -3,7 +3,7 @@ Git v2.41 Release Notes

UI, Workflows & Features

* Allow information carried on the WWW-AUthenticate header to be
* Allow information carried on the WWW-Authenticate header to be
passed to the credential helpers.

* A new "fetch.hideRefs" option can be used to exclude specified refs
@ -48,7 +48,7 @@ UI, Workflows & Features

* "git clone" from an empty repository learned to propagate the
choice of the hash algorithm from the source repository to the
newly created repository.
newly created repository over any one of the v0/v1/v2 protocol.

* "git mergetool" and "git difftool" learns a new configuration
guiDefault to optionally favor configured guitool over non-gui-tool
@ -113,6 +113,10 @@ UI, Workflows & Features
* "git fetch" learned the "--porcelain" option that emits what it did
in a machine-parseable format.

* "git --attr-source=<tree> cmd $args" is a new way to have any
command to read attributes not from the working tree but from the
given tree object.


Performance, Internal Implementation, Development Support etc.

@ -365,6 +369,10 @@ Fixes since v2.40
by git forges to disable replace-refs feature.
(merge b6551feadf ds/merge-tree-use-config later to maint).

* A few bugs in the sequencer machinery that results in miscounting
the steps have been corrected.
(merge 170eea9750 js/rebase-count-fixes later to maint).

* Other code cleanup, docfix, build fix, etc.
(merge f7111175df as/doc-markup-fix later to maint).
(merge 90ff7c9898 fc/test-aggregation-clean-up later to maint).

View File

@ -246,8 +246,9 @@ significantly since the entire buffer is allocated even for small
pushes.

http.lowSpeedLimit, http.lowSpeedTime::
If the HTTP transfer speed is less than 'http.lowSpeedLimit'
for longer than 'http.lowSpeedTime' seconds, the transfer is aborted.
If the HTTP transfer speed, in bytes per second, is less than
'http.lowSpeedLimit' for longer than 'http.lowSpeedTime' seconds,
the transfer is aborted.
Can be overridden by the `GIT_HTTP_LOW_SPEED_LIMIT` and
`GIT_HTTP_LOW_SPEED_TIME` environment variables.


View File

@ -212,6 +212,11 @@ If you just want to run git as if it was started in `<path>` then use
nohelpers (exclude helper commands), alias and config
(retrieve command list from config variable completion.commands)

--attr-source=<tree-ish>::
Read gitattributes from <tree-ish> instead of the worktree. See
linkgit:gitattributes[5]. This is equivalent to setting the
`GIT_ATTR_SOURCE` environment variable.

GIT COMMANDS
------------

@ -686,6 +691,9 @@ for further details.
tells Git not to verify the SSL certificate when fetching or
pushing over HTTPS.

`GIT_ATTR_SOURCE`::
Sets the treeish that gitattributes will be read from.

`GIT_ASKPASS`::
If this environment variable is set, then Git commands which need to
acquire passwords or passphrases (e.g. for HTTP or IMAP authentication)

View File

@ -1,7 +1,7 @@
#!/bin/sh

GVF=GIT-VERSION-FILE
DEF_VER=v2.40.GIT
DEF_VER=v2.41.0-rc1

LF='
'

View File

@ -130,7 +130,7 @@ static const struct attr_check *get_archive_attrs(struct index_state *istate,
static struct attr_check *check;
if (!check)
check = attr_check_initl("export-ignore", "export-subst", NULL);
git_check_attr(istate, NULL, path, check);
git_check_attr(istate, path, check);
return check;
}


37
attr.c
View File

@ -21,6 +21,7 @@
#include "setup.h"
#include "thread-utils.h"
#include "tree-walk.h"
#include "object-name.h"

const char git_attr__true[] = "(builtin)true";
const char git_attr__false[] = "\0(builtin)false";
@ -1170,11 +1171,42 @@ static void collect_some_attrs(struct index_state *istate,
fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
}

static const char *default_attr_source_tree_object_name;

void set_git_attr_source(const char *tree_object_name)
{
default_attr_source_tree_object_name = xstrdup(tree_object_name);
}

static void compute_default_attr_source(struct object_id *attr_source)
{
if (!default_attr_source_tree_object_name)
default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);

if (!default_attr_source_tree_object_name || !is_null_oid(attr_source))
return;

if (repo_get_oid_treeish(the_repository, default_attr_source_tree_object_name, attr_source))
die(_("bad --attr-source or GIT_ATTR_SOURCE"));
}

static struct object_id *default_attr_source(void)
{
static struct object_id attr_source;

if (is_null_oid(&attr_source))
compute_default_attr_source(&attr_source);
if (is_null_oid(&attr_source))
return NULL;
return &attr_source;
}

void git_check_attr(struct index_state *istate,
const struct object_id *tree_oid, const char *path,
const char *path,
struct attr_check *check)
{
int i;
const struct object_id *tree_oid = default_attr_source();

collect_some_attrs(istate, tree_oid, path, check);

@ -1187,10 +1219,11 @@ void git_check_attr(struct index_state *istate,
}
}

void git_all_attrs(struct index_state *istate, const struct object_id *tree_oid,
void git_all_attrs(struct index_state *istate,
const char *path, struct attr_check *check)
{
int i;
const struct object_id *tree_oid = default_attr_source();

attr_check_reset(check);
collect_some_attrs(istate, tree_oid, path, check);

13
attr.h
View File

@ -45,7 +45,7 @@
* const char *path;
*
* setup_check();
* git_check_attr(&the_index, tree_oid, path, check);
* git_check_attr(&the_index, path, check);
* ------------
*
* - Act on `.value` member of the result, left in `check->items[]`:
@ -120,7 +120,6 @@
#define ATTR_MAX_FILE_SIZE (100 * 1024 * 1024)

struct index_state;
struct object_id;

/**
* An attribute is an opaque object that is identified by its name. Pass the
@ -135,6 +134,12 @@ struct git_attr;
struct all_attrs_item;
struct attr_stack;

/*
* The textual object name for the tree-ish used by git_check_attr()
* to read attributes from (instead of from the working tree).
*/
void set_git_attr_source(const char *);

/*
* Given a string, return the gitattribute object that
* corresponds to it.
@ -203,14 +208,14 @@ void attr_check_free(struct attr_check *check);
const char *git_attr_name(const struct git_attr *);

void git_check_attr(struct index_state *istate,
const struct object_id *tree_oid, const char *path,
const char *path,
struct attr_check *check);

/*
* Retrieve all attributes that apply to the specified path.
* check holds the attributes and their values.
*/
void git_all_attrs(struct index_state *istate, const struct object_id *tree_oid,
void git_all_attrs(struct index_state *istate,
const char *path, struct attr_check *check);

enum git_attr_direction {

View File

@ -64,7 +64,7 @@ static void output_attr(struct attr_check *check, const char *file)
}

static void check_attr(const char *prefix, struct attr_check *check,
const struct object_id *tree_oid, int collect_all,
int collect_all,
const char *file)

{
@ -72,9 +72,9 @@ static void check_attr(const char *prefix, struct attr_check *check,
prefix_path(prefix, prefix ? strlen(prefix) : 0, file);

if (collect_all) {
git_all_attrs(&the_index, tree_oid, full_path, check);
git_all_attrs(&the_index, full_path, check);
} else {
git_check_attr(&the_index, tree_oid, full_path, check);
git_check_attr(&the_index, full_path, check);
}
output_attr(check, file);

@ -82,7 +82,7 @@ static void check_attr(const char *prefix, struct attr_check *check,
}

static void check_attr_stdin_paths(const char *prefix, struct attr_check *check,
const struct object_id *tree_oid, int collect_all)
int collect_all)
{
struct strbuf buf = STRBUF_INIT;
struct strbuf unquoted = STRBUF_INIT;
@ -96,7 +96,7 @@ static void check_attr_stdin_paths(const char *prefix, struct attr_check *check,
die("line is badly quoted");
strbuf_swap(&buf, &unquoted);
}
check_attr(prefix, check, tree_oid, collect_all, buf.buf);
check_attr(prefix, check, collect_all, buf.buf);
maybe_flush_or_die(stdout, "attribute to stdout");
}
strbuf_release(&buf);
@ -112,7 +112,6 @@ static NORETURN void error_with_usage(const char *msg)
int cmd_check_attr(int argc, const char **argv, const char *prefix)
{
struct attr_check *check;
struct object_id *tree_oid = NULL;
struct object_id initialized_oid;
int cnt, i, doubledash, filei;

@ -188,14 +187,14 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
if (source) {
if (repo_get_oid_tree(the_repository, source, &initialized_oid))
die("%s: not a valid tree-ish source", source);
tree_oid = &initialized_oid;
set_git_attr_source(source);
}

if (stdin_paths)
check_attr_stdin_paths(prefix, check, tree_oid, all_attrs);
check_attr_stdin_paths(prefix, check, all_attrs);
else {
for (i = filei; i < argc; i++)
check_attr(prefix, check, tree_oid, all_attrs, argv[i]);
check_attr(prefix, check, all_attrs, argv[i]);
maybe_flush_or_die(stdout, "attribute to stdout");
}


View File

@ -1331,7 +1331,7 @@ static int no_try_delta(const char *path)

if (!check)
check = attr_check_initl("delta", NULL);
git_check_attr(the_repository->index, NULL, path, check);
git_check_attr(the_repository->index, path, check);
if (ATTR_FALSE(check->items[0].value))
return 1;
return 0;

View File

@ -1315,7 +1315,7 @@ void convert_attrs(struct index_state *istate,
git_config(read_convert_config, NULL);
}

git_check_attr(istate, NULL, path, check);
git_check_attr(istate, path, check);
ccheck = check->items;
ca->crlf_action = git_path_check_crlf(ccheck + 4);
if (ca->crlf_action == CRLF_UNDEFINED)

View File

@ -55,6 +55,7 @@ const char *getenv_safe(struct strvec *argv, const char *name);
#define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH"
#define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS"
#define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR"
#define GIT_ATTR_SOURCE_ENVIRONMENT "GIT_ATTR_SOURCE"

/*
* Environment variable used in handshaking the wire protocol.

View File

@ -1788,6 +1788,7 @@ sub pre_process_file {
$subject = $initial_subject;
$message = "";
$message_num++;
undef $message_id;
# Retrieve and unfold header fields.
my @header_lines = ();
while(<$fh>) {

16
git.c
View File

@ -9,6 +9,7 @@
#include "alias.h"
#include "replace-object.h"
#include "setup.h"
#include "attr.h"
#include "shallow.h"
#include "trace.h"
#include "trace2.h"
@ -314,6 +315,21 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
} else {
exit(list_cmds(cmd));
}
} else if (!strcmp(cmd, "--attr-source")) {
if (*argc < 2) {
fprintf(stderr, _("no attribute source given for --attr-source\n" ));
usage(git_usage_string);
}
setenv(GIT_ATTR_SOURCE_ENVIRONMENT, (*argv)[1], 1);
if (envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
} else if (skip_prefix(cmd, "--attr-source=", &cmd)) {
set_git_attr_source(cmd);
setenv(GIT_ATTR_SOURCE_ENVIRONMENT, cmd, 1);
if (envchanged)
*envchanged = 1;
} else {
fprintf(stderr, _("unknown option: %s\n"), cmd);
usage(git_usage_string);

View File

@ -29,6 +29,7 @@
#include "run-command.h"
#include "parse-options.h"
#include "setup.h"
#include "strbuf.h"
#include "wrapper.h"
#if defined(NO_OPENSSL) && !defined(HAVE_OPENSSL_CSPRNG)
typedef void *SSL;

View File

@ -394,7 +394,7 @@ enum ll_merge_result ll_merge(mmbuffer_t *result_buf,
normalize_file(theirs, path, istate);
}

git_check_attr(istate, NULL, path, check);
git_check_attr(istate, path, check);
ll_driver_name = check->items[0].value;
if (check->items[1].value) {
marker_size = atoi(check->items[1].value);
@ -422,7 +422,7 @@ int ll_merge_marker_size(struct index_state *istate, const char *path)

if (!check)
check = attr_check_initl("conflict-marker-size", NULL);
git_check_attr(istate, NULL, path, check);
git_check_attr(istate, path, check);
if (check->items[0].value) {
marker_size = atoi(check->items[0].value);
if (marker_size <= 0)

View File

@ -736,7 +736,7 @@ int match_pathspec_attrs(struct index_state *istate,
if (name[namelen])
name = to_free = xmemdupz(name, namelen);

git_check_attr(istate, NULL, name, item->attr_check);
git_check_attr(istate, name, item->attr_check);

free(to_free);


View File

@ -16,6 +16,7 @@
#include "packfile.h"
#include "hook.h"
#include "compat/nonblock.h"
#include "alloc.h"

void child_process_init(struct child_process *child)
{

View File

@ -2477,7 +2477,6 @@ void todo_list_release(struct todo_list *todo_list)
static struct todo_item *append_new_todo(struct todo_list *todo_list)
{
ALLOC_GROW(todo_list->items, todo_list->nr + 1, todo_list->alloc);
todo_list->total_nr++;
return todo_list->items + todo_list->nr++;
}

@ -2668,7 +2667,7 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf,
char *p = buf, *next_p;
int i, res = 0, fixup_okay = file_exists(rebase_path_done());

todo_list->current = todo_list->nr = 0;
todo_list->current = todo_list->nr = todo_list->total_nr = 0;

for (i = 1; *p; i++, p = next_p) {
char *eol = strchrnul(p, '\n');
@ -2689,6 +2688,9 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf,
item->commit = NULL;
}

if (item->command != TODO_COMMENT)
todo_list->total_nr++;

if (fixup_okay)
; /* do nothing */
else if (is_fixup(item->command))
@ -4270,7 +4272,7 @@ void todo_list_filter_update_refs(struct repository *r,
if (!is_null_oid(&rec->after))
continue;

for (j = 0; !found && j < todo_list->total_nr; j++) {
for (j = 0; !found && j < todo_list->nr; j++) {
struct todo_item *item = &todo_list->items[j];
const char *arg = todo_list->buf.buf + item->arg_offset;

@ -4300,7 +4302,7 @@ void todo_list_filter_update_refs(struct repository *r,
* For each todo_item, check if its ref is in the update_refs list.
* If not, then add it as an un-updated ref.
*/
for (i = 0; i < todo_list->total_nr; i++) {
for (i = 0; i < todo_list->nr; i++) {
struct todo_item *item = &todo_list->items[i];
const char *arg = todo_list->buf.buf + item->arg_offset;
int j, found = 0;
@ -6148,7 +6150,8 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
todo_list_to_strbuf(r, &new_todo, &buf2, -1, 0);
strbuf_swap(&new_todo.buf, &buf2);
strbuf_release(&buf2);
new_todo.total_nr -= new_todo.nr;
/* Nothing is done yet, and we're reparsing, so let's reset the count */
new_todo.total_nr = 0;
if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) < 0)
BUG("invalid todo list after expanding IDs:\n%s",
new_todo.buf.buf);

View File

@ -112,15 +112,36 @@ EOF

STRATEGY=$1

test_expect_success "$STRATEGY diff from attributes" '
test_expect_success "setup attributes files for tests with $STRATEGY" '
git checkout -b master &&
echo "file* diff=driver" >.gitattributes &&
git config diff.driver.algorithm "$STRATEGY" &&
test_must_fail git diff --no-index file1 file2 > output &&
cat expect &&
cat output &&
git add file1 file2 .gitattributes &&
git commit -m "adding files" &&
git checkout -b branchA &&
echo "file* diff=driverA" >.gitattributes &&
git add .gitattributes &&
git commit -m "adding driverA as diff driver" &&
git checkout master &&
git clone --bare --no-local . bare.git
'

test_expect_success "$STRATEGY diff from attributes" '
test_must_fail git -c diff.driver.algorithm=$STRATEGY diff --no-index file1 file2 > output &&
test_cmp expect output
'

test_expect_success "diff from attributes with bare repo with source" '
git -C bare.git --attr-source=branchA -c diff.driver.algorithm=myers \
-c diff.driverA.algorithm=$STRATEGY \
diff HEAD:file1 HEAD:file2 >output &&
test_cmp expect output
'

test_expect_success "diff from attributes with bare repo with invalid source" '
test_must_fail git -C bare.git --attr-source=invalid-branch diff \
HEAD:file1 HEAD:file2
'

test_expect_success "$STRATEGY diff from attributes has valid diffstat" '
echo "file* diff=driver" >.gitattributes &&
git config diff.driver.algorithm "$STRATEGY" &&

View File

@ -191,6 +191,20 @@ enable_http2 () {
test_set_prereq HTTP2
}

enable_cgipassauth () {
# We are looking for 2.4.13 or more recent. Since we only support
# 2.4 and up, no need to check for older major/minor.
if test "$HTTPD_VERSION_MAJOR" = 2 &&
test "$HTTPD_VERSION_MINOR" = 4 &&
test "$(echo $HTTPD_VERSION | cut -d. -f3)" -lt 13
then
echo >&4 "apache $HTTPD_VERSION too old for CGIPassAuth"
return
fi
HTTPD_PARA="$HTTPD_PARA -DUSE_CGIPASSAUTH"
test_set_prereq CGIPASSAUTH
}

start_httpd() {
prepare_httpd >&3 2>&4


View File

@ -146,7 +146,9 @@ SetEnv PERL_PATH ${PERL_PATH}
<LocationMatch /custom_auth/>
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
<IfDefine USE_CGIPASSAUTH>
CGIPassAuth on
</IfDefine>
</LocationMatch>
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/

View File

@ -802,7 +802,7 @@ test_submodule_recursing_with_args_common () {
git branch -t no_submodule origin/no_submodule &&
$command no_submodule &&
test_superproject_content origin/no_submodule &&
! test_path_is_dir sub1 &&
test_path_is_missing sub1 &&
test_must_fail git config -f .git/modules/sub1/config core.worktree &&
test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree
)

View File

@ -30,8 +30,17 @@ attr_check_quote () {
attr_check_source () {
path="$1" expect="$2" source="$3" git_opts="$4" &&

git $git_opts check-attr --source $source test -- "$path" >actual 2>err &&
echo "$path: test: $expect" >expect &&

git $git_opts check-attr --source $source test -- "$path" >actual 2>err &&
test_cmp expect actual &&
test_must_be_empty err &&

git $git_opts --attr-source="$source" check-attr test -- "$path" >actual 2>err &&
test_cmp expect actual &&
test_must_be_empty err

GIT_ATTR_SOURCE="$source" git $git_opts check-attr test -- "$path" >actual 2>err &&
test_cmp expect actual &&
test_must_be_empty err
}

View File

@ -77,7 +77,7 @@ test_expect_success 'checkout --overwrite-ignore should succeed if only ignored
echo autogenerated information >some_dir/ignore &&
echo ignore >.git/info/exclude &&
git checkout --overwrite-ignore df_conflict &&
! test_path_is_dir some_dir
test_path_is_file some_dir
'

test_done

View File

@ -578,4 +578,12 @@ test_expect_success '--rebase-merges with message matched with onto label' '
EOF
'

test_expect_success 'progress shows the correct total' '
git checkout -b progress H &&
git rebase --rebase-merges --force-rebase --verbose A 2> err &&
# Expecting "Rebasing (N/14)" here, no bogus total number
grep "^Rebasing.*/14.$" err >progress &&
test_line_count = 14 progress
'

test_done

View File

@ -63,6 +63,25 @@ do
test_i18ngrep ! fatal msg &&
test_i18ngrep ! error msg
'

test_expect_success "builtin $p pattern compiles on bare repo with --attr-source" '
test_when_finished "rm -rf bare.git" &&
git checkout -B master &&
git add . &&
echo "*.java diff=notexist" >.gitattributes &&
git add .gitattributes &&
git commit -am "changing gitattributes" &&
git checkout -B branchA &&
echo "*.java diff=$p" >.gitattributes &&
git add .gitattributes &&
git commit -am "changing gitattributes" &&
git clone --bare --no-local . bare.git &&
git -C bare.git symbolic-ref HEAD refs/heads/master &&
test_expect_code 1 git -C bare.git --attr-source=branchA \
diff --exit-code HEAD:A.java HEAD:B.java 2>msg &&
test_i18ngrep ! fatal msg &&
test_i18ngrep ! error msg
'
done

test_expect_success 'last regexp must not be negated' '

View File

@ -151,7 +151,7 @@ test_expect_success 'diff does not fetch anything if inexact rename detection is

# Ensure no fetches.
GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD &&
! test_path_exists trace
test_path_is_missing trace
'

test_expect_success 'diff --break-rewrites fetches only if necessary, and batches blobs if it does' '
@ -171,7 +171,7 @@ test_expect_success 'diff --break-rewrites fetches only if necessary, and batche

# Ensure no fetches.
GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD &&
! test_path_exists trace &&
test_path_is_missing trace &&

# But with --break-rewrites, ensure that there is exactly 1 negotiation
# by checking that there is only 1 "done" line sent. ("done" marks the

View File

@ -74,7 +74,7 @@ test_expect_success SYMLINKS 'symlink escape when creating new files' '
error: affected file ${SQ}renamed-symlink/create-me${SQ} is beyond a symbolic link
EOF
test_cmp expected_stderr stderr &&
! test_path_exists .git/create-me
test_path_is_missing .git/create-me
'

test_expect_success SYMLINKS 'symlink escape when modifying file' '

View File

@ -611,6 +611,33 @@ test_expect_success 'client falls back from v2 to v0 to match server' '
grep symref=HEAD:refs/heads/ trace
'

test_expect_success 'create empty http-accessible SHA-256 repository' '
mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
git --bare init --object-format=sha256
)
'

test_expect_success 'clone empty SHA-256 repository with protocol v2' '
rm -fr sha256 &&
echo sha256 >expected &&
git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" &&
git -C sha256 rev-parse --show-object-format >actual &&
test_cmp actual expected &&
git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
test_must_be_empty actual
'

test_expect_success 'clone empty SHA-256 repository with protocol v0' '
rm -fr sha256 &&
echo sha256 >expected &&
GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" &&
git -C sha256 rev-parse --show-object-format >actual &&
test_cmp actual expected &&
git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
test_must_be_empty actual
'

test_expect_success 'passing hostname resolution information works' '
BOGUS_HOST=gitbogusexamplehost.invalid &&
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&

View File

@ -5,6 +5,12 @@ test_description='test http auth header and credential helper interop'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh

enable_cgipassauth
if ! test_have_prereq CGIPASSAUTH
then
skip_all="no CGIPassAuth support"
test_done
fi
start_httpd

test_expect_success 'setup_credential_helper' '

View File

@ -121,7 +121,7 @@ test_expect_success "fetch.recurseSubmodules option triggers recursive fetch (bu
sub_oid=$(git -C child rev-parse HEAD) &&
git -C super/sub cat-file -e $sub_oid &&
# Check that the submodule worktree did not update
! test_path_is_file super/sub/merge_strategy_5.t
test_path_is_missing super/sub/merge_strategy_5.t
'

test_expect_success "fetch.recurseSubmodules takes precedence over submodule.recurse" '
@ -134,7 +134,7 @@ test_expect_success "fetch.recurseSubmodules takes precedence over submodule.rec
sub_oid=$(git -C child rev-parse HEAD) &&
git -C super/sub cat-file -e $sub_oid &&
# Check that the submodule worktree did not update
! test_path_is_file super/sub/merge_strategy_6.t
test_path_is_missing super/sub/merge_strategy_6.t
'

test_expect_success 'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' '

View File

@ -244,15 +244,28 @@ test_expect_success 'push with ssh:// using protocol v1' '
grep "push< version 1" log
'

test_expect_success 'clone propagates object-format from empty repo' '
test_when_finished "rm -fr src256 dst256" &&

echo sha256 >expect &&
git init --object-format=sha256 src256 &&
git clone --no-local src256 dst256 &&
git -C dst256 rev-parse --show-object-format >actual &&

test_cmp expect actual
'

# Test protocol v1 with 'http://' transport
#
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd

test_expect_success 'create repo to be served by http:// transport' '
test_expect_success 'create repos to be served by http:// transport' '
git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true &&
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
git init --object-format=sha256 "$HTTPD_DOCUMENT_ROOT_PATH/sha256" &&
git -C "$HTTPD_DOCUMENT_ROOT_PATH/sha256" config http.receivepack true
'

test_expect_success 'clone with http:// using protocol v1' '
@ -269,6 +282,20 @@ test_expect_success 'clone with http:// using protocol v1' '
grep "git< version 1" log
'

test_expect_success 'clone with http:// using protocol v1 with empty SHA-256 repo' '
GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \
clone "$HTTPD_URL/smart/sha256" sha256 2>log &&

echo sha256 >expect &&
git -C sha256 rev-parse --show-object-format >actual &&
test_cmp expect actual &&

# Client requested to use protocol v1
grep "Git-Protocol: version=1" log &&
# Server responded using protocol v1
grep "git< version 1" log
'

test_expect_success 'fetch with http:// using protocol v1' '
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&


View File

@ -4,7 +4,7 @@ test_description='git send-email'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME

TEST_PASSES_SANITIZE_LEAK=true
# no longer TEST_PASSES_SANITIZE_LEAK=true - format-patch --thread leaks
. ./test-lib.sh

# May be altered later in the test
@ -47,7 +47,7 @@ clean_fake_sendmail () {

test_expect_success $PREREQ 'Extract patches' '
patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1) &&
threaded_patches=$(git format-patch -o threaded -s --in-reply-to="format" HEAD^1)
threaded_patches=$(git format-patch -o threaded --thread=shallow -s --in-reply-to="format" HEAD^1)
'

# Test no confirm early to ensure remaining tests will not hang
@ -655,6 +655,21 @@ test_expect_success $PREREQ "--validate hook supports header argument" '
outdir/000?-*.patch
'

test_expect_success $PREREQ 'clear message-id before parsing a new message' '
clean_fake_sendmail &&
echo true | write_script my-hooks/sendemail-validate &&
test_config core.hooksPath my-hooks &&
GIT_SEND_EMAIL_NOTTY=1 \
git send-email --validate --to=recipient@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
$patches $threaded_patches &&
id0=$(grep "^Message-ID: " $threaded_patches) &&
id1=$(grep "^Message-ID: " msgtxt1) &&
id2=$(grep "^Message-ID: " msgtxt2) &&
test "z$id0" = "z$id2" &&
test "z$id1" != "z$id2"
'

for enc in 7bit 8bit quoted-printable base64
do
test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '

View File

@ -120,6 +120,7 @@ struct upload_pack_data {
unsigned allow_ref_in_want : 1; /* v2 only */
unsigned allow_sideband_all : 1; /* v2 only */
unsigned advertise_sid : 1;
unsigned sent_capabilities : 1;
};

static void upload_pack_data_init(struct upload_pack_data *data)
@ -1206,18 +1207,17 @@ static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
strbuf_addf(buf, " session-id=%s", trace2_session_id());
}

static int send_ref(const char *refname, const struct object_id *oid,
int flag UNUSED, void *cb_data)
static void write_v0_ref(struct upload_pack_data *data,
const char *refname, const char *refname_nons,
const struct object_id *oid)
{
static const char *capabilities = "multi_ack thin-pack side-band"
" side-band-64k ofs-delta shallow deepen-since deepen-not"
" deepen-relative no-progress include-tag multi_ack_detailed";
const char *refname_nons = strip_namespace(refname);
struct object_id peeled;
struct upload_pack_data *data = cb_data;

if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
return 0;
return;

if (capabilities) {
struct strbuf symref_info = STRBUF_INIT;
@ -1240,12 +1240,20 @@ static int send_ref(const char *refname, const struct object_id *oid,
git_user_agent_sanitized());
strbuf_release(&symref_info);
strbuf_release(&session_id);
data->sent_capabilities = 1;
} else {
packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
}
capabilities = NULL;
if (!peel_iterated_oid(oid, &peeled))
packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
return;
}

static int send_ref(const char *refname, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
return 0;
}

@ -1379,6 +1387,10 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
data.no_done = 1;
head_ref_namespaced(send_ref, &data);
for_each_namespaced_ref(send_ref, &data);
if (!data.sent_capabilities) {
const char *refname = "capabilities^{}";
write_v0_ref(&data, refname, refname, null_oid());
}
/*
* fflush stdout before calling advertise_shallow_grafts because send_ref
* uses stdio.

View File

@ -444,7 +444,7 @@ struct userdiff_driver *userdiff_find_by_path(struct index_state *istate,
check = attr_check_initl("diff", NULL);
if (!path)
return NULL;
git_check_attr(istate, NULL, path, check);
git_check_attr(istate, path, check);

if (ATTR_TRUE(check->items[0].value))
return &driver_true;

2
ws.c
View File

@ -83,7 +83,7 @@ unsigned whitespace_rule(struct index_state *istate, const char *pathname)
if (!attr_whitespace_rule)
attr_whitespace_rule = attr_check_initl("whitespace", NULL);

git_check_attr(istate, NULL, pathname, attr_whitespace_rule);
git_check_attr(istate, pathname, attr_whitespace_rule);
value = attr_whitespace_rule->items[0].value;
if (ATTR_TRUE(value)) {
/* true (whitespace) */