mirror of
https://github.com/git-for-windows/git.git
synced 2026-04-27 18:11:59 -05:00
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:
230
.github/workflows/main.yml
vendored
Normal file
230
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
name: CI/PR
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
DEVELOPER: 1
|
||||
|
||||
jobs:
|
||||
windows-build:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: download git-sdk-64-minimal
|
||||
shell: bash
|
||||
run: a=git-sdk-64-minimal && mkdir -p $a && curl -# https://wingit.blob.core.windows.net/ci-artifacts/$a.tar.xz | tar -C $a -xJf -
|
||||
- name: build
|
||||
shell: powershell
|
||||
env:
|
||||
HOME: ${{runner.workspace}}
|
||||
MSYSTEM: MINGW64
|
||||
NO_PERL: 1
|
||||
run: |
|
||||
& .\git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
printf '%s\n' /git-sdk-64-minimal/ >>.git/info/exclude
|
||||
|
||||
ci/make-test-artifacts.sh artifacts
|
||||
"@
|
||||
- name: upload build artifacts
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: artifacts
|
||||
windows-test:
|
||||
runs-on: windows-latest
|
||||
needs: [windows-build]
|
||||
strategy:
|
||||
matrix:
|
||||
nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: download git-sdk-64-minimal
|
||||
shell: bash
|
||||
run: a=git-sdk-64-minimal && mkdir -p $a && curl -# https://wingit.blob.core.windows.net/ci-artifacts/$a.tar.xz | tar -C $a -xJf -
|
||||
- name: download build artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: ${{github.workspace}}
|
||||
- name: extract build artifacts
|
||||
shell: bash
|
||||
run: tar xf artifacts.tar.gz
|
||||
- name: test
|
||||
shell: powershell
|
||||
run: |
|
||||
& .\git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
# Let Git ignore the SDK
|
||||
printf '%s\n' /git-sdk-64-minimal/ >>.git/info/exclude
|
||||
|
||||
ci/run-test-slice.sh ${{matrix.nr}} 10
|
||||
"@
|
||||
- name: ci/print-test-failures.sh
|
||||
if: failure()
|
||||
shell: powershell
|
||||
run: |
|
||||
& .\git-sdk-64-minimal\usr\bin\bash.exe -lc ci/print-test-failures.sh
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: failed-tests-windows
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
vs-build:
|
||||
env:
|
||||
MSYSTEM: MINGW64
|
||||
NO_PERL: 1
|
||||
GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'"
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: download git-sdk-64-minimal
|
||||
shell: bash
|
||||
run: a=git-sdk-64-minimal && mkdir -p $a && curl -# https://wingit.blob.core.windows.net/ci-artifacts/$a.tar.xz | tar -C $a -xJf -
|
||||
- name: generate Visual Studio solution
|
||||
shell: powershell
|
||||
run: |
|
||||
& .\git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
make NDEBUG=1 DEVELOPER=1 vcxproj
|
||||
"@
|
||||
if (!$?) { exit(1) }
|
||||
- name: download vcpkg artifacts
|
||||
shell: powershell
|
||||
run: |
|
||||
$urlbase = "https://dev.azure.com/git/git/_apis/build/builds"
|
||||
$id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=9&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id
|
||||
$downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[0].resource.downloadUrl
|
||||
(New-Object Net.WebClient).DownloadFile($downloadUrl, "compat.zip")
|
||||
Expand-Archive compat.zip -DestinationPath . -Force
|
||||
Remove-Item compat.zip
|
||||
- name: add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.0
|
||||
- name: MSBuild
|
||||
run: msbuild git.sln -property:Configuration=Release -property:Platform=x64 -maxCpuCount:4 -property:PlatformToolset=v142
|
||||
- name: bundle artifact tar
|
||||
shell: powershell
|
||||
env:
|
||||
MSVC: 1
|
||||
VCPKG_ROOT: ${{github.workspace}}\compat\vcbuild\vcpkg
|
||||
run: |
|
||||
& compat\vcbuild\vcpkg_copy_dlls.bat release
|
||||
if (!$?) { exit(1) }
|
||||
& git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
mkdir -p artifacts &&
|
||||
eval \"`$(make -n artifacts-tar INCLUDE_DLLS_IN_ARTIFACTS=YesPlease ARTIFACTS_DIRECTORY=artifacts 2>&1 | grep ^tar)\"
|
||||
"@
|
||||
- name: upload build artifacts
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: vs-artifacts
|
||||
path: artifacts
|
||||
vs-test:
|
||||
runs-on: windows-latest
|
||||
needs: [vs-build]
|
||||
strategy:
|
||||
matrix:
|
||||
nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: download git-64-portable
|
||||
shell: bash
|
||||
run: a=git-64-portable && mkdir -p $a && curl -# https://wingit.blob.core.windows.net/ci-artifacts/$a.tar.xz | tar -C $a -xJf -
|
||||
- name: download build artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: vs-artifacts
|
||||
path: ${{github.workspace}}
|
||||
- name: extract build artifacts
|
||||
shell: bash
|
||||
run: tar xf artifacts.tar.gz
|
||||
- name: test (parallel)
|
||||
shell: powershell
|
||||
env:
|
||||
MSYSTEM: MINGW64
|
||||
NO_SVN_TESTS: 1
|
||||
GIT_TEST_SKIP_REBASE_P: 1
|
||||
run: |
|
||||
& git-64-portable\git-cmd.exe --command=usr\bin\bash.exe -lc @"
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
printf '%s\n' /git-64-portable/ /test-cache/ >>.git/info/exclude
|
||||
|
||||
cd t &&
|
||||
PATH=\"`$PWD/helper:`$PATH\" &&
|
||||
test-tool.exe run-command testsuite --jobs=10 -V -x --write-junit-xml \
|
||||
`$(test-tool.exe path-utils slice-tests \
|
||||
${{matrix.nr}} 10 t[0-9]*.sh)
|
||||
"@
|
||||
regular:
|
||||
strategy:
|
||||
matrix:
|
||||
vector:
|
||||
- jobname: linux-clang
|
||||
cc: clang
|
||||
pool: ubuntu-latest
|
||||
- jobname: linux-gcc
|
||||
cc: gcc
|
||||
pool: ubuntu-latest
|
||||
- jobname: osx-clang
|
||||
cc: clang
|
||||
pool: macos-latest
|
||||
- jobname: osx-gcc
|
||||
cc: gcc
|
||||
pool: macos-latest
|
||||
- jobname: GETTEXT_POISON
|
||||
cc: gcc
|
||||
pool: ubuntu-latest
|
||||
env:
|
||||
CC: ${{matrix.vector.cc}}
|
||||
jobname: ${{matrix.vector.jobname}}
|
||||
runs-on: ${{matrix.vector.pool}}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/run-build-and-tests.sh
|
||||
- run: ci/print-test-failures.sh
|
||||
if: failure()
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: failed-tests-${{matrix.vector.jobname}}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
dockerized:
|
||||
strategy:
|
||||
matrix:
|
||||
vector:
|
||||
- jobname: linux-musl
|
||||
image: alpine
|
||||
- jobname: Linux32
|
||||
image: daald/ubuntu32:xenial
|
||||
env:
|
||||
jobname: ${{matrix.vector.jobname}}
|
||||
runs-on: ubuntu-latest
|
||||
container: ${{matrix.vector.image}}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- run: ci/install-docker-dependencies.sh
|
||||
- run: ci/run-build-and-tests.sh
|
||||
- run: ci/print-test-failures.sh
|
||||
if: failure()
|
||||
- name: Upload failed tests' directories
|
||||
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: failed-tests-${{matrix.vector.jobname}}
|
||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||
static-analysis:
|
||||
env:
|
||||
jobname: StaticAnalysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/run-static-analysis.sh
|
||||
documentation:
|
||||
env:
|
||||
jobname: Documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- run: ci/install-dependencies.sh
|
||||
- run: ci/test-documentation.sh
|
||||
12
.travis.yml
12
.travis.yml
@@ -16,7 +16,7 @@ compiler:
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: jobname=GIT_TEST_GETTEXT_POISON
|
||||
- env: jobname=GETTEXT_POISON
|
||||
os: linux
|
||||
compiler:
|
||||
addons:
|
||||
@@ -32,7 +32,15 @@ matrix:
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
script: ci/run-linux32-docker.sh
|
||||
script: ci/run-docker.sh
|
||||
- env: jobname=linux-musl
|
||||
os: linux
|
||||
compiler:
|
||||
addons:
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
script: ci/run-docker.sh
|
||||
- env: jobname=StaticAnalysis
|
||||
os: linux
|
||||
compiler:
|
||||
|
||||
@@ -431,6 +431,8 @@ include::config/reset.txt[]
|
||||
|
||||
include::config/sendemail.txt[]
|
||||
|
||||
include::config/sendpack.txt[]
|
||||
|
||||
include::config/sequencer.txt[]
|
||||
|
||||
include::config/showbranch.txt[]
|
||||
|
||||
@@ -152,11 +152,13 @@ http.sslBackend::
|
||||
|
||||
http.schannelCheckRevoke::
|
||||
Used to enforce or disable certificate revocation checks in cURL
|
||||
when http.sslBackend is set to "schannel". Defaults to `true` if
|
||||
unset. Only necessary to disable this if Git consistently errors
|
||||
and the message is about checking the revocation status of a
|
||||
certificate. This option is ignored if cURL lacks support for
|
||||
setting the relevant SSL option at runtime.
|
||||
when http.sslBackend is set to "schannel" via "true" and "false",
|
||||
respectively. Another accepted value is "best-effort" (the default)
|
||||
in which case revocation checks are performed, but errors due to
|
||||
revocation list distribution points that are offline are silently
|
||||
ignored, as well as errors due to certificates missing revocation
|
||||
list distribution points. This option is ignored if cURL lacks
|
||||
support for setting the relevant SSL option at runtime.
|
||||
|
||||
http.schannelUseSSLCAInfo::
|
||||
As of cURL v7.60.0, the Secure Channel backend can use the
|
||||
|
||||
5
Documentation/config/sendpack.txt
Normal file
5
Documentation/config/sendpack.txt
Normal 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.
|
||||
5
Makefile
5
Makefile
@@ -2720,6 +2720,11 @@ ifdef GIT_INTEROP_MAKE_OPTS
|
||||
endif
|
||||
ifdef GIT_TEST_INDEX_VERSION
|
||||
@echo GIT_TEST_INDEX_VERSION=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_INDEX_VERSION)))'\' >>$@+
|
||||
endif
|
||||
ifdef RUNTIME_PREFIX
|
||||
@echo RUNTIME_PREFIX=\'true\' >>$@+
|
||||
else
|
||||
@echo RUNTIME_PREFIX=\'false\' >>$@+
|
||||
endif
|
||||
@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://dev.azure.com/git/git/_build/latest?definitionId=11)
|
||||
[](https://github.com/git/git/actions?query=branch%3Amaster+event%3Apush)
|
||||
|
||||
Git - fast, scalable, distributed revision control system
|
||||
=========================================================
|
||||
|
||||
@@ -95,6 +95,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (platform_strbuf_realpath(resolved, path))
|
||||
return resolved->buf;
|
||||
|
||||
strbuf_addstr(&remaining, path);
|
||||
get_root_part(resolved, &remaining);
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ static unsigned long offset;
|
||||
|
||||
static int tar_umask = 002;
|
||||
|
||||
static gzFile gzip;
|
||||
|
||||
static int write_tar_filter_archive(const struct archiver *ar,
|
||||
struct archiver_args *args);
|
||||
|
||||
@@ -38,11 +40,21 @@ static int write_tar_filter_archive(const struct archiver *ar,
|
||||
#define USTAR_MAX_MTIME 077777777777ULL
|
||||
#endif
|
||||
|
||||
/* writes out the whole block, or dies if fails */
|
||||
static void write_block_or_die(const char *block) {
|
||||
if (gzip) {
|
||||
if (gzwrite(gzip, block, (unsigned) BLOCKSIZE) != BLOCKSIZE)
|
||||
die(_("gzwrite failed"));
|
||||
} else {
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* writes out the whole block, but only if it is full */
|
||||
static void write_if_needed(void)
|
||||
{
|
||||
if (offset == BLOCKSIZE) {
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
write_block_or_die(block);
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +78,7 @@ static void do_write_blocked(const void *data, unsigned long size)
|
||||
write_if_needed();
|
||||
}
|
||||
while (size >= BLOCKSIZE) {
|
||||
write_or_die(1, buf, BLOCKSIZE);
|
||||
write_block_or_die(buf);
|
||||
size -= BLOCKSIZE;
|
||||
buf += BLOCKSIZE;
|
||||
}
|
||||
@@ -101,10 +113,10 @@ static void write_trailer(void)
|
||||
{
|
||||
int tail = BLOCKSIZE - offset;
|
||||
memset(block + offset, 0, tail);
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
write_block_or_die(block);
|
||||
if (tail < 2 * RECORDSIZE) {
|
||||
memset(block, 0, offset);
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
write_block_or_die(block);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,18 +473,34 @@ static int write_tar_filter_archive(const struct archiver *ar,
|
||||
filter.use_shell = 1;
|
||||
filter.in = -1;
|
||||
|
||||
if (start_command(&filter) < 0)
|
||||
die_errno(_("unable to start '%s' filter"), argv[0]);
|
||||
close(1);
|
||||
if (dup2(filter.in, 1) < 0)
|
||||
die_errno(_("unable to redirect descriptor"));
|
||||
close(filter.in);
|
||||
if (!strcmp("gzip -cn", ar->data)) {
|
||||
char outmode[4] = "wb\0";
|
||||
|
||||
if (args->compression_level >= 0 && args->compression_level <= 9)
|
||||
outmode[2] = '0' + args->compression_level;
|
||||
|
||||
gzip = gzdopen(fileno(stdout), outmode);
|
||||
if (!gzip)
|
||||
die(_("Could not gzdopen stdout"));
|
||||
} else {
|
||||
if (start_command(&filter) < 0)
|
||||
die_errno(_("unable to start '%s' filter"), argv[0]);
|
||||
close(1);
|
||||
if (dup2(filter.in, 1) < 0)
|
||||
die_errno(_("unable to redirect descriptor"));
|
||||
close(filter.in);
|
||||
}
|
||||
|
||||
r = write_tar_archive(ar, args);
|
||||
|
||||
close(1);
|
||||
if (finish_command(&filter) != 0)
|
||||
die(_("'%s' filter reported error"), argv[0]);
|
||||
if (gzip) {
|
||||
if (gzclose(gzip) != Z_OK)
|
||||
die(_("gzclose failed"));
|
||||
} else {
|
||||
close(1);
|
||||
if (finish_command(&filter) != 0)
|
||||
die(_("'%s' filter reported error"), argv[0]);
|
||||
}
|
||||
|
||||
strbuf_release(&cmd);
|
||||
return r;
|
||||
|
||||
@@ -1,558 +0,0 @@
|
||||
variables:
|
||||
Agent.Source.Git.ShallowFetchDepth: 1
|
||||
|
||||
jobs:
|
||||
- job: windows_build
|
||||
displayName: Windows Build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
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: |
|
||||
$urlbase = "https://dev.azure.com/git-for-windows/git/_apis/build/builds"
|
||||
$id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=22&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id
|
||||
$downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[1].resource.downloadUrl
|
||||
(New-Object Net.WebClient).DownloadFile($downloadUrl,"git-sdk-64-minimal.zip")
|
||||
Expand-Archive git-sdk-64-minimal.zip -DestinationPath . -Force
|
||||
Remove-Item git-sdk-64-minimal.zip
|
||||
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
"/git-sdk-64-minimal/`n/test-cache/`n" | Out-File -NoNewLine -Encoding ascii -Append "$(Build.SourcesDirectory)\.git\info\exclude"
|
||||
displayName: 'Download git-sdk-64-minimal'
|
||||
- powershell: |
|
||||
& git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
ci/make-test-artifacts.sh artifacts
|
||||
"@
|
||||
if (!$?) { exit(1) }
|
||||
displayName: Build
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
DEVELOPER: 1
|
||||
NO_PERL: 1
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Pipeline Artifact: test artifacts'
|
||||
inputs:
|
||||
artifactName: 'windows-artifacts'
|
||||
targetPath: '$(Build.SourcesDirectory)\artifacts'
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Pipeline Artifact: git-sdk-64-minimal'
|
||||
inputs:
|
||||
artifactName: 'git-sdk-64-minimal'
|
||||
targetPath: '$(Build.SourcesDirectory)\git-sdk-64-minimal'
|
||||
- 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)
|
||||
|
||||
- job: windows_test
|
||||
displayName: Windows Test
|
||||
dependsOn: windows_build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
timeoutInMinutes: 240
|
||||
strategy:
|
||||
parallel: 10
|
||||
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)
|
||||
- task: DownloadPipelineArtifact@0
|
||||
displayName: 'Download Pipeline Artifact: test artifacts'
|
||||
inputs:
|
||||
artifactName: 'windows-artifacts'
|
||||
targetPath: '$(Build.SourcesDirectory)'
|
||||
- task: DownloadPipelineArtifact@0
|
||||
displayName: 'Download Pipeline Artifact: git-sdk-64-minimal'
|
||||
inputs:
|
||||
artifactName: 'git-sdk-64-minimal'
|
||||
targetPath: '$(Build.SourcesDirectory)\git-sdk-64-minimal'
|
||||
- powershell: |
|
||||
& git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
test -f artifacts.tar.gz || {
|
||||
echo No test artifacts found\; skipping >&2
|
||||
exit 0
|
||||
}
|
||||
tar xf artifacts.tar.gz || exit 1
|
||||
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
printf '%s\n' /git-sdk-64-minimal/ /test-cache/ >>.git/info/exclude
|
||||
|
||||
ci/run-test-slice.sh `$SYSTEM_JOBPOSITIONINPHASE `$SYSTEM_TOTALJOBSINPHASE || {
|
||||
ci/print-test-failures.sh
|
||||
exit 1
|
||||
}
|
||||
"@
|
||||
if (!$?) { exit(1) }
|
||||
displayName: 'Test (parallel)'
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
NO_SVN_TESTS: 1
|
||||
GIT_TEST_SKIP_REBASE_P: 1
|
||||
- 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()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: vs_build
|
||||
displayName: Visual Studio Build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
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: |
|
||||
$urlbase = "https://dev.azure.com/git-for-windows/git/_apis/build/builds"
|
||||
$id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=22&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id
|
||||
$downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[1].resource.downloadUrl
|
||||
(New-Object Net.WebClient).DownloadFile($downloadUrl,"git-sdk-64-minimal.zip")
|
||||
Expand-Archive git-sdk-64-minimal.zip -DestinationPath . -Force
|
||||
Remove-Item git-sdk-64-minimal.zip
|
||||
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
"/git-sdk-64-minimal/`n/test-cache/`n" | Out-File -NoNewLine -Encoding ascii -Append "$(Build.SourcesDirectory)\.git\info\exclude"
|
||||
displayName: 'Download git-sdk-64-minimal'
|
||||
- powershell: |
|
||||
& git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
make NDEBUG=1 DEVELOPER=1 vcxproj
|
||||
"@
|
||||
if (!$?) { exit(1) }
|
||||
displayName: Generate Visual Studio Solution
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
DEVELOPER: 1
|
||||
NO_PERL: 1
|
||||
GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'"
|
||||
- powershell: |
|
||||
$urlbase = "https://dev.azure.com/git/git/_apis/build/builds"
|
||||
$id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=9&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id
|
||||
$downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[0].resource.downloadUrl
|
||||
(New-Object Net.WebClient).DownloadFile($downloadUrl, "compat.zip")
|
||||
Expand-Archive compat.zip -DestinationPath . -Force
|
||||
Remove-Item compat.zip
|
||||
displayName: 'Download vcpkg artifacts'
|
||||
- task: MSBuild@1
|
||||
inputs:
|
||||
solution: git.sln
|
||||
platform: x64
|
||||
configuration: Release
|
||||
maximumCpuCount: 4
|
||||
msbuildArguments: /p:PlatformToolset=v142
|
||||
- powershell: |
|
||||
& compat\vcbuild\vcpkg_copy_dlls.bat release
|
||||
if (!$?) { exit(1) }
|
||||
& git-sdk-64-minimal\usr\bin\bash.exe -lc @"
|
||||
mkdir -p artifacts &&
|
||||
eval \"`$(make -n artifacts-tar INCLUDE_DLLS_IN_ARTIFACTS=YesPlease ARTIFACTS_DIRECTORY=artifacts | grep ^tar)\"
|
||||
"@
|
||||
if (!$?) { exit(1) }
|
||||
displayName: Bundle artifact tar
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
DEVELOPER: 1
|
||||
NO_PERL: 1
|
||||
MSVC: 1
|
||||
VCPKG_ROOT: $(Build.SourcesDirectory)\compat\vcbuild\vcpkg
|
||||
- powershell: |
|
||||
$tag = (Invoke-WebRequest -UseBasicParsing "https://gitforwindows.org/latest-tag.txt").content
|
||||
$version = (Invoke-WebRequest -UseBasicParsing "https://gitforwindows.org/latest-version.txt").content
|
||||
$url = "https://github.com/git-for-windows/git/releases/download/${tag}/PortableGit-${version}-64-bit.7z.exe"
|
||||
(New-Object Net.WebClient).DownloadFile($url,"PortableGit.exe")
|
||||
& .\PortableGit.exe -y -oartifacts\PortableGit
|
||||
# Wait until it is unpacked
|
||||
while (-not @(Remove-Item -ErrorAction SilentlyContinue PortableGit.exe; $?)) { sleep 1 }
|
||||
displayName: Download & extract portable Git
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Pipeline Artifact: MSVC test artifacts'
|
||||
inputs:
|
||||
artifactName: 'vs-artifacts'
|
||||
targetPath: '$(Build.SourcesDirectory)\artifacts'
|
||||
- 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)
|
||||
|
||||
- job: vs_test
|
||||
displayName: Visual Studio Test
|
||||
dependsOn: vs_build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
timeoutInMinutes: 240
|
||||
strategy:
|
||||
parallel: 10
|
||||
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)
|
||||
- task: DownloadPipelineArtifact@0
|
||||
displayName: 'Download Pipeline Artifact: VS test artifacts'
|
||||
inputs:
|
||||
artifactName: 'vs-artifacts'
|
||||
targetPath: '$(Build.SourcesDirectory)'
|
||||
- powershell: |
|
||||
& PortableGit\git-cmd.exe --command=usr\bin\bash.exe -lc @"
|
||||
test -f artifacts.tar.gz || {
|
||||
echo No test artifacts found\; skipping >&2
|
||||
exit 0
|
||||
}
|
||||
tar xf artifacts.tar.gz || exit 1
|
||||
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
printf '%s\n' /PortableGit/ /test-cache/ >>.git/info/exclude
|
||||
|
||||
cd t &&
|
||||
PATH=\"`$PWD/helper:`$PATH\" &&
|
||||
test-tool.exe run-command testsuite --jobs=10 -V -x --write-junit-xml \
|
||||
`$(test-tool.exe path-utils slice-tests \
|
||||
`$SYSTEM_JOBPOSITIONINPHASE `$SYSTEM_TOTALJOBSINPHASE t[0-9]*.sh)
|
||||
"@
|
||||
if (!$?) { exit(1) }
|
||||
displayName: 'Test (parallel)'
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
NO_SVN_TESTS: 1
|
||||
GIT_TEST_SKIP_REBASE_P: 1
|
||||
- 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: 'vs'
|
||||
platform: Windows
|
||||
publishRunAttachments: false
|
||||
condition: succeededOrFailed()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-vs-test-artifacts
|
||||
|
||||
- job: linux_clang
|
||||
displayName: linux-clang
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
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 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 || 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: 'linux-clang'
|
||||
platform: Linux
|
||||
publishRunAttachments: false
|
||||
condition: succeededOrFailed()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: linux_gcc
|
||||
displayName: linux-gcc
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
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 add-apt-repository ppa:ubuntu-toolchain-r/test &&
|
||||
sudo apt-get update &&
|
||||
sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev apache2 language-pack-is git-svn gcc-8 || exit 1
|
||||
|
||||
ci/install-dependencies.sh || 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: 'linux-gcc'
|
||||
platform: Linux
|
||||
publishRunAttachments: false
|
||||
condition: succeededOrFailed()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: osx_clang
|
||||
displayName: osx-clang
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: macOS-latest
|
||||
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 || exit 1
|
||||
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()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: osx_gcc
|
||||
displayName: osx-gcc
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: macOS-latest
|
||||
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 || exit 1
|
||||
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()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: gettext_poison
|
||||
displayName: GETTEXT_POISON
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
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 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()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: linux32
|
||||
displayName: Linux32
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- bash: |
|
||||
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1
|
||||
|
||||
res=0
|
||||
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="$MAKEFLAGS" bash -lxc ci/run-linux32-docker.sh || res=1
|
||||
|
||||
sudo chmod a+r t/out/TEST-*.xml
|
||||
test ! -d t/failed-test-artifacts || sudo chmod a+r t/failed-test-artifacts
|
||||
|
||||
test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || res=1
|
||||
exit $res
|
||||
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()
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish trash directories of failed tests'
|
||||
condition: failed()
|
||||
inputs:
|
||||
PathtoPublish: t/failed-test-artifacts
|
||||
ArtifactName: failed-test-artifacts
|
||||
|
||||
- job: static_analysis
|
||||
displayName: StaticAnalysis
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
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 apt-get install -y coccinelle libcurl4-openssl-dev libssl-dev libexpat-dev gettext &&
|
||||
|
||||
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)
|
||||
|
||||
- job: documentation
|
||||
displayName: Documentation
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
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 apt-get install -y asciidoc xmlto asciidoctor docbook-xsl-ns &&
|
||||
|
||||
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)
|
||||
@@ -33,6 +33,10 @@ static const char *msg_remove = N_("Removing %s\n");
|
||||
static const char *msg_would_remove = N_("Would remove %s\n");
|
||||
static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
|
||||
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
|
||||
#ifndef CAN_UNLINK_MOUNT_POINTS
|
||||
static const char *msg_skip_mount_point = N_("Skipping mount point %s\n");
|
||||
static const char *msg_would_skip_mount_point = N_("Would skip mount point %s\n");
|
||||
#endif
|
||||
static const char *msg_warn_remove_failed = N_("failed to remove %s");
|
||||
static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
|
||||
|
||||
@@ -170,6 +174,29 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_mount_point(path)) {
|
||||
#ifndef CAN_UNLINK_MOUNT_POINTS
|
||||
if (!quiet) {
|
||||
quote_path_relative(path->buf, prefix, "ed);
|
||||
printf(dry_run ?
|
||||
_(msg_would_skip_mount_point) :
|
||||
_(msg_skip_mount_point), quoted.buf);
|
||||
}
|
||||
*dir_gone = 0;
|
||||
#else
|
||||
if (!dry_run && unlink(path->buf)) {
|
||||
int saved_errno = errno;
|
||||
quote_path_relative(path->buf, prefix, "ed);
|
||||
errno = saved_errno;
|
||||
warning_errno(_(msg_warn_remove_failed), quoted.buf);
|
||||
*dir_gone = 0;
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
dir = opendir(path->buf);
|
||||
if (!dir) {
|
||||
/* an empty dir could be removed even if it is unreadble */
|
||||
@@ -580,6 +607,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
|
||||
clean_get_color(CLEAN_COLOR_RESET));
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
if (strbuf_getline_lf(&choice, stdin) != EOF) {
|
||||
strbuf_trim(&choice);
|
||||
} else {
|
||||
@@ -662,6 +690,7 @@ static int filter_by_patterns_cmd(void)
|
||||
clean_print_color(CLEAN_COLOR_PROMPT);
|
||||
printf(_("Input ignore patterns>> "));
|
||||
clean_print_color(CLEAN_COLOR_RESET);
|
||||
fflush(stdout);
|
||||
if (strbuf_getline_lf(&confirm, stdin) != EOF)
|
||||
strbuf_trim(&confirm);
|
||||
else
|
||||
@@ -760,6 +789,7 @@ static int ask_each_cmd(void)
|
||||
qname = quote_path_relative(item->string, NULL, &buf);
|
||||
/* TRANSLATORS: Make sure to keep [y/N] as is */
|
||||
printf(_("Remove %s [y/N]? "), qname);
|
||||
fflush(stdout);
|
||||
if (strbuf_getline_lf(&confirm, stdin) != EOF) {
|
||||
strbuf_trim(&confirm);
|
||||
} else {
|
||||
|
||||
@@ -1229,7 +1229,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 =
|
||||
|
||||
@@ -1037,7 +1037,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
|
||||
}
|
||||
|
||||
cp_diff_tree.git_cmd = 1;
|
||||
argv_array_pushl(&cp_diff_tree.args, "diff-tree", "-p", "HEAD",
|
||||
argv_array_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD",
|
||||
oid_to_hex(&info->w_tree), "--", NULL);
|
||||
if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
|
||||
ret = -1;
|
||||
|
||||
1
cache.h
1
cache.h
@@ -1325,6 +1325,7 @@ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
|
||||
int normalize_path_copy(char *dst, const char *src);
|
||||
int longest_ancestor_length(const char *path, struct string_list *prefixes);
|
||||
char *strip_path_suffix(const char *path, const char *suffix);
|
||||
int is_mount_point_via_stat(struct strbuf *path);
|
||||
int daemon_avoid_alias(const char *path);
|
||||
|
||||
/*
|
||||
|
||||
16
ci/git-problem-matcher.json
Normal file
16
ci/git-problem-matcher.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "git-test-suite",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([^ :]+\\.sh):(\\d+): (error|warning|info):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"severity": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -7,12 +7,17 @@
|
||||
|
||||
P4WHENCE=http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION
|
||||
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
|
||||
UBUNTU_COMMON_PKGS="make libssl-dev libcurl4-openssl-dev libexpat-dev
|
||||
perl-modules liberror-perl tcl tk gettext zlib1g-dev apache2
|
||||
libauthen-sasl-perl libemail-valid-perl libio-socket-ssl-perl
|
||||
libnet-smtp-ssl-perl"
|
||||
|
||||
case "$jobname" in
|
||||
linux-clang|linux-gcc)
|
||||
sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
|
||||
sudo apt-get -q update
|
||||
sudo apt-get -q -y install language-pack-is libsvn-perl apache2
|
||||
sudo apt-get -q -y install language-pack-is libsvn-perl apache2 \
|
||||
$UBUNTU_COMMON_PKGS
|
||||
case "$jobname" in
|
||||
linux-gcc)
|
||||
sudo apt-get -q -y install gcc-8
|
||||
@@ -63,10 +68,15 @@ StaticAnalysis)
|
||||
;;
|
||||
Documentation)
|
||||
sudo apt-get -q update
|
||||
sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns
|
||||
sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns \
|
||||
libcurl4-openssl-dev
|
||||
|
||||
test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
|
||||
gem install --version 1.5.8 asciidoctor
|
||||
sudo gem install --version 1.5.8 asciidoctor
|
||||
;;
|
||||
GETTEXT_POISON)
|
||||
sudo apt-get -q update
|
||||
sudo apt-get -q -y install $UBUNTU_COMMON_PKGS
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
18
ci/install-docker-dependencies.sh
Executable file
18
ci/install-docker-dependencies.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Install dependencies required to build and test Git inside container
|
||||
#
|
||||
|
||||
case "$jobname" in
|
||||
Linux32)
|
||||
linux32 --32bit i386 sh -c '
|
||||
apt update >/dev/null &&
|
||||
apt install -y build-essential libcurl4-openssl-dev \
|
||||
libssl-dev libexpat-dev gettext python >/dev/null
|
||||
'
|
||||
;;
|
||||
linux-musl)
|
||||
apk add --update build-base curl-dev openssl-dev expat-dev gettext \
|
||||
pcre2-dev python3 musl-libintl perl-utils ncurses >/dev/null
|
||||
;;
|
||||
esac
|
||||
39
ci/lib.sh
39
ci/lib.sh
@@ -34,7 +34,7 @@ save_good_tree () {
|
||||
# successfully before (e.g. because the branch got rebased, changing only
|
||||
# the commit messages).
|
||||
skip_good_tree () {
|
||||
if test "$TRAVIS_DEBUG_MODE" = true
|
||||
if test "$TRAVIS_DEBUG_MODE" = true || test true = "$GITHUB_ACTIONS"
|
||||
then
|
||||
return
|
||||
fi
|
||||
@@ -79,6 +79,9 @@ check_unignored_build_artifacts ()
|
||||
}
|
||||
}
|
||||
|
||||
# GitHub Action doesn't set TERM, which is required by tput
|
||||
export TERM=${TERM:-dumb}
|
||||
|
||||
# Clear MAKEFLAGS that may come from the outside world.
|
||||
export MAKEFLAGS=
|
||||
|
||||
@@ -136,8 +139,32 @@ then
|
||||
MAKEFLAGS="$MAKEFLAGS --jobs=10"
|
||||
test windows_nt != "$CI_OS_NAME" ||
|
||||
GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS"
|
||||
elif test true = "$GITHUB_ACTIONS"
|
||||
then
|
||||
CI_TYPE=github-actions
|
||||
CI_BRANCH="$GITHUB_REF"
|
||||
CI_COMMIT="$GITHUB_SHA"
|
||||
CI_OS_NAME="$(echo "$RUNNER_OS" | tr A-Z a-z)"
|
||||
test macos != "$CI_OS_NAME" || CI_OS_NAME=osx
|
||||
CI_REPO_SLUG="$GITHUB_REPOSITORY"
|
||||
CI_JOB_ID="$GITHUB_RUN_ID"
|
||||
CC="${CC:-gcc}"
|
||||
|
||||
cache_dir="$HOME/none"
|
||||
|
||||
export GIT_PROVE_OPTS="--timer --jobs 10"
|
||||
export GIT_TEST_OPTS="--verbose-log -x"
|
||||
MAKEFLAGS="$MAKEFLAGS --jobs=10"
|
||||
test windows != "$CI_OS_NAME" ||
|
||||
GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS"
|
||||
|
||||
# https://github.com/actions/toolkit/blob/master/docs/commands.md#problem-matchers
|
||||
echo "::add-matcher::ci/git-problem-matcher.json"
|
||||
test linux-musl = "$jobname" ||
|
||||
MAKEFLAGS="$MAKEFLAGS TEST_SHELL_PATH=/bin/sh"
|
||||
else
|
||||
echo "Could not identify CI type" >&2
|
||||
env >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -189,9 +216,17 @@ osx-clang|osx-gcc)
|
||||
# Travis CI OS X
|
||||
export GIT_SKIP_TESTS="t9810 t9816"
|
||||
;;
|
||||
GIT_TEST_GETTEXT_POISON)
|
||||
GETTEXT_POISON)
|
||||
export GIT_TEST_GETTEXT_POISON=true
|
||||
;;
|
||||
Linux32)
|
||||
CC=gcc
|
||||
;;
|
||||
linux-musl)
|
||||
CC=gcc
|
||||
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3 USE_LIBPCRE2=Yes"
|
||||
MAKEFLAGS="$MAKEFLAGS NO_REGEX=Yes ICONV_OMITS_BOM=Yes"
|
||||
;;
|
||||
esac
|
||||
|
||||
MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
|
||||
|
||||
@@ -46,6 +46,13 @@ do
|
||||
mv "$trash_dir" failed-test-artifacts
|
||||
continue
|
||||
;;
|
||||
github-actions)
|
||||
mkdir -p failed-test-artifacts
|
||||
echo "::set-env name=FAILED_TEST_ARTIFACTS::t/failed-test-artifacts"
|
||||
cp "${TEST_EXIT%.exit}.out" failed-test-artifacts/
|
||||
tar czf failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir"
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
echo "Unhandled CI type: $CI_TYPE" >&2
|
||||
exit 1
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Build and test Git in a 32-bit environment
|
||||
# Build and test Git inside container
|
||||
#
|
||||
# Usage:
|
||||
# run-linux32-build.sh <host-user-id>
|
||||
# run-docker-build.sh <host-user-id>
|
||||
#
|
||||
|
||||
set -ex
|
||||
|
||||
if test $# -ne 1 || test -z "$1"
|
||||
then
|
||||
echo >&2 "usage: run-linux32-build.sh <host-user-id>"
|
||||
echo >&2 "usage: run-docker-build.sh <host-user-id>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update packages to the latest available versions
|
||||
linux32 --32bit i386 sh -c '
|
||||
apt update >/dev/null &&
|
||||
apt install -y build-essential libcurl4-openssl-dev libssl-dev \
|
||||
libexpat-dev gettext python >/dev/null
|
||||
'
|
||||
case "$jobname" in
|
||||
Linux32)
|
||||
switch_cmd="linux32 --32bit i386"
|
||||
;;
|
||||
linux-musl)
|
||||
switch_cmd=
|
||||
useradd () { adduser -D "$@"; }
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
"${0%/*}/install-docker-dependencies.sh"
|
||||
|
||||
# If this script runs inside a docker container, then all commands are
|
||||
# usually executed as root. Consequently, the host user might not be
|
||||
@@ -51,10 +59,17 @@ else
|
||||
fi
|
||||
|
||||
# Build and test
|
||||
linux32 --32bit i386 su -m -l $CI_USER -c '
|
||||
command $switch_cmd su -m -l $CI_USER -c "
|
||||
set -ex
|
||||
export DEVELOPER='$DEVELOPER'
|
||||
export DEFAULT_TEST_TARGET='$DEFAULT_TEST_TARGET'
|
||||
export GIT_PROVE_OPTS='$GIT_PROVE_OPTS'
|
||||
export GIT_TEST_OPTS='$GIT_TEST_OPTS'
|
||||
export GIT_TEST_CLONE_2GB='$GIT_TEST_CLONE_2GB'
|
||||
export MAKEFLAGS='$MAKEFLAGS'
|
||||
export cache_dir='$cache_dir'
|
||||
cd /usr/src/git
|
||||
test -n "$cache_dir" && ln -s "$cache_dir/.prove" t/.prove
|
||||
test -n '$cache_dir' && ln -s '$cache_dir/.prove' t/.prove
|
||||
make
|
||||
make test
|
||||
'
|
||||
"
|
||||
47
ci/run-docker.sh
Executable file
47
ci/run-docker.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Download and run Docker image to build and test Git
|
||||
#
|
||||
|
||||
. ${0%/*}/lib.sh
|
||||
|
||||
case "$jobname" in
|
||||
Linux32)
|
||||
CI_CONTAINER="daald/ubuntu32:xenial"
|
||||
;;
|
||||
linux-musl)
|
||||
CI_CONTAINER=alpine
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
docker pull "$CI_CONTAINER"
|
||||
|
||||
# Use the following command to debug the docker build locally:
|
||||
# <host-user-id> must be 0 if podman is used as drop-in replacement for docker
|
||||
# $ docker run -itv "${PWD}:/usr/src/git" --entrypoint /bin/sh "$CI_CONTAINER"
|
||||
# root@container:/# export jobname=<jobname>
|
||||
# root@container:/# /usr/src/git/ci/run-docker-build.sh <host-user-id>
|
||||
|
||||
container_cache_dir=/tmp/travis-cache
|
||||
|
||||
docker run \
|
||||
--interactive \
|
||||
--env DEVELOPER \
|
||||
--env DEFAULT_TEST_TARGET \
|
||||
--env GIT_PROVE_OPTS \
|
||||
--env GIT_TEST_OPTS \
|
||||
--env GIT_TEST_CLONE_2GB \
|
||||
--env MAKEFLAGS \
|
||||
--env jobname \
|
||||
--env cache_dir="$container_cache_dir" \
|
||||
--volume "${PWD}:/usr/src/git" \
|
||||
--volume "$cache_dir:$container_cache_dir" \
|
||||
"$CI_CONTAINER" \
|
||||
/usr/src/git/ci/run-docker-build.sh $(id -u $USER)
|
||||
|
||||
check_unignored_build_artifacts
|
||||
|
||||
save_good_tree
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Download and run Docker image to build and test 32-bit Git
|
||||
#
|
||||
|
||||
. ${0%/*}/lib.sh
|
||||
|
||||
docker pull daald/ubuntu32:xenial
|
||||
|
||||
# Use the following command to debug the docker build locally:
|
||||
# $ docker run -itv "${PWD}:/usr/src/git" --entrypoint /bin/bash daald/ubuntu32:xenial
|
||||
# root@container:/# /usr/src/git/ci/run-linux32-build.sh <host-user-id>
|
||||
|
||||
container_cache_dir=/tmp/travis-cache
|
||||
|
||||
docker run \
|
||||
--interactive \
|
||||
--env DEVELOPER \
|
||||
--env DEFAULT_TEST_TARGET \
|
||||
--env GIT_PROVE_OPTS \
|
||||
--env GIT_TEST_OPTS \
|
||||
--env GIT_TEST_CLONE_2GB \
|
||||
--env cache_dir="$container_cache_dir" \
|
||||
--volume "${PWD}:/usr/src/git" \
|
||||
--volume "$cache_dir:$container_cache_dir" \
|
||||
daald/ubuntu32:xenial \
|
||||
/usr/src/git/ci/run-linux32-build.sh $(id -u $USER)
|
||||
|
||||
check_unignored_build_artifacts
|
||||
|
||||
save_good_tree
|
||||
377
compat/mingw.c
377
compat/mingw.c
@@ -460,8 +460,19 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
|
||||
handle = CreateFileW(wfilename, FILE_APPEND_DATA,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||||
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return errno = err_win_to_posix(GetLastError()), -1;
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
DWORD err = GetLastError();
|
||||
/*
|
||||
* Some network storage solutions (e.g. Isilon) might return
|
||||
* ERROR_INVALID_PARAMETER instead of expected error
|
||||
* ERROR_PATH_NOT_FOUND, which results in a unknow error. If
|
||||
* so, the error is now forced to be an ERROR_PATH_NOT_FOUND
|
||||
* error instead.
|
||||
*/
|
||||
if (err == ERROR_INVALID_PARAMETER)
|
||||
err = ERROR_PATH_NOT_FOUND;
|
||||
return errno = err_win_to_posix(err), -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* No O_APPEND here, because the CRT uses it only to reset the
|
||||
@@ -964,7 +975,15 @@ revert_attrs:
|
||||
size_t mingw_strftime(char *s, size_t max,
|
||||
const char *format, const struct tm *tm)
|
||||
{
|
||||
size_t ret = strftime(s, max, format, tm);
|
||||
/* a pointer to the original strftime in case we can't find the UCRT version */
|
||||
static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime;
|
||||
size_t ret;
|
||||
DECLARE_PROC_ADDR(ucrtbase.dll, size_t, strftime, char *, size_t,
|
||||
const char *, const struct tm *);
|
||||
if (INIT_PROC_ADDR(strftime))
|
||||
ret = strftime(s, max, format, tm);
|
||||
else
|
||||
ret = fallback(s, max, format, tm);
|
||||
|
||||
if (!ret && errno == EINVAL)
|
||||
die("invalid strftime format: '%s'", format);
|
||||
@@ -980,11 +999,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;
|
||||
}
|
||||
@@ -1047,33 +1074,65 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
|
||||
{
|
||||
wchar_t wpath[MAX_PATH];
|
||||
HANDLE h;
|
||||
DWORD ret;
|
||||
int len;
|
||||
|
||||
if (xutftowcs_path(wpath, path) < 0)
|
||||
return NULL;
|
||||
|
||||
h = CreateFileW(wpath, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
ret = GetFinalPathNameByHandleW(h, wpath, ARRAY_SIZE(wpath), 0);
|
||||
CloseHandle(h);
|
||||
if (!ret || ret >= ARRAY_SIZE(wpath))
|
||||
return NULL;
|
||||
|
||||
len = wcslen(wpath) * 3;
|
||||
strbuf_grow(resolved, len);
|
||||
len = xwcstoutf(resolved->buf, normalize_ntpath(wpath), len);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
resolved->len = len;
|
||||
return resolved->buf;
|
||||
|
||||
}
|
||||
|
||||
char *mingw_getcwd(char *pointer, int len)
|
||||
{
|
||||
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
|
||||
DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
|
||||
HANDLE hnd;
|
||||
|
||||
if (!ret || ret >= ARRAY_SIZE(cwd)) {
|
||||
errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
|
||||
if (!ret && GetLastError() == ERROR_ACCESS_DENIED) {
|
||||
HANDLE hnd = CreateFileW(cwd, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (hnd == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
hnd = CreateFileW(cwd, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (hnd != INVALID_HANDLE_VALUE) {
|
||||
ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
|
||||
CloseHandle(hnd);
|
||||
if (!ret || ret >= ARRAY_SIZE(wpointer))
|
||||
return NULL;
|
||||
if (!ret || ret >= ARRAY_SIZE(wpointer)) {
|
||||
ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
|
||||
if (!ret || ret >= ARRAY_SIZE(wpointer)) {
|
||||
errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0)
|
||||
return NULL;
|
||||
return pointer;
|
||||
}
|
||||
if (!ret || ret >= ARRAY_SIZE(wpointer))
|
||||
return NULL;
|
||||
if (xwcstoutf(pointer, wpointer, len) < 0)
|
||||
if (xwcstoutf(pointer, cwd, len) < 0)
|
||||
return NULL;
|
||||
convert_slashes(pointer);
|
||||
return pointer;
|
||||
@@ -1479,6 +1538,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
|
||||
const char *(*quote_arg)(const char *arg) =
|
||||
is_msys2_sh(cmd ? cmd : *argv) ?
|
||||
quote_arg_msys2 : quote_arg_msvc;
|
||||
const char *strace_env;
|
||||
|
||||
/* Make sure to override previous errors, if any */
|
||||
errno = 0;
|
||||
@@ -1562,6 +1622,31 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
|
||||
free(quoted);
|
||||
}
|
||||
|
||||
strace_env = getenv("GIT_STRACE_COMMANDS");
|
||||
if (strace_env) {
|
||||
char *p = path_lookup("strace.exe", 1);
|
||||
if (!p)
|
||||
return error("strace not found!");
|
||||
if (xutftowcs_path(wcmd, p) < 0) {
|
||||
free(p);
|
||||
return -1;
|
||||
}
|
||||
free(p);
|
||||
if (!strcmp("1", strace_env) ||
|
||||
!strcasecmp("yes", strace_env) ||
|
||||
!strcasecmp("true", strace_env))
|
||||
strbuf_insert(&args, 0, "strace ", 7);
|
||||
else {
|
||||
const char *quoted = quote_arg(strace_env);
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addf(&buf, "strace -o %s ", quoted);
|
||||
if (quoted != strace_env)
|
||||
free((char *)quoted);
|
||||
strbuf_insert(&args, 0, buf.buf, buf.len);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
}
|
||||
|
||||
ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
|
||||
xutftowcs(wargs, args.buf, 2 * args.len + 1);
|
||||
strbuf_release(&args);
|
||||
@@ -1920,18 +2005,150 @@ static void ensure_socket_initialization(void)
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
static int winsock_error_to_errno(DWORD err)
|
||||
{
|
||||
switch (err) {
|
||||
case WSAEINTR: return EINTR;
|
||||
case WSAEBADF: return EBADF;
|
||||
case WSAEACCES: return EACCES;
|
||||
case WSAEFAULT: return EFAULT;
|
||||
case WSAEINVAL: return EINVAL;
|
||||
case WSAEMFILE: return EMFILE;
|
||||
case WSAEWOULDBLOCK: return EWOULDBLOCK;
|
||||
case WSAEINPROGRESS: return EINPROGRESS;
|
||||
case WSAEALREADY: return EALREADY;
|
||||
case WSAENOTSOCK: return ENOTSOCK;
|
||||
case WSAEDESTADDRREQ: return EDESTADDRREQ;
|
||||
case WSAEMSGSIZE: return EMSGSIZE;
|
||||
case WSAEPROTOTYPE: return EPROTOTYPE;
|
||||
case WSAENOPROTOOPT: return ENOPROTOOPT;
|
||||
case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT;
|
||||
case WSAEOPNOTSUPP: return EOPNOTSUPP;
|
||||
case WSAEAFNOSUPPORT: return EAFNOSUPPORT;
|
||||
case WSAEADDRINUSE: return EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL;
|
||||
case WSAENETDOWN: return ENETDOWN;
|
||||
case WSAENETUNREACH: return ENETUNREACH;
|
||||
case WSAENETRESET: return ENETRESET;
|
||||
case WSAECONNABORTED: return ECONNABORTED;
|
||||
case WSAECONNRESET: return ECONNRESET;
|
||||
case WSAENOBUFS: return ENOBUFS;
|
||||
case WSAEISCONN: return EISCONN;
|
||||
case WSAENOTCONN: return ENOTCONN;
|
||||
case WSAETIMEDOUT: return ETIMEDOUT;
|
||||
case WSAECONNREFUSED: return ECONNREFUSED;
|
||||
case WSAELOOP: return ELOOP;
|
||||
case WSAENAMETOOLONG: return ENAMETOOLONG;
|
||||
case WSAEHOSTUNREACH: return EHOSTUNREACH;
|
||||
case WSAENOTEMPTY: return ENOTEMPTY;
|
||||
/* No errno equivalent; default to EIO */
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
case WSAEPFNOSUPPORT:
|
||||
case WSAESHUTDOWN:
|
||||
case WSAETOOMANYREFS:
|
||||
case WSAEHOSTDOWN:
|
||||
case WSAEPROCLIM:
|
||||
case WSAEUSERS:
|
||||
case WSAEDQUOT:
|
||||
case WSAESTALE:
|
||||
case WSAEREMOTE:
|
||||
case WSASYSNOTREADY:
|
||||
case WSAVERNOTSUPPORTED:
|
||||
case WSANOTINITIALISED:
|
||||
case WSAEDISCON:
|
||||
case WSAENOMORE:
|
||||
case WSAECANCELLED:
|
||||
case WSAEINVALIDPROCTABLE:
|
||||
case WSAEINVALIDPROVIDER:
|
||||
case WSAEPROVIDERFAILEDINIT:
|
||||
case WSASYSCALLFAILURE:
|
||||
case WSASERVICE_NOT_FOUND:
|
||||
case WSATYPE_NOT_FOUND:
|
||||
case WSA_E_NO_MORE:
|
||||
case WSA_E_CANCELLED:
|
||||
case WSAEREFUSED:
|
||||
case WSAHOST_NOT_FOUND:
|
||||
case WSATRY_AGAIN:
|
||||
case WSANO_RECOVERY:
|
||||
case WSANO_DATA:
|
||||
case WSA_QOS_RECEIVERS:
|
||||
case WSA_QOS_SENDERS:
|
||||
case WSA_QOS_NO_SENDERS:
|
||||
case WSA_QOS_NO_RECEIVERS:
|
||||
case WSA_QOS_REQUEST_CONFIRMED:
|
||||
case WSA_QOS_ADMISSION_FAILURE:
|
||||
case WSA_QOS_POLICY_FAILURE:
|
||||
case WSA_QOS_BAD_STYLE:
|
||||
case WSA_QOS_BAD_OBJECT:
|
||||
case WSA_QOS_TRAFFIC_CTRL_ERROR:
|
||||
case WSA_QOS_GENERIC_ERROR:
|
||||
case WSA_QOS_ESERVICETYPE:
|
||||
case WSA_QOS_EFLOWSPEC:
|
||||
case WSA_QOS_EPROVSPECBUF:
|
||||
case WSA_QOS_EFILTERSTYLE:
|
||||
case WSA_QOS_EFILTERTYPE:
|
||||
case WSA_QOS_EFILTERCOUNT:
|
||||
case WSA_QOS_EOBJLENGTH:
|
||||
case WSA_QOS_EFLOWCOUNT:
|
||||
#ifndef _MSC_VER
|
||||
case WSA_QOS_EUNKNOWNPSOBJ:
|
||||
#endif
|
||||
case WSA_QOS_EPOLICYOBJ:
|
||||
case WSA_QOS_EFLOWDESC:
|
||||
case WSA_QOS_EPSFLOWSPEC:
|
||||
case WSA_QOS_EPSFILTERSPEC:
|
||||
case WSA_QOS_ESDMODEOBJ:
|
||||
case WSA_QOS_ESHAPERATEOBJ:
|
||||
case WSA_QOS_RESERVED_PETYPE:
|
||||
default: return EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* On Windows, `errno` is a global macro to a function call.
|
||||
* This makes it difficult to debug and single-step our mappings.
|
||||
*/
|
||||
static inline void set_wsa_errno(void)
|
||||
{
|
||||
DWORD wsa = WSAGetLastError();
|
||||
int e = winsock_error_to_errno(wsa);
|
||||
errno = e;
|
||||
|
||||
#ifdef DEBUG_WSA_ERRNO
|
||||
fprintf(stderr, "winsock error: %d -> %d\n", wsa, e);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int winsock_return(int ret)
|
||||
{
|
||||
if (ret < 0)
|
||||
set_wsa_errno();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define WINSOCK_RETURN(x) do { return winsock_return(x); } while (0)
|
||||
|
||||
#undef gethostname
|
||||
int mingw_gethostname(char *name, int namelen)
|
||||
{
|
||||
ensure_socket_initialization();
|
||||
return gethostname(name, namelen);
|
||||
ensure_socket_initialization();
|
||||
WINSOCK_RETURN(gethostname(name, namelen));
|
||||
}
|
||||
|
||||
#undef gethostbyname
|
||||
struct hostent *mingw_gethostbyname(const char *host)
|
||||
{
|
||||
struct hostent *ret;
|
||||
|
||||
ensure_socket_initialization();
|
||||
return gethostbyname(host);
|
||||
|
||||
ret = gethostbyname(host);
|
||||
if (!ret)
|
||||
set_wsa_errno();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef getaddrinfo
|
||||
@@ -1939,7 +2156,7 @@ int mingw_getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
ensure_socket_initialization();
|
||||
return getaddrinfo(node, service, hints, res);
|
||||
WINSOCK_RETURN(getaddrinfo(node, service, hints, res));
|
||||
}
|
||||
|
||||
int mingw_socket(int domain, int type, int protocol)
|
||||
@@ -1959,7 +2176,7 @@ int mingw_socket(int domain, int type, int protocol)
|
||||
* in errno so that _if_ someone looks up the code somewhere,
|
||||
* then it is at least the number that are usually listed.
|
||||
*/
|
||||
errno = WSAGetLastError();
|
||||
set_wsa_errno();
|
||||
return -1;
|
||||
}
|
||||
/* convert into a file descriptor */
|
||||
@@ -1975,35 +2192,35 @@ int mingw_socket(int domain, int type, int protocol)
|
||||
int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
|
||||
{
|
||||
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
|
||||
return connect(s, sa, sz);
|
||||
WINSOCK_RETURN(connect(s, sa, sz));
|
||||
}
|
||||
|
||||
#undef bind
|
||||
int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
|
||||
{
|
||||
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
|
||||
return bind(s, sa, sz);
|
||||
WINSOCK_RETURN(bind(s, sa, sz));
|
||||
}
|
||||
|
||||
#undef setsockopt
|
||||
int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
|
||||
{
|
||||
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
|
||||
return setsockopt(s, lvl, optname, (const char*)optval, optlen);
|
||||
WINSOCK_RETURN(setsockopt(s, lvl, optname, (const char*)optval, optlen));
|
||||
}
|
||||
|
||||
#undef shutdown
|
||||
int mingw_shutdown(int sockfd, int how)
|
||||
{
|
||||
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
|
||||
return shutdown(s, how);
|
||||
WINSOCK_RETURN(shutdown(s, how));
|
||||
}
|
||||
|
||||
#undef listen
|
||||
int mingw_listen(int sockfd, int backlog)
|
||||
{
|
||||
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
|
||||
return listen(s, backlog);
|
||||
WINSOCK_RETURN(listen(s, backlog));
|
||||
}
|
||||
|
||||
#undef accept
|
||||
@@ -2014,6 +2231,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
|
||||
SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
|
||||
SOCKET s2 = accept(s1, sa, sz);
|
||||
|
||||
if (s2 == INVALID_SOCKET) {
|
||||
set_wsa_errno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert into a file descriptor */
|
||||
if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
|
||||
int err = errno;
|
||||
@@ -2408,6 +2630,28 @@ pid_t waitpid(pid_t pid, int *status, int options)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mingw_is_mount_point(struct strbuf *path)
|
||||
{
|
||||
WIN32_FIND_DATAW findbuf = { 0 };
|
||||
HANDLE handle;
|
||||
wchar_t wfilename[MAX_PATH];
|
||||
int wlen = xutftowcs_path(wfilename, path->buf);
|
||||
if (wlen < 0)
|
||||
die(_("could not get long path for '%s'"), path->buf);
|
||||
|
||||
/* remove trailing slash, if any */
|
||||
if (wlen > 0 && wfilename[wlen - 1] == L'/')
|
||||
wfilename[--wlen] = L'\0';
|
||||
|
||||
handle = FindFirstFileW(wfilename, &findbuf);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
FindClose(handle);
|
||||
|
||||
return (findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||
(findbuf.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT);
|
||||
}
|
||||
|
||||
int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
|
||||
{
|
||||
int upos = 0, wpos = 0;
|
||||
@@ -2493,6 +2737,47 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef ENSURE_MSYSTEM_IS_SET
|
||||
static size_t append_system_bin_dirs(char *path, size_t size)
|
||||
{
|
||||
#if !defined(RUNTIME_PREFIX) || !defined(HAVE_WPGMPTR)
|
||||
return 0;
|
||||
#else
|
||||
char prefix[32768];
|
||||
const char *slash;
|
||||
size_t len = xwcstoutf(prefix, _wpgmptr, sizeof(prefix)), off = 0;
|
||||
|
||||
if (len == 0 || len >= sizeof(prefix) ||
|
||||
!(slash = find_last_dir_sep(prefix)))
|
||||
return 0;
|
||||
/* strip trailing `git.exe` */
|
||||
len = slash - prefix;
|
||||
|
||||
/* strip trailing `cmd` or `mingw64\bin` or `mingw32\bin` or `bin` or `libexec\git-core` */
|
||||
if (strip_suffix_mem(prefix, &len, "\\mingw64\\libexec\\git-core") ||
|
||||
strip_suffix_mem(prefix, &len, "\\mingw64\\bin"))
|
||||
off += xsnprintf(path + off, size - off,
|
||||
"%.*s\\mingw64\\bin;", (int)len, prefix);
|
||||
else if (strip_suffix_mem(prefix, &len, "\\mingw32\\libexec\\git-core") ||
|
||||
strip_suffix_mem(prefix, &len, "\\mingw32\\bin"))
|
||||
off += xsnprintf(path + off, size - off,
|
||||
"%.*s\\mingw32\\bin;", (int)len, prefix);
|
||||
else if (strip_suffix_mem(prefix, &len, "\\cmd") ||
|
||||
strip_suffix_mem(prefix, &len, "\\bin") ||
|
||||
strip_suffix_mem(prefix, &len, "\\libexec\\git-core"))
|
||||
off += xsnprintf(path + off, size - off,
|
||||
"%.*s\\mingw%d\\bin;", (int)len, prefix,
|
||||
(int)(sizeof(void *) * 8));
|
||||
else
|
||||
return 0;
|
||||
|
||||
off += xsnprintf(path + off, size - off,
|
||||
"%.*s\\usr\\bin;", (int)len, prefix);
|
||||
return off;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void setup_windows_environment(void)
|
||||
{
|
||||
char *tmp = getenv("TMPDIR");
|
||||
@@ -2544,6 +2829,37 @@ static void setup_windows_environment(void)
|
||||
if (!tmp && (tmp = getenv("USERPROFILE")))
|
||||
setenv("HOME", tmp, 1);
|
||||
}
|
||||
|
||||
if (!getenv("PLINK_PROTOCOL"))
|
||||
setenv("PLINK_PROTOCOL", "ssh", 0);
|
||||
|
||||
#ifdef ENSURE_MSYSTEM_IS_SET
|
||||
if (!(tmp = getenv("MSYSTEM")) || !tmp[0]) {
|
||||
const char *home = getenv("HOME"), *path = getenv("PATH");
|
||||
char buf[32768];
|
||||
size_t off = 0;
|
||||
|
||||
xsnprintf(buf, sizeof(buf),
|
||||
"MINGW%d", (int)(sizeof(void *) * 8));
|
||||
setenv("MSYSTEM", buf, 1);
|
||||
|
||||
if (home)
|
||||
off += xsnprintf(buf + off, sizeof(buf) - off,
|
||||
"%s\\bin;", home);
|
||||
off += append_system_bin_dirs(buf + off, sizeof(buf) - off);
|
||||
if (path)
|
||||
off += xsnprintf(buf + off, sizeof(buf) - off,
|
||||
"%s", path);
|
||||
else if (off > 0)
|
||||
buf[off - 1] = '\0';
|
||||
else
|
||||
buf[0] = '\0';
|
||||
setenv("PATH", buf, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!getenv("LC_ALL") && !getenv("LC_CTYPE") && !getenv("LANG"))
|
||||
setenv("LC_CTYPE", "C", 1);
|
||||
}
|
||||
|
||||
int is_valid_win32_path(const char *path, int allow_literal_nul)
|
||||
@@ -2581,12 +2897,14 @@ not_a_reserved_name:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 'c': case 'C': /* COM<N>, CON, CONIN$, CONOUT$ */
|
||||
case 'c': case 'C':
|
||||
/* COM1 ... COM9, CON, CONIN$, CONOUT$ */
|
||||
if ((c = path[++i]) != 'o' && c != 'O')
|
||||
goto not_a_reserved_name;
|
||||
c = path[++i];
|
||||
if (c == 'm' || c == 'M') { /* COM<N> */
|
||||
if (!isdigit(path[++i]))
|
||||
if (c == 'm' || c == 'M') { /* COM1 ... COM9 */
|
||||
c = path[++i];
|
||||
if (c < '1' || c > '9')
|
||||
goto not_a_reserved_name;
|
||||
} else if (c == 'n' || c == 'N') { /* CON */
|
||||
c = path[i + 1];
|
||||
@@ -2786,6 +3104,7 @@ int wmain(int argc, const wchar_t **wargv)
|
||||
#endif
|
||||
|
||||
maybe_redirect_std_handles();
|
||||
fsync_object_files = 1;
|
||||
|
||||
/* determine size of argv and environ conversion buffer */
|
||||
maxlen = wcslen(wargv[0]);
|
||||
|
||||
@@ -442,9 +442,15 @@ static inline void convert_slashes(char *path)
|
||||
if (*path == '\\')
|
||||
*path = '/';
|
||||
}
|
||||
struct strbuf;
|
||||
int mingw_is_mount_point(struct strbuf *path);
|
||||
#define is_mount_point mingw_is_mount_point
|
||||
#define CAN_UNLINK_MOUNT_POINTS 1
|
||||
#define PATH_SEP ';'
|
||||
char *mingw_query_user_email(void);
|
||||
#define query_user_email mingw_query_user_email
|
||||
char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path);
|
||||
#define platform_strbuf_realpath mingw_strbuf_realpath
|
||||
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
|
||||
#define PRIuMAX "I64u"
|
||||
#define PRId64 "I64d"
|
||||
|
||||
@@ -54,7 +54,8 @@ while (@ARGV) {
|
||||
# need to use that instead?
|
||||
foreach my $flag (@lflags) {
|
||||
if ($flag =~ /^-LIBPATH:(.*)/) {
|
||||
foreach my $l ("libcurl_imp.lib", "libcurl.lib") {
|
||||
my $libcurl = $is_debug ? "libcurl-d.lib" : "libcurl.lib";
|
||||
foreach my $l ("libcurl_imp.lib", $libcurl) {
|
||||
if (-f "$1/$l") {
|
||||
$lib = $l;
|
||||
last;
|
||||
|
||||
@@ -36,6 +36,13 @@ REM ================================================================
|
||||
|
||||
dir vcpkg\vcpkg.exe >nul 2>nul && GOTO :install_libraries
|
||||
|
||||
git.exe version 2>nul
|
||||
IF ERRORLEVEL 1 (
|
||||
echo "***"
|
||||
echo "Git not found. Please adjust your CMD path or Git install option."
|
||||
echo "***"
|
||||
EXIT /B 1 )
|
||||
|
||||
echo Fetching vcpkg in %cwd%vcpkg
|
||||
git.exe clone https://github.com/Microsoft/vcpkg vcpkg
|
||||
IF ERRORLEVEL 1 ( EXIT /B 1 )
|
||||
@@ -73,6 +80,12 @@ REM ================================================================
|
||||
:sub__install_one
|
||||
echo Installing package %1...
|
||||
|
||||
REM vcpkg may not be reliable on slow, intermittent or proxy
|
||||
REM connections, see e.g.
|
||||
REM https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/4a8f7be5-5e15-4213-a7bb-ddf424a954e6/winhttpsendrequest-ends-with-12002-errorhttptimeout-after-21-seconds-no-matter-what-timeout?forum=windowssdk
|
||||
REM which explains the hidden 21 second timeout
|
||||
REM (last post by Dave : Microsoft - Windows Networking team)
|
||||
|
||||
.\vcpkg.exe install %1:%arch%
|
||||
IF ERRORLEVEL 1 ( EXIT /B 1 )
|
||||
|
||||
|
||||
6
config.c
6
config.c
@@ -1662,9 +1662,11 @@ static int git_config_from_blob_ref(config_fn_t fn,
|
||||
|
||||
const char *git_etc_gitconfig(void)
|
||||
{
|
||||
static const char *system_wide;
|
||||
if (!system_wide)
|
||||
static char *system_wide;
|
||||
if (!system_wide) {
|
||||
system_wide = system_path(ETC_GITCONFIG);
|
||||
normalize_path_copy(system_wide, system_wide);
|
||||
}
|
||||
return system_wide;
|
||||
}
|
||||
|
||||
|
||||
@@ -424,6 +424,11 @@ ifeq ($(uname_S),Windows)
|
||||
NO_POSIX_GOODIES = UnfortunatelyYes
|
||||
NATIVE_CRLF = YesPlease
|
||||
DEFAULT_HELP_FORMAT = html
|
||||
ifeq (/mingw64,$(subst 32,64,$(prefix)))
|
||||
# Move system config into top-level /etc/
|
||||
ETC_GITCONFIG = ../etc/gitconfig
|
||||
ETC_GITATTRIBUTES = ../etc/gitattributes
|
||||
endif
|
||||
|
||||
CC = compat/vcbuild/scripts/clink.pl
|
||||
AR = compat/vcbuild/scripts/lib.pl
|
||||
@@ -434,7 +439,7 @@ ifeq ($(uname_S),Windows)
|
||||
compat/win32/pthread.o compat/win32/syslog.o \
|
||||
compat/win32/trace2_win32_process_info.o \
|
||||
compat/win32/dirent.o
|
||||
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
|
||||
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DENSURE_MSYSTEM_IS_SET -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
|
||||
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE
|
||||
# invalidcontinue.obj allows Git's source code to close the same file
|
||||
# handle twice, or to access the osfhandle of an already-closed stdout
|
||||
@@ -657,7 +662,7 @@ else
|
||||
endif
|
||||
CC = gcc
|
||||
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \
|
||||
-fstack-protector-strong
|
||||
-DENSURE_MSYSTEM_IS_SET -fstack-protector-strong
|
||||
EXTLIBS += -lntdll
|
||||
INSTALL = /bin/install
|
||||
NO_R_TO_GCC_LINKER = YesPlease
|
||||
@@ -665,10 +670,15 @@ else
|
||||
HAVE_LIBCHARSET_H = YesPlease
|
||||
NO_GETTEXT =
|
||||
USE_GETTEXT_SCHEME = fallthrough
|
||||
USE_LIBPCRE= YesPlease
|
||||
NO_LIBPCRE1_JIT = UnfortunatelyYes
|
||||
USE_LIBPCRE = YesPlease
|
||||
NO_CURL =
|
||||
USE_NED_ALLOCATOR = YesPlease
|
||||
NO_PYTHON =
|
||||
ifeq (/mingw64,$(subst 32,64,$(prefix)))
|
||||
# Move system config into top-level /etc/
|
||||
ETC_GITCONFIG = ../etc/gitconfig
|
||||
ETC_GITATTRIBUTES = ../etc/gitattributes
|
||||
endif
|
||||
else
|
||||
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO
|
||||
NO_CURL = YesPlease
|
||||
|
||||
@@ -25,14 +25,16 @@ ASCIIDOC_HTML = xhtml11
|
||||
ASCIIDOC_DOCBOOK = docbook
|
||||
ASCIIDOC_EXTRA =
|
||||
XMLTO = xmlto
|
||||
XMLTO_EXTRA =
|
||||
|
||||
ifdef USE_ASCIIDOCTOR
|
||||
ASCIIDOC = asciidoctor
|
||||
ASCIIDOC_CONF =
|
||||
ASCIIDOC_HTML = xhtml5
|
||||
ASCIIDOC_DOCBOOK = docbook45
|
||||
ASCIIDOC_DOCBOOK = docbook
|
||||
ASCIIDOC_EXTRA += -I../../Documentation -rasciidoctor-extensions
|
||||
ASCIIDOC_EXTRA += -alitdd='&\#x2d;&\#x2d;'
|
||||
XMLTO_EXTRA += --skip-validation
|
||||
endif
|
||||
|
||||
ifndef SHELL_PATH
|
||||
@@ -78,7 +80,7 @@ install-html: $(GIT_SUBTREE_HTML)
|
||||
$(INSTALL) -m 644 $^ $(DESTDIR)$(htmldir)
|
||||
|
||||
$(GIT_SUBTREE_DOC): $(GIT_SUBTREE_XML)
|
||||
$(XMLTO) -m $(MANPAGE_XSL) man $^
|
||||
$(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $^
|
||||
|
||||
$(GIT_SUBTREE_XML): $(GIT_SUBTREE_TXT)
|
||||
$(ASCIIDOC) -b $(ASCIIDOC_DOCBOOK) -d manpage $(ASCIIDOC_CONF) \
|
||||
|
||||
@@ -176,7 +176,7 @@ int credential_read(struct credential *c, FILE *fp)
|
||||
{
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
|
||||
while (strbuf_getline_lf(&line, fp) != EOF) {
|
||||
while (strbuf_getline(&line, fp) != EOF) {
|
||||
char *key = line.buf;
|
||||
char *value = strchr(key, '=');
|
||||
|
||||
|
||||
@@ -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 = first + ((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++;
|
||||
|
||||
@@ -389,10 +389,18 @@ static inline char *git_find_last_dir_sep(const char *path)
|
||||
#define find_last_dir_sep git_find_last_dir_sep
|
||||
#endif
|
||||
|
||||
#ifndef is_mount_point
|
||||
#define is_mount_point is_mount_point_via_stat
|
||||
#endif
|
||||
|
||||
#ifndef query_user_email
|
||||
#define query_user_email() NULL
|
||||
#endif
|
||||
|
||||
#ifndef platform_strbuf_realpath
|
||||
#define platform_strbuf_realpath(resolved, path) NULL
|
||||
#endif
|
||||
|
||||
#ifdef __TANDEM
|
||||
#include <floss.h(floss_execl,floss_execlp,floss_execv,floss_execvp)>
|
||||
#include <floss.h(floss_getpwuid)>
|
||||
|
||||
@@ -213,7 +213,7 @@ create_stash () {
|
||||
w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
|
||||
die "$(gettext "Cannot save the current worktree state")"
|
||||
|
||||
git diff-tree -p HEAD $w_tree -- >"$TMP-patch" &&
|
||||
git diff-tree -p -U1 HEAD $w_tree -- >"$TMP-patch" &&
|
||||
test -s "$TMP-patch" ||
|
||||
die "$(gettext "No changes selected")"
|
||||
|
||||
|
||||
@@ -354,6 +354,16 @@ proc parseviewrevs {view revs} {
|
||||
return $ret
|
||||
}
|
||||
|
||||
# Escapes a list of filter paths to be passed to git log via stdin. Note that
|
||||
# paths must not be quoted.
|
||||
proc escape_filter_paths {paths} {
|
||||
set escaped [list]
|
||||
foreach path $paths {
|
||||
lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path]
|
||||
}
|
||||
return $escaped
|
||||
}
|
||||
|
||||
# Start off a git log process and arrange to read its output
|
||||
proc start_rev_list {view} {
|
||||
global startmsecs commitidx viewcomplete curview
|
||||
@@ -406,14 +416,17 @@ proc start_rev_list {view} {
|
||||
if {$revs eq {}} {
|
||||
return 0
|
||||
}
|
||||
set args [concat $vflags($view) $revs]
|
||||
set args $vflags($view)
|
||||
} else {
|
||||
set revs {}
|
||||
set args $vorigargs($view)
|
||||
}
|
||||
|
||||
if {[catch {
|
||||
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
|
||||
--parents --boundary $args "--" $files] r]
|
||||
--parents --boundary $args --stdin \
|
||||
"<<[join [concat $revs "--" \
|
||||
[escape_filter_paths $files]] "\\n"]"] r]
|
||||
} err]} {
|
||||
error_popup "[mc "Error executing git log:"] $err"
|
||||
return 0
|
||||
@@ -555,13 +568,20 @@ proc updatecommits {} {
|
||||
set revs $newrevs
|
||||
set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
|
||||
}
|
||||
set args [concat $vflags($view) $revs --not $oldpos]
|
||||
set args $vflags($view)
|
||||
foreach r $oldpos {
|
||||
lappend revs "^$r"
|
||||
}
|
||||
} else {
|
||||
set revs {}
|
||||
set args $vorigargs($view)
|
||||
}
|
||||
if {[catch {
|
||||
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
|
||||
--parents --boundary $args "--" $vfilelimit($view)] r]
|
||||
--parents --boundary $args --stdin \
|
||||
"<<[join [concat $revs "--" \
|
||||
[escape_filter_paths \
|
||||
$vfilelimit($view)]] "\\n"]"] r]
|
||||
} err]} {
|
||||
error_popup "[mc "Error executing git log:"] $err"
|
||||
return
|
||||
@@ -10210,10 +10230,16 @@ proc getallcommits {} {
|
||||
foreach id $seeds {
|
||||
lappend ids "^$id"
|
||||
}
|
||||
lappend ids "--"
|
||||
}
|
||||
}
|
||||
if {$ids ne {}} {
|
||||
set fd [open [concat $cmd $ids] r]
|
||||
if {$ids eq "--all"} {
|
||||
set cmd [concat $cmd "--all"]
|
||||
} else {
|
||||
set cmd [concat $cmd --stdin "<<[join $ids "\\n"]"]
|
||||
}
|
||||
set fd [open $cmd r]
|
||||
fconfigure $fd -blocking 0
|
||||
incr allcommits
|
||||
nowbusy allcommits
|
||||
|
||||
26
http.c
26
http.c
@@ -158,7 +158,13 @@ static char *cached_accept_language;
|
||||
|
||||
static char *http_ssl_backend;
|
||||
|
||||
static int http_schannel_check_revoke = 1;
|
||||
static int http_schannel_check_revoke_mode =
|
||||
#ifdef CURLSSLOPT_REVOKE_BEST_EFFORT
|
||||
CURLSSLOPT_REVOKE_BEST_EFFORT;
|
||||
#else
|
||||
CURLSSLOPT_NO_REVOKE;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* With the backend being set to `schannel`, setting sslCAinfo would override
|
||||
* the Certificate Store in cURL v7.60.0 and later, which is not what we want
|
||||
@@ -323,7 +329,19 @@ static int http_options(const char *var, const char *value, void *cb)
|
||||
}
|
||||
|
||||
if (!strcmp("http.schannelcheckrevoke", var)) {
|
||||
http_schannel_check_revoke = git_config_bool(var, value);
|
||||
if (value && !strcmp(value, "best-effort")) {
|
||||
http_schannel_check_revoke_mode =
|
||||
#ifdef CURLSSLOPT_REVOKE_BEST_EFFORT
|
||||
CURLSSLOPT_REVOKE_BEST_EFFORT;
|
||||
#else
|
||||
CURLSSLOPT_NO_REVOKE;
|
||||
warning(_("%s=%s unsupported by current cURL"),
|
||||
var, value);
|
||||
#endif
|
||||
} else
|
||||
http_schannel_check_revoke_mode =
|
||||
(git_config_bool(var, value) ?
|
||||
0 : CURLSSLOPT_NO_REVOKE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -869,9 +887,9 @@ static CURL *get_curl_handle(void)
|
||||
#endif
|
||||
|
||||
if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
|
||||
!http_schannel_check_revoke) {
|
||||
http_schannel_check_revoke_mode) {
|
||||
#if LIBCURL_VERSION_NUM >= 0x072c00
|
||||
curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
|
||||
curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, http_schannel_check_revoke_mode);
|
||||
#else
|
||||
warning(_("CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0"));
|
||||
#endif
|
||||
|
||||
44
path.c
44
path.c
@@ -12,6 +12,7 @@
|
||||
#include "packfile.h"
|
||||
#include "object-store.h"
|
||||
#include "lockfile.h"
|
||||
#include "exec-cmd.h"
|
||||
|
||||
static int get_st_mode_bits(const char *path, int *mode)
|
||||
{
|
||||
@@ -732,6 +733,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;
|
||||
@@ -1289,6 +1294,45 @@ char *strip_path_suffix(const char *path, const char *suffix)
|
||||
return offset == -1 ? NULL : xstrndup(path, offset);
|
||||
}
|
||||
|
||||
int is_mount_point_via_stat(struct strbuf *path)
|
||||
{
|
||||
size_t len = path->len;
|
||||
unsigned int current_dev;
|
||||
struct stat st;
|
||||
|
||||
if (!strcmp("/", path->buf))
|
||||
return 1;
|
||||
|
||||
strbuf_addstr(path, "/.");
|
||||
if (lstat(path->buf, &st)) {
|
||||
/*
|
||||
* If we cannot access the current directory, we cannot say
|
||||
* that it is a bind mount.
|
||||
*/
|
||||
strbuf_setlen(path, len);
|
||||
return 0;
|
||||
}
|
||||
current_dev = st.st_dev;
|
||||
|
||||
/* Now look at the parent directory */
|
||||
strbuf_addch(path, '.');
|
||||
if (lstat(path->buf, &st)) {
|
||||
/*
|
||||
* If we cannot access the parent directory, we cannot say
|
||||
* that it is a bind mount.
|
||||
*/
|
||||
strbuf_setlen(path, len);
|
||||
return 0;
|
||||
}
|
||||
strbuf_setlen(path, len);
|
||||
|
||||
/*
|
||||
* If the device ID differs between current and parent directory,
|
||||
* then it is a bind mount.
|
||||
*/
|
||||
return current_dev != st.st_dev;
|
||||
}
|
||||
|
||||
int daemon_avoid_alias(const char *p)
|
||||
{
|
||||
int sl, ndot;
|
||||
|
||||
14
send-pack.c
14
send-pack.c
@@ -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 &&
|
||||
@@ -393,6 +403,8 @@ int send_pack(struct send_pack_args *args,
|
||||
const char *push_cert_nonce = NULL;
|
||||
struct packet_reader reader;
|
||||
|
||||
git_config(send_pack_config, NULL);
|
||||
|
||||
/* Does the other end support the reporting? */
|
||||
if (server_supports("report-status"))
|
||||
status_report = 1;
|
||||
@@ -400,7 +412,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;
|
||||
|
||||
@@ -67,7 +67,7 @@ static void unpack_sideband(void)
|
||||
case PACKET_READ_NORMAL:
|
||||
band = reader.line[0] & 0xff;
|
||||
if (band < 1 || band > 2)
|
||||
die("unexpected side band %d", band);
|
||||
continue; /* skip non-sideband packets */
|
||||
fd = band;
|
||||
|
||||
write_or_die(fd, reader.line + 1, reader.pktlen - 1);
|
||||
|
||||
@@ -395,7 +395,7 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' '
|
||||
# Tests for the hidden file attribute on windows
|
||||
is_hidden () {
|
||||
# Use the output of `attrib`, ignore the absolute path
|
||||
case "$(attrib "$1")" in *H*?:*) return 0;; esac
|
||||
case "$("$SYSTEMROOT"/system32/attrib "$1")" in *H*?:*) return 0;; esac
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
@@ -476,6 +476,7 @@ test_expect_success MINGW 'is_valid_path() on Windows' '
|
||||
C:\\git \
|
||||
comm \
|
||||
conout.c \
|
||||
com0.c \
|
||||
lptN \
|
||||
\
|
||||
--not \
|
||||
@@ -488,9 +489,48 @@ test_expect_success MINGW 'is_valid_path() on Windows' '
|
||||
"AUX.c" \
|
||||
"abc/conOut\$ .xyz/test" \
|
||||
lpt8 \
|
||||
com9.c \
|
||||
"lpt*" \
|
||||
Nul \
|
||||
"PRN./abc"
|
||||
'
|
||||
|
||||
test_expect_success MINGW 'MSYSTEM/PATH is adjusted if necessary' '
|
||||
mkdir -p "$HOME"/bin pretend/mingw64/bin \
|
||||
pretend/mingw64/libexec/git-core pretend/usr/bin &&
|
||||
cp "$GIT_EXEC_PATH"/git.exe pretend/mingw64/bin/ &&
|
||||
cp "$GIT_EXEC_PATH"/git.exe pretend/mingw64/libexec/git-core/ &&
|
||||
echo "env | grep MSYSTEM=" | write_script "$HOME"/bin/git-test-home &&
|
||||
echo "echo mingw64" | write_script pretend/mingw64/bin/git-test-bin &&
|
||||
echo "echo usr" | write_script pretend/usr/bin/git-test-bin2 &&
|
||||
|
||||
(
|
||||
MSYSTEM= &&
|
||||
GIT_EXEC_PATH= &&
|
||||
pretend/mingw64/libexec/git-core/git.exe test-home >actual &&
|
||||
pretend/mingw64/libexec/git-core/git.exe test-bin >>actual &&
|
||||
pretend/mingw64/bin/git.exe test-bin2 >>actual
|
||||
) &&
|
||||
test_write_lines MSYSTEM=$MSYSTEM mingw64 usr >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_lazy_prereq RUNTIME_PREFIX '
|
||||
test true = "$RUNTIME_PREFIX"
|
||||
'
|
||||
|
||||
test_lazy_prereq CAN_EXEC_IN_PWD '
|
||||
cp "$GIT_EXEC_PATH"/git$X ./ &&
|
||||
./git rev-parse
|
||||
'
|
||||
|
||||
test_expect_success RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' '
|
||||
mkdir -p pretend/git pretend/libexec/git-core &&
|
||||
echo "echo HERE" | write_script pretend/libexec/git-core/git-here &&
|
||||
cp "$GIT_EXEC_PATH"/git$X pretend/git/ &&
|
||||
GIT_EXEC_PATH= ./pretend/git/git here >actual &&
|
||||
echo HERE >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -423,4 +423,15 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
|
||||
git add "$downcased"
|
||||
'
|
||||
|
||||
test_expect_success MINGW 'can add files via NTFS junctions' '
|
||||
test_when_finished "cmd //c rmdir junction && rm -rf target" &&
|
||||
test_create_repo target &&
|
||||
cmd //c "mklink /j junction target" &&
|
||||
>target/via-junction &&
|
||||
git -C junction add "$(pwd)/junction/via-junction" &&
|
||||
echo via-junction >expect &&
|
||||
git -C target diff --cached --name-only >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -89,7 +89,7 @@ test_expect_success 'none of this moved HEAD' '
|
||||
verify_saved_head
|
||||
'
|
||||
|
||||
test_expect_failure 'stash -p with split hunk' '
|
||||
test_expect_success 'stash -p with split hunk' '
|
||||
git reset --hard &&
|
||||
cat >test <<-\EOF &&
|
||||
aaa
|
||||
@@ -106,8 +106,8 @@ test_expect_failure 'stash -p with split hunk' '
|
||||
ccc
|
||||
EOF
|
||||
printf "%s\n" s n y q |
|
||||
test_might_fail git stash -p 2>error &&
|
||||
! test_must_be_empty error &&
|
||||
git stash -p 2>error &&
|
||||
test_must_be_empty error &&
|
||||
grep "added line 1" test &&
|
||||
! grep "added line 2" test
|
||||
'
|
||||
|
||||
@@ -17,7 +17,7 @@ compare_diff () {
|
||||
# Compare blame output using the expectation for a diff as reference.
|
||||
# Only look for the lines coming from non-boundary commits.
|
||||
compare_blame () {
|
||||
sed -n -e "1,4d" -e "s/^\+//p" <"$1" >.tmp-1
|
||||
sed -n -e "1,4d" -e "s/^+//p" <"$1" >.tmp-1
|
||||
sed -ne "s/^[^^][^)]*) *//p" <"$2" >.tmp-2
|
||||
test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
|
||||
}
|
||||
|
||||
@@ -52,6 +52,13 @@ test_fix () {
|
||||
|
||||
# find touched lines
|
||||
$DIFF file target | sed -n -e "s/^> //p" >fixed
|
||||
# busybox's diff(1) doesn't output normal format
|
||||
if ! test -s fixed
|
||||
then
|
||||
$DIFF -u file target |
|
||||
grep -v '^+++ target' |
|
||||
sed -ne "/^+/s/+//p" >fixed
|
||||
fi
|
||||
|
||||
# the changed lines are all expected to change
|
||||
fixed_cnt=$(wc -l <fixed)
|
||||
|
||||
@@ -7,12 +7,12 @@ test_description='git archive --format=zip test'
|
||||
SUBSTFORMAT=%H%n
|
||||
|
||||
test_lazy_prereq UNZIP_SYMLINKS '
|
||||
(
|
||||
mkdir unzip-symlinks &&
|
||||
cd unzip-symlinks &&
|
||||
"$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip &&
|
||||
test -h symlink
|
||||
)
|
||||
"$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip &&
|
||||
test -h symlink
|
||||
'
|
||||
|
||||
test_lazy_prereq UNZIP_CONVERT '
|
||||
"$GIT_UNZIP" -a "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip
|
||||
'
|
||||
|
||||
check_zip() {
|
||||
@@ -39,33 +39,33 @@ check_zip() {
|
||||
extracted=${dir_with_prefix}a
|
||||
original=a
|
||||
|
||||
test_expect_success UNZIP " extract ZIP archive with EOL conversion" '
|
||||
test_expect_success UNZIP_CONVERT " extract ZIP archive with EOL conversion" '
|
||||
(mkdir $dir && cd $dir && "$GIT_UNZIP" -a ../$zipfile)
|
||||
'
|
||||
|
||||
test_expect_success UNZIP " validate that text files are converted" "
|
||||
test_expect_success UNZIP_CONVERT " validate that text files are converted" "
|
||||
test_cmp_bin $extracted/text.cr $extracted/text.crlf &&
|
||||
test_cmp_bin $extracted/text.cr $extracted/text.lf
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate that binary files are unchanged" "
|
||||
test_expect_success UNZIP_CONVERT " validate that binary files are unchanged" "
|
||||
test_cmp_bin $original/binary.cr $extracted/binary.cr &&
|
||||
test_cmp_bin $original/binary.crlf $extracted/binary.crlf &&
|
||||
test_cmp_bin $original/binary.lf $extracted/binary.lf
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate that diff files are converted" "
|
||||
test_expect_success UNZIP_CONVERT " validate that diff files are converted" "
|
||||
test_cmp_bin $extracted/diff.cr $extracted/diff.crlf &&
|
||||
test_cmp_bin $extracted/diff.cr $extracted/diff.lf
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate that -diff files are unchanged" "
|
||||
test_expect_success UNZIP_CONVERT " validate that -diff files are unchanged" "
|
||||
test_cmp_bin $original/nodiff.cr $extracted/nodiff.cr &&
|
||||
test_cmp_bin $original/nodiff.crlf $extracted/nodiff.crlf &&
|
||||
test_cmp_bin $original/nodiff.lf $extracted/nodiff.lf
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate that custom diff is unchanged " "
|
||||
test_expect_success UNZIP_CONVERT " validate that custom diff is unchanged " "
|
||||
test_cmp_bin $original/custom.cr $extracted/custom.cr &&
|
||||
test_cmp_bin $original/custom.crlf $extracted/custom.crlf &&
|
||||
test_cmp_bin $original/custom.lf $extracted/custom.lf
|
||||
|
||||
@@ -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
|
||||
'
|
||||
|
||||
@@ -95,7 +95,7 @@ test_expect_success 'clone -c remote.<remote>.fetch=<refspec> --origin=<name>' '
|
||||
# Tests for the hidden file attribute on windows
|
||||
is_hidden () {
|
||||
# Use the output of `attrib`, ignore the absolute path
|
||||
case "$(attrib "$1")" in *H*?:*) return 0;; esac
|
||||
case "$("$SYSTEMROOT"/system32/attrib "$1")" in *H*?:*) return 0;; esac
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ test_expect_success 'do partial clone 1' '
|
||||
test_expect_success 'verify that .promisor file contains refs fetched' '
|
||||
ls pc1/.git/objects/pack/pack-*.promisor >promisorlist &&
|
||||
test_line_count = 1 promisorlist &&
|
||||
git -C srv.bare rev-list HEAD >headhash &&
|
||||
git -C srv.bare rev-parse --verify HEAD >headhash &&
|
||||
grep "$(cat headhash) HEAD" $(cat promisorlist) &&
|
||||
grep "$(cat headhash) refs/heads/master" $(cat promisorlist)
|
||||
'
|
||||
|
||||
@@ -13,10 +13,7 @@ get_actual_refs () {
|
||||
}
|
||||
|
||||
get_actual_commits () {
|
||||
sed -n -e '/packfile/,/0000/{
|
||||
/packfile/d
|
||||
p
|
||||
}' <out | test-tool pkt-line unpack-sideband >o.pack &&
|
||||
test-tool pkt-line unpack-sideband <out >o.pack &&
|
||||
git index-pack o.pack &&
|
||||
git verify-pack -v o.idx >objs &&
|
||||
grep commit objs | cut -d" " -f1 | sort >actual_commits
|
||||
|
||||
@@ -230,7 +230,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
|
||||
|
||||
@@ -18,7 +18,7 @@ GIT_FORCE_UNTRACKED_CACHE=true
|
||||
export GIT_FORCE_UNTRACKED_CACHE
|
||||
|
||||
sync_mtime () {
|
||||
find . -type d -ls >/dev/null
|
||||
find . -type d -exec ls -ld {} + >/dev/null
|
||||
}
|
||||
|
||||
avoid_racy() {
|
||||
|
||||
@@ -746,4 +746,14 @@ test_expect_success 'clean untracked paths by pathspec' '
|
||||
test_must_be_empty actual
|
||||
'
|
||||
|
||||
test_expect_success MINGW 'clean does not traverse mount points' '
|
||||
mkdir target &&
|
||||
>target/dont-clean-me &&
|
||||
git init with-mountpoint &&
|
||||
cmd //c "mklink /j with-mountpoint\\mountpoint target" &&
|
||||
git -C with-mountpoint clean -dfx &&
|
||||
test_path_is_missing with-mountpoint/mountpoint &&
|
||||
test_path_is_file target/dont-clean-me
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -747,4 +747,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
|
||||
|
||||
@@ -905,7 +905,7 @@ test_expect_code () {
|
||||
# - not all diff versions understand "-u"
|
||||
|
||||
test_cmp() {
|
||||
$GIT_TEST_CMP "$@"
|
||||
eval "$GIT_TEST_CMP" '"$@"'
|
||||
}
|
||||
|
||||
# Check that the given config key has the expected value.
|
||||
|
||||
@@ -657,6 +657,18 @@ die () {
|
||||
fi
|
||||
}
|
||||
|
||||
file_lineno () {
|
||||
test -z "$GIT_TEST_FRAMEWORK_SELFTEST" && test -n "$BASH" || return 0
|
||||
local i
|
||||
for i in ${!BASH_SOURCE[*]}
|
||||
do
|
||||
case $i,"${BASH_SOURCE[$i]##*/}" in
|
||||
0,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:$LINENO: ${1+$1: }"; return;;
|
||||
*,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:${BASH_LINENO[$(($i-1))]}: ${1+$1: }"; return;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
GIT_EXIT_OK=
|
||||
trap 'die' EXIT
|
||||
# Disable '-x' tracing, because with some shells, notably dash, it
|
||||
@@ -702,7 +714,7 @@ test_failure_ () {
|
||||
write_junit_xml_testcase "$1" " $junit_insert"
|
||||
fi
|
||||
test_failure=$(($test_failure + 1))
|
||||
say_color error "not ok $test_count - $1"
|
||||
say_color error "$(file_lineno error)not ok $test_count - $1"
|
||||
shift
|
||||
printf '%s\n' "$*" | sed -e 's/^/# /'
|
||||
test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; }
|
||||
|
||||
@@ -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;
|
||||
@@ -474,10 +476,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)
|
||||
{
|
||||
@@ -514,6 +531,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
|
||||
@@ -547,6 +565,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;
|
||||
}
|
||||
|
||||
@@ -1020,6 +1044,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user