aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.5.1.txt16
-rw-r--r--Documentation/git.txt3
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile4
-rw-r--r--alias.c3
-rw-r--r--builtin/clone.c3
-rw-r--r--builtin/fetch.c14
-rw-r--r--cache.h1
-rw-r--r--compat/mingw.c2
-rw-r--r--config.c39
-rwxr-xr-xgenerate-cmdlist.perl50
-rwxr-xr-xgenerate-cmdlist.sh50
-rw-r--r--git-compat-util.h2
-rwxr-xr-xgit-pull.sh2
-rw-r--r--pager.c3
-rw-r--r--run-command.c17
-rw-r--r--sha1_file.c5
-rw-r--r--strbuf.c10
-rwxr-xr-xt/t1509-root-worktree.sh8
-rwxr-xr-xt/t2019-checkout-ambiguous-ref.sh2
-rwxr-xr-xt/t5603-clone-dirname.sh106
-rwxr-xr-xt/t7006-pager.sh9
-rw-r--r--t/test-lib.sh13
-rw-r--r--transport-helper.c8
-rw-r--r--usage.c31
25 files changed, 282 insertions, 121 deletions
diff --git a/Documentation/RelNotes/2.5.1.txt b/Documentation/RelNotes/2.5.1.txt
index 3c468519b..b70553308 100644
--- a/Documentation/RelNotes/2.5.1.txt
+++ b/Documentation/RelNotes/2.5.1.txt
@@ -45,5 +45,21 @@ Fixes since v2.5
stable, which was a no-no. Apply a workaround to force a
particular date format.
+ * "git clone $URL" in recent releases of Git contains a regression in
+ the code that invents a new repository name incorrectly based on
+ the $URL. This has been corrected.
+ (merge db2e220 jk/guess-repo-name-regression-fix later to maint).
+
+ * Running tests with the "-x" option to make them verbose had some
+ unpleasant interactions with other features of the test suite.
+ (merge 9b5fe78 jk/test-with-x later to maint).
+
+ * "git pull" in recent releases of Git has a regression in the code
+ that allows custom path to the --upload-pack=<program>. This has
+ been corrected.
+
+ * pipe() emulation used in Git for Windows looked at a wrong variable
+ when checking for an error from an _open_osfhandle() call.
+
Also contains typofixes, documentation updates and trivial code
clean-ups.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 8b7e3a2d6..5a78d7753 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v2.5.0/git.html[documentation for release 2.5]
+* link:v2.5.1/git.html[documentation for release 2.5.1]
* release notes for
+ link:RelNotes/2.5.1.txt[2.5.1],
link:RelNotes/2.5.0.txt[2.5].
* link:v2.4.8/git.html[documentation for release 2.4.8]
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 5cadf44e1..5e23aba39 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.5.0
+DEF_VER=v2.5.1
LF='
'
diff --git a/Makefile b/Makefile
index 8c3c724a7..ce0cfe2a4 100644
--- a/Makefile
+++ b/Makefile
@@ -1696,10 +1696,10 @@ $(BUILT_INS): git$X
ln -s $< $@ 2>/dev/null || \
cp $< $@
-common-cmds.h: generate-cmdlist.perl command-list.txt
+common-cmds.h: generate-cmdlist.sh command-list.txt
common-cmds.h: $(wildcard Documentation/git-*.txt)
- $(QUIET_GEN)$(PERL_PATH) generate-cmdlist.perl command-list.txt > $@+ && mv $@+ $@
+ $(QUIET_GEN)./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
diff --git a/alias.c b/alias.c
index 6aa164a36..a11229db9 100644
--- a/alias.c
+++ b/alias.c
@@ -5,7 +5,8 @@ char *alias_lookup(const char *alias)
char *v = NULL;
struct strbuf key = STRBUF_INIT;
strbuf_addf(&key, "alias.%s", alias);
- git_config_get_string(key.buf, &v);
+ if (git_config_key_is_valid(key.buf))
+ git_config_get_string(key.buf, &v);
strbuf_release(&key);
return v;
}
diff --git a/builtin/clone.c b/builtin/clone.c
index a72ff7e00..53cf545c5 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -174,7 +174,8 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
/*
* Strip .{bundle,git}.
*/
- strip_suffix(start, is_bundle ? ".bundle" : ".git" , &len);
+ len = end - start;
+ strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
if (is_bare)
dir = xstrfmt("%.*s.git", (int)len, start);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8d5b2dba2..635bbdfc8 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -979,17 +979,15 @@ static int get_remote_group(const char *key, const char *value, void *priv)
{
struct remote_group_data *g = priv;
- if (starts_with(key, "remotes.") &&
- !strcmp(key + 8, g->name)) {
+ if (skip_prefix(key, "remotes.", &key) && !strcmp(key, g->name)) {
/* split list by white space */
- int space = strcspn(value, " \t\n");
while (*value) {
- if (space > 1) {
+ size_t wordlen = strcspn(value, " \t\n");
+
+ if (wordlen >= 1)
string_list_append(g->list,
- xstrndup(value, space));
- }
- value += space + (value[space] != '\0');
- space = strcspn(value, " \t\n");
+ xstrndup(value, wordlen));
+ value += wordlen + (value[wordlen] != '\0');
}
}
diff --git a/cache.h b/cache.h
index 4f554664c..c9e2f7487 100644
--- a/cache.h
+++ b/cache.h
@@ -1446,6 +1446,7 @@ extern int git_config_pathname(const char **, const char *, const char *);
extern int git_config_set_in_file(const char *, const char *, const char *);
extern int git_config_set(const char *, const char *);
extern int git_config_parse_key(const char *, char **, int *);
+extern int git_config_key_is_valid(const char *key);
extern int git_config_set_multivar(const char *, const char *, const char *, int);
extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
extern int git_config_rename_section(const char *, const char *);
diff --git a/compat/mingw.c b/compat/mingw.c
index 496e6f8bb..f74da235f 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -681,7 +681,7 @@ int pipe(int filedes[2])
return -1;
}
filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT);
- if (filedes[0] < 0) {
+ if (filedes[1] < 0) {
close(filedes[0]);
CloseHandle(h[1]);
return -1;
diff --git a/config.c b/config.c
index 9fd275f2c..8adc15a44 100644
--- a/config.c
+++ b/config.c
@@ -1848,7 +1848,7 @@ int git_config_set(const char *key, const char *value)
* baselen - pointer to int which will hold the length of the
* section + subsection part, can be NULL
*/
-int git_config_parse_key(const char *key, char **store_key, int *baselen_)
+static int git_config_parse_key_1(const char *key, char **store_key, int *baselen_, int quiet)
{
int i, dot, baselen;
const char *last_dot = strrchr(key, '.');
@@ -1859,12 +1859,14 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_)
*/
if (last_dot == NULL || last_dot == key) {
- error("key does not contain a section: %s", key);
+ if (!quiet)
+ error("key does not contain a section: %s", key);
return -CONFIG_NO_SECTION_OR_NAME;
}
if (!last_dot[1]) {
- error("key does not contain variable name: %s", key);
+ if (!quiet)
+ error("key does not contain variable name: %s", key);
return -CONFIG_NO_SECTION_OR_NAME;
}
@@ -1875,7 +1877,8 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_)
/*
* Validate the key and while at it, lower case it for matching.
*/
- *store_key = xmalloc(strlen(key) + 1);
+ if (store_key)
+ *store_key = xmalloc(strlen(key) + 1);
dot = 0;
for (i = 0; key[i]; i++) {
@@ -1886,26 +1889,42 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_)
if (!dot || i > baselen) {
if (!iskeychar(c) ||
(i == baselen + 1 && !isalpha(c))) {
- error("invalid key: %s", key);
+ if (!quiet)
+ error("invalid key: %s", key);
goto out_free_ret_1;
}
c = tolower(c);
} else if (c == '\n') {
- error("invalid key (newline): %s", key);
+ if (!quiet)
+ error("invalid key (newline): %s", key);
goto out_free_ret_1;
}
- (*store_key)[i] = c;
+ if (store_key)
+ (*store_key)[i] = c;
}
- (*store_key)[i] = 0;
+ if (store_key)
+ (*store_key)[i] = 0;
return 0;
out_free_ret_1:
- free(*store_key);
- *store_key = NULL;
+ if (store_key) {
+ free(*store_key);
+ *store_key = NULL;
+ }
return -CONFIG_INVALID_KEY;
}
+int git_config_parse_key(const char *key, char **store_key, int *baselen)
+{
+ return git_config_parse_key_1(key, store_key, baselen, 0);
+}
+
+int git_config_key_is_valid(const char *key)
+{
+ return !git_config_parse_key_1(key, NULL, NULL, 1);
+}
+
/*
* If value==NULL, unset in (remove from) config,
* if value_regex!=NULL, disregard key/value pairs where value does not match.
diff --git a/generate-cmdlist.perl b/generate-cmdlist.perl
deleted file mode 100755
index 31516e36a..000000000
--- a/generate-cmdlist.perl
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-print <<"EOT";
-/* Automatically generated by $0 */
-
-struct cmdname_help {
- char name[16];
- char help[80];
- unsigned char group;
-};
-
-static char *common_cmd_groups[] = {
-EOT
-
-my $n = 0;
-my %grp;
-while (<>) {
- last if /^### command list/;
- next if (1../^### common groups/) || /^#/ || /^\s*$/;
- chop;
- my ($k, $v) = split ' ', $_, 2;
- $grp{$k} = $n++;
- print "\tN_(\"$v\"),\n";
-}
-
-print "};\n\nstatic struct cmdname_help common_cmds[] = {\n";
-
-while (<>) {
- next if /^#/ || /^\s*$/;
- my @tags = split;
- my $cmd = shift @tags;
- for my $t (@tags) {
- if (exists $grp{$t}) {
- my $s;
- open my $f, '<', "Documentation/$cmd.txt" or die;
- while (<$f>) {
- ($s) = /^$cmd - (.+)$/;
- last if $s;
- }
- close $f;
- $cmd =~ s/^git-//;
- print "\t{\"$cmd\", N_(\"$s\"), $grp{$t}},\n";
- last;
- }
- }
-}
-
-print "};\n";
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
new file mode 100755
index 000000000..ab0d1b0c0
--- /dev/null
+++ b/generate-cmdlist.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+echo "/* Automatically generated by $0 */
+struct cmdname_help {
+ char name[16];
+ char help[80];
+ unsigned char group;
+};
+
+static const char *common_cmd_groups[] = {"
+
+grps=grps$$.tmp
+match=match$$.tmp
+trap "rm -f '$grps' '$match'" 0 1 2 3 15
+
+sed -n '
+ 1,/^### common groups/b
+ /^### command list/q
+ /^#/b
+ /^[ ]*$/b
+ h;s/^[^ ][^ ]*[ ][ ]*\(.*\)/ N_("\1"),/p
+ g;s/^\([^ ][^ ]*\)[ ].*/\1/w '$grps'
+ ' "$1"
+printf '};\n\n'
+
+n=0
+substnum=
+while read grp
+do
+ echo "^git-..*[ ]$grp"
+ substnum="$substnum${substnum:+;}s/[ ]$grp/$n/"
+ n=$(($n+1))
+done <"$grps" >"$match"
+
+printf 'static struct cmdname_help common_cmds[] = {\n'
+grep -f "$match" "$1" |
+sed 's/^git-//' |
+sort |
+while read cmd tags
+do
+ tag=$(echo "$tags" | sed "$substnum; s/[^0-9]//g")
+ sed -n '
+ /^NAME/,/git-'"$cmd"'/H
+ ${
+ x
+ s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", N_("\1"), '$tag'},/
+ p
+ }' "Documentation/git-$cmd.txt"
+done
+echo "};"
diff --git a/git-compat-util.h b/git-compat-util.h
index c6d391f86..076461e8c 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -389,7 +389,6 @@ struct strbuf;
/* General helper functions */
extern void vreportf(const char *prefix, const char *err, va_list params);
-extern void vwritef(int fd, const char *prefix, const char *err, va_list params);
extern NORETURN void usage(const char *err);
extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
@@ -425,6 +424,7 @@ static inline int const_error(void)
extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
extern void set_error_routine(void (*routine)(const char *err, va_list params));
extern void set_die_is_recursing_routine(int (*routine)(void));
+extern void set_error_handle(FILE *);
extern int starts_with(const char *str, const char *prefix);
diff --git a/git-pull.sh b/git-pull.sh
index a814bf61a..e8dc2e0e7 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -295,7 +295,7 @@ test true = "$rebase" && {
}
orig_head=$(git rev-parse -q --verify HEAD)
git fetch $verbosity $progress $dry_run $recurse_submodules $all $append \
-$upload_pack $force $tags $prune $keep $depth $unshallow $update_shallow \
+${upload_pack:+"$upload_pack"} $force $tags $prune $keep $depth $unshallow $update_shallow \
$refmap --update-head-ok "$@" || exit 1
test -z "$dry_run" || exit 0
diff --git a/pager.c b/pager.c
index 070dc11cb..27d4c8a17 100644
--- a/pager.c
+++ b/pager.c
@@ -150,7 +150,8 @@ int check_pager_config(const char *cmd)
struct strbuf key = STRBUF_INIT;
const char *value = NULL;
strbuf_addf(&key, "pager.%s", cmd);
- if (!git_config_get_value(key.buf, &value)) {
+ if (git_config_key_is_valid(key.buf) &&
+ !git_config_get_value(key.buf, &value)) {
int b = git_config_maybe_bool(key.buf, value);
if (b >= 0)
want = b;
diff --git a/run-command.c b/run-command.c
index 4d73e90fa..0d01671c1 100644
--- a/run-command.c
+++ b/run-command.c
@@ -200,7 +200,6 @@ static int execv_shell_cmd(const char **argv)
#endif
#ifndef GIT_WINDOWS_NATIVE
-static int child_err = 2;
static int child_notifier = -1;
static void notify_parent(void)
@@ -212,17 +211,6 @@ static void notify_parent(void)
*/
xwrite(child_notifier, "", 1);
}
-
-static NORETURN void die_child(const char *err, va_list params)
-{
- vwritef(child_err, "fatal: ", err, params);
- exit(128);
-}
-
-static void error_child(const char *err, va_list params)
-{
- vwritef(child_err, "error: ", err, params);
-}
#endif
static inline void set_cloexec(int fd)
@@ -362,11 +350,10 @@ fail_pipe:
* in subsequent call paths use the parent's stderr.
*/
if (cmd->no_stderr || need_err) {
- child_err = dup(2);
+ int child_err = dup(2);
set_cloexec(child_err);
+ set_error_handle(fdopen(child_err, "w"));
}
- set_die_routine(die_child);
- set_error_routine(error_child);
close(notify_pipe[0]);
set_cloexec(notify_pipe[1]);
diff --git a/sha1_file.c b/sha1_file.c
index 1cee43842..f2e993e0b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1461,7 +1461,10 @@ int git_open_noatime(const char *name)
static int sha1_file_open_flag = O_NOATIME;
for (;;) {
- int fd = open(name, O_RDONLY | sha1_file_open_flag);
+ int fd;
+
+ errno = 0;
+ fd = open(name, O_RDONLY | sha1_file_open_flag);
if (fd >= 0)
return fd;
diff --git a/strbuf.c b/strbuf.c
index bbaf32eef..c606f339d 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -364,19 +364,19 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
strbuf_grow(sb, hint ? hint : 8192);
for (;;) {
- ssize_t cnt;
+ ssize_t want = sb->alloc - sb->len - 1;
+ ssize_t got = read_in_full(fd, sb->buf + sb->len, want);
- cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
- if (cnt < 0) {
+ if (got < 0) {
if (oldalloc == 0)
strbuf_release(sb);
else
strbuf_setlen(sb, oldlen);
return -1;
}
- if (!cnt)
+ sb->len += got;
+ if (got < want)
break;
- sb->len += cnt;
strbuf_grow(sb, 8192);
}
diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh
index b6977d4b3..553a3f601 100755
--- a/t/t1509-root-worktree.sh
+++ b/t/t1509-root-worktree.sh
@@ -125,7 +125,7 @@ fi
ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
test_expect_success 'setup' '
- rm -rf /foo
+ rm -rf /foo &&
mkdir /foo &&
mkdir /foo/bar &&
echo 1 > /foo/foome &&
@@ -218,7 +218,7 @@ unset GIT_WORK_TREE
test_expect_success 'go to /' 'cd /'
test_expect_success 'setup' '
- rm -rf /.git
+ rm -rf /.git &&
echo "Initialized empty Git repository in /.git/" > expected &&
git init > result &&
test_cmp expected result
@@ -241,8 +241,8 @@ say "auto bare gitdir"
# DESTROYYYYY!!!!!
test_expect_success 'setup' '
- rm -rf /refs /objects /info /hooks
- rm /*
+ rm -rf /refs /objects /info /hooks &&
+ rm -f /expected /ls.expected /me /result &&
cd / &&
echo "Initialized empty Git repository in /" > expected &&
git init --bare > result &&
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index 8396320d5..199b22d85 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -69,7 +69,7 @@ test_expect_success 'wildcard ambiguation, paths win' '
)
'
-test_expect_success 'wildcard ambiguation, refs lose' '
+test_expect_success !MINGW 'wildcard ambiguation, refs lose' '
git init ambi2 &&
(
cd ambi2 &&
diff --git a/t/t5603-clone-dirname.sh b/t/t5603-clone-dirname.sh
new file mode 100755
index 000000000..765cc434e
--- /dev/null
+++ b/t/t5603-clone-dirname.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='check output directory names used by git-clone'
+. ./test-lib.sh
+
+# we use a fake ssh wrapper that ignores the arguments
+# entirely; we really only care that we get _some_ repo,
+# as the real test is what clone does on the local side
+test_expect_success 'setup ssh wrapper' '
+ write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF &&
+ git upload-pack "$TRASH_DIRECTORY"
+ EOF
+ GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" &&
+ export GIT_SSH &&
+ export TRASH_DIRECTORY
+'
+
+# make sure that cloning $1 results in local directory $2
+test_clone_dir () {
+ url=$1; shift
+ dir=$1; shift
+ expect=success
+ bare=non-bare
+ clone_opts=
+ for i in "$@"
+ do
+ case "$i" in
+ fail)
+ expect=failure
+ ;;
+ bare)
+ bare=bare
+ clone_opts=--bare
+ ;;
+ esac
+ done
+ test_expect_$expect "clone of $url goes to $dir ($bare)" "
+ rm -rf $dir &&
+ git clone $clone_opts $url &&
+ test_path_is_dir $dir
+ "
+}
+
+# basic syntax with bare and non-bare variants
+test_clone_dir host:foo foo
+test_clone_dir host:foo foo.git bare
+test_clone_dir host:foo.git foo
+test_clone_dir host:foo.git foo.git bare
+test_clone_dir host:foo/.git foo
+test_clone_dir host:foo/.git foo.git bare
+
+# similar, but using ssh URL rather than host:path syntax
+test_clone_dir ssh://host/foo foo
+test_clone_dir ssh://host/foo foo.git bare
+test_clone_dir ssh://host/foo.git foo
+test_clone_dir ssh://host/foo.git foo.git bare
+test_clone_dir ssh://host/foo/.git foo
+test_clone_dir ssh://host/foo/.git foo.git bare
+
+# we should remove trailing slashes and .git suffixes
+test_clone_dir ssh://host/foo/ foo
+test_clone_dir ssh://host/foo/// foo
+test_clone_dir ssh://host/foo/.git/ foo
+test_clone_dir ssh://host/foo.git/ foo
+test_clone_dir ssh://host/foo.git/// foo
+test_clone_dir ssh://host/foo///.git/ foo
+test_clone_dir ssh://host/foo/.git/// foo
+
+test_clone_dir host:foo/ foo
+test_clone_dir host:foo/// foo
+test_clone_dir host:foo.git/ foo
+test_clone_dir host:foo/.git/ foo
+test_clone_dir host:foo.git/// foo
+test_clone_dir host:foo///.git/ foo
+test_clone_dir host:foo/.git/// foo
+
+# omitting the path should default to the hostname
+test_clone_dir ssh://host/ host
+test_clone_dir ssh://host:1234/ host fail
+test_clone_dir ssh://user@host/ host fail
+test_clone_dir host:/ host fail
+
+# auth materials should be redacted
+test_clone_dir ssh://user:password@host/ host fail
+test_clone_dir ssh://user:password@host:1234/ host fail
+test_clone_dir ssh://user:passw@rd@host:1234/ host fail
+test_clone_dir user@host:/ host fail
+test_clone_dir user:password@host:/ host fail
+test_clone_dir user:passw@rd@host:/ host fail
+
+# auth-like material should not be dropped
+test_clone_dir ssh://host/foo@bar foo@bar
+test_clone_dir ssh://host/foo@bar.git foo@bar
+test_clone_dir ssh://user:password@host/foo@bar foo@bar
+test_clone_dir ssh://user:passw@rd@host/foo@bar.git foo@bar
+
+test_clone_dir host:/foo@bar foo@bar
+test_clone_dir host:/foo@bar.git foo@bar
+test_clone_dir user:password@host:/foo@bar foo@bar
+test_clone_dir user:passw@rd@host:/foo@bar.git foo@bar
+
+# trailing port-like numbers should not be stripped for paths
+test_clone_dir ssh://user:password@host/test:1234 1234
+test_clone_dir ssh://user:password@host/test:1234.git 1234
+
+test_done
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 947b690fd..6ea7ac4c4 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -447,4 +447,13 @@ test_expect_success TTY 'external command pagers override sub-commands' '
test_cmp expect actual
'
+test_expect_success 'command with underscores does not complain' '
+ write_script git-under_score <<-\EOF &&
+ echo ok
+ EOF
+ git --exec-path=. under_score >actual 2>&1 &&
+ echo ok >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index cea6cda60..16c4d7b51 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -531,6 +531,10 @@ maybe_setup_valgrind () {
fi
}
+want_trace () {
+ test "$trace" = t && test "$verbose" = t
+}
+
# This is a separate function because some tests use
# "return" to end a test_expect_success block early
# (and we want to make sure we run any cleanup like
@@ -538,7 +542,7 @@ maybe_setup_valgrind () {
test_eval_inner_ () {
# Do not add anything extra (including LF) after '$*'
eval "
- test \"$trace\" = t && set -x
+ want_trace && set -x
$*"
}
@@ -554,7 +558,7 @@ test_eval_ () {
{
test_eval_inner_ "$@" </dev/null >&3 2>&4
test_eval_ret_=$?
- if test "$trace" = t
+ if want_trace
then
set +x
if test "$test_eval_ret_" != 0
@@ -571,12 +575,17 @@ test_run_ () {
expecting_failure=$2
if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then
+ # turn off tracing for this test-eval, as it simply creates
+ # confusing noise in the "-x" output
+ trace_tmp=$trace
+ trace=
# 117 is magic because it is unlikely to match the exit
# code of other programs
test_eval_ "(exit 117) && $1"
if test "$?" != 117; then
error "bug in the test script: broken &&-chain: $1"
fi
+ trace=$trace_tmp
fi
setup_malloc_check
diff --git a/transport-helper.c b/transport-helper.c
index 5d99a6bc2..68e498eeb 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -490,7 +490,8 @@ static int fetch_with_import(struct transport *transport,
else
private = xstrdup(name);
if (private) {
- read_ref(private, posn->old_sha1);
+ if (read_ref(private, posn->old_sha1) < 0)
+ die("Could not read ref %s", private);
free(private);
}
}
@@ -1019,7 +1020,10 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
if (eon) {
if (has_attribute(eon + 1, "unchanged")) {
(*tail)->status |= REF_STATUS_UPTODATE;
- read_ref((*tail)->name, (*tail)->old_sha1);
+ if (read_ref((*tail)->name,
+ (*tail)->old_sha1) < 0)
+ die(N_("Could not read ref %s"),
+ (*tail)->name);
}
}
tail = &((*tail)->next);
diff --git a/usage.c b/usage.c
index ed146453c..82ff13163 100644
--- a/usage.c
+++ b/usage.c
@@ -6,23 +6,22 @@
#include "git-compat-util.h"
#include "cache.h"
+static FILE *error_handle;
+static int tweaked_error_buffering;
+
void vreportf(const char *prefix, const char *err, va_list params)
{
- char msg[4096];
- vsnprintf(msg, sizeof(msg), err, params);
- fprintf(stderr, "%s%s\n", prefix, msg);
-}
+ FILE *fh = error_handle ? error_handle : stderr;
-void vwritef(int fd, const char *prefix, const char *err, va_list params)
-{
- char msg[4096];
- int len = vsnprintf(msg, sizeof(msg), err, params);
- if (len > sizeof(msg))
- len = sizeof(msg);
+ fflush(fh);
+ if (!tweaked_error_buffering) {
+ setvbuf(fh, NULL, _IOLBF, 0);
+ tweaked_error_buffering = 1;
+ }
- write_in_full(fd, prefix, strlen(prefix));
- write_in_full(fd, msg, len);
- write_in_full(fd, "\n", 1);
+ fputs(prefix, fh);
+ vfprintf(fh, err, params);
+ fputc('\n', fh);
}
static NORETURN void usage_builtin(const char *err, va_list params)
@@ -76,6 +75,12 @@ void set_die_is_recursing_routine(int (*routine)(void))
die_is_recursing = routine;
}
+void set_error_handle(FILE *fh)
+{
+ error_handle = fh;
+ tweaked_error_buffering = 0;
+}
+
void NORETURN usagef(const char *err, ...)
{
va_list params;