Merge branch 'ready-for-upstream'

This is the branch thicket of patches in Git for Windows that are
considered ready for upstream. To keep them in a ready-to-submit shape,
they are kept as close to the beginning of the branch thicket as
possible.
This commit is contained in:
Johannes Schindelin
2018-10-11 13:38:58 +02:00
44 changed files with 1018 additions and 64 deletions

View File

@@ -406,6 +406,8 @@ include::config/reset.txt[]
include::config/sendemail.txt[]
include::config/sendpack.txt[]
include::config/sequencer.txt[]
include::config/showbranch.txt[]

View File

@@ -0,0 +1,5 @@
sendpack.sideband::
Allows to disable the side-band-64k capability for send-pack even
when it is advertised by the server. Makes it possible to work
around a limitation in the git for windows implementation together
with the dump git protocol. Defaults to true.

View File

@@ -10,6 +10,7 @@ SYNOPSIS
[verse]
'git reset' [-q] [<tree-ish>] [--] <paths>...
'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
EXPERIMENTAL: 'git reset' [-q] [--stdin [-z]] [<tree-ish>]
'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
DESCRIPTION
@@ -100,6 +101,15 @@ OPTIONS
`reset.quiet` config option. `--quiet` and `--no-quiet` will
override the default behavior.
--stdin::
EXPERIMENTAL: Instead of taking list of paths from the
command line, read list of paths from the standard input.
Paths are separated by LF (i.e. one path per line) by
default.
-z::
EXPERIMENTAL: Only meaningful with `--stdin`; paths are
separated with NUL character instead of LF.
EXAMPLES
--------

View File

@@ -1,3 +1,5 @@
[![Build Status](https:/dev.azure.com/git/git/_apis/build/status/test-git.git)](https://dev.azure.com/git/git/_build/latest?definitionId=2)
Git - fast, scalable, distributed revision control system
=========================================================

342
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,342 @@
resources:
- repo: self
fetchDepth: 1
phases:
- phase: linux_clang
displayName: linux-clang
condition: succeeded()
queue:
name: Hosted Ubuntu 1604
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
sudo apt-get update &&
sudo rm /var/lib/apt/lists/lock &&
sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev apache2-bin &&
export CC=clang || exit 1
ci/install-dependencies.sh
ci/run-build-and-tests.sh || {
ci/print-test-failures.sh
exit 1
}
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-build-and-tests.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'linux-clang'
platform: Linux
publishRunAttachments: false
condition: succeededOrFailed()
- phase: linux_gcc
displayName: linux-gcc
condition: succeeded()
queue:
name: Hosted Ubuntu 1604
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
sudo apt-get update &&
sudo rm /var/lib/apt/lists/lock &&
sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev apache2-bin || exit 1
ci/install-dependencies.sh
ci/run-build-and-tests.sh || {
ci/print-test-failures.sh
exit 1
}
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-build-and-tests.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'linux-gcc'
platform: Linux
publishRunAttachments: false
condition: succeededOrFailed()
- phase: osx_clang
displayName: osx-clang
condition: succeeded()
queue:
name: Hosted macOS
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
export CC=clang
ci/install-dependencies.sh
ci/run-build-and-tests.sh || {
ci/print-test-failures.sh
exit 1
}
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-build-and-tests.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'osx-clang'
platform: macOS
publishRunAttachments: false
condition: succeededOrFailed()
- phase: osx_gcc
displayName: osx-gcc
condition: succeeded()
queue:
name: Hosted macOS
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
ci/install-dependencies.sh
ci/run-build-and-tests.sh || {
ci/print-test-failures.sh
exit 1
}
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-build-and-tests.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'osx-gcc'
platform: macOS
publishRunAttachments: false
condition: succeededOrFailed()
- phase: gettext_poison
displayName: GETTEXT_POISON
condition: succeeded()
queue:
name: Hosted Ubuntu 1604
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
sudo apt-get update &&
sudo rm /var/lib/apt/lists/lock &&
sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev &&
export jobname=GETTEXT_POISON || exit 1
ci/run-build-and-tests.sh || {
ci/print-test-failures.sh
exit 1
}
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-build-and-tests.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'gettext-poison'
platform: Linux
publishRunAttachments: false
condition: succeededOrFailed()
- phase: windows
displayName: Windows
queue:
name: Hosted
timeoutInMinutes: 240
steps:
- powershell: |
if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") {
net use s: \\gitfileshare.file.core.windows.net\test-cache "$GITFILESHAREPWD" /user:AZURE\gitfileshare /persistent:no
cmd /c mklink /d "$(Build.SourcesDirectory)\test-cache" S:\
}
displayName: 'Mount test-cache'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- powershell: |
# Helper to check the error level of the latest command (exit with error when appropriate)
function c() { if (!$?) { exit(1) } }
# Add build agent's MinGit to PATH
$env:PATH = $env:AGENT_HOMEDIRECTORY +"\externals\\git\cmd;" +$env:PATH
# Helper to initialize (or update) a Git worktree
function init ($path, $url, $set_origin) {
if (Test-Path $path) {
cd $path; c
if (Test-Path .git) {
git init; c
} else {
git status
}
} else {
git init $path; c
cd $path; c
}
git config core.autocrlf false; c
git config core.untrackedCache true; c
if (($set_origin -ne 0) -and !(git config remote.origin.url)) {
git remote add origin $url; c
}
git fetch --depth=1 $url master; c
git reset --hard FETCH_HEAD; c
git clean -df; c
}
# Initialize Git for Windows' SDK
$sdk_path = "$(Build.SourcesDirectory)\git-sdk-64"
init "$sdk_path" "https://dev.azure.com/git-for-windows/git-sdk-64/_git/git-sdk-64" 0
init usr\src\build-extra https://github.com/git-for-windows/build-extra 1
# Let Git ignore the SDK and the test-cache
"/git-sdk-64/`n/test-cache/`n" | Out-File -NoNewLine -Encoding ascii -Append "$(Build.SourcesDirectory)\.git\info\exclude"
# Help MSYS2 runtime startup by initializing /etc/passwd
& "$sdk_path\git-cmd" --command=usr\\bin\\bash.exe -lc "mkpasswd -c >>/etc/passwd"; c
displayName: 'Initialize the Git for Windows SDK'
- powershell: |
# Helper to check the error level of the latest command (exit with error when appropriate)
function c() { if (!$?) { exit(1) } }
cd "$(Build.SourcesDirectory)"; c
git-sdk-64\git-cmd --command=usr\\bin\\bash.exe -lc @"
export MAKEFLAGS=-j10
export DEVELOPER=1
export NO_PERL=1
export NO_SVN_TESTS=1
export GIT_TEST_SKIP_REBASE_P=1
ci/run-build-and-tests.sh || {
ci/print-test-failures.sh
exit 1
}
"@
c
displayName: 'Build & Test'
env:
HOME: $(Build.SourcesDirectory)
MSYSTEM: MINGW64
- powershell: |
if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") {
cmd /c rmdir "$(Build.SourcesDirectory)\test-cache"
}
displayName: 'Unmount test-cache'
condition: true
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'windows'
platform: Windows
publishRunAttachments: false
condition: succeededOrFailed()
- phase: linux32
displayName: Linux32
condition: succeeded()
queue:
name: Hosted Ubuntu 1604
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
sudo apt-get update &&
sudo rm /var/lib/apt/lists/lock &&
sudo apt-get -y install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common &&
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - &&
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable" &&
sudo apt-get update &&
sudo apt-get -y install docker-ce &&
sudo AGENT_OS="$AGENT_OS" BUILD_BUILDNUMBER="$BUILD_BUILDNUMBER" BUILD_REPOSITORY_URI="$BUILD_REPOSITORY_URI" BUILD_SOURCEBRANCH="$BUILD_SOURCEBRANCH" BUILD_SOURCEVERSION="$BUILD_SOURCEVERSION" SYSTEM_PHASENAME="$SYSTEM_PHASENAME" SYSTEM_TASKDEFINITIONSURI="$SYSTEM_TASKDEFINITIONSURI" SYSTEM_TEAMPROJECT="$SYSTEM_TEAMPROJECT" CC=$CC MAKEFLAGS=-j3 bash -lxc ci/run-linux32-docker.sh || exit 1
sudo chmod a+r t/out/TEST-*.xml
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-linux32-docker.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- task: PublishTestResults@2
displayName: 'Publish Test Results **/TEST-*.xml'
inputs:
mergeTestResults: true
testRunTitle: 'linux32'
platform: Linux
publishRunAttachments: false
condition: succeededOrFailed()
- phase: static_analysis
displayName: StaticAnalysis
condition: succeeded()
queue:
name: Hosted Ubuntu 1604
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
sudo apt-get update &&
sudo rm /var/lib/apt/lists/lock &&
sudo apt-get install -y coccinelle &&
export jobname=StaticAnalysis &&
ci/run-static-analysis.sh || exit 1
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1
displayName: 'ci/run-static-analysis.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)
- phase: documentation
displayName: Documentation
condition: succeeded()
queue:
name: Hosted Ubuntu 1604
steps:
- bash: |
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
sudo apt-get update &&
sudo rm /var/lib/apt/lists/lock &&
sudo apt-get install -y asciidoc xmlto asciidoctor &&
export ALREADY_HAVE_ASCIIDOCTOR=yes. &&
export jobname=Documentation &&
ci/test-documentation.sh || exit 1
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1
displayName: 'ci/test-documentation.sh'
env:
GITFILESHAREPWD: $(gitfileshare.pwd)

View File

@@ -239,7 +239,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
rev.diffopt.use_color = 0;
rev.diffopt.flags.ignore_dirty_submodules = 1;
out = open(file, O_CREAT | O_WRONLY, 0666);
out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (out < 0)
die(_("Could not open '%s' for writing."), file);
rev.diffopt.file = xfdopen(out, "w");

View File

@@ -1167,7 +1167,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
if (!is_local && !complete_refs_before_fetch)
transport_fetch_refs(transport, mapped_refs);
if (transport_fetch_refs(transport, mapped_refs))
die(_("could not fetch refs from %s"),
transport->url);
remote_head = find_ref_by_name(refs, "HEAD");
remote_head_points_at =

View File

@@ -874,9 +874,20 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
}
}
static void handle_reset(const char *name, struct object *object)
{
int mark = get_object_mark(object);
if (mark)
printf("reset %s\nfrom :%d\n\n", name,
get_object_mark(object));
else
printf("reset %s\nfrom %s\n\n", name,
oid_to_hex(&object->oid));
}
static void handle_tags_and_duplicates(void)
{
struct commit *commit;
int i;
for (i = extra_refs.nr - 1; i >= 0; i--) {
@@ -890,9 +901,7 @@ static void handle_tags_and_duplicates(void)
if (anonymize)
name = anonymize_refname(name);
/* create refs pointing to already seen commits */
commit = (struct commit *)object;
printf("reset %s\nfrom :%d\n\n", name,
get_object_mark(&commit->object));
handle_reset(name, object);
show_progress();
break;
}

View File

@@ -659,8 +659,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
report_garbage = report_pack_garbage;
reprepare_packed_git(the_repository);
if (pack_garbage.nr > 0)
if (pack_garbage.nr > 0) {
close_all_packs(the_repository->objects);
clean_pack_garbage();
}
if (gc_write_commit_graph)
write_commit_graph_reachable(get_object_directory(), 0,

View File

@@ -155,6 +155,9 @@ static int git_init_db_config(const char *k, const char *v, void *cb)
if (!strcmp(k, "init.templatedir"))
return git_config_pathname(&init_db_template_dir, k, v);
if (starts_with(k, "core."))
return platform_core_config(k, v, cb);
return 0;
}
@@ -361,6 +364,9 @@ int init_db(const char *git_dir, const char *real_git_dir,
}
startup_info->have_repository = 1;
/* Just look for `init.templatedir` and `core.hidedotfiles` */
git_config(git_init_db_config, NULL);
safe_create_dir(git_dir, 0);
init_is_bare_repository = is_bare_repository();

View File

@@ -419,6 +419,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (!names.nr && !po_args.quiet)
printf("Nothing new to pack.\n");
close_all_packs(the_repository->objects);
/*
* Ok we have prepared all new packfiles.
* First see if there are packs of the same name and if so

View File

@@ -24,12 +24,15 @@
#include "cache-tree.h"
#include "submodule.h"
#include "submodule-config.h"
#include "strbuf.h"
#include "quote.h"
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
static const char * const git_reset_usage[] = {
N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
N_("EXPERIMENTAL: git reset [-q] [--stdin [-z]] [<tree-ish>]"),
N_("git reset --patch [<tree-ish>] [--] [<paths>...]"),
NULL
};
@@ -283,7 +286,9 @@ static int git_reset_config(const char *var, const char *value, void *cb)
int cmd_reset(int argc, const char **argv, const char *prefix)
{
int reset_type = NONE, update_ref_status = 0, quiet = 0;
int patch_mode = 0, unborn;
int patch_mode = 0, nul_term_line = 0, read_from_stdin = 0, unborn;
char **stdin_paths = NULL;
int stdin_nr = 0, stdin_alloc = 0;
const char *rev;
struct object_id oid;
struct pathspec pathspec;
@@ -305,6 +310,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
OPT_BOOL('N', "intent-to-add", &intent_to_add,
N_("record only the fact that removed paths will be added later")),
OPT_BOOL('z', NULL, &nul_term_line,
N_("EXPERIMENTAL: paths are separated with NUL character")),
OPT_BOOL(0, "stdin", &read_from_stdin,
N_("EXPERIMENTAL: read paths from <stdin>")),
OPT_END()
};
@@ -315,6 +324,42 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_DASHDASH);
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
if (read_from_stdin) {
strbuf_getline_fn getline_fn = nul_term_line ?
strbuf_getline_nul : strbuf_getline_lf;
int flags = PATHSPEC_PREFER_FULL;
struct strbuf buf = STRBUF_INIT;
struct strbuf unquoted = STRBUF_INIT;
if (patch_mode)
die(_("--stdin is incompatible with --patch"));
if (pathspec.nr)
die(_("--stdin is incompatible with path arguments"));
while (getline_fn(&buf, stdin) != EOF) {
if (!nul_term_line && buf.buf[0] == '"') {
strbuf_reset(&unquoted);
if (unquote_c_style(&unquoted, buf.buf, NULL))
die(_("line is badly quoted"));
strbuf_swap(&buf, &unquoted);
}
ALLOC_GROW(stdin_paths, stdin_nr + 1, stdin_alloc);
stdin_paths[stdin_nr++] = xstrdup(buf.buf);
strbuf_reset(&buf);
}
strbuf_release(&unquoted);
strbuf_release(&buf);
ALLOC_GROW(stdin_paths, stdin_nr + 1, stdin_alloc);
stdin_paths[stdin_nr++] = NULL;
flags |= PATHSPEC_LITERAL_PATH;
parse_pathspec(&pathspec, 0, flags, prefix,
(const char **)stdin_paths);
} else if (nul_term_line)
die(_("-z requires --stdin"));
unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
if (unborn) {
/* reset on unborn branch: treat as reset to empty tree */
@@ -415,5 +460,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (!pathspec.nr)
remove_branch_state();
if (stdin_paths) {
while (stdin_nr)
free(stdin_paths[--stdin_nr]);
free(stdin_paths);
}
return update_ref_status;
}

View File

@@ -3,7 +3,7 @@
# Install dependencies required to build and test Git on Linux and macOS
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
P4WHENCE=http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
@@ -37,7 +37,8 @@ osx-clang|osx-gcc)
brew update --quiet
# Uncomment this if you want to run perf tests:
# brew install gnu-time
brew install git-lfs gettext
test -z "$BREW_INSTALL_PACKAGES" ||
brew install $BREW_INSTALL_PACKAGES
brew link --force gettext
brew install caskroom/cask/perforce
;;

View File

@@ -1,5 +1,51 @@
# Library of functions shared by all CI scripts
if test true = "$TRAVIS"
then
# We are running within Travis CI
CI_BRANCH="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}"
CI_COMMIT="$TRAVIS_COMMIT"
CI_JOB_ID="$TRAVIS_JOB_ID"
CI_JOB_NUMBER="$TRAVIS_JOB_NUMBER"
CI_OS_NAME="$TRAVIS_OS_NAME"
CI_REPO_SLUG="$TRAVIS_REPO_SLUG"
cache_dir="$HOME/travis-cache"
url_for_job_id () {
echo "https://travis-ci.org/$CI_REPO_SLUG/jobs/$1"
}
BREW_INSTALL_PACKAGES="git-lfs gettext"
export GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save"
export GIT_TEST_OPTS="--verbose-log -x --immediate"
elif test -n "$SYSTEM_TASKDEFINITIONSURI"
then
# We are running in Azure Pipelines
CI_BRANCH="$BUILD_SOURCEBRANCH"
CI_COMMIT="$BUILD_SOURCEVERSION"
CI_JOB_ID="$BUILD_BUILDID"
CI_JOB_NUMBER="$BUILD_BUILDNUMBER"
CI_OS_NAME="$(echo "$AGENT_OS" | tr A-Z a-z)"
test darwin != "$CI_OS_NAME" || CI_OS_NAME=osx
CI_REPO_SLUG="$(expr "$BUILD_REPOSITORY_URI" : '.*/\([^/]*/[^/]*\)$')"
CC="${CC:-gcc}"
# use a subdirectory of the cache dir (because the file share is shared
# among *all* phases)
cache_dir="$HOME/test-cache/$SYSTEM_PHASENAME"
url_for_job_id () {
echo "$SYSTEM_TASKDEFINITIONSURI$SYSTEM_TEAMPROJECT/_build/results?buildId=$1"
}
BREW_INSTALL_PACKAGES=
export GIT_PROVE_OPTS="--timer --jobs 10 --state=failed,slow,save"
export GIT_TEST_OPTS="--verbose-log -x --write-junit-xml"
test windows_nt != "$CI_OS_NAME" ||
GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS"
fi
skip_branch_tip_with_tag () {
# Sometimes, a branch is pushed at the same time the tag that points
# at the same commit as the tip of the branch is pushed, and building
@@ -13,10 +59,10 @@ skip_branch_tip_with_tag () {
# we can skip the build because we won't be skipping a build
# of a tag.
if TAG=$(git describe --exact-match "$TRAVIS_BRANCH" 2>/dev/null) &&
test "$TAG" != "$TRAVIS_BRANCH"
if TAG=$(git describe --exact-match "$CI_BRANCH" 2>/dev/null) &&
test "$TAG" != "$CI_BRANCH"
then
echo "$(tput setaf 2)Tip of $TRAVIS_BRANCH is exactly at $TAG$(tput sgr0)"
echo "$(tput setaf 2)Tip of $CI_BRANCH is exactly at $TAG$(tput sgr0)"
exit 0
fi
}
@@ -25,7 +71,7 @@ skip_branch_tip_with_tag () {
# job if we encounter the same tree again and can provide a useful info
# message.
save_good_tree () {
echo "$(git rev-parse $TRAVIS_COMMIT^{tree}) $TRAVIS_COMMIT $TRAVIS_JOB_NUMBER $TRAVIS_JOB_ID" >>"$good_trees_file"
echo "$(git rev-parse $CI_COMMIT^{tree}) $CI_COMMIT $CI_JOB_NUMBER $CI_JOB_ID" >>"$good_trees_file"
# limit the file size
tail -1000 "$good_trees_file" >"$good_trees_file".tmp
mv "$good_trees_file".tmp "$good_trees_file"
@@ -35,7 +81,7 @@ save_good_tree () {
# successfully before (e.g. because the branch got rebased, changing only
# the commit messages).
skip_good_tree () {
if ! good_tree_info="$(grep "^$(git rev-parse $TRAVIS_COMMIT^{tree}) " "$good_trees_file")"
if ! good_tree_info="$(grep "^$(git rev-parse $CI_COMMIT^{tree}) " "$good_trees_file")"
then
# Haven't seen this tree yet, or no cached good trees file yet.
# Continue the build job.
@@ -45,18 +91,18 @@ skip_good_tree () {
echo "$good_tree_info" | {
read tree prev_good_commit prev_good_job_number prev_good_job_id
if test "$TRAVIS_JOB_ID" = "$prev_good_job_id"
if test "$CI_JOB_ID" = "$prev_good_job_id"
then
cat <<-EOF
$(tput setaf 2)Skipping build job for commit $TRAVIS_COMMIT.$(tput sgr0)
$(tput setaf 2)Skipping build job for commit $CI_COMMIT.$(tput sgr0)
This commit has already been built and tested successfully by this build job.
To force a re-build delete the branch's cache and then hit 'Restart job'.
EOF
else
cat <<-EOF
$(tput setaf 2)Skipping build job for commit $TRAVIS_COMMIT.$(tput sgr0)
$(tput setaf 2)Skipping build job for commit $CI_COMMIT.$(tput sgr0)
This commit's tree has already been built and tested successfully in build job $prev_good_job_number for commit $prev_good_commit.
The log of that build job is available at https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$prev_good_job_id
The log of that build job is available at $(url_for_job_id $prev_good_job_id)
To force a re-build delete the branch's cache and then hit 'Restart job'.
EOF
fi
@@ -81,7 +127,6 @@ check_unignored_build_artifacts ()
# and installing dependencies.
set -ex
cache_dir="$HOME/travis-cache"
good_trees_file="$cache_dir/good-trees"
mkdir -p "$cache_dir"
@@ -91,13 +136,11 @@ skip_good_tree
if test -z "$jobname"
then
jobname="$TRAVIS_OS_NAME-$CC"
jobname="$CI_OS_NAME-$CC"
fi
export DEVELOPER=1
export DEFAULT_TEST_TARGET=prove
export GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save"
export GIT_TEST_OPTS="--verbose-log -x --immediate"
export GIT_TEST_CLONE_2GB=YesPlease
if [ "$jobname" = linux-gcc ]; then
export CC=gcc-8

26
ci/mount-fileshare.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/sh
die () {
echo "$*" >&2
exit 1
}
test $# = 4 ||
die "Usage: $0 <share> <username> <password> <mountpoint"
mkdir -p "$4" || die "Could not create $4"
case "$(uname -s)" in
Linux)
sudo mount -t cifs -o vers=3.0,username="$2",password="$3",dir_mode=0777,file_mode=0777,serverino "$1" "$4"
;;
Darwin)
pass="$(echo "$3" | sed -e 's/\//%2F/g' -e 's/+/%2B/g')" &&
mount -t smbfs,soft "smb://$2:$pass@${1#//}" "$4"
;;
*)
die "No support for $(uname -s)"
;;
esac ||
die "Could not mount $4"

View File

@@ -3,7 +3,7 @@
# Print output of failing tests
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
# Tracing executed commands would produce too much noise in the loop below.
set +x
@@ -69,7 +69,7 @@ do
fi
done
if [ $combined_trash_size -gt 0 ]
if [ -n "$TRAVIS_JOB_ID" -a $combined_trash_size -gt 0 ]
then
echo "------------------------------------------------------------------------"
echo "Trash directories embedded in this log can be extracted by running:"

View File

@@ -3,11 +3,14 @@
# Build and test Git
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
ln -s "$cache_dir/.prove" t/.prove
case "$CI_OS_NAME" in
windows*) cmd //c mklink //j t\\.prove "$(cygpath -aw "$cache_dir/.prove")";;
*) ln -s "$cache_dir/.prove" t/.prove;;
esac
make --jobs=2
make
make --quiet test
if test "$jobname" = "linux-gcc"
then

View File

@@ -3,7 +3,7 @@
# Download and run Docker image to build and test 32-bit Git
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
docker pull daald/ubuntu32:xenial

View File

@@ -3,7 +3,7 @@
# Perform various static code analysis checks
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
make --jobs=2 coccicheck

View File

@@ -6,7 +6,7 @@
# supported) and a commit hash.
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
test $# -ne 2 && echo "Unexpected number of parameters" && exit 1
test -z "$GFW_CI_TOKEN" && echo "GFW_CI_TOKEN not defined" && exit

View File

@@ -3,8 +3,9 @@
# Perform sanity checks on documentation and build it.
#
. ${0%/*}/lib-travisci.sh
. ${0%/*}/lib.sh
test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
gem install asciidoctor
make check-builtins

View File

@@ -928,11 +928,19 @@ unsigned int sleep (unsigned int seconds)
char *mingw_mktemp(char *template)
{
wchar_t wtemplate[MAX_PATH];
int offset = 0;
if (xutftowcs_path(wtemplate, template) < 0)
return NULL;
if (is_dir_sep(template[0]) && !is_dir_sep(template[1]) &&
iswalpha(wtemplate[0]) && wtemplate[1] == L':') {
/* We have an absolute path missing the drive prefix */
offset = 2;
}
if (!_wmktemp(wtemplate))
return NULL;
if (xwcstoutf(template, wtemplate, strlen(template) + 1) < 0)
if (xwcstoutf(template, wtemplate + offset, strlen(template) + 1) < 0)
return NULL;
return template;
}
@@ -1031,7 +1039,7 @@ char *mingw_getcwd(char *pointer, int len)
* See "Parsing C++ Command-Line Arguments" at Microsoft's Docs:
* https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments
*/
static const char *quote_arg(const char *arg)
static const char *quote_arg_msvc(const char *arg)
{
/* count chars to quote */
int len = 0, n = 0;
@@ -1086,6 +1094,37 @@ static const char *quote_arg(const char *arg)
return q;
}
#include "quote.h"
static const char *quote_arg_msys2(const char *arg)
{
struct strbuf buf = STRBUF_INIT;
const char *p2 = arg, *p;
for (p = arg; *p; p++) {
int ws = isspace(*p);
if (!ws && *p != '\\' && *p != '"' && *p != '{')
continue;
if (!buf.len)
strbuf_addch(&buf, '"');
if (p != p2)
strbuf_add(&buf, p2, p - p2);
if (!ws && *p != '{')
strbuf_addch(&buf, '\\');
p2 = p;
}
if (p == arg)
strbuf_addch(&buf, '"');
else if (!buf.len)
return arg;
else
strbuf_add(&buf, p2, p - p2),
strbuf_addch(&buf, '"');
return strbuf_detach(&buf, 0);
}
static const char *parse_interpreter(const char *cmd)
{
static char buf[100];
@@ -1129,14 +1168,21 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
int isexe, int exe_only)
{
char path[MAX_PATH];
wchar_t wpath[MAX_PATH];
snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
if (!isexe && access(path, F_OK) == 0)
if (xutftowcs_path(wpath, path) < 0)
return NULL;
if (!isexe && _waccess(wpath, F_OK) == 0)
return xstrdup(path);
path[strlen(path)-4] = '\0';
if ((!exe_only || isexe) && access(path, F_OK) == 0)
if (!(GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY))
wpath[wcslen(wpath)-4] = '\0';
if ((!exe_only || isexe) && _waccess(wpath, F_OK) == 0) {
if (!(GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY)) {
path[strlen(path)-4] = '\0';
return xstrdup(path);
}
}
return NULL;
}
@@ -1317,6 +1363,34 @@ struct pinfo_t {
static struct pinfo_t *pinfo = NULL;
CRITICAL_SECTION pinfo_cs;
static int is_msys2_sh(const char *cmd)
{
if (cmd && !strcmp(cmd, "sh")) {
static int ret = -1;
char *p;
if (ret >= 0)
return ret;
p = path_lookup(cmd, 0);
if (!p)
ret = 0;
else {
size_t len = strlen(p);
ret = len > 15 &&
is_dir_sep(p[len - 15]) &&
!strncasecmp(p + len - 14, "usr", 3) &&
is_dir_sep(p[len - 11]) &&
!strncasecmp(p + len - 10, "bin", 3) &&
is_dir_sep(p[len - 7]) &&
!strcasecmp(p + len - 6, "sh.exe");
free(p);
}
return ret;
}
return 0;
}
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
const char *dir,
int prepend_cmd, int fhin, int fhout, int fherr)
@@ -1328,6 +1402,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
unsigned flags = CREATE_UNICODE_ENVIRONMENT;
BOOL ret;
HANDLE cons;
const char *(*quote_arg)(const char *arg) =
is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc;
do_unset_environment_variables();

View File

@@ -269,6 +269,20 @@ win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
return happened;
}
#include <windows.h>
#include "compat/win32/lazyload.h"
static ULONGLONG CompatGetTickCount64(void)
{
DECLARE_PROC_ADDR(kernel32.dll, ULONGLONG, GetTickCount64, void);
if (!INIT_PROC_ADDR(GetTickCount64))
return (ULONGLONG)GetTickCount();
return GetTickCount64();
}
#define GetTickCount64 CompatGetTickCount64
#else /* !MinGW */
/* Convert select(2) returned fd_sets into poll(2) revents values. */

View File

@@ -551,11 +551,19 @@ else
ifeq ($(shell expr "$(uname_R)" : '2\.'),2)
# MSys2
prefix = /usr/
# Enable DEP
BASIC_LDFLAGS += -Wl,--nxcompat
# Enable ASLR (unless debugging)
ifneq (,$(findstring -O,$(CFLAGS)))
BASIC_LDFLAGS += -Wl,--dynamicbase
endif
ifeq (MINGW32,$(MSYSTEM))
prefix = /mingw32
BASIC_LDFLAGS += -Wl,--pic-executable,-e,_mainCRTStartup
endif
ifeq (MINGW64,$(MSYSTEM))
prefix = /mingw64
BASIC_LDFLAGS += -Wl,--pic-executable,-e,mainCRTStartup
else
COMPAT_CFLAGS += -D_USE_32BIT_TIME_T
BASIC_LDFLAGS += -Wl,--large-address-aware

View File

@@ -918,6 +918,10 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
if (protocol == PROTO_LOCAL)
path = end;
else if (protocol == PROTO_FILE && *host != '/' &&
!has_dos_drive_prefix(host) &&
offset_1st_component(host - 2) > 1)
path = host - 2; /* include the leading "//" */
else if (protocol == PROTO_FILE && has_dos_drive_prefix(end))
path = end; /* "file://$(pwd)" may be "file://C:/projects/repo" */
else

View File

@@ -136,7 +136,9 @@ static void credential_getpass(struct credential *c)
{
if (!c->username)
c->username = credential_ask_one("Username", c,
PROMPT_ASKPASS|PROMPT_ECHO);
(getenv("GIT_ASKPASS") ?
PROMPT_ASKPASS : 0) |
PROMPT_ECHO);
if (!c->password)
c->password = credential_ask_one("Password", c,
PROMPT_ASKPASS);

View File

@@ -82,6 +82,18 @@ static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
first = 0;
last = rename_src_nr;
if (last > 0) {
struct diff_rename_src *src = &(rename_src[last-1]);
int cmp = strcmp(one->path, src->p->one->path);
if (!cmp)
return src;
if (cmp > 0) {
first = last;
goto append_it;
}
}
while (last > first) {
int next = (last + first) >> 1;
struct diff_rename_src *src = &(rename_src[next]);
@@ -95,6 +107,7 @@ static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
first = next+1;
}
append_it:
/* insert to make it at "first" */
ALLOC_GROW(rename_src, rename_src_nr + 1, rename_src_alloc);
rename_src_nr++;

View File

@@ -431,6 +431,7 @@ END
sub safe_pipe_capture {
my @output;
if (my $pid = open my $child, '-|') {
binmode($child, ":crlf");
@output = (<$child>);
close $child or die join(' ',@_).": $! $?";
} else {

5
path.c
View File

@@ -11,6 +11,7 @@
#include "path.h"
#include "packfile.h"
#include "object-store.h"
#include "exec-cmd.h"
static int get_st_mode_bits(const char *path, int *mode)
{
@@ -711,6 +712,10 @@ char *expand_user_path(const char *path, int real_home)
if (path == NULL)
goto return_null;
#ifdef __MINGW32__
if (path[0] == '/')
return system_path(path + 1);
#endif
if (path[0] == '~') {
const char *first_slash = strchrnul(path, '/');
const char *username = path + 1;

View File

@@ -38,6 +38,16 @@ int option_parse_push_signed(const struct option *opt,
die("bad %s argument: %s", opt->long_name, arg);
}
static int config_use_sideband = 1;
static int send_pack_config(const char *var, const char *value, void *unused)
{
if (!strcmp("sendpack.sideband", var))
config_use_sideband = git_config_bool(var, value);
return 0;
}
static void feed_object(const struct object_id *oid, FILE *fh, int negative)
{
if (negative && !has_sha1_file(oid->hash))
@@ -391,6 +401,8 @@ int send_pack(struct send_pack_args *args,
struct async demux;
const char *push_cert_nonce = NULL;
git_config(send_pack_config, NULL);
/* Does the other end support the reporting? */
if (server_supports("report-status"))
status_report = 1;
@@ -398,7 +410,7 @@ int send_pack(struct send_pack_args *args,
allow_deleting_refs = 1;
if (server_supports("ofs-delta"))
args->use_ofs_delta = 1;
if (server_supports("side-band-64k"))
if (config_use_sideband && server_supports("side-band-64k"))
use_sideband = 1;
if (server_supports("quiet"))
quiet_supported = 1;

16
setup.c
View File

@@ -39,7 +39,7 @@ static int abspath_part_inside_repo(char *path)
off = offset_1st_component(path);
/* check if work tree is already the prefix */
if (wtlen <= len && !strncmp(path, work_tree, wtlen)) {
if (wtlen <= len && !fspathncmp(path, work_tree, wtlen)) {
if (path[wtlen] == '/') {
memmove(path, path + wtlen + 1, len - wtlen);
return 0;
@@ -59,7 +59,7 @@ static int abspath_part_inside_repo(char *path)
path++;
if (*path == '/') {
*path = '\0';
if (strcmp(real_path(path0), work_tree) == 0) {
if (fspathcmp(real_path(path0), work_tree) == 0) {
memmove(path0, path + 1, len - (path - path0));
return 0;
}
@@ -68,7 +68,7 @@ static int abspath_part_inside_repo(char *path)
}
/* check whole path */
if (strcmp(real_path(path0), work_tree) == 0) {
if (fspathcmp(real_path(path0), work_tree) == 0) {
*path0 = '\0';
return 0;
}
@@ -784,7 +784,7 @@ static const char *setup_discovered_git_dir(const char *gitdir,
set_git_dir(gitdir);
inside_git_dir = 0;
inside_work_tree = 1;
if (offset == cwd->len)
if (offset >= cwd->len)
return NULL;
/* Make "offset" point past the '/' (already the case for root dirs) */
@@ -916,7 +916,7 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
const char *gitdirenv;
int ceil_offset = -1, min_offset = has_dos_drive_prefix(dir->buf) ? 3 : 1;
int ceil_offset = -1, min_offset = offset_1st_component(dir->buf);
dev_t current_device = 0;
int one_filesystem = 1;
@@ -944,6 +944,12 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
if (ceil_offset < 0)
ceil_offset = min_offset - 2;
if (min_offset && min_offset == dir->len &&
!is_dir_sep(dir->buf[min_offset - 1])) {
strbuf_addch(dir, '/');
min_offset++;
}
/*
* Test in the following order (relative to the dir):
* - .git (file containing "gitdir: <path>")

1
t/.gitignore vendored
View File

@@ -2,3 +2,4 @@
/test-results
/.prove
/chainlinttmp
/out/

View File

@@ -170,6 +170,15 @@ appropriately before running "make".
implied by other options like --valgrind and
GIT_TEST_INSTALLED.
--no-bin-wrappers::
By default, the test suite uses the wrappers in
`../bin-wrappers/` to execute `git` and friends. With this option,
`../git` and friends are run directly. This is not recommended
in general, as the wrappers contain safeguards to ensure that no
files from an installed Git are used, but can speed up test runs
especially on platforms where running shell scripts is expensive
(most notably, Windows).
--root=<directory>::
Create "trash" directories used to store all temporary data during
testing under <directory>, instead of the t/ directory.

View File

@@ -7,6 +7,7 @@ static const char *usage_msg = "\n"
" test-tool date parse [date]...\n"
" test-tool date approxidate [date]...\n"
" test-tool date timestamp [date]...\n"
" test-tool date getnanos [start-nanos]\n"
" test-tool date is64bit\n"
" test-tool date time_t-is64bit\n";
@@ -82,6 +83,15 @@ static void parse_approx_timestamp(const char **argv, struct timeval *now)
}
}
static void getnanos(const char **argv, struct timeval *now)
{
double seconds = getnanotime() / 1.0e9;
if (*argv)
seconds -= strtod(*argv, NULL);
printf("%lf\n", seconds);
}
int cmd__date(int argc, const char **argv)
{
struct timeval now;
@@ -108,6 +118,8 @@ int cmd__date(int argc, const char **argv)
parse_approxidate(argv+1, &now);
else if (!strcmp(*argv, "timestamp"))
parse_approx_timestamp(argv+1, &now);
else if (!strcmp(*argv, "getnanos"))
getnanos(argv+1, &now);
else if (!strcmp(*argv, "is64bit"))
return sizeof(timestamp_t) == 8 ? 0 : 1;
else if (!strcmp(*argv, "time_t-is64bit"))

View File

@@ -453,6 +453,18 @@ test_expect_success 're-init from a linked worktree' '
)
'
test_expect_success MINGW 'core.hidedotfiles = false' '
git config --global core.hidedotfiles false &&
rm -rf newdir &&
(
sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
mkdir newdir &&
cd newdir &&
git init
) &&
! is_hidden newdir/.git
'
test_expect_success MINGW 'redirect std handles' '
GIT_REDIRECT_STDOUT=output.txt git rev-parse --git-dir &&
test .git = "$(cat output.txt)" &&

View File

@@ -158,7 +158,8 @@ test_trace () {
expect="$1"
shift
GIT_TRACE=1 test-tool run-command "$@" run-command true 2>&1 >/dev/null | \
sed -e 's/.* run_command: //' -e '/trace: .*/d' >actual &&
sed -e 's/.* run_command: //' -e '/trace: .*/d' \
-e '/RUNTIME_PREFIX requested/d' >actual &&
echo "$expect true" >expect &&
test_cmp expect actual
}
@@ -191,4 +192,14 @@ test_expect_success 'GIT_TRACE with environment variables' '
)
'
test_expect_success MINGW 'verify curlies are quoted properly' '
: force the rev-parse through the MSYS2 Bash &&
git -c alias.r="!git rev-parse" r -- a{b}c >actual &&
cat >expect <<-\EOF &&
--
a{b}c
EOF
test_cmp expect actual
'
test_done

View File

@@ -402,4 +402,11 @@ test_expect_success 'all statuses changed in folder if . is given' '
test $(git ls-files --stage | grep ^100755 | wc -l) -eq 0
'
test_expect_success MINGW 'path is case-insensitive' '
path="$(pwd)/BLUB" &&
touch "$path" &&
downcased="$(echo "$path" | tr A-Z a-z)" &&
git add "$downcased"
'
test_done

View File

@@ -698,13 +698,22 @@ do
# file with scheme
for p in file
do
test_expect_success "fetch-pack --diag-url $p://$h/$r" '
test_expect_success !MINGW "fetch-pack --diag-url $p://$h/$r" '
check_prot_path $p://$h/$r $p "/$r"
'
test_expect_success MINGW "fetch-pack --diag-url $p://$h/$r" '
check_prot_path $p://$h/$r $p "//$h/$r"
'
test_expect_success MINGW "fetch-pack --diag-url $p:///$r" '
check_prot_path $p:///$r $p "/$r"
'
# No "/~" -> "~" conversion for file
test_expect_success "fetch-pack --diag-url $p://$h/~$r" '
test_expect_success !MINGW "fetch-pack --diag-url $p://$h/~$r" '
check_prot_path $p://$h/~$r $p "/~$r"
'
test_expect_success MINGW "fetch-pack --diag-url $p://$h/~$r" '
check_prot_path $p://$h/~$r $p "//$h/~$r"
'
done
# file without scheme
for h in nohost nohost:12 [::1] [::1]:23 [ [:aa

View File

@@ -17,14 +17,11 @@ fi
UNCPATH="$(winpwd)"
case "$UNCPATH" in
[A-Z]:*)
WITHOUTDRIVE="${UNCPATH#?:}"
# Use administrative share e.g. \\localhost\C$\git-sdk-64\usr\src\git
# (we use forward slashes here because MSYS2 and Git accept them, and
# they are easier on the eyes)
UNCPATH="//localhost/${UNCPATH%%:*}\$/${UNCPATH#?:}"
test -d "$UNCPATH" || {
skip_all='could not access administrative share; skipping'
test_done
}
UNCPATH="//localhost/${UNCPATH%%:*}\$$WITHOUTDRIVE"
;;
*)
skip_all='skipping UNC path tests, cannot determine current path as UNC'
@@ -32,6 +29,18 @@ case "$UNCPATH" in
;;
esac
test_expect_success 'clone into absolute path lacking a drive prefix' '
USINGBACKSLASHES="$(echo "$WITHOUTDRIVE"/without-drive-prefix |
tr / \\\\)" &&
git clone . "$USINGBACKSLASHES" &&
test -f without-drive-prefix/.git/HEAD
'
test -d "$UNCPATH" || {
skip_all='could not access administrative share; skipping'
test_done
}
test_expect_success setup '
test_commit initial
'
@@ -40,6 +49,23 @@ test_expect_success clone '
git clone "file://$UNCPATH" clone
'
test_expect_success 'clone without file://' '
git clone "$UNCPATH" clone-without-file
'
test_expect_success 'clone with backslashed path' '
BACKSLASHED="$(echo "$UNCPATH" | tr / \\\\)" &&
git clone "$BACKSLASHED" backslashed
'
test_expect_success fetch '
git init to-fetch &&
(
cd to-fetch &&
git fetch "$UNCPATH" master
)
'
test_expect_success push '
(
cd clone &&
@@ -57,4 +83,16 @@ test_expect_success MINGW 'remote nick cannot contain backslashes' '
test_i18ngrep ! "unable to access" err
'
test_expect_success 'unc alternates' '
tree="$(git rev-parse HEAD:)" &&
mkdir test-unc-alternate &&
(
cd test-unc-alternate &&
git init &&
test_must_fail git show $tree &&
echo "$UNCPATH/.git/objects" >.git/objects/info/alternates &&
git show $tree
)
'
test_done

View File

@@ -228,7 +228,7 @@ test_expect_success 'push update refs failure' '
echo "update fail" >>file &&
git commit -a -m "update fail" &&
git rev-parse --verify testgit/origin/heads/update >expect &&
test_expect_code 1 env GIT_REMOTE_TESTGIT_FAILURE="non-fast forward" \
test_must_fail env GIT_REMOTE_TESTGIT_FAILURE="non-fast forward" \
git push origin update &&
git rev-parse --verify testgit/origin/heads/update >actual &&
test_cmp expect actual

32
t/t7108-reset-stdin.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/bin/sh
test_description='reset --stdin'
. ./test-lib.sh
test_expect_success 'reset --stdin' '
test_commit hello &&
git rm hello.t &&
test -z "$(git ls-files hello.t)" &&
echo hello.t | git reset --stdin &&
test hello.t = "$(git ls-files hello.t)"
'
test_expect_success 'reset --stdin -z' '
test_commit world &&
git rm hello.t world.t &&
test -z "$(git ls-files hello.t world.t)" &&
printf world.tQworld.tQhello.tQ | q_to_nul | git reset --stdin -z &&
printf "hello.t\nworld.t\n" >expect &&
git ls-files >actual &&
test_cmp expect actual
'
test_expect_success '--stdin requires --mixed' '
echo hello.t >list &&
test_must_fail git reset --soft --stdin <list &&
test_must_fail git reset --hard --stdin <list &&
git reset --mixed --stdin <list
'
test_done

View File

@@ -556,4 +556,15 @@ test_expect_success 'merge commit gets exported with --import-marks' '
)
'
cat > expected << EOF
reset refs/heads/master
from $(git rev-parse master)
EOF
test_expect_failure 'refs are updated even if no commits need to be exported' '
git fast-export master..master > actual &&
test_cmp expected actual
'
test_done

View File

@@ -95,6 +95,13 @@ done,*)
test "$(cat "$BASE.exit")" = 0
exit
;;
*' --write-junit-xml '*)
# record how to call this script *with* --verbose-log, in case
# we encounter a breakage
junit_rerun_options_sq="$(printf '%s\n' "$0" --verbose-log -x "$@" |
sed -e "s/'/'\\\\''/g" -e "s/^/'/" -e "s/\$/'/" |
tr '\012' ' ')"
;;
esac
# For repeatability, reset the environment to known value.
@@ -294,6 +301,8 @@ do
test -z "$HARNESS_ACTIVE" && quiet=t; shift ;;
--with-dashes)
with_dashes=t; shift ;;
--no-bin-wrappers)
no_bin_wrappers=t; shift ;;
--no-color)
color=; shift ;;
--va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
@@ -339,6 +348,9 @@ do
-V|--verbose-log)
verbose_log=t
shift ;;
--write-junit-xml)
write_junit_xml=t
shift ;;
*)
echo "error: unknown test option '$1'" >&2; exit 1 ;;
esac
@@ -486,11 +498,34 @@ trap 'exit $?' INT
# the test_expect_* functions instead.
test_ok_ () {
if test -n "$write_junit_xml"
then
write_junit_xml_testcase "$*"
fi
test_success=$(($test_success + 1))
say_color "" "ok $test_count - $@"
}
test_failure_ () {
if test -n "$write_junit_xml"
then
junit_insert="<failure message=\"not ok $test_count -"
junit_insert="$junit_insert $(xml_attr_encode "$1")\">"
junit_insert="$junit_insert $(xml_attr_encode \
"$(if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
then
cut -c "$GIT_TEST_TEE_OFFSET-" <"$GIT_TEST_TEE_OUTPUT_FILE"
else
printf '%s\n' "$@" | sed 1d
fi)")"
junit_insert="$junit_insert</failure>"
if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
then
junit_insert="$junit_insert<system-err>$(xml_attr_encode \
"$(cat "$GIT_TEST_TEE_OUTPUT_FILE")")</system-err>"
fi
write_junit_xml_testcase "$1" " $junit_insert"
fi
test_failure=$(($test_failure + 1))
say_color error "not ok $test_count - $1"
shift
@@ -499,11 +534,19 @@ test_failure_ () {
}
test_known_broken_ok_ () {
if test -n "$write_junit_xml"
then
write_junit_xml_testcase "$* (breakage fixed)"
fi
test_fixed=$(($test_fixed+1))
say_color error "ok $test_count - $@ # TODO known breakage vanished"
}
test_known_broken_failure_ () {
if test -n "$write_junit_xml"
then
write_junit_xml_testcase "$* (known breakage)"
fi
test_broken=$(($test_broken+1))
say_color warn "not ok $test_count - $@ # TODO known breakage"
}
@@ -761,6 +804,10 @@ test_start_ () {
test_count=$(($test_count+1))
maybe_setup_verbose
maybe_setup_valgrind
if test -n "$write_junit_xml"
then
junit_start=$(test-tool date getnanos)
fi
}
test_finish_ () {
@@ -798,6 +845,13 @@ test_skip () {
case "$to_skip" in
t)
if test -n "$write_junit_xml"
then
message="$(xml_attr_encode "$skipped_reason")"
write_junit_xml_testcase "$1" \
" <skipped message=\"$message\" />"
fi
say_color skip >&3 "skipping test: $@"
say_color skip "ok $test_count # skip $1 ($skipped_reason)"
: true
@@ -813,9 +867,66 @@ test_at_end_hook_ () {
:
}
write_junit_xml () {
case "$1" in
--truncate)
>"$junit_xml_path"
junit_have_testcase=
shift
;;
esac
printf '%s\n' "$@" >>"$junit_xml_path"
}
xml_attr_encode () {
# We do not translate CR to &#x0d; because BSD sed does not handle
# \r in the regex. In practice, the output should not even have any
# carriage returns.
printf '%s\n' "$@" |
sed -e 's/&/\&amp;/g' -e "s/'/\&apos;/g" -e 's/"/\&quot;/g' \
-e 's/</\&lt;/g' -e 's/>/\&gt;/g' \
-e "s/$(printf \\x1c)/\\&#xfffd;/g" \
-e "s/$(printf \\x1d)/\\&#xfffd;/g" \
-e "s/$(printf \\x1e)/\\&#xfffd;/g" \
-e "s/$(printf \\x1f)/\\&#xfffd;/g" \
-e 's/ /\&#x09;/g' -e 's/$/\&#x0a;/' -e '$s/&#x0a;$//' |
tr -d '\012\015'
}
write_junit_xml_testcase () {
junit_attrs="name=\"$(xml_attr_encode "$this_test.$test_count $1")\""
shift
junit_attrs="$junit_attrs classname=\"$this_test\""
junit_attrs="$junit_attrs time=\"$(test-tool \
date getnanos $junit_start)\""
write_junit_xml "$(printf '%s\n' \
" <testcase $junit_attrs>" "$@" " </testcase>")"
junit_have_testcase=t
if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
then
GIT_TEST_TEE_OFFSET=$(perl -e 'print -s $ARGV[0]' "$GIT_TEST_TEE_OUTPUT_FILE")
fi
}
test_done () {
GIT_EXIT_OK=t
if test -n "$write_junit_xml" && test -n "$junit_xml_path"
then
test -n "$junit_have_testcase" || {
junit_start=$(test-tool date getnanos)
write_junit_xml_testcase "all tests skipped"
}
# adjust the overall time
junit_time=$(test-tool date getnanos $junit_suite_start)
sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \
<"$junit_xml_path" >"$junit_xml_path.new"
mv "$junit_xml_path.new" "$junit_xml_path"
write_junit_xml " </testsuite>" "</testsuites>"
fi
if test -z "$HARNESS_ACTIVE"
then
test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
@@ -878,7 +989,11 @@ test_done () {
error "Tests passed but trash directory already removed before test cleanup; aborting"
cd "$TRASH_DIRECTORY/.." &&
rm -fr "$TRASH_DIRECTORY" ||
rm -fr "$TRASH_DIRECTORY" || {
# try again in a bit
sleep 5;
rm -fr "$TRASH_DIRECTORY"
} ||
error "Tests passed but test cleanup failed; aborting"
fi
test_at_end_hook_
@@ -984,20 +1099,25 @@ then
PATH=$GIT_TEST_INSTALLED:$GIT_BUILD_DIR/t/helper:$PATH
GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH}
else # normal case, use ../bin-wrappers only unless $with_dashes:
git_bin_dir="$GIT_BUILD_DIR/bin-wrappers"
if ! test -x "$git_bin_dir/git"
if test -n "$no_bin_wrappers"
then
if test -z "$with_dashes"
then
say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH"
fi
with_dashes=t
else
git_bin_dir="$GIT_BUILD_DIR/bin-wrappers"
if ! test -x "$git_bin_dir/git"
then
if test -z "$with_dashes"
then
say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH"
fi
with_dashes=t
fi
PATH="$git_bin_dir:$PATH"
fi
PATH="$git_bin_dir:$PATH"
GIT_EXEC_PATH=$GIT_BUILD_DIR
if test -n "$with_dashes"
then
PATH="$GIT_BUILD_DIR:$PATH"
PATH="$GIT_BUILD_DIR:$GIT_BUILD_DIR/t/helper:$PATH"
fi
fi
GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt
@@ -1021,7 +1141,7 @@ test -d "$GIT_BUILD_DIR"/templates/blt || {
error "You haven't built things yet, have you?"
}
if ! test -x "$GIT_BUILD_DIR"/t/helper/test-tool
if ! test -x "$GIT_BUILD_DIR"/t/helper/test-tool$X
then
echo >&2 'You need to build test-tool:'
echo >&2 'Run "make t/helper/test-tool" in the source (toplevel) directory'
@@ -1051,6 +1171,7 @@ then
else
mkdir -p "$TRASH_DIRECTORY"
fi
# Use -P to resolve symlinks in our working directory so that the cwd
# in subprocesses like git equals our $PWD (for pathname comparisons).
cd -P "$TRASH_DIRECTORY" || exit 1
@@ -1064,6 +1185,24 @@ then
test_done
fi
if test -n "$write_junit_xml"
then
junit_xml_dir="$TEST_OUTPUT_DIRECTORY/out"
mkdir -p "$junit_xml_dir"
junit_xml_base=${0##*/}
junit_xml_path="$junit_xml_dir/TEST-${junit_xml_base%.sh}.xml"
junit_attrs="name=\"${junit_xml_base%.sh}\""
junit_attrs="$junit_attrs timestamp=\"$(TZ=UTC \
date +%Y-%m-%dT%H:%M:%S)\""
write_junit_xml --truncate "<testsuites>" " <testsuite $junit_attrs>"
junit_suite_start=$(test-tool date getnanos)
if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
then
GIT_TEST_TEE_OFFSET=0
GIT_TEST_TEE_ERR_OFFSET=0
fi
fi
# Provide an implementation of the 'yes' utility
yes () {
if test $# = 0

View File

@@ -16,6 +16,8 @@
#include "protocol.h"
static int debug;
/* TODO: put somewhere sensible, e.g. git_transport_options? */
static int auto_gc = 1;
struct helper_data {
const char *name;
@@ -460,10 +462,25 @@ static int get_exporter(struct transport *transport,
for (i = 0; i < revlist_args->nr; i++)
argv_array_push(&fastexport->args, revlist_args->items[i].string);
argv_array_push(&fastexport->args, "--");
fastexport->git_cmd = 1;
return start_command(fastexport);
}
static void check_helper_status(struct helper_data *data)
{
int pid, status;
pid = waitpid(data->helper->pid, &status, WNOHANG);
if (pid < 0)
die("Could not retrieve status of remote helper '%s'",
data->name);
if (pid > 0 && WIFEXITED(status))
die("Remote helper '%s' died with %d",
data->name, WEXITSTATUS(status));
}
static int fetch_with_import(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
@@ -500,6 +517,7 @@ static int fetch_with_import(struct transport *transport,
if (finish_command(&fastimport))
die(_("error while running fast-import"));
check_helper_status(data);
/*
* The fast-import stream of a remote helper that advertises
@@ -533,6 +551,12 @@ static int fetch_with_import(struct transport *transport,
}
}
strbuf_release(&buf);
if (auto_gc) {
const char *argv_gc_auto[] = {
"gc", "--auto", "--quiet", NULL,
};
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
return 0;
}
@@ -987,6 +1011,7 @@ static int push_refs_with_export(struct transport *transport,
if (finish_command(&exporter))
die(_("error while running fast-export"));
check_helper_status(data);
if (push_update_refs_status(data, remote_refs, flags))
return 1;