mirror of https://github.com/git/git.git
Merge branch 'js/azure-pipelines-msvc'
CI updates. * js/azure-pipelines-msvc: ci: also build and test with MS Visual Studio on Azure Pipelines ci: really use shallow clones on Azure Pipelines tests: let --immediate and --write-junit-xml play well together test-tool run-command: learn to run (parts of) the testsuite vcxproj: include more generated files vcxproj: only copy `git-remote-http.exe` once it was built msvc: work around a bug in GetEnvironmentVariable() msvc: handle DEVELOPER=1 msvc: ignore some libraries when linking compat/win32/path-utils.h: add #include guards winansi: use FLEX_ARRAY to avoid compiler warning msvc: avoid using minus operator on unsigned types push: do not pretend to return `int` from `die_push_simple()`
This commit is contained in:
commit
6d5291be45
4
Makefile
4
Makefile
|
@ -3042,6 +3042,10 @@ rpm::
|
||||||
@false
|
@false
|
||||||
.PHONY: rpm
|
.PHONY: rpm
|
||||||
|
|
||||||
|
ifneq ($(INCLUDE_DLLS_IN_ARTIFACTS),)
|
||||||
|
OTHER_PROGRAMS += $(shell echo *.dll t/helper/*.dll)
|
||||||
|
endif
|
||||||
|
|
||||||
artifacts-tar:: $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) \
|
artifacts-tar:: $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) \
|
||||||
GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
|
GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
|
||||||
$(MOFILES)
|
$(MOFILES)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
resources:
|
variables:
|
||||||
- repo: self
|
Agent.Source.Git.ShallowFetchDepth: 1
|
||||||
fetchDepth: 1
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: windows_build
|
- job: windows_build
|
||||||
|
@ -131,6 +130,165 @@ jobs:
|
||||||
PathtoPublish: t/failed-test-artifacts
|
PathtoPublish: t/failed-test-artifacts
|
||||||
ArtifactName: failed-test-artifacts
|
ArtifactName: failed-test-artifacts
|
||||||
|
|
||||||
|
- job: vs_build
|
||||||
|
displayName: Visual Studio Build
|
||||||
|
condition: succeeded()
|
||||||
|
pool: Hosted VS2017
|
||||||
|
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 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
|
||||||
|
- 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: Hosted
|
||||||
|
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 -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
|
- job: linux_clang
|
||||||
displayName: linux-clang
|
displayName: linux-clang
|
||||||
condition: succeeded()
|
condition: succeeded()
|
||||||
|
|
|
@ -143,8 +143,8 @@ static int push_url_of_remote(struct remote *remote, const char ***url_p)
|
||||||
return remote->url_nr;
|
return remote->url_nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NORETURN int die_push_simple(struct branch *branch,
|
static NORETURN void die_push_simple(struct branch *branch,
|
||||||
struct remote *remote)
|
struct remote *remote)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* There's no point in using shorten_unambiguous_ref here,
|
* There's no point in using shorten_unambiguous_ref here,
|
||||||
|
|
13
cache.h
13
cache.h
|
@ -748,6 +748,19 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na
|
||||||
*/
|
*/
|
||||||
int index_name_pos(const struct index_state *, const char *name, int namelen);
|
int index_name_pos(const struct index_state *, const char *name, int namelen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some functions return the negative complement of an insert position when a
|
||||||
|
* precise match was not found but a position was found where the entry would
|
||||||
|
* need to be inserted. This helper protects that logic from any integer
|
||||||
|
* underflow.
|
||||||
|
*/
|
||||||
|
static inline int index_pos_to_insert_pos(uintmax_t pos)
|
||||||
|
{
|
||||||
|
if (pos > INT_MAX)
|
||||||
|
die("overflow: -1 - %"PRIuMAX, pos);
|
||||||
|
return -1 - (int)pos;
|
||||||
|
}
|
||||||
|
|
||||||
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
|
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
|
||||||
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
|
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
|
||||||
#define ADD_CACHE_SKIP_DFCHECK 4 /* Ok to skip DF conflict checks */
|
#define ADD_CACHE_SKIP_DFCHECK 4 /* Ok to skip DF conflict checks */
|
||||||
|
|
|
@ -1665,6 +1665,8 @@ char *mingw_getenv(const char *name)
|
||||||
if (!w_key)
|
if (!w_key)
|
||||||
die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
|
die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
|
||||||
xutftowcs(w_key, name, len_key);
|
xutftowcs(w_key, name, len_key);
|
||||||
|
/* GetEnvironmentVariableW() only sets the last error upon failure */
|
||||||
|
SetLastError(ERROR_SUCCESS);
|
||||||
len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
|
len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
|
||||||
if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
||||||
free(w_key);
|
free(w_key);
|
||||||
|
|
|
@ -68,8 +68,54 @@ while (@ARGV) {
|
||||||
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
|
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
|
||||||
$arg =~ s/^-L/-LIBPATH:/;
|
$arg =~ s/^-L/-LIBPATH:/;
|
||||||
push(@lflags, $arg);
|
push(@lflags, $arg);
|
||||||
} elsif ("$arg" =~ /^-R/) {
|
} elsif ("$arg" =~ /^-[Rl]/) {
|
||||||
# eat
|
# eat
|
||||||
|
} elsif ("$arg" eq "-Werror") {
|
||||||
|
push(@cflags, "-WX");
|
||||||
|
} elsif ("$arg" eq "-Wall") {
|
||||||
|
# cl.exe understands -Wall, but it is really overzealous
|
||||||
|
push(@cflags, "-W4");
|
||||||
|
# disable the "signed/unsigned mismatch" warnings; our source code violates that
|
||||||
|
push(@cflags, "-wd4018");
|
||||||
|
push(@cflags, "-wd4245");
|
||||||
|
push(@cflags, "-wd4389");
|
||||||
|
# disable the "unreferenced formal parameter" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4100");
|
||||||
|
# disable the "conditional expression is constant" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4127");
|
||||||
|
# disable the "const object should be initialized" warning; these warnings affect only objects that are `static`
|
||||||
|
push(@cflags, "-wd4132");
|
||||||
|
# disable the "function/data pointer conversion in expression" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4152");
|
||||||
|
# disable the "non-constant aggregate initializer" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4204");
|
||||||
|
# disable the "cannot be initialized using address of automatic variable" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4221");
|
||||||
|
# disable the "possible loss of data" warnings; our source code violates that
|
||||||
|
push(@cflags, "-wd4244");
|
||||||
|
push(@cflags, "-wd4267");
|
||||||
|
# disable the "array is too small to include a terminating null character" warning; we ab-use strings to initialize OIDs
|
||||||
|
push(@cflags, "-wd4295");
|
||||||
|
# disable the "'<<': result of 32-bit shift implicitly converted to 64 bits" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4334");
|
||||||
|
# disable the "declaration hides previous local declaration" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4456");
|
||||||
|
# disable the "declaration hides function parameter" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4457");
|
||||||
|
# disable the "declaration hides global declaration" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4459");
|
||||||
|
# disable the "potentially uninitialized local variable '<name>' used" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4701");
|
||||||
|
# disable the "unreachable code" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4702");
|
||||||
|
# disable the "potentially uninitialized local pointer variable used" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4703");
|
||||||
|
# disable the "assignment within conditional expression" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4706");
|
||||||
|
# disable the "'inet_ntoa': Use inet_ntop() or InetNtop() instead" warning; our source code violates that
|
||||||
|
push(@cflags, "-wd4996");
|
||||||
|
} elsif ("$arg" =~ /^-W[a-z]/) {
|
||||||
|
# let's ignore those
|
||||||
} else {
|
} else {
|
||||||
push(@args, $arg);
|
push(@args, $arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef WIN32_PATH_UTILS_H
|
||||||
|
#define WIN32_PATH_UTILS_H
|
||||||
|
|
||||||
#define has_dos_drive_prefix(path) \
|
#define has_dos_drive_prefix(path) \
|
||||||
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
|
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
|
||||||
int win32_skip_dos_drive_prefix(char **path);
|
int win32_skip_dos_drive_prefix(char **path);
|
||||||
|
@ -18,3 +21,5 @@ static inline char *win32_find_last_dir_sep(const char *path)
|
||||||
#define find_last_dir_sep win32_find_last_dir_sep
|
#define find_last_dir_sep win32_find_last_dir_sep
|
||||||
int win32_offset_1st_component(const char *path);
|
int win32_offset_1st_component(const char *path);
|
||||||
#define offset_1st_component win32_offset_1st_component
|
#define offset_1st_component win32_offset_1st_component
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -546,7 +546,7 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
|
||||||
typedef struct _OBJECT_NAME_INFORMATION
|
typedef struct _OBJECT_NAME_INFORMATION
|
||||||
{
|
{
|
||||||
UNICODE_STRING Name;
|
UNICODE_STRING Name;
|
||||||
WCHAR NameBuffer[0];
|
WCHAR NameBuffer[FLEX_ARRAY];
|
||||||
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
|
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
|
||||||
|
|
||||||
#define ObjectNameInformation 1
|
#define ObjectNameInformation 1
|
||||||
|
|
|
@ -703,20 +703,24 @@ vcxproj:
|
||||||
perl contrib/buildsystems/generate -g Vcxproj
|
perl contrib/buildsystems/generate -g Vcxproj
|
||||||
git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj
|
git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj
|
||||||
|
|
||||||
# Generate the LinkOrCopyBuiltins.targets file
|
# Generate the LinkOrCopyBuiltins.targets and LinkOrCopyRemoteHttp.targets file
|
||||||
(echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \
|
(echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \
|
||||||
echo ' <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \
|
echo ' <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \
|
||||||
for name in $(BUILT_INS);\
|
for name in $(BUILT_INS);\
|
||||||
do \
|
do \
|
||||||
echo ' <Copy SourceFiles="$$(OutDir)\git.exe" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
|
echo ' <Copy SourceFiles="$$(OutDir)\git.exe" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
|
||||||
done && \
|
done && \
|
||||||
|
echo ' </Target>' && \
|
||||||
|
echo '</Project>') >git/LinkOrCopyBuiltins.targets
|
||||||
|
(echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \
|
||||||
|
echo ' <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \
|
||||||
for name in $(REMOTE_CURL_ALIASES); \
|
for name in $(REMOTE_CURL_ALIASES); \
|
||||||
do \
|
do \
|
||||||
echo ' <Copy SourceFiles="$$(OutDir)\'"$(REMOTE_CURL_PRIMARY)"'" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
|
echo ' <Copy SourceFiles="$$(OutDir)\'"$(REMOTE_CURL_PRIMARY)"'" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
|
||||||
done && \
|
done && \
|
||||||
echo ' </Target>' && \
|
echo ' </Target>' && \
|
||||||
echo '</Project>') >git/LinkOrCopyBuiltins.targets
|
echo '</Project>') >git-remote-http/LinkOrCopyRemoteHttp.targets
|
||||||
git add -f git/LinkOrCopyBuiltins.targets
|
git add -f git/LinkOrCopyBuiltins.targets git-remote-http/LinkOrCopyRemoteHttp.targets
|
||||||
|
|
||||||
# Add command-list.h
|
# Add command-list.h
|
||||||
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 command-list.h
|
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 command-list.h
|
||||||
|
@ -724,11 +728,10 @@ vcxproj:
|
||||||
|
|
||||||
# Add scripts
|
# Add scripts
|
||||||
rm -f perl/perl.mak
|
rm -f perl/perl.mak
|
||||||
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 \
|
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(SCRIPT_LIB) $(SCRIPTS)
|
||||||
$(SCRIPT_LIB) $(SCRIPT_SH_GEN) $(SCRIPT_PERL_GEN)
|
|
||||||
# Strip out the sane tool path, needed only for building
|
# Strip out the sane tool path, needed only for building
|
||||||
sed -i '/^git_broken_path_fix ".*/d' git-sh-setup
|
sed -i '/^git_broken_path_fix ".*/d' git-sh-setup
|
||||||
git add -f $(SCRIPT_LIB) $(SCRIPT_SH_GEN) $(SCRIPT_PERL_GEN)
|
git add -f $(SCRIPT_LIB) $(SCRIPTS)
|
||||||
|
|
||||||
# Add Perl module
|
# Add Perl module
|
||||||
$(MAKE) $(LIB_PERL_GEN)
|
$(MAKE) $(LIB_PERL_GEN)
|
||||||
|
@ -758,6 +761,10 @@ vcxproj:
|
||||||
$(MAKE) -C templates
|
$(MAKE) -C templates
|
||||||
git add -f templates/boilerplates.made templates/blt/
|
git add -f templates/boilerplates.made templates/blt/
|
||||||
|
|
||||||
|
# Add the translated messages
|
||||||
|
make MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(MOFILES)
|
||||||
|
git add -f $(MOFILES)
|
||||||
|
|
||||||
# Add build options
|
# Add build options
|
||||||
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 GIT-BUILD-OPTIONS
|
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 GIT-BUILD-OPTIONS
|
||||||
git add -f GIT-BUILD-OPTIONS
|
git add -f GIT-BUILD-OPTIONS
|
||||||
|
|
|
@ -278,6 +278,9 @@ EOM
|
||||||
if ($target eq 'git') {
|
if ($target eq 'git') {
|
||||||
print F " <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
|
print F " <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
|
||||||
}
|
}
|
||||||
|
if ($target eq 'git-remote-http') {
|
||||||
|
print F " <Import Project=\"LinkOrCopyRemoteHttp.targets\" />\n";
|
||||||
|
}
|
||||||
print F << "EOM";
|
print F << "EOM";
|
||||||
</Project>
|
</Project>
|
||||||
EOM
|
EOM
|
||||||
|
|
|
@ -1276,7 +1276,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
|
||||||
*/
|
*/
|
||||||
if (istate->cache_nr > 0 &&
|
if (istate->cache_nr > 0 &&
|
||||||
strcmp(ce->name, istate->cache[istate->cache_nr - 1]->name) > 0)
|
strcmp(ce->name, istate->cache[istate->cache_nr - 1]->name) > 0)
|
||||||
pos = -istate->cache_nr - 1;
|
pos = index_pos_to_insert_pos(istate->cache_nr);
|
||||||
else
|
else
|
||||||
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));
|
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));
|
||||||
|
|
||||||
|
@ -1915,7 +1915,7 @@ static size_t estimate_cache_size(size_t ondisk_size, unsigned int entries)
|
||||||
/*
|
/*
|
||||||
* Account for potential alignment differences.
|
* Account for potential alignment differences.
|
||||||
*/
|
*/
|
||||||
per_entry += align_padding_size(sizeof(struct cache_entry), -sizeof(struct ondisk_cache_entry));
|
per_entry += align_padding_size(per_entry, 0);
|
||||||
return ondisk_size + entries * per_entry;
|
return ondisk_size + entries * per_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ int sha1_pos(const unsigned char *hash, void *table, size_t nr,
|
||||||
if (miv < lov)
|
if (miv < lov)
|
||||||
return -1;
|
return -1;
|
||||||
if (hiv < miv)
|
if (hiv < miv)
|
||||||
return -1 - nr;
|
return index_pos_to_insert_pos(nr);
|
||||||
if (lov != hiv) {
|
if (lov != hiv) {
|
||||||
/*
|
/*
|
||||||
* At this point miv could be equal
|
* At this point miv could be equal
|
||||||
|
@ -97,7 +97,7 @@ int sha1_pos(const unsigned char *hash, void *table, size_t nr,
|
||||||
lo = mi + 1;
|
lo = mi + 1;
|
||||||
mi = lo + (hi - lo) / 2;
|
mi = lo + (hi - lo) / 2;
|
||||||
} while (lo < hi);
|
} while (lo < hi);
|
||||||
return -lo-1;
|
return index_pos_to_insert_pos(lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bsearch_hash(const unsigned char *sha1, const uint32_t *fanout_nbo,
|
int bsearch_hash(const unsigned char *sha1, const uint32_t *fanout_nbo,
|
||||||
|
|
|
@ -10,9 +10,14 @@
|
||||||
|
|
||||||
#include "test-tool.h"
|
#include "test-tool.h"
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
|
#include "cache.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
#include "argv-array.h"
|
#include "argv-array.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
#include "string-list.h"
|
||||||
|
#include "thread-utils.h"
|
||||||
|
#include "wildmatch.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
@ -50,11 +55,159 @@ static int task_finished(int result,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct testsuite {
|
||||||
|
struct string_list tests, failed;
|
||||||
|
int next;
|
||||||
|
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
|
||||||
|
};
|
||||||
|
#define TESTSUITE_INIT \
|
||||||
|
{ STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, -1, 0, 0, 0, 0, 0, 0 }
|
||||||
|
|
||||||
|
static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
|
||||||
|
void **task_cb)
|
||||||
|
{
|
||||||
|
struct testsuite *suite = cb;
|
||||||
|
const char *test;
|
||||||
|
if (suite->next >= suite->tests.nr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
test = suite->tests.items[suite->next++].string;
|
||||||
|
argv_array_pushl(&cp->args, "sh", test, NULL);
|
||||||
|
if (suite->quiet)
|
||||||
|
argv_array_push(&cp->args, "--quiet");
|
||||||
|
if (suite->immediate)
|
||||||
|
argv_array_push(&cp->args, "-i");
|
||||||
|
if (suite->verbose)
|
||||||
|
argv_array_push(&cp->args, "-v");
|
||||||
|
if (suite->verbose_log)
|
||||||
|
argv_array_push(&cp->args, "-V");
|
||||||
|
if (suite->trace)
|
||||||
|
argv_array_push(&cp->args, "-x");
|
||||||
|
if (suite->write_junit_xml)
|
||||||
|
argv_array_push(&cp->args, "--write-junit-xml");
|
||||||
|
|
||||||
|
strbuf_addf(err, "Output of '%s':\n", test);
|
||||||
|
*task_cb = (void *)test;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_finished(int result, struct strbuf *err, void *cb,
|
||||||
|
void *task_cb)
|
||||||
|
{
|
||||||
|
struct testsuite *suite = cb;
|
||||||
|
const char *name = (const char *)task_cb;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
string_list_append(&suite->failed, name);
|
||||||
|
|
||||||
|
strbuf_addf(err, "%s: '%s'\n", result ? "FAIL" : "SUCCESS", name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_failed(struct strbuf *out, void *cb, void *task_cb)
|
||||||
|
{
|
||||||
|
struct testsuite *suite = cb;
|
||||||
|
const char *name = (const char *)task_cb;
|
||||||
|
|
||||||
|
string_list_append(&suite->failed, name);
|
||||||
|
strbuf_addf(out, "FAILED TO START: '%s'\n", name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * const testsuite_usage[] = {
|
||||||
|
"test-run-command testsuite [<options>] [<pattern>...]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int testsuite(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
struct testsuite suite = TESTSUITE_INIT;
|
||||||
|
int max_jobs = 1, i, ret;
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *d;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_BOOL('i', "immediate", &suite.immediate,
|
||||||
|
"stop at first failed test case(s)"),
|
||||||
|
OPT_INTEGER('j', "jobs", &max_jobs, "run <N> jobs in parallel"),
|
||||||
|
OPT_BOOL('q', "quiet", &suite.quiet, "be terse"),
|
||||||
|
OPT_BOOL('v', "verbose", &suite.verbose, "be verbose"),
|
||||||
|
OPT_BOOL('V', "verbose-log", &suite.verbose_log,
|
||||||
|
"be verbose, redirected to a file"),
|
||||||
|
OPT_BOOL('x', "trace", &suite.trace, "trace shell commands"),
|
||||||
|
OPT_BOOL(0, "write-junit-xml", &suite.write_junit_xml,
|
||||||
|
"write JUnit-style XML files"),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
memset(&suite, 0, sizeof(suite));
|
||||||
|
suite.tests.strdup_strings = suite.failed.strdup_strings = 1;
|
||||||
|
|
||||||
|
argc = parse_options(argc, argv, NULL, options,
|
||||||
|
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
|
|
||||||
|
if (max_jobs <= 0)
|
||||||
|
max_jobs = online_cpus();
|
||||||
|
|
||||||
|
dir = opendir(".");
|
||||||
|
if (!dir)
|
||||||
|
die("Could not open the current directory");
|
||||||
|
while ((d = readdir(dir))) {
|
||||||
|
const char *p = d->d_name;
|
||||||
|
|
||||||
|
if (*p != 't' || !isdigit(p[1]) || !isdigit(p[2]) ||
|
||||||
|
!isdigit(p[3]) || !isdigit(p[4]) || p[5] != '-' ||
|
||||||
|
!ends_with(p, ".sh"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* No pattern: match all */
|
||||||
|
if (!argc) {
|
||||||
|
string_list_append(&suite.tests, p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
if (!wildmatch(argv[i], p, 0)) {
|
||||||
|
string_list_append(&suite.tests, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
if (!suite.tests.nr)
|
||||||
|
die("No tests match!");
|
||||||
|
if (max_jobs > suite.tests.nr)
|
||||||
|
max_jobs = suite.tests.nr;
|
||||||
|
|
||||||
|
fprintf(stderr, "Running %d tests (%d at a time)\n",
|
||||||
|
suite.tests.nr, max_jobs);
|
||||||
|
|
||||||
|
ret = run_processes_parallel(max_jobs, next_test, test_failed,
|
||||||
|
test_finished, &suite);
|
||||||
|
|
||||||
|
if (suite.failed.nr > 0) {
|
||||||
|
ret = 1;
|
||||||
|
fprintf(stderr, "%d tests failed:\n\n", suite.failed.nr);
|
||||||
|
for (i = 0; i < suite.failed.nr; i++)
|
||||||
|
fprintf(stderr, "\t%s\n", suite.failed.items[i].string);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_list_clear(&suite.tests, 0);
|
||||||
|
string_list_clear(&suite.failed, 0);
|
||||||
|
|
||||||
|
return !!ret;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd__run_command(int argc, const char **argv)
|
int cmd__run_command(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
struct child_process proc = CHILD_PROCESS_INIT;
|
struct child_process proc = CHILD_PROCESS_INIT;
|
||||||
int jobs;
|
int jobs;
|
||||||
|
|
||||||
|
if (argc > 1 && !strcmp(argv[1], "testsuite"))
|
||||||
|
exit(testsuite(argc - 1, argv + 1));
|
||||||
|
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
return 1;
|
return 1;
|
||||||
while (!strcmp(argv[1], "env")) {
|
while (!strcmp(argv[1], "env")) {
|
||||||
|
|
|
@ -572,6 +572,7 @@ export TERM
|
||||||
|
|
||||||
error () {
|
error () {
|
||||||
say_color error "error: $*"
|
say_color error "error: $*"
|
||||||
|
finalize_junit_xml
|
||||||
GIT_EXIT_OK=t
|
GIT_EXIT_OK=t
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
@ -700,7 +701,7 @@ test_failure_ () {
|
||||||
say_color error "not ok $test_count - $1"
|
say_color error "not ok $test_count - $1"
|
||||||
shift
|
shift
|
||||||
printf '%s\n' "$*" | sed -e 's/^/# /'
|
printf '%s\n' "$*" | sed -e 's/^/# /'
|
||||||
test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
|
test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
test_known_broken_ok_ () {
|
test_known_broken_ok_ () {
|
||||||
|
@ -1068,6 +1069,25 @@ write_junit_xml_testcase () {
|
||||||
junit_have_testcase=t
|
junit_have_testcase=t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finalize_junit_xml () {
|
||||||
|
if test -n "$write_junit_xml" && test -n "$junit_xml_path"
|
||||||
|
then
|
||||||
|
test -n "$junit_have_testcase" || {
|
||||||
|
junit_start=$(test-tool date getnanos)
|
||||||
|
write_junit_xml_testcase "all tests skipped"
|
||||||
|
}
|
||||||
|
|
||||||
|
# adjust the overall time
|
||||||
|
junit_time=$(test-tool date getnanos $junit_suite_start)
|
||||||
|
sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \
|
||||||
|
<"$junit_xml_path" >"$junit_xml_path.new"
|
||||||
|
mv "$junit_xml_path.new" "$junit_xml_path"
|
||||||
|
|
||||||
|
write_junit_xml " </testsuite>" "</testsuites>"
|
||||||
|
write_junit_xml=
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
test_atexit_cleanup=:
|
test_atexit_cleanup=:
|
||||||
test_atexit_handler () {
|
test_atexit_handler () {
|
||||||
# In a succeeding test script 'test_atexit_handler' is invoked
|
# In a succeeding test script 'test_atexit_handler' is invoked
|
||||||
|
@ -1090,21 +1110,7 @@ test_done () {
|
||||||
# removed, so the commands can access pidfiles and socket files.
|
# removed, so the commands can access pidfiles and socket files.
|
||||||
test_atexit_handler
|
test_atexit_handler
|
||||||
|
|
||||||
if test -n "$write_junit_xml" && test -n "$junit_xml_path"
|
finalize_junit_xml
|
||||||
then
|
|
||||||
test -n "$junit_have_testcase" || {
|
|
||||||
junit_start=$(test-tool date getnanos)
|
|
||||||
write_junit_xml_testcase "all tests skipped"
|
|
||||||
}
|
|
||||||
|
|
||||||
# adjust the overall time
|
|
||||||
junit_time=$(test-tool date getnanos $junit_suite_start)
|
|
||||||
sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \
|
|
||||||
<"$junit_xml_path" >"$junit_xml_path.new"
|
|
||||||
mv "$junit_xml_path.new" "$junit_xml_path"
|
|
||||||
|
|
||||||
write_junit_xml " </testsuite>" "</testsuites>"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test -z "$HARNESS_ACTIVE"
|
if test -z "$HARNESS_ACTIVE"
|
||||||
then
|
then
|
||||||
|
|
Loading…
Reference in New Issue