mirror of
https://github.com/git-for-windows/git.git
synced 2026-03-30 18:13:46 -05:00
Merge pull request #3960 from dscho/fix-vimdiff-with-spaces-in-paths
mergetool(vimdiff): allow paths to contain spaces again
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -4,7 +4,6 @@
|
||||
*.perl eol=lf diff=perl
|
||||
*.pl eof=lf diff=perl
|
||||
*.pm eol=lf diff=perl
|
||||
*.png binary
|
||||
*.py eol=lf diff=python
|
||||
*.bat eol=crlf
|
||||
CODE_OF_CONDUCT.md -whitespace
|
||||
|
||||
64
.github/ISSUE_TEMPLATE.md
vendored
64
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,64 +0,0 @@
|
||||
- [ ] I was not able to find an [open](https://github.com/git-for-windows/git/issues?q=is%3Aopen) or [closed](https://github.com/git-for-windows/git/issues?q=is%3Aclosed) issue matching what I'm seeing
|
||||
|
||||
### Setup
|
||||
|
||||
- Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
|
||||
|
||||
```
|
||||
$ git --version --build-options
|
||||
|
||||
** insert your machine's response here **
|
||||
```
|
||||
|
||||
- Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
|
||||
|
||||
```
|
||||
$ cmd.exe /c ver
|
||||
|
||||
** insert your machine's response here **
|
||||
```
|
||||
|
||||
- What options did you set as part of the installation? Or did you choose the
|
||||
defaults?
|
||||
|
||||
```
|
||||
# One of the following:
|
||||
> type "C:\Program Files\Git\etc\install-options.txt"
|
||||
> type "C:\Program Files (x86)\Git\etc\install-options.txt"
|
||||
> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt"
|
||||
> type "$env:USERPROFILE\AppData\Local\Programs\Git\etc\install-options.txt"
|
||||
$ cat /etc/install-options.txt
|
||||
|
||||
** insert your machine's response here **
|
||||
```
|
||||
|
||||
- Any other interesting things about your environment that might be related
|
||||
to the issue you're seeing?
|
||||
|
||||
** insert your response here **
|
||||
|
||||
### Details
|
||||
|
||||
- Which terminal/shell are you running Git from? e.g Bash/CMD/PowerShell/other
|
||||
|
||||
** insert your response here **
|
||||
|
||||
- What commands did you run to trigger this issue? If you can provide a
|
||||
[Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve)
|
||||
this will help us understand the issue.
|
||||
|
||||
```
|
||||
** insert your commands here **
|
||||
```
|
||||
- What did you expect to occur after running these commands?
|
||||
|
||||
** insert here **
|
||||
|
||||
- What actually happened instead?
|
||||
|
||||
** insert here **
|
||||
|
||||
- If the problem was occurring with a specific repository, can you provide the
|
||||
URL to that repository to help us with testing?
|
||||
|
||||
** insert URL here **
|
||||
20
.github/PULL_REQUEST_TEMPLATE.md
vendored
20
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,19 +1,7 @@
|
||||
Thanks for taking the time to contribute to Git!
|
||||
|
||||
Those seeking to contribute to the Git for Windows fork should see
|
||||
http://gitforwindows.org/#contribute on how to contribute Windows specific
|
||||
enhancements.
|
||||
|
||||
If your contribution is for the core Git functions and documentation
|
||||
please be aware that the Git community does not use the github.com issues
|
||||
or pull request mechanism for their contributions.
|
||||
|
||||
Instead, we use the Git mailing list (git@vger.kernel.org) for code and
|
||||
documentation submissions, code reviews, and bug reports. The
|
||||
mailing list is plain text only (anything with HTML is sent directly
|
||||
to the spam folder).
|
||||
|
||||
Nevertheless, you can use GitGitGadget (https://gitgitgadget.github.io/)
|
||||
Thanks for taking the time to contribute to Git! Please be advised that the
|
||||
Git community does not use github.com for their contributions. Instead, we use
|
||||
a mailing list (git@vger.kernel.org) for code submissions, code reviews, and
|
||||
bug reports. Nevertheless, you can use GitGitGadget (https://gitgitgadget.github.io/)
|
||||
to conveniently send your Pull Requests commits to our mailing list.
|
||||
|
||||
Please read the "guidelines for contributing" linked above!
|
||||
|
||||
10
.github/config.yml
vendored
10
.github/config.yml
vendored
@@ -1,10 +0,0 @@
|
||||
# Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot
|
||||
|
||||
# *Required* toxicity threshold between 0 and .99 with the higher numbers being
|
||||
# the most toxic. Anything higher than this threshold will be marked as toxic
|
||||
# and commented on
|
||||
sentimentBotToxicityThreshold: .7
|
||||
|
||||
# *Required* Comment to reply with
|
||||
sentimentBotReplyComment: >
|
||||
Please be sure to review the code of conduct and be respectful of other users. cc/ @git-for-windows/trusted-git-for-windows-developers
|
||||
514
.github/workflows/git-artifacts.yml
vendored
514
.github/workflows/git-artifacts.yml
vendored
@@ -1,514 +0,0 @@
|
||||
name: git-artifacts
|
||||
|
||||
on:
|
||||
# This workflow can be triggered manually in the Actions tab, see
|
||||
# https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_only:
|
||||
description: 'Optionally restrict what artifacts to build'
|
||||
required: false
|
||||
ref:
|
||||
description: 'Optionally override which branch to build'
|
||||
required: false
|
||||
repository:
|
||||
description: 'Optionally override from where to fetch the specified ref'
|
||||
required: false
|
||||
|
||||
env:
|
||||
GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback"
|
||||
HOME: "${{github.workspace}}\\home"
|
||||
MSYSTEM: MINGW64
|
||||
USERPROFILE: "${{github.workspace}}\\home"
|
||||
BUILD_ONLY: "${{github.event.inputs.build_only}}"
|
||||
REPOSITORY: "${{github.event.inputs.repository}}"
|
||||
REF: "${{github.event.inputs.ref}}"
|
||||
|
||||
jobs:
|
||||
bundle-artifacts:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Configure user
|
||||
shell: bash
|
||||
run:
|
||||
USER_NAME="${{github.actor}}" &&
|
||||
USER_EMAIL="${{github.actor}}@users.noreply.github.com" &&
|
||||
mkdir "$HOME" &&
|
||||
git config --global user.name "$USER_NAME" &&
|
||||
git config --global user.email "$USER_EMAIL" &&
|
||||
echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
with:
|
||||
flavor: build-installers
|
||||
- name: Clone build-extra
|
||||
shell: bash
|
||||
run: |
|
||||
d=/usr/src/build-extra &&
|
||||
if test ! -d $d/.git
|
||||
then
|
||||
git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d
|
||||
else
|
||||
git -C $d fetch https://github.com/git-for-windows/build-extra main &&
|
||||
git -C $d switch -C main FETCH_HEAD
|
||||
fi
|
||||
- name: Prepare home directory for GPG signing
|
||||
if: env.GPGKEY != ''
|
||||
shell: bash
|
||||
run: |
|
||||
echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import &&
|
||||
mkdir -p home &&
|
||||
git config --global gpg.program "/usr/src/build-extra/gnupg-with-gpgkey.sh" &&
|
||||
info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" &&
|
||||
git config --global user.name "${info% <*}" &&
|
||||
git config --global user.email "<${info#*<}"
|
||||
env:
|
||||
GPGKEY: ${{secrets.GPGKEY}}
|
||||
- name: Generate bundle artifacts
|
||||
env:
|
||||
GPGKEY: ${{secrets.GPGKEY}}
|
||||
shell: bash
|
||||
run: |
|
||||
printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "$@"\n' >/usr/bin/git &&
|
||||
mkdir -p bundle-artifacts &&
|
||||
|
||||
{ test -n "$REPOSITORY" || REPOSITORY='${{github.repository}}'; } &&
|
||||
{ test -n "$REF" || REF='${{github.ref}}'; } &&
|
||||
git -c init.defaultBranch=main init --bare &&
|
||||
git remote add -f origin https://github.com/git-for-windows/git &&
|
||||
git fetch "https://github.com/$REPOSITORY" "$REF:$REF" &&
|
||||
|
||||
tag_name="$(git describe --match 'v[0-9]*' FETCH_HEAD)-$(date +%Y%m%d%H%M%S)" &&
|
||||
echo "prerelease-${tag_name#v}" >bundle-artifacts/ver &&
|
||||
echo "${tag_name#v}" >bundle-artifacts/display_version &&
|
||||
echo "$tag_name" >bundle-artifacts/next_version &&
|
||||
git tag $(test -z "$GPGKEY" || echo " -s") -m "Snapshot build" "$tag_name" FETCH_HEAD &&
|
||||
git bundle create bundle-artifacts/git.bundle origin/main.."$tag_name" &&
|
||||
|
||||
sh -x /usr/src/build-extra/please.sh mention feature "Snapshot of $(git show -s --pretty='tformat:%h (%s, %ad)' --date=short FETCH_HEAD)" &&
|
||||
git -C /usr/src/build-extra bundle create "$PWD/bundle-artifacts/build-extra.bundle" origin/main..main
|
||||
- name: Clean up temporary files
|
||||
if: always()
|
||||
shell: bash
|
||||
run: rm -rf home
|
||||
- name: 'Publish Pipeline Artifact: bundle-artifacts'
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: bundle-artifacts
|
||||
path: bundle-artifacts
|
||||
pkg:
|
||||
runs-on: windows-latest
|
||||
needs: bundle-artifacts
|
||||
strategy:
|
||||
matrix:
|
||||
arch:
|
||||
- name: x86_64
|
||||
bitness: 64
|
||||
bin: /amd64
|
||||
- name: i686
|
||||
bitness: 32
|
||||
bin: ''
|
||||
steps:
|
||||
- name: Determine whether this job should be skipped
|
||||
shell: bash
|
||||
run: |
|
||||
for e in ${BUILD_ONLY:-pkg}
|
||||
do
|
||||
case $e in
|
||||
*-${{matrix.arch.name}}) exit 0;; # build this artifact
|
||||
*-arm64) test i686 != ${{matrix.arch.name}} || exit 0;; # pkg-i686 is required for the ARM64 version
|
||||
*-*) ;; # not this build artifact, keep looking
|
||||
*) exit 0;; # build this artifact
|
||||
esac
|
||||
done
|
||||
echo "SKIP=true" >>$GITHUB_ENV
|
||||
- name: Configure user
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run:
|
||||
USER_NAME="${{github.actor}}" &&
|
||||
USER_EMAIL="${{github.actor}}@users.noreply.github.com" &&
|
||||
mkdir "$HOME" &&
|
||||
git config --global user.name "$USER_NAME" &&
|
||||
git config --global user.email "$USER_EMAIL" &&
|
||||
echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
if: env.SKIP != 'true'
|
||||
with:
|
||||
flavor: build-installers
|
||||
- name: Download bundle-artifacts
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: bundle-artifacts
|
||||
path: bundle-artifacts
|
||||
- name: Clone and update build-extra
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
d=/usr/src/build-extra &&
|
||||
if test ! -d $d/.git
|
||||
then
|
||||
git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d
|
||||
else
|
||||
git -C $d fetch https://github.com/git-for-windows/build-extra main &&
|
||||
git -C $d switch -C main FETCH_HEAD
|
||||
fi &&
|
||||
git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main
|
||||
- name: Check out git/git
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
git -c init.defaultBranch=main init &&
|
||||
git remote add -f origin https://github.com/git-for-windows/git &&
|
||||
git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) &&
|
||||
git reset --hard $(cat bundle-artifacts/next_version)
|
||||
- name: Prepare home directory for code-signing
|
||||
env:
|
||||
CODESIGN_P12: ${{secrets.CODESIGN_P12}}
|
||||
CODESIGN_PASS: ${{secrets.CODESIGN_PASS}}
|
||||
if: env.SKIP != 'true' && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != ''
|
||||
shell: bash
|
||||
run: |
|
||||
cd home &&
|
||||
mkdir -p .sig &&
|
||||
echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >.sig/codesign.p12 &&
|
||||
echo -n "$CODESIGN_PASS" >.sig/codesign.pass
|
||||
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"'
|
||||
- name: Prepare home directory for GPG signing
|
||||
if: env.SKIP != 'true' && env.GPGKEY != ''
|
||||
shell: bash
|
||||
run: |
|
||||
echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import &&
|
||||
info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" &&
|
||||
git config --global user.name "${info% <*}" &&
|
||||
git config --global user.email "<${info#*<}"
|
||||
env:
|
||||
GPGKEY: ${{secrets.GPGKEY}}
|
||||
- name: Build mingw-w64-${{matrix.arch.name}}-git
|
||||
if: env.SKIP != 'true'
|
||||
env:
|
||||
GPGKEY: "${{secrets.GPGKEY}}"
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
|
||||
# Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw`
|
||||
printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "$@"\n' >/usr/bin/git &&
|
||||
|
||||
# Restrict `PATH` to MSYS2 and to Visual Studio (to let `cv2pdb` find the relevant DLLs)
|
||||
PATH="/mingw64/bin:/usr/bin:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}:/C/Windows/system32"
|
||||
|
||||
type -p mspdb140.dll || exit 1
|
||||
sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-${{matrix.arch.bitness}}-bit --build-src-pkg -o artifacts HEAD &&
|
||||
cp bundle-artifacts/ver artifacts/ &&
|
||||
if test -n "$GPGKEY"
|
||||
then
|
||||
for tar in artifacts/*.tar*
|
||||
do
|
||||
/usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar
|
||||
done
|
||||
fi &&
|
||||
|
||||
b=$PWD/artifacts &&
|
||||
version=$(cat bundle-artifacts/next_version) &&
|
||||
(cd /usr/src/MINGW-packages/mingw-w64-git &&
|
||||
cp PKGBUILD.$version PKGBUILD &&
|
||||
git commit -s -m "mingw-w64-git: new version ($version)" PKGBUILD &&
|
||||
git bundle create "$b"/MINGW-packages.bundle origin/main..main)
|
||||
- name: Clean up temporary files
|
||||
if: always() && env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: rm -rf home
|
||||
- name: Publish mingw-w64-${{matrix.arch.name}}-git
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: pkg-${{matrix.arch.name}}
|
||||
path: artifacts
|
||||
build-arm64:
|
||||
needs: bundle-artifacts
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Determine whether this job should be skipped
|
||||
shell: bash
|
||||
run: |
|
||||
for e in ${BUILD_ONLY:-pkg}
|
||||
do
|
||||
case $e in
|
||||
*-arm64) exit 0;; # build this artifact
|
||||
*-*) ;; # not this build artifact, keep looking
|
||||
*) exit 0;; # build this artifact
|
||||
esac
|
||||
done
|
||||
echo "SKIP=true" >>$GITHUB_ENV
|
||||
- name: Configure user
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run:
|
||||
USER_NAME="${{github.actor}}" &&
|
||||
USER_EMAIL="${{github.actor}}@users.noreply.github.com" &&
|
||||
mkdir -p "$HOME" &&
|
||||
git config --global user.name "$USER_NAME" &&
|
||||
git config --global user.email "$USER_EMAIL"
|
||||
- name: Download bundle-artifacts
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: bundle-artifacts
|
||||
path: bundle-artifacts
|
||||
- name: Check out git/git
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
git -c init.defaultBranch=main init &&
|
||||
git remote add -f origin https://github.com/git-for-windows/git &&
|
||||
git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) &&
|
||||
git reset --hard $(cat bundle-artifacts/next_version)
|
||||
- name: initialize vcpkg
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'microsoft/vcpkg'
|
||||
path: 'compat/vcbuild/vcpkg'
|
||||
- name: download vcpkg artifacts
|
||||
if: env.SKIP != 'true'
|
||||
uses: git-for-windows/get-azure-pipelines-artifact@v0
|
||||
with:
|
||||
repository: git/git
|
||||
definitionId: 9
|
||||
- name: add msbuild to PATH
|
||||
if: env.SKIP != 'true'
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
- name: copy dlls to root
|
||||
if: env.SKIP != 'true'
|
||||
shell: powershell
|
||||
run: |
|
||||
& compat\vcbuild\vcpkg_copy_dlls.bat release arm64-windows
|
||||
if (!$?) { exit(1) }
|
||||
- name: generate Visual Studio solution
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/arm64-windows \
|
||||
-DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON -DCMAKE_GENERATOR_PLATFORM=arm64 -DVCPKG_ARCH=arm64-windows \
|
||||
-DCMAKE_INSTALL_PREFIX="`pwd`/git-arm64" -DSKIP_DASHED_BUILT_INS=ON -DHOST_CPU=arm64
|
||||
- name: MSBuild
|
||||
if: env.SKIP != 'true'
|
||||
run: msbuild git.sln -property:Configuration=Release
|
||||
- name: Link the Git executables
|
||||
if: env.SKIP != 'true'
|
||||
run: msbuild INSTALL.vcxproj -property:Configuration=Release
|
||||
- name: upload build artifacts
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: arm64-artifacts
|
||||
path: ./git-arm64
|
||||
artifacts:
|
||||
runs-on: windows-latest
|
||||
needs: [pkg, build-arm64]
|
||||
strategy:
|
||||
matrix:
|
||||
artifact:
|
||||
- name: installer
|
||||
fileprefix: Git
|
||||
fileextension: exe
|
||||
- name: portable
|
||||
fileprefix: PortableGit
|
||||
fileextension: exe
|
||||
- name: archive
|
||||
fileprefix: Git
|
||||
fileextension: tar.bz2
|
||||
- name: mingit
|
||||
fileprefix: MinGit
|
||||
fileextension: zip
|
||||
- name: mingit-busybox
|
||||
fileprefix: MinGit
|
||||
fileextension: zip
|
||||
arch:
|
||||
- name: x86_64
|
||||
bitness: 64
|
||||
arm64: false
|
||||
- name: i686
|
||||
bitness: 32
|
||||
arm64: false
|
||||
- name: i686
|
||||
bitness: 32
|
||||
arm64: true
|
||||
fail-fast: false
|
||||
env:
|
||||
MSYSTEM: MINGW${{matrix.arch.bitness}}
|
||||
steps:
|
||||
- name: Determine whether this job should be skipped
|
||||
shell: bash
|
||||
run: |
|
||||
suffix=${{matrix.arch.name}}
|
||||
if test true = ${{matrix.arch.arm64}}
|
||||
then
|
||||
suffix=arm64
|
||||
fi
|
||||
case " $BUILD_ONLY " in
|
||||
' ') ;; # not set; build all
|
||||
*" ${{matrix.artifact.name}} "*|*" ${{matrix.artifact.name}}-$suffix "*) ;; # build this artifact
|
||||
*) echo "SKIP=true" >>$GITHUB_ENV;;
|
||||
esac
|
||||
- name: Download pkg-${{matrix.arch.name}}
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: pkg-${{matrix.arch.name}}
|
||||
path: pkg-${{matrix.arch.name}}
|
||||
- name: Download bundle-artifacts
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: bundle-artifacts
|
||||
path: bundle-artifacts
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
if: env.SKIP != 'true' && matrix.arch.bitness == '64'
|
||||
with:
|
||||
flavor: build-installers
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
if: env.SKIP != 'true' && matrix.arch.bitness == '32'
|
||||
with:
|
||||
flavor: build-installers
|
||||
architecture: i686
|
||||
- name: Download arm64 artifact
|
||||
if: env.SKIP != 'true' && matrix.arch.arm64 == true
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: arm64-artifacts
|
||||
path: ${{github.workspace}}/arm64
|
||||
# Workaround for Git Credential Manager Core on ARM64: https://github.com/git-for-windows/git/issues/3015
|
||||
- name: Create git-credential-manager-core wrapper for ARM64
|
||||
if: env.SKIP != 'true' && matrix.arch.arm64 == true
|
||||
shell: bash
|
||||
run: |
|
||||
printf '%s\n' '#!/bin/sh' 'exec /mingw32/libexec/git-core/git-credential-manager-core.exe "$@"' > arm64/libexec/git-core/git-credential-manager-core
|
||||
chmod +x arm64/libexec/git-core/git-credential-manager-core
|
||||
- name: Clone and update build-extra
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
d=/usr/src/build-extra &&
|
||||
if test ! -d $d/.git
|
||||
then
|
||||
git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d
|
||||
else
|
||||
git -C $d fetch https://github.com/git-for-windows/build-extra main &&
|
||||
git -C $d switch -C main FETCH_HEAD
|
||||
fi &&
|
||||
git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main
|
||||
- name: Prepare home directory for code-signing
|
||||
env:
|
||||
CODESIGN_P12: ${{secrets.CODESIGN_P12}}
|
||||
CODESIGN_PASS: ${{secrets.CODESIGN_PASS}}
|
||||
if: env.SKIP != 'true' && (matrix.artifact.name == 'installer' || matrix.artifact.name == 'portable') && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != ''
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p home/.sig &&
|
||||
echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >home/.sig/codesign.p12 &&
|
||||
echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass &&
|
||||
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"'
|
||||
- name: Build ${{matrix.arch.bitness}}-bit ${{matrix.artifact.name}}
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
if test "${{matrix.arch.arm64}}" = true
|
||||
then
|
||||
ARM64="--include-arm64-artifacts=\"$PWD/arm64\""
|
||||
else
|
||||
ARM64=
|
||||
fi
|
||||
|
||||
eval /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git $ARM64 --version=$(cat pkg-${{matrix.arch.name}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-[0-9]*.tar.xz --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-doc-html-[0-9]*.tar.xz &&
|
||||
if test portable = '${{matrix.artifact.name}}' && test -n "$(git config alias.signtool)"
|
||||
then
|
||||
git signtool artifacts/PortableGit-*.exe
|
||||
fi &&
|
||||
openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.${{matrix.artifact.fileextension}} | sed "s/.* //" >artifacts/sha-256.txt
|
||||
- name: Copy package-versions and pdbs
|
||||
if: env.SKIP != 'true' && matrix.artifact.name == 'installer'
|
||||
shell: bash
|
||||
run: |
|
||||
cp /usr/src/build-extra/installer/package-versions.txt artifacts/ &&
|
||||
|
||||
a=$PWD/artifacts &&
|
||||
p=$PWD/pkg-${{matrix.arch.name}} &&
|
||||
(cd /usr/src/build-extra &&
|
||||
mkdir -p cached-source-packages &&
|
||||
cp "$p"/*-pdb* cached-source-packages/ &&
|
||||
GIT_CONFIG_PARAMETERS="'windows.sdk${{matrix.arch.bitness}}.path='" ./please.sh bundle_pdbs --arch=${{matrix.arch.name}} --directory="$a" installer/package-versions.txt)
|
||||
- name: Clean up temporary files
|
||||
if: always() && env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: rm -rf home
|
||||
- name: Publish ${{matrix.artifact.name}}-${{matrix.arch.name}}
|
||||
if: env.SKIP != 'true' && matrix.arch.arm64 != true
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{matrix.artifact.name}}-${{matrix.arch.name}}
|
||||
path: artifacts
|
||||
- name: Publish ${{matrix.artifact.name}}-arm64
|
||||
if: env.SKIP != 'true' && matrix.arch.arm64 == true
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{matrix.artifact.name}}-arm64
|
||||
path: artifacts
|
||||
nuget:
|
||||
runs-on: windows-latest
|
||||
needs: pkg
|
||||
steps:
|
||||
- name: Determine whether this job should be skipped
|
||||
shell: bash
|
||||
run: |
|
||||
case " $BUILD_ONLY " in
|
||||
' ') ;; # not set; build all
|
||||
*" nuget "*) ;; # build this artifact
|
||||
*) echo "SKIP=true" >>$GITHUB_ENV;;
|
||||
esac
|
||||
- name: Download pkg-x86_64
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: pkg-x86_64
|
||||
path: pkg-x86_64
|
||||
- name: Download bundle-artifacts
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: bundle-artifacts
|
||||
path: bundle-artifacts
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
if: env.SKIP != 'true'
|
||||
with:
|
||||
flavor: build-installers
|
||||
- name: Clone and update build-extra
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
d=/usr/src/build-extra &&
|
||||
if test ! -d $d/.git
|
||||
then
|
||||
git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d
|
||||
else
|
||||
git -C $d fetch https://github.com/git-for-windows/build-extra main &&
|
||||
git -C $d switch -C main FETCH_HEAD
|
||||
fi &&
|
||||
git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main
|
||||
- uses: nuget/setup-nuget@v1
|
||||
if: env.SKIP != 'true'
|
||||
- name: Build 64-bit NuGet packages
|
||||
if: env.SKIP != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
/usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=$(cat pkg-x86_64/ver) -o artifacts --nuget --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz &&
|
||||
/usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=$(cat pkg-x86_64/ver) -o artifacts --nuget-mingit &&
|
||||
openssl dgst -sha256 artifacts/Git*.nupkg | sed "s/.* //" >artifacts/sha-256.txt
|
||||
- name: Publish nuget-x86_64
|
||||
if: env.SKIP != 'true'
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: nuget-x86_64
|
||||
path: artifacts
|
||||
27
.github/workflows/main.yml
vendored
27
.github/workflows/main.yml
vendored
@@ -137,9 +137,6 @@ jobs:
|
||||
NO_PERL: 1
|
||||
GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'"
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
||||
@@ -149,22 +146,26 @@ jobs:
|
||||
repository: 'microsoft/vcpkg'
|
||||
path: 'compat/vcbuild/vcpkg'
|
||||
- name: download vcpkg artifacts
|
||||
uses: git-for-windows/get-azure-pipelines-artifact@v0
|
||||
with:
|
||||
repository: git/git
|
||||
definitionId: 9
|
||||
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
|
||||
- name: copy dlls to root
|
||||
shell: cmd
|
||||
run: compat\vcbuild\vcpkg_copy_dlls.bat release ${{ matrix.arch }}-windows
|
||||
run: compat\vcbuild\vcpkg_copy_dlls.bat release
|
||||
- name: generate Visual Studio solution
|
||||
shell: bash
|
||||
run: |
|
||||
cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/${{ matrix.arch }}-windows \
|
||||
-DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON -DCMAKE_GENERATOR_PLATFORM=${{ matrix.arch }} -DVCPKG_ARCH=${{ matrix.arch }}-windows -DHOST_CPU=${{ matrix.arch }}
|
||||
cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/x64-windows \
|
||||
-DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON
|
||||
- name: MSBuild
|
||||
run: msbuild git.sln -property:Configuration=Release -property:Platform=${{ matrix.arch }} -maxCpuCount:4 -property:PlatformToolset=v142
|
||||
run: msbuild git.sln -property:Configuration=Release -property:Platform=x64 -maxCpuCount:4 -property:PlatformToolset=v142
|
||||
- name: bundle artifact tar
|
||||
shell: bash
|
||||
env:
|
||||
@@ -178,7 +179,7 @@ jobs:
|
||||
- name: upload tracked files and build artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: vs-artifacts-${{ matrix.arch }}
|
||||
name: vs-artifacts
|
||||
path: artifacts
|
||||
vs-test:
|
||||
name: win+VS test
|
||||
@@ -193,7 +194,7 @@ jobs:
|
||||
- name: download tracked files and build artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: vs-artifacts-x64
|
||||
name: vs-artifacts
|
||||
path: ${{github.workspace}}
|
||||
- name: extract tracked files and build artifacts
|
||||
shell: bash
|
||||
|
||||
86
.github/workflows/monitor-components.yml
vendored
86
.github/workflows/monitor-components.yml
vendored
@@ -1,86 +0,0 @@
|
||||
name: Monitor component updates
|
||||
|
||||
# Git for Windows is a slightly modified subset of MSYS2. Some of its
|
||||
# components are maintained by Git for Windows, others by MSYS2. To help
|
||||
# keeping the former up to date, this workflow monitors the Atom/RSS feeds
|
||||
# and opens new tickets for each new component version.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "23 8,11,14,17 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CHARACTER_LIMIT: 5000
|
||||
MAX_AGE: 48h
|
||||
|
||||
jobs:
|
||||
job:
|
||||
runs-on: ubuntu-latest
|
||||
environment: monitor-components
|
||||
strategy:
|
||||
matrix:
|
||||
component:
|
||||
- label: git
|
||||
feed: https://github.com/git/git/tags.atom
|
||||
- label: git-lfs
|
||||
feed: https://github.com/git-lfs/git-lfs/tags.atom
|
||||
- label: gcm-core
|
||||
feed: https://github.com/microsoft/git-credential-manager-core/tags.atom
|
||||
- label: tig
|
||||
feed: https://github.com/jonas/tig/tags.atom
|
||||
- label: cygwin
|
||||
feed: https://github.com/cygwin/cygwin/releases.atom
|
||||
title-pattern: ^(?!.*newlib)
|
||||
- label: msys2-runtime-package
|
||||
feed: https://github.com/msys2/MSYS2-packages/commits/master/msys2-runtime.atom
|
||||
- label: msys2-runtime
|
||||
feed: https://github.com/msys2/msys2-runtime/commits/HEAD.atom
|
||||
aggregate: true
|
||||
- label: openssh
|
||||
feed: https://github.com/openssh/openssh-portable/tags.atom
|
||||
- label: openssl
|
||||
feed: https://github.com/openssl/openssl/tags.atom
|
||||
title-pattern: ^(?!.*alpha)
|
||||
- label: gnutls
|
||||
feed: https://gnutls.org/news.atom
|
||||
- label: heimdal
|
||||
feed: https://github.com/heimdal/heimdal/tags.atom
|
||||
- label: git-sizer
|
||||
feed: https://github.com/github/git-sizer/tags.atom
|
||||
- label: gitflow
|
||||
feed: https://github.com/petervanderdoes/gitflow-avh/tags.atom
|
||||
- label: curl
|
||||
feed: https://github.com/curl/curl/tags.atom
|
||||
- label: libgpg-error
|
||||
feed: https://github.com/gpg/libgpg-error/releases.atom
|
||||
title-pattern: ^libgpg-error-[0-9\.]*$
|
||||
- label: libgcrypt
|
||||
feed: https://github.com/gpg/libgcrypt/releases.atom
|
||||
title-pattern: ^libgcrypt-[0-9\.]*$
|
||||
- label: gpg
|
||||
feed: https://github.com/gpg/gnupg/releases.atom
|
||||
- label: mintty
|
||||
feed: https://github.com/mintty/mintty/releases.atom
|
||||
- label: p7zip
|
||||
feed: https://sourceforge.net/projects/p7zip/rss?path=/p7zip
|
||||
- label: bash
|
||||
feed: https://git.savannah.gnu.org/cgit/bash.git/atom/?h=master
|
||||
aggregate: true
|
||||
- label: perl
|
||||
feed: https://github.com/Perl/perl5/tags.atom
|
||||
title-pattern: ^(?!.*(5\.[0-9]+[13579]|RC))
|
||||
- label: pcre2
|
||||
feed: https://github.com/PCRE2Project/pcre2/tags.atom
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: git-for-windows/rss-to-issues@v0
|
||||
with:
|
||||
feed: ${{matrix.component.feed}}
|
||||
prefix: "[New ${{matrix.component.label}} version]"
|
||||
labels: component-update
|
||||
github-token: ${{ secrets.MONITOR_COMPONENTS_PAT }}
|
||||
character-limit: ${{ env.CHARACTER_LIMIT }}
|
||||
max-age: ${{ env.MAX_AGE }}
|
||||
aggregate: ${{matrix.component.aggregate}}
|
||||
title-pattern: ${{matrix.component.title-pattern}}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -246,4 +246,3 @@ Release/
|
||||
/git.VC.db
|
||||
*.dSYM
|
||||
/contrib/buildsystems/out
|
||||
CMakeSettings.json
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Git for Windows Code of Conduct
|
||||
# Git Code of Conduct
|
||||
|
||||
This code of conduct outlines our expectations for participants within
|
||||
the **Git for Windows** community, as well as steps for reporting unacceptable
|
||||
behavior. We are committed to providing a welcoming and inspiring community
|
||||
for all and expect our code of conduct to be honored. Anyone who violates
|
||||
the Git community, as well as steps for reporting unacceptable behavior.
|
||||
We are committed to providing a welcoming and inspiring community for
|
||||
all and expect our code of conduct to be honored. Anyone who violates
|
||||
this code of conduct may be banned from the community.
|
||||
|
||||
## Our Pledge
|
||||
@@ -65,8 +65,8 @@ representative at an online or offline event.
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the Git for Windows maintainer or the community leaders
|
||||
responsible for enforcement at git@sfconservancy.org, or individually:
|
||||
reported to the community leaders responsible for enforcement at
|
||||
git@sfconservancy.org, or individually:
|
||||
|
||||
- Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||
- Christian Couder <christian.couder@gmail.com>
|
||||
|
||||
417
CONTRIBUTING.md
417
CONTRIBUTING.md
@@ -1,417 +0,0 @@
|
||||
How to Contribute to Git for Windows
|
||||
====================================
|
||||
|
||||
Git was originally designed for Unix systems and still today, all the build tools for the Git
|
||||
codebase assume you have standard Unix tools available in your path. If you have an open-source
|
||||
mindset and want to start contributing to Git, but primarily use a Windows machine, then you may
|
||||
have trouble getting started. This guide is for you.
|
||||
|
||||
Get the Source
|
||||
--------------
|
||||
|
||||
Clone the [GitForWindows repository on GitHub](https://github.com/git-for-windows/git).
|
||||
It is helpful to create your own fork for storing your development branches.
|
||||
|
||||
Windows uses different line endings than Unix systems. See
|
||||
[this GitHub article on working with line endings](https://help.github.com/articles/dealing-with-line-endings/#refreshing-a-repository-after-changing-line-endings)
|
||||
if you have trouble with line endings.
|
||||
|
||||
Build the Source
|
||||
----------------
|
||||
|
||||
First, download and install the latest [Git for Windows SDK (64-bit)](https://github.com/git-for-windows/build-extra/releases/latest).
|
||||
When complete, you can run the Git SDK, which creates a new Git Bash terminal window with
|
||||
the additional development commands, such as `make`.
|
||||
|
||||
As of time of writing, the SDK uses a different credential manager, so you may still want to use normal Git
|
||||
Bash for interacting with your remotes. Alternatively, use SSH rather than HTTPS and
|
||||
avoid credential manager problems.
|
||||
|
||||
You should now be ready to type `make` from the root of your `git` source directory.
|
||||
Here are some helpful variations:
|
||||
|
||||
* `make -j[N] DEVELOPER=1`: Compile new sources using up to N concurrent processes.
|
||||
The `DEVELOPER` flag turns on all warnings; code failing these warnings will not be
|
||||
accepted upstream ("upstream" = "the core Git project").
|
||||
* `make clean`: Delete all compiled files.
|
||||
|
||||
When running `make`, you can use `-j$(nproc)` to automatically use the number of processors
|
||||
on your machine as the number of concurrent build processes.
|
||||
|
||||
You can go deeper on the Windows-specific build process by reading the
|
||||
[technical overview](https://github.com/git-for-windows/git/wiki/Technical-overview) or the
|
||||
[guide to compiling Git with Visual Studio](https://github.com/git-for-windows/git/wiki/Compiling-Git-with-Visual-Studio).
|
||||
|
||||
## Building `git` on Windows with Visual Studio
|
||||
|
||||
The typical approach to building `git` is to use the standard `Makefile` with GCC, as
|
||||
above. Developers working in a Windows environment may want to instead build with the
|
||||
[Microsoft Visual C++ compiler and libraries toolset (MSVC)](https://blogs.msdn.microsoft.com/vcblog/2017/03/07/msvc-the-best-choice-for-windows/).
|
||||
There are a few benefits to using MSVC over GCC during your development, including creating
|
||||
symbols for debugging and [performance tracing](https://github.com/Microsoft/perfview#perfview-overview).
|
||||
|
||||
There are two ways to build Git for Windows using MSVC. Each have their own merits.
|
||||
|
||||
### Using SDK Command Line
|
||||
|
||||
Use one of the following commands from the SDK Bash window to build Git for Windows:
|
||||
|
||||
```
|
||||
make MSVC=1 -j12
|
||||
make MSVC=1 DEBUG=1 -j12
|
||||
```
|
||||
|
||||
The first form produces release-mode binaries; the second produces debug-mode binaries.
|
||||
Both forms produce PDB files and can be debugged. However, the first is best for perf
|
||||
tracing and the second is best for single-stepping.
|
||||
|
||||
You can then open Visual Studio and select File -> Open -> Project/Solution and select
|
||||
the compiled `git.exe` file. This creates a basic solution and you can use the debugging
|
||||
and performance tracing tools in Visual Studio to monitor a Git process. Use the Debug
|
||||
Properties page to set the working directory and command line arguments.
|
||||
|
||||
Be sure to clean up before switching back to GCC (or to switch between debug and
|
||||
release MSVC builds):
|
||||
|
||||
```
|
||||
make MSVC=1 -j12 clean
|
||||
make MSVC=1 DEBUG=1 -j12 clean
|
||||
```
|
||||
|
||||
### Using the IDE
|
||||
|
||||
If you prefer working in Visual Studio with a solution full of projects, then you can use
|
||||
CMake, either by letting Visual Studio configure it automatically (simply open Git's
|
||||
top-level directory via `File>Open>Folder...`) or by (downloading and) running
|
||||
[CMake](https://cmake.org) manually.
|
||||
|
||||
What to Change?
|
||||
---------------
|
||||
|
||||
Many new contributors ask: What should I start working on?
|
||||
|
||||
One way to win big with the open-source community is to look at the
|
||||
[issues page](https://github.com/git-for-windows/git/issues) and see if there are any issues that
|
||||
you can fix quickly, or if anything catches your eye.
|
||||
|
||||
You can also look at [the unofficial Chromium issues page](https://crbug.com/git) for
|
||||
multi-platform issues. You can look at recent user questions on
|
||||
[the Git mailing list](https://public-inbox.org/git).
|
||||
|
||||
Or you can "scratch your own itch", i.e. address an issue you have with Git. The team at Microsoft where the Git for Windows maintainer works, for example, is focused almost entirely on [improving performance](https://blogs.msdn.microsoft.com/devops/2018/01/11/microsofts-performance-contributions-to-git-in-2017/).
|
||||
We approach our work by finding something that is slow and try to speed it up. We start our
|
||||
investigation by reliably reproducing the slow behavior, then running that example using
|
||||
the MSVC build and tracing the results in PerfView.
|
||||
|
||||
You could also think of something you wish Git could do, and make it do that thing! The
|
||||
only concern I would have with this approach is whether or not that feature is something
|
||||
the community also wants. If this excites you though, go for it! Don't be afraid to
|
||||
[get involved in the mailing list](http://vger.kernel.org/vger-lists.html#git) early for
|
||||
feedback on the idea.
|
||||
|
||||
Test Your Changes
|
||||
-----------------
|
||||
|
||||
After you make your changes, it is important that you test your changes. Manual testing is
|
||||
important, but checking and extending the existing test suite is even more important. You
|
||||
want to run the functional tests to see if you broke something else during your change, and
|
||||
you want to extend the functional tests to be sure no one breaks your feature in the future.
|
||||
|
||||
### Functional Tests
|
||||
|
||||
Navigate to the `t/` directory and type `make` to run all tests or use `prove` as
|
||||
[described in the Git for Windows wiki](https://github.com/git-for-windows/git/wiki/Building-Git):
|
||||
|
||||
```
|
||||
prove -j12 --state=failed,save ./t[0-9]*.sh
|
||||
```
|
||||
|
||||
You can also run each test directly by running the corresponding shell script with a name
|
||||
like `tNNNN-descriptor.sh`.
|
||||
|
||||
If you are adding new functionality, you may need to create unit tests by creating
|
||||
helper commands that test a very limited action. These commands are stored in `t/helpers`.
|
||||
When adding a helper, be sure to add a line to `t/Makefile` and to the `.gitignore` for the
|
||||
binary file you add. The Git community prefers functional tests using the full `git`
|
||||
executable, so try to exercise your new code using `git` commands before creating a test
|
||||
helper.
|
||||
|
||||
To find out why a test failed, repeat the test with the `-x -v -d -i` options and then
|
||||
navigate to the appropriate "trash" directory to see the data shape that was used for the
|
||||
test failed step.
|
||||
|
||||
Read [`t/README`](t/README) for more details.
|
||||
|
||||
### Performance Tests
|
||||
|
||||
If you are working on improving performance, you will need to be acquainted with the
|
||||
performance tests in `t/perf`. There are not too many performance tests yet, but adding one
|
||||
as your first commit in a patch series helps to communicate the boost your change provides.
|
||||
|
||||
To check the change in performance across multiple versions of `git`, you can use the
|
||||
`t/perf/run` script. For example, to compare the performance of `git rev-list` across the
|
||||
`core/master` and `core/next` branches compared to a `topic` branch, you can run
|
||||
|
||||
```
|
||||
cd t/perf
|
||||
./run core/master core/next topic -- p0001-rev-list.sh
|
||||
```
|
||||
|
||||
You can also set certain environment variables to help test the performance on different
|
||||
repositories or with more repetitions. The full list is available in
|
||||
[the `t/perf/README` file](t/perf/README),
|
||||
but here are a few important ones:
|
||||
|
||||
```
|
||||
GIT_PERF_REPO=/path/to/repo
|
||||
GIT_PERF_LARGE_REPO=/path/to/large/repo
|
||||
GIT_PERF_REPEAT_COUNT=10
|
||||
```
|
||||
|
||||
When running the performance tests on Linux, you may see a message "Can't locate JSON.pm in
|
||||
@INC" and that means you need to run `sudo cpanm install JSON` to get the JSON perl package.
|
||||
|
||||
For running performance tests, it can be helpful to set up a few repositories with strange
|
||||
data shapes, such as:
|
||||
|
||||
**Many objects:** Clone repos such as [Kotlin](https://github.com/jetbrains/kotlin), [Linux](https://github.com/torvalds/linux), or [Android](https://source.android.com/setup/downloading).
|
||||
|
||||
**Many pack-files:** You can split a fresh clone into multiple pack-files of size at most
|
||||
16MB by running `git repack -adfF --max-pack-size=16m`. See the
|
||||
[`git repack` documentation](https://git-scm.com/docs/git-repack) for more information.
|
||||
You can count the number of pack-files using `ls .git/objects/pack/*.pack | wc -l`.
|
||||
|
||||
**Many loose objects:** If you already split your repository into multiple pack-files, then
|
||||
you can pick one to split into loose objects using `cat .git/objects/pack/[id].pack | git unpack-objects`;
|
||||
delete the `[id].pack` and `[id].idx` files after this. You can count the number of loose
|
||||
bjects using `ls .git/objects/??/* | wc -l`.
|
||||
|
||||
**Deep history:** Usually large repositories also have deep histories, but you can use the
|
||||
[test-many-commits-1m repo](https://github.com/cirosantilli/test-many-commits-1m/) to
|
||||
target deep histories without the overhead of many objects. One issue with this repository:
|
||||
there are no merge commits, so you will need to use a different repository to test a "wide"
|
||||
commit history.
|
||||
|
||||
**Large Index:** You can generate a large index and repo by using the scripts in
|
||||
`t/perf/repos`. There are two scripts. `many-files.sh` which will generate a repo with
|
||||
same tree and blobs but different paths. Using `many-files.sh -d 5 -w 10 -f 9` will create
|
||||
a repo with ~1 million entries in the index. `inflate-repo.sh` will use an existing repo
|
||||
and copy the current work tree until it is a specified size.
|
||||
|
||||
Test Your Changes on Linux
|
||||
--------------------------
|
||||
|
||||
It can be important to work directly on the [core Git codebase](https://github.com/git/git),
|
||||
such as a recent commit into the `master` or `next` branch that has not been incorporated
|
||||
into Git for Windows. Also, it can help to run functional and performance tests on your
|
||||
code in Linux before submitting patches to the mailing list, which focuses on many platforms.
|
||||
The differences between Windows and Linux are usually enough to catch most cross-platform
|
||||
issues.
|
||||
|
||||
### Using the Windows Subsystem for Linux
|
||||
|
||||
The [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
|
||||
allows you to [install Ubuntu Linux as an app](https://www.microsoft.com/en-us/store/p/ubuntu/9nblggh4msv6)
|
||||
that can run Linux executables on top of the Windows kernel. Internally,
|
||||
Linux syscalls are interpreted by the WSL, everything else is plain Ubuntu.
|
||||
|
||||
First, open WSL (either type "Bash" in Cortana, or execute "bash.exe" in a CMD window).
|
||||
Then install the prerequisites, and `git` for the initial clone:
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install git gcc make libssl-dev libcurl4-openssl-dev \
|
||||
libexpat-dev tcl tk gettext git-email zlib1g-dev
|
||||
```
|
||||
|
||||
Then, clone and build:
|
||||
|
||||
```
|
||||
git clone https://github.com/git-for-windows/git
|
||||
cd git
|
||||
git remote add -f upstream https://github.com/git/git
|
||||
make
|
||||
```
|
||||
|
||||
Be sure to clone into `/home/[user]/` and not into any folder under `/mnt/?/` or your build
|
||||
will fail due to colons in file names.
|
||||
|
||||
### Using a Linux Virtual Machine with Hyper-V
|
||||
|
||||
If you prefer, you can use a virtual machine (VM) to run Linux and test your changes in the
|
||||
full environment. The test suite runs a lot faster on Linux than on Windows or with the WSL.
|
||||
You can connect to the VM using an SSH terminal like
|
||||
[PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/).
|
||||
|
||||
The following instructions are for using Hyper-V, which is available in some versions of Windows.
|
||||
There are many virtual machine alternatives available, if you do not have such a version installed.
|
||||
|
||||
* [Download an Ubuntu Server ISO](https://www.ubuntu.com/download/server).
|
||||
* Open [Hyper-V Manager](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v).
|
||||
* [Set up a virtual switch](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/connect-to-network)
|
||||
so your VM can reach the network.
|
||||
* Select "Quick Create", name your machine, select the ISO as installation source, and un-check
|
||||
"This virtual machine will run Windows."
|
||||
* Go through the Ubuntu install process, being sure to select to install OpenSSH Server.
|
||||
* When install is complete, log in and check the SSH server status with `sudo service ssh status`.
|
||||
* If the service is not found, install with `sudo apt-get install openssh-server`.
|
||||
* If the service is not running, then use `sudo service ssh start`.
|
||||
* Use `shutdown -h now` to shutdown the VM, go to the Hyper-V settings for the VM, expand Network Adapter
|
||||
to select "Advanced Features", and set the MAC address to be static (this can save your VM from losing
|
||||
network if shut down incorrectly).
|
||||
* Provide as many cores to your VM as you can (for parallel builds).
|
||||
* Restart your VM, but do not connect.
|
||||
* Use `ssh` in Git Bash, download [PuTTY](http://www.putty.org/), or use your favorite SSH client to connect to the VM through SSH.
|
||||
|
||||
In order to build and use `git`, you will need the following libraries via `apt-get`:
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install git gcc make libssl-dev libcurl4-openssl-dev \
|
||||
libexpat-dev tcl tk gettext git-email zlib1g-dev
|
||||
```
|
||||
|
||||
To get your code from your Windows machine to the Linux VM, it is easiest to push the branch to your fork of Git and clone your fork in the Linux VM.
|
||||
|
||||
Don't forget to set your `git` config with your preferred name, email, and editor.
|
||||
|
||||
Polish Your Commits
|
||||
-------------------
|
||||
|
||||
Before submitting your patch, be sure to read the [coding guidelines](https://github.com/git/git/blob/master/Documentation/CodingGuidelines)
|
||||
and check your code to match as best you can. This can be a lot of effort, but it saves
|
||||
time during review to avoid style issues.
|
||||
|
||||
The other possibly major difference between the mailing list submissions and GitHub PR workflows
|
||||
is that each commit will be reviewed independently. Even if you are submitting a
|
||||
patch series with multiple commits, each commit must stand on it's own and be reviewable
|
||||
by itself. Make sure the commit message clearly explain the why of the commit not the how.
|
||||
Describe what is wrong with the current code and how your changes have made the code better.
|
||||
|
||||
When preparing your patch, it is important to put yourself in the shoes of the Git community.
|
||||
Accepting a patch requires more justification than approving a pull request from someone on
|
||||
your team. The community has a stable product and is responsible for keeping it stable. If
|
||||
you introduce a bug, then they cannot count on you being around to fix it. When you decided
|
||||
to start work on a new feature, they were not part of the design discussion and may not
|
||||
even believe the feature is worth introducing.
|
||||
|
||||
Questions to answer in your patch message (and commit messages) may include:
|
||||
* Why is this patch necessary?
|
||||
* How does the current behavior cause pain for users?
|
||||
* What kinds of repositories are necessary for noticing a difference?
|
||||
* What design options did you consider before writing this version? Do you have links to
|
||||
code for those alternate designs?
|
||||
* Is this a performance fix? Provide clear performance numbers for various well-known repos.
|
||||
|
||||
Here are some other tips that we use when cleaning up our commits:
|
||||
|
||||
* Commit messages should be wrapped at 76 columns per line (or less; 72 is also a
|
||||
common choice).
|
||||
* Make sure the commits are signed off using `git commit (-s|--signoff)`. See
|
||||
[SubmittingPatches](https://github.com/git/git/blob/v2.8.1/Documentation/SubmittingPatches#L234-L286)
|
||||
for more details about what this sign-off means.
|
||||
* Check for whitespace errors using `git diff --check [base]...HEAD` or `git log --check`.
|
||||
* Run `git rebase --whitespace=fix` to correct upstream issues with whitespace.
|
||||
* Become familiar with interactive rebase (`git rebase -i`) because you will be reordering,
|
||||
squashing, and editing commits as your patch or series of patches is reviewed.
|
||||
* Make sure any shell scripts that you add have the executable bit set on them. This is
|
||||
usually for test files that you add in the `/t` directory. You can use
|
||||
`git add --chmod=+x [file]` to update it. You can test whether a file is marked as executable
|
||||
using `git ls-files --stage \*.sh`; the first number is 100755 for executable files.
|
||||
* Your commit titles should match the "area: change description" format. Rules of thumb:
|
||||
* Choose "<area>: " prefix appropriately.
|
||||
* Keep the description short and to the point.
|
||||
* The word that follows the "<area>: " prefix is not capitalized.
|
||||
* Do not include a full-stop at the end of the title.
|
||||
* Read a few commit messages -- using `git log origin/master`, for instance -- to
|
||||
become acquainted with the preferred commit message style.
|
||||
* Build source using `make DEVELOPER=1` for extra-strict compiler warnings.
|
||||
|
||||
Submit Your Patch
|
||||
-----------------
|
||||
|
||||
Git for Windows [accepts pull requests on GitHub](https://github.com/git-for-windows/git/pulls), but
|
||||
these are reserved for Windows-specific improvements. For core Git, submissions are accepted on
|
||||
[the Git mailing list](https://public-inbox.org/git).
|
||||
|
||||
### Configure Git to Send Emails
|
||||
|
||||
There are a bunch of options for configuring the `git send-email` command. These options can
|
||||
be found in the documentation for
|
||||
[`git config`](https://git-scm.com/docs/git-config) and
|
||||
[`git send-email`](https://git-scm.com/docs/git-send-email).
|
||||
|
||||
```
|
||||
git config --global sendemail.smtpserver <smtp server>
|
||||
git config --global sendemail.smtpserverport 587
|
||||
git config --global sendemail.smtpencryption tls
|
||||
git config --global sendemail.smtpuser <email address>
|
||||
```
|
||||
|
||||
To avoid storing your password in the config file, store it in the Git credential manager:
|
||||
|
||||
```
|
||||
$ git credential fill
|
||||
protocol=smtp
|
||||
host=<stmp server>
|
||||
username=<email address>
|
||||
password=password
|
||||
```
|
||||
|
||||
Before submitting a patch, read the [Git documentation on submitting patches](https://github.com/git/git/blob/master/Documentation/SubmittingPatches).
|
||||
|
||||
To construct a patch set, use the `git format-patch` command. There are three important options:
|
||||
|
||||
* `--cover-letter`: If specified, create a `[v#-]0000-cover-letter.patch` file that can be
|
||||
edited to describe the patch as a whole. If you previously added a branch description using
|
||||
`git branch --edit-description`, you will end up with a 0/N mail with that description and
|
||||
a nice overall diffstat.
|
||||
* `--in-reply-to=[Message-ID]`: This will mark your cover letter as replying to the given
|
||||
message (which should correspond to your previous iteration). To determine the correct Message-ID,
|
||||
find the message you are replying to on [public-inbox.org/git](https://public-inbox.org/git) and take
|
||||
the ID from between the angle brackets.
|
||||
|
||||
* `--subject-prefix=[prefix]`: This defaults to [PATCH]. For subsequent iterations, you will want to
|
||||
override it like `--subject-prefix="[PATCH v2]"`. You can also use the `-v` option to have it
|
||||
automatically generate the version number in the patches.
|
||||
|
||||
If you have multiple commits and use the `--cover-letter` option be sure to open the
|
||||
`0000-cover-letter.patch` file to update the subject and add some details about the overall purpose
|
||||
of the patch series.
|
||||
|
||||
### Examples
|
||||
|
||||
To generate a single commit patch file:
|
||||
```
|
||||
git format-patch -s -o [dir] -1
|
||||
```
|
||||
To generate four patch files from the last three commits with a cover letter:
|
||||
```
|
||||
git format-patch --cover-letter -s -o [dir] HEAD~4
|
||||
```
|
||||
To generate version 3 with four patch files from the last four commits with a cover letter:
|
||||
```
|
||||
git format-patch --cover-letter -s -o [dir] -v 3 HEAD~4
|
||||
```
|
||||
|
||||
### Submit the Patch
|
||||
|
||||
Run [`git send-email`](https://git-scm.com/docs/git-send-email), starting with a test email:
|
||||
|
||||
```
|
||||
git send-email --to=yourself@address.com [dir with patches]/*.patch
|
||||
```
|
||||
|
||||
After checking the receipt of your test email, you can send to the list and to any
|
||||
potentially interested reviewers.
|
||||
|
||||
```
|
||||
git send-email --to=git@vger.kernel.org --cc=<email1> --cc=<email2> [dir with patches]/*.patch
|
||||
```
|
||||
|
||||
To submit a nth version patch (say version 3):
|
||||
|
||||
```
|
||||
git send-email --to=git@vger.kernel.org --cc=<email1> --cc=<email2> \
|
||||
--in-reply-to=<the message id of cover letter of patch v2> [dir with patches]/*.patch
|
||||
```
|
||||
@@ -503,8 +503,6 @@ include::config/safe.txt[]
|
||||
|
||||
include::config/sendemail.txt[]
|
||||
|
||||
include::config/sendpack.txt[]
|
||||
|
||||
include::config/sequencer.txt[]
|
||||
|
||||
include::config/showbranch.txt[]
|
||||
@@ -541,6 +539,4 @@ include::config/versionsort.txt[]
|
||||
|
||||
include::config/web.txt[]
|
||||
|
||||
include::config/windows.txt[]
|
||||
|
||||
include::config/worktree.txt[]
|
||||
|
||||
@@ -118,9 +118,6 @@ advice.*::
|
||||
waitingForEditor::
|
||||
Print a message to the terminal whenever Git is waiting for
|
||||
editor input from the user.
|
||||
nameTooLong::
|
||||
Advice shown if a filepath operation is attempted where the
|
||||
path was too long.
|
||||
nestedTag::
|
||||
Advice shown if a user attempts to recursively tag a tag object.
|
||||
submoduleAlternateErrorStrategyDie::
|
||||
@@ -139,7 +136,4 @@ advice.*::
|
||||
Advice shown when either linkgit:git-add[1] or linkgit:git-rm[1]
|
||||
is asked to update index entries outside the current sparse
|
||||
checkout.
|
||||
useCoreFSMonitorConfig::
|
||||
Advice shown if the deprecated 'core.useBuiltinFSMonitor' config
|
||||
setting is in use.
|
||||
--
|
||||
|
||||
@@ -655,19 +655,6 @@ relatively high IO latencies. When enabled, Git will do the
|
||||
index comparison to the filesystem data in parallel, allowing
|
||||
overlapping IO's. Defaults to true.
|
||||
|
||||
core.fscache::
|
||||
Enable additional caching of file system data for some operations.
|
||||
+
|
||||
Git for Windows uses this to bulk-read and cache lstat data of entire
|
||||
directories (instead of doing lstat file by file).
|
||||
|
||||
core.longpaths::
|
||||
Enable long path (> 260) support for builtin commands in Git for
|
||||
Windows. This is disabled by default, as long paths are not supported
|
||||
by Windows Explorer, cmd.exe and the Git for Windows tool chain
|
||||
(msys, bash, tcl, perl...). Only enable this if you know what you're
|
||||
doing and are prepared to live with a few quirks.
|
||||
|
||||
core.unsetenvvars::
|
||||
Windows-only: comma-separated list of environment variables'
|
||||
names that need to be unset before spawning any other process.
|
||||
|
||||
@@ -189,13 +189,11 @@ http.sslBackend::
|
||||
|
||||
http.schannelCheckRevoke::
|
||||
Used to enforce or disable certificate revocation checks in cURL
|
||||
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.
|
||||
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.
|
||||
|
||||
http.schannelUseSSLCAInfo::
|
||||
As of cURL v7.60.0, the Secure Channel backend can use the
|
||||
@@ -205,11 +203,6 @@ http.schannelUseSSLCAInfo::
|
||||
when the `schannel` backend was configured via `http.sslBackend`,
|
||||
unless `http.schannelUseSSLCAInfo` overrides this behavior.
|
||||
|
||||
http.sslAutoClientCert::
|
||||
As of cURL v7.77.0, the Secure Channel backend won't automatically
|
||||
send client certificates from the Windows Certificate Store anymore.
|
||||
To opt in to the old behavior, http.sslAutoClientCert can be set.
|
||||
|
||||
http.pinnedPubkey::
|
||||
Public key of the https service. It may either be the filename of
|
||||
a PEM or DER encoded public key file or a string starting with
|
||||
|
||||
@@ -40,9 +40,3 @@ which id the original user has.
|
||||
If that is not what you would prefer and want git to only trust
|
||||
repositories that are owned by root instead, then you can remove
|
||||
the `SUDO_UID` variable from root's environment before invoking git.
|
||||
+
|
||||
Due to the permission model on Windows where ACLs are used instead of
|
||||
Unix' simpler permission model, it can be a bit tricky to figure out why
|
||||
a directory is considered unsafe. To help with this, Git will provide
|
||||
more detailed information when the environment variable
|
||||
`GIT_TEST_DEBUG_UNSAFE_DIRECTORIES` is set to `true`.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
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.
|
||||
@@ -1,4 +0,0 @@
|
||||
windows.appendAtomically::
|
||||
By default, append atomic API is used on windows. But it works only with
|
||||
local disk files, if you're working on a network file system, you should
|
||||
set it false to turn it off.
|
||||
@@ -12,7 +12,6 @@ SYNOPSIS
|
||||
'git reset' [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]
|
||||
'git reset' (--patch | -p) [<tree-ish>] [--] [<pathspec>...]
|
||||
'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
|
||||
DEPRECATED: 'git reset' [-q] [--stdin [-z]] [<tree-ish>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -133,16 +132,6 @@ OPTIONS
|
||||
+
|
||||
For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
|
||||
|
||||
--stdin::
|
||||
DEPRECATED (use `--pathspec-from-file=-` instead): Instead of taking
|
||||
list of paths from the command line, read list of paths from the
|
||||
standard input. Paths are separated by LF (i.e. one path per line) by
|
||||
default.
|
||||
|
||||
-z::
|
||||
DEPRECATED (use `--pathspec-file-nul` instead): Only meaningful with
|
||||
`--stdin`; paths are separated with NUL character instead of LF.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
|
||||
@@ -443,14 +443,6 @@ Environment Variables
|
||||
---------------------
|
||||
Various Git commands use the following environment variables:
|
||||
|
||||
System
|
||||
~~~~~~
|
||||
`HOME`::
|
||||
Specifies the path to the user's home directory. On Windows, if
|
||||
unset, Git will set a process environment variable equal to:
|
||||
`$HOMEDRIVE$HOMEPATH` if both `$HOMEDRIVE` and `$HOMEPATH` exist;
|
||||
otherwise `$USERPROFILE` if `$USERPROFILE` exists.
|
||||
|
||||
The Git Repository
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
These environment variables apply to 'all' core Git commands. Nb: it
|
||||
|
||||
@@ -385,36 +385,6 @@ sign `$` upon checkout. Any byte sequence that begins with
|
||||
with `$Id$` upon check-in.
|
||||
|
||||
|
||||
`symlink`
|
||||
^^^^^^^^^
|
||||
|
||||
On Windows, symbolic links have a type: a "file symlink" must point at
|
||||
a file, and a "directory symlink" must point at a directory. If the
|
||||
type of symlink does not match its target, it doesn't work.
|
||||
|
||||
Git does not record the type of symlink in the index or in a tree. On
|
||||
checkout it'll guess the type, which only works if the target exists
|
||||
at the time the symlink is created. This may often not be the case,
|
||||
for example when the link points at a directory inside a submodule.
|
||||
|
||||
The `symlink` attribute allows you to explicitly set the type of symlink
|
||||
to `file` or `dir`, so Git doesn't have to guess. If you have a set of
|
||||
symlinks that point at other files, you can do:
|
||||
|
||||
------------------------
|
||||
*.gif symlink=file
|
||||
------------------------
|
||||
|
||||
To tell Git that a symlink points at a directory, use:
|
||||
|
||||
------------------------
|
||||
tools_folder symlink=dir
|
||||
------------------------
|
||||
|
||||
The `symlink` attribute is ignored on platforms other than Windows,
|
||||
since they don't distinguish between different types of symlinks.
|
||||
|
||||
|
||||
`filter`
|
||||
^^^^^^^^
|
||||
|
||||
|
||||
14
Makefile
14
Makefile
@@ -715,7 +715,6 @@ TEST_BUILTINS_OBJS += test-advise.o
|
||||
TEST_BUILTINS_OBJS += test-bitmap.o
|
||||
TEST_BUILTINS_OBJS += test-bloom.o
|
||||
TEST_BUILTINS_OBJS += test-chmtime.o
|
||||
TEST_BUILTINS_OBJS += test-cmp.o
|
||||
TEST_BUILTINS_OBJS += test-config.o
|
||||
TEST_BUILTINS_OBJS += test-crontab.o
|
||||
TEST_BUILTINS_OBJS += test-csprng.o
|
||||
@@ -738,7 +737,6 @@ TEST_BUILTINS_OBJS += test-hash-speed.o
|
||||
TEST_BUILTINS_OBJS += test-hash.o
|
||||
TEST_BUILTINS_OBJS += test-hashmap.o
|
||||
TEST_BUILTINS_OBJS += test-hexdump.o
|
||||
TEST_BUILTINS_OBJS += test-iconv.o
|
||||
TEST_BUILTINS_OBJS += test-index-version.o
|
||||
TEST_BUILTINS_OBJS += test-json-writer.o
|
||||
TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
|
||||
@@ -2656,13 +2654,6 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
|
||||
compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null
|
||||
endif
|
||||
|
||||
headless-git.o: compat/win32/headless.c GIT-CFLAGS
|
||||
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
|
||||
-fno-stack-protector -o $@ -c -Wall -Wwrite-strings $<
|
||||
|
||||
headless-git$X: headless-git.o git.res GIT-LDFLAGS
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -mwindows -o $@ $< git.res
|
||||
|
||||
git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
||||
|
||||
@@ -3419,7 +3410,6 @@ clean: profile-clean coverage-clean cocciclean
|
||||
$(RM) po/git.pot po/git-core.pot
|
||||
$(RM) *.res
|
||||
$(RM) $(OBJECTS)
|
||||
$(RM) headless-git.o
|
||||
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
|
||||
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
|
||||
$(RM) $(TEST_PROGRAMS)
|
||||
@@ -3449,17 +3439,13 @@ endif
|
||||
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
|
||||
ifdef MSVC
|
||||
$(RM) $(patsubst %.o,%.o.pdb,$(OBJECTS))
|
||||
$(RM) headless-git.o.pdb
|
||||
$(RM) $(patsubst %.exe,%.pdb,$(OTHER_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.ilk,$(OTHER_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.iobj,$(OTHER_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.ipdb,$(OTHER_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.pdb,$(PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.ilk,$(PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.iobj,$(PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.ipdb,$(PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.pdb,$(TEST_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.ilk,$(TEST_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.iobj,$(TEST_PROGRAMS))
|
||||
$(RM) $(patsubst %.exe,%.ipdb,$(TEST_PROGRAMS))
|
||||
$(RM) compat/vcbuild/MSVC-DEFS-GEN
|
||||
|
||||
77
README.md
77
README.md
@@ -1,76 +1,4 @@
|
||||
Git for Windows
|
||||
===============
|
||||
|
||||
[](https://open.vscode.dev/git-for-windows/git)
|
||||
[](https://github.com/git-for-windows/git/actions?query=branch%3Amain+event%3Apush)
|
||||
[](https://gitter.im/git-for-windows/git?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
This is [Git for Windows](http://git-for-windows.github.io/), the Windows port
|
||||
of [Git](http://git-scm.com/).
|
||||
|
||||
The Git for Windows project is run using a [governance
|
||||
model](http://git-for-windows.github.io/governance-model.html). If you
|
||||
encounter problems, you can report them as [GitHub
|
||||
issues](https://github.com/git-for-windows/git/issues), discuss them on Git
|
||||
for Windows' [Google Group](http://groups.google.com/group/git-for-windows),
|
||||
and [contribute bug
|
||||
fixes](https://github.com/git-for-windows/git/wiki/How-to-participate).
|
||||
|
||||
To build Git for Windows, please either install [Git for Windows'
|
||||
SDK](https://gitforwindows.org/#download-sdk), start its `git-bash.exe`, `cd`
|
||||
to your Git worktree and run `make`, or open the Git worktree as a folder in
|
||||
Visual Studio.
|
||||
|
||||
To verify that your build works, use one of the following methods:
|
||||
|
||||
- If you want to test the built executables within Git for Windows' SDK,
|
||||
prepend `<worktree>/bin-wrappers` to the `PATH`.
|
||||
- Alternatively, run `make install` in the Git worktree.
|
||||
- If you need to test this in a full installer, run `sdk build
|
||||
git-and-installer`.
|
||||
- You can also "install" Git into an existing portable Git via `make install
|
||||
DESTDIR=<dir>` where `<dir>` refers to the top-level directory of the
|
||||
portable Git. In this instance, you will want to prepend that portable Git's
|
||||
`/cmd` directory to the `PATH`, or test by running that portable Git's
|
||||
`git-bash.exe` or `git-cmd.exe`.
|
||||
- If you built using a recent Visual Studio, you can use the menu item
|
||||
`Build>Install git` (you will want to click on `Project>CMake Settings for
|
||||
Git` first, then click on `Edit JSON` and then point `installRoot` to the
|
||||
`mingw64` directory of an already-unpacked portable Git).
|
||||
|
||||
As in the previous bullet point, you will then prepend `/cmd` to the `PATH`
|
||||
or run using the portable Git's `git-bash.exe` or `git-cmd.exe`.
|
||||
- If you want to run the built executables in-place, but in a CMD instead of
|
||||
inside a Bash, you can run a snippet like this in the `git-bash.exe` window
|
||||
where Git was built (ensure that the `EOF` line has no leading spaces), and
|
||||
then paste into the CMD window what was put in the clipboard:
|
||||
|
||||
```sh
|
||||
clip.exe <<EOF
|
||||
set GIT_EXEC_PATH=$(cygpath -aw .)
|
||||
set PATH=$(cygpath -awp ".:contrib/scalar:/mingw64/bin:/usr/bin:$PATH")
|
||||
set GIT_TEMPLATE_DIR=$(cygpath -aw templates/blt)
|
||||
set GITPERLLIB=$(cygpath -aw perl/build/lib)
|
||||
EOF
|
||||
```
|
||||
- If you want to run the built executables in-place, but outside of Git for
|
||||
Windows' SDK, and without an option to set/override any environment
|
||||
variables (e.g. in Visual Studio's debugger), you can call the Git executable
|
||||
by its absolute path and use the `--exec-path` option, like so:
|
||||
|
||||
```cmd
|
||||
C:\git-sdk-64\usr\src\git\git.exe --exec-path=C:\git-sdk-64\usr\src\git help
|
||||
```
|
||||
|
||||
Note: for this to work, you have to hard-link (or copy) the `.dll` files from
|
||||
the `/mingw64/bin` directory to the Git worktree, or add the `/mingw64/bin`
|
||||
directory to the `PATH` somehow or other.
|
||||
|
||||
To make sure that you are testing the correct binary, call `./git.exe version`
|
||||
in the Git worktree, and then call `git version` in a directory/window where
|
||||
you want to test Git, and verify that they refer to the same version (you may
|
||||
even want to pass the command-line option `--build-options` to look at the
|
||||
exact commit from which the Git version was built).
|
||||
[](https://github.com/git/git/actions?query=branch%3Amaster+event%3Apush)
|
||||
|
||||
Git - fast, scalable, distributed revision control system
|
||||
=========================================================
|
||||
@@ -101,7 +29,7 @@ CVS users may also want to read [Documentation/gitcvs-migration.txt][]
|
||||
(`man gitcvs-migration` or `git help cvs-migration` if git is
|
||||
installed).
|
||||
|
||||
The user discussion and development of core Git take place on the Git
|
||||
The user discussion and development of Git take place on the Git
|
||||
mailing list -- everyone is welcome to post bug reports, feature
|
||||
requests, comments and patches to git@vger.kernel.org (read
|
||||
[Documentation/SubmittingPatches][] for instructions on patch submission
|
||||
@@ -115,7 +43,6 @@ To subscribe to the list, send an email with just "subscribe git" in
|
||||
the body to majordomo@vger.kernel.org (not the Git list). The mailing
|
||||
list archives are available at <https://lore.kernel.org/git/>,
|
||||
<http://marc.info/?l=git> and other archival sites.
|
||||
The core git mailing list is plain text (no HTML!).
|
||||
|
||||
Issues which are security relevant should be disclosed privately to
|
||||
the Git Security mailing list <git-security@googlegroups.com>.
|
||||
|
||||
50
SECURITY.md
50
SECURITY.md
@@ -28,38 +28,24 @@ Examples for details to include:
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Git for Windows is a "friendly fork" of [Git](https://git-scm.com/), i.e. changes in Git for Windows are frequently contributed back, and Git for Windows' release cycle closely following Git's.
|
||||
There are no official "Long Term Support" versions in Git.
|
||||
Instead, the maintenance track (i.e. the versions based on the
|
||||
most recently published feature release, also known as ".0"
|
||||
version) sees occasional updates with bug fixes.
|
||||
|
||||
While Git maintains several release trains (when v2.19.1 was released, there were updates to v2.14.x-v2.18.x, too, for example), Git for Windows follows only the latest Git release. For example, there is no Git for Windows release corresponding to Git v2.16.5 (which was released after v2.19.0).
|
||||
Fixes to vulnerabilities are made for the maintenance track for
|
||||
the latest feature release and merged up to the in-development
|
||||
branches. The Git project makes no formal guarantee for any
|
||||
older maintenance tracks to receive updates. In practice,
|
||||
though, critical vulnerability fixes are applied not only to the
|
||||
most recent track, but to at least a couple more maintenance
|
||||
tracks.
|
||||
|
||||
One exception is [MinGit for Windows](https://github.com/git-for-windows/git/wiki/MinGit) (a minimal subset of Git for Windows, intended for bundling with third-party applications that do not need any interactive commands nor support for `git svn`): critical security fixes are backported to the v2.11.x, v2.14.x, v2.19.x, v2.21.x and v2.23.x release trains.
|
||||
This is typically done by making the fix on the oldest and still
|
||||
relevant maintenance track, and merging it upwards to newer and
|
||||
newer maintenance tracks.
|
||||
|
||||
## Version number scheme
|
||||
|
||||
The Git for Windows versions reflect the Git version on which they are based. For example, Git for Windows v2.21.0 is based on Git v2.21.0.
|
||||
|
||||
As Git for Windows bundles more than just Git (such as Bash, OpenSSL, OpenSSH, GNU Privacy Guard), sometimes there are interim releases without corresponding Git releases. In these cases, Git for Windows appends a number in parentheses, starting with the number 2, then 3, etc. For example, both Git for Windows v2.17.1 and v2.17.1(2) were based on Git v2.17.1, but the latter included updates for Git Credential Manager and Git LFS, fixing critical regressions.
|
||||
|
||||
## Tag naming scheme
|
||||
|
||||
Every Git for Windows version is tagged using a name that starts with the Git version on which it is based, with the suffix `.windows.<patchlevel>` appended. For example, Git for Windows v2.17.1' source code is tagged as [`v2.17.1.windows.1`](https://github.com/git-for-windows/git/releases/tag/v2.17.1.windows.1) (the patch level is always at least 1, given that Git for Windows always has patches on top of Git). Likewise, Git for Windows v2.17.1(2)' source code is tagged as [`v2.17.1.windows.2`](https://github.com/git-for-windows/git/releases/tag/v2.17.1.windows.2).
|
||||
|
||||
## Release Candidate (rc) versions
|
||||
|
||||
As a friendly fork of Git (the "upstream" project), Git for Windows is closely corelated to that project.
|
||||
|
||||
Consequently, Git for Windows publishes versions based on Git's release candidates (for upcoming "`.0`" versions, see [Git's release schedule](https://tinyurl.com/gitCal)). These versions end in `-rc<n>`, starting with `-rc0` for a very early preview of what is to come, and as with regular versions, Git for Windows tries to follow Git's releases as quickly as possible.
|
||||
|
||||
Note: there is currently a bug in the "Check daily for updates" code, where it mistakes the final version as a downgrade from release candidates. Example: if you installed Git for Windows v2.23.0-rc3 and enabled the auto-updater, it would ask you whether you want to "downgrade" to v2.23.0 when that version was available.
|
||||
|
||||
[All releases](https://github.com/git-for-windows/git/releases/), including release candidates, are listed via a link at the footer of the [Git for Windows](https://gitforwindows.org/) home page.
|
||||
|
||||
## Snapshot versions ('nightly builds')
|
||||
|
||||
Git for Windows also provides snapshots (these are not releases) of the the current development as per git-for-Windows/git's `master` branch at the [Snapshots](https://wingit.blob.core.windows.net/files/index.html) page. This link is also listed in the footer of the [Git for Windows](https://gitforwindows.org/) home page.
|
||||
|
||||
Note: even if those builds are not exactly "nightly", they are sometimes referred to as "nightly builds" to keep with other projects' nomenclature.
|
||||
|
||||
## Following upstream's developments
|
||||
|
||||
The [gitforwindows/git repository](https://github.com/git-for-windows/git) also provides the `shears/*` branches. The `shears/*` branches reflect Git for Windows' patches, rebased onto the upstream integration branches, [updated (mostly) via automated CI builds](https://dev.azure.com/git-for-windows/git/_build?definitionId=25).
|
||||
For example, v2.24.1 was released to address a couple of
|
||||
[CVEs](https://cve.mitre.org/), and at the same time v2.14.6,
|
||||
v2.15.4, v2.16.6, v2.17.3, v2.18.2, v2.19.3, v2.20.2, v2.21.1,
|
||||
v2.22.2 and v2.23.1 were released.
|
||||
|
||||
@@ -91,9 +91,6 @@ static char *strbuf_realpath_1(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);
|
||||
|
||||
|
||||
2
advice.c
2
advice.c
@@ -48,7 +48,6 @@ static struct {
|
||||
[ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated", 1 },
|
||||
[ADVICE_IGNORED_HOOK] = { "ignoredHook", 1 },
|
||||
[ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity", 1 },
|
||||
[ADVICE_NAME_TOO_LONG] = { "nameTooLong", 1 },
|
||||
[ADVICE_NESTED_TAG] = { "nestedTag", 1 },
|
||||
[ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning", 1 },
|
||||
[ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists", 1 },
|
||||
@@ -75,7 +74,6 @@ static struct {
|
||||
[ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 },
|
||||
[ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated", 1 },
|
||||
[ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath", 1 },
|
||||
[ADVICE_USE_CORE_FSMONITOR_CONFIG] = { "useCoreFSMonitorConfig", 1 },
|
||||
[ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
|
||||
};
|
||||
|
||||
|
||||
2
advice.h
2
advice.h
@@ -26,7 +26,6 @@ struct string_list;
|
||||
ADVICE_GRAFT_FILE_DEPRECATED,
|
||||
ADVICE_IGNORED_HOOK,
|
||||
ADVICE_IMPLICIT_IDENTITY,
|
||||
ADVICE_NAME_TOO_LONG,
|
||||
ADVICE_NESTED_TAG,
|
||||
ADVICE_OBJECT_NAME_WARNING,
|
||||
ADVICE_PUSH_ALREADY_EXISTS,
|
||||
@@ -49,7 +48,6 @@ struct string_list;
|
||||
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
|
||||
ADVICE_SUBMODULES_NOT_UPDATED,
|
||||
ADVICE_UPDATE_SPARSE_PATH,
|
||||
ADVICE_USE_CORE_FSMONITOR_CONFIG,
|
||||
ADVICE_WAITING_FOR_EDITOR,
|
||||
ADVICE_SKIPPED_CHERRY_PICKS,
|
||||
};
|
||||
|
||||
2
apply.c
2
apply.c
@@ -4366,7 +4366,7 @@ static int try_create_file(struct apply_state *state, const char *path,
|
||||
/* Although buf:size is counted string, it also is NUL
|
||||
* terminated.
|
||||
*/
|
||||
return !!create_symlink(state && state->repo ? state->repo->index : NULL, buf, path);
|
||||
return !!symlink(buf, path);
|
||||
|
||||
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
|
||||
if (fd < 0)
|
||||
|
||||
@@ -17,8 +17,6 @@ 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);
|
||||
|
||||
@@ -40,21 +38,11 @@ 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_block_or_die(block);
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +66,7 @@ static void do_write_blocked(const void *data, unsigned long size)
|
||||
write_if_needed();
|
||||
}
|
||||
while (size >= BLOCKSIZE) {
|
||||
write_block_or_die(buf);
|
||||
write_or_die(1, buf, BLOCKSIZE);
|
||||
size -= BLOCKSIZE;
|
||||
buf += BLOCKSIZE;
|
||||
}
|
||||
@@ -113,10 +101,10 @@ static void write_trailer(void)
|
||||
{
|
||||
int tail = BLOCKSIZE - offset;
|
||||
memset(block + offset, 0, tail);
|
||||
write_block_or_die(block);
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
if (tail < 2 * RECORDSIZE) {
|
||||
memset(block, 0, offset);
|
||||
write_block_or_die(block);
|
||||
write_or_die(1, block, BLOCKSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,34 +443,18 @@ static int write_tar_filter_archive(const struct archiver *ar,
|
||||
filter.use_shell = 1;
|
||||
filter.in = -1;
|
||||
|
||||
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"), cmd.buf);
|
||||
close(1);
|
||||
if (dup2(filter.in, 1) < 0)
|
||||
die_errno(_("unable to redirect descriptor"));
|
||||
close(filter.in);
|
||||
}
|
||||
if (start_command(&filter) < 0)
|
||||
die_errno(_("unable to start '%s' filter"), cmd.buf);
|
||||
close(1);
|
||||
if (dup2(filter.in, 1) < 0)
|
||||
die_errno(_("unable to redirect descriptor"));
|
||||
close(filter.in);
|
||||
|
||||
r = write_tar_archive(ar, args);
|
||||
|
||||
if (gzip) {
|
||||
if (gzclose(gzip) != Z_OK)
|
||||
die(_("gzclose failed"));
|
||||
} else {
|
||||
close(1);
|
||||
if (finish_command(&filter) != 0)
|
||||
die(_("'%s' filter reported error"), cmd.buf);
|
||||
}
|
||||
close(1);
|
||||
if (finish_command(&filter) != 0)
|
||||
die(_("'%s' filter reported error"), cmd.buf);
|
||||
|
||||
strbuf_release(&cmd);
|
||||
return r;
|
||||
|
||||
@@ -1,393 +0,0 @@
|
||||
variables:
|
||||
Agent.Source.Git.ShallowFetchDepth: 1
|
||||
GIT_CONFIG_PARAMETERS: "'checkout.workers=56' 'user.name=CI' 'user.email=ci@git'"
|
||||
|
||||
jobs:
|
||||
- job: windows_build
|
||||
displayName: Windows Build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
timeoutInMinutes: 240
|
||||
steps:
|
||||
- bash: git clone --bare --depth=1 --filter=blob:none --single-branch -b main https://github.com/git-for-windows/git-sdk-64
|
||||
displayName: 'clone git-sdk-64'
|
||||
- bash: git clone --depth=1 --single-branch -b main https://github.com/git-for-windows/build-extra
|
||||
displayName: 'clone build-extra'
|
||||
- bash: sh -x ./build-extra/please.sh create-sdk-artifact --sdk=git-sdk-64.git --out=git-sdk-64-minimal minimal-sdk
|
||||
displayName: 'build git-sdk-64-minimal-sdk'
|
||||
- bash: |
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
printf "%s\n" /git-sdk-64.git/ /build-extra/ /git-sdk-64-minimal/ /test-cache/ >>'.git/info/exclude'
|
||||
displayName: 'Ignore untracked directories'
|
||||
- bash: ci/make-test-artifacts.sh artifacts
|
||||
displayName: Build
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
DEVELOPER: 1
|
||||
NO_PERL: 1
|
||||
PATH: "$(Build.SourcesDirectory)\\git-sdk-64-minimal\\mingw64\\bin;$(Build.SourcesDirectory)\\git-sdk-64-minimal\\usr\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\system32\\wbem"
|
||||
- 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'
|
||||
|
||||
- job: windows_test
|
||||
displayName: Windows Test
|
||||
dependsOn: windows_build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
timeoutInMinutes: 240
|
||||
strategy:
|
||||
parallel: 10
|
||||
steps:
|
||||
- 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'
|
||||
- bash: |
|
||||
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.git/ /build-extra/ /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
|
||||
}
|
||||
displayName: 'Test (parallel)'
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
NO_SVN_TESTS: 1
|
||||
GIT_TEST_SKIP_REBASE_P: 1
|
||||
PATH: "$(Build.SourcesDirectory)\\git-sdk-64-minimal\\mingw64\\bin;$(Build.SourcesDirectory)\\git-sdk-64-minimal\\usr\\bin\\core_perl;$(Build.SourcesDirectory)\\git-sdk-64-minimal\\usr\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\system32\\wbem"
|
||||
- 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:
|
||||
- bash: git clone --bare --depth=1 --filter=blob:none --single-branch -b main https://github.com/git-for-windows/git-sdk-64
|
||||
displayName: 'clone git-sdk-64'
|
||||
- bash: git clone --depth=1 --single-branch -b main https://github.com/git-for-windows/build-extra
|
||||
displayName: 'clone build-extra'
|
||||
- bash: sh -x ./build-extra/please.sh create-sdk-artifact --sdk=git-sdk-64.git --out=git-sdk-64-minimal minimal-sdk
|
||||
displayName: 'build git-sdk-64-minimal-sdk'
|
||||
- bash: |
|
||||
# Let Git ignore the SDK and the test-cache
|
||||
printf "%s\n" /git-sdk-64-minimal/ /test-cache/ >>'.git/info/exclude'
|
||||
displayName: 'Ignore untracked directories'
|
||||
- bash: make NDEBUG=1 DEVELOPER=1 vcxproj
|
||||
displayName: Generate Visual Studio Solution
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
DEVELOPER: 1
|
||||
NO_PERL: 1
|
||||
PATH: "$(Build.SourcesDirectory)\\git-sdk-64-minimal\\mingw64\\bin;$(Build.SourcesDirectory)\\git-sdk-64-minimal\\usr\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\system32\\wbem"
|
||||
- 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
|
||||
- bash: |
|
||||
./compat/vcbuild/vcpkg_copy_dlls.bat release &&
|
||||
mkdir -p artifacts &&
|
||||
eval "$(make -n artifacts-tar INCLUDE_DLLS_IN_ARTIFACTS=YesPlease ARTIFACTS_DIRECTORY=artifacts | grep ^tar)"
|
||||
displayName: Bundle artifact tar
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
DEVELOPER: 1
|
||||
NO_PERL: 1
|
||||
MSVC: 1
|
||||
VCPKG_ROOT: $(Build.SourcesDirectory)\compat\vcbuild\vcpkg
|
||||
PATH: "$(Build.SourcesDirectory)\\git-sdk-64-minimal\\mingw64\\bin;$(Build.SourcesDirectory)\\git-sdk-64-minimal\\usr\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\system32\\wbem"
|
||||
- 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'
|
||||
|
||||
- job: vs_test
|
||||
displayName: Visual Studio Test
|
||||
dependsOn: vs_build
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
timeoutInMinutes: 240
|
||||
strategy:
|
||||
parallel: 10
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
displayName: 'Download Pipeline Artifact: VS test artifacts'
|
||||
inputs:
|
||||
artifactName: 'vs-artifacts'
|
||||
targetPath: '$(Build.SourcesDirectory)'
|
||||
- bash: |
|
||||
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)
|
||||
displayName: 'Test (parallel)'
|
||||
env:
|
||||
HOME: $(Build.SourcesDirectory)
|
||||
MSYSTEM: MINGW64
|
||||
NO_SVN_TESTS: 1
|
||||
GIT_TEST_SKIP_REBASE_P: 1
|
||||
PATH: "$(Build.SourcesDirectory)\\PortableGit\\mingw64\\bin;$(Build.SourcesDirectory)\\PortableGit\\usr\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\system32\\wbem"
|
||||
- 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: |
|
||||
export CC=clang || exit 1
|
||||
|
||||
ci/install-dependencies.sh || exit 1
|
||||
ci/run-build-and-tests.sh || {
|
||||
ci/print-test-failures.sh
|
||||
exit 1
|
||||
}
|
||||
displayName: 'ci/run-build-and-tests.sh'
|
||||
- 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: |
|
||||
ci/install-dependencies.sh || exit 1
|
||||
ci/run-build-and-tests.sh || {
|
||||
ci/print-test-failures.sh
|
||||
exit 1
|
||||
}
|
||||
displayName: 'ci/run-build-and-tests.sh'
|
||||
- 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: |
|
||||
export CC=clang
|
||||
|
||||
ci/install-dependencies.sh || exit 1
|
||||
ci/run-build-and-tests.sh || {
|
||||
ci/print-test-failures.sh
|
||||
exit 1
|
||||
}
|
||||
displayName: 'ci/run-build-and-tests.sh'
|
||||
- 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: |
|
||||
ci/install-dependencies.sh || exit 1
|
||||
ci/run-build-and-tests.sh || {
|
||||
ci/print-test-failures.sh
|
||||
exit 1
|
||||
}
|
||||
displayName: 'ci/run-build-and-tests.sh'
|
||||
- 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: linux32
|
||||
displayName: Linux32
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- bash: |
|
||||
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" jobname=linux32 bash -lxc ci/run-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
|
||||
|
||||
exit $res
|
||||
displayName: 'jobname=linux32 ci/run-docker.sh'
|
||||
- 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-18.04
|
||||
steps:
|
||||
- bash: |
|
||||
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
|
||||
displayName: 'ci/run-static-analysis.sh'
|
||||
|
||||
- job: documentation
|
||||
displayName: Documentation
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- bash: |
|
||||
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
|
||||
displayName: 'ci/test-documentation.sh'
|
||||
@@ -593,10 +593,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
die_in_unpopulated_submodule(&the_index, prefix);
|
||||
die_path_inside_submodule(&the_index, &pathspec);
|
||||
|
||||
enable_fscache(0);
|
||||
/* We do not really re-read the index but update the up-to-date flags */
|
||||
preload_index(&the_index, &pathspec, 0);
|
||||
|
||||
if (add_new_files) {
|
||||
int baselen;
|
||||
|
||||
@@ -699,7 +695,6 @@ finish:
|
||||
die(_("Unable to write new index file"));
|
||||
|
||||
dir_clear(&dir);
|
||||
enable_fscache(0);
|
||||
UNLEAK(pathspec);
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "parse-options.h"
|
||||
#include "pkt-line.h"
|
||||
#include "sideband.h"
|
||||
#include "config.h"
|
||||
|
||||
static void create_output_file(const char *output_file)
|
||||
{
|
||||
@@ -94,7 +93,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, local_opts, NULL,
|
||||
PARSE_OPT_KEEP_ALL);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "prompt.h"
|
||||
#include "quote.h"
|
||||
#include "revision.h"
|
||||
#include "config.h"
|
||||
|
||||
static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
|
||||
static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
|
||||
@@ -1323,7 +1322,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
git_bisect_helper_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "parse-options.h"
|
||||
#include "cache.h"
|
||||
#include "bundle.h"
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* Basic handler for bundle files to connect repositories via sneakernet.
|
||||
@@ -111,7 +110,6 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
|
||||
};
|
||||
char *bundle_file;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options_cmd_bundle(argc, argv, prefix,
|
||||
builtin_bundle_verify_usage, options, &bundle_file);
|
||||
/* bundle internals use argv[1] as further parameters */
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "refs.h"
|
||||
#include "builtin.h"
|
||||
#include "strbuf.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char builtin_check_ref_format_usage[] =
|
||||
"git check-ref-format [--normalize] [<options>] <refname>\n"
|
||||
@@ -59,7 +58,6 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
|
||||
int flags = 0;
|
||||
const char *refname;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage(builtin_check_ref_format_usage);
|
||||
|
||||
|
||||
@@ -391,7 +391,6 @@ static int checkout_worktree(const struct checkout_opts *opts,
|
||||
if (pc_workers > 1)
|
||||
init_parallel_checkout();
|
||||
|
||||
enable_fscache(active_nr);
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
struct cache_entry *ce = active_cache[pos];
|
||||
if (ce->ce_flags & CE_MATCHED) {
|
||||
@@ -416,7 +415,6 @@ static int checkout_worktree(const struct checkout_opts *opts,
|
||||
errs |= run_parallel_checkout(&state, pc_workers, pc_threshold,
|
||||
NULL, NULL);
|
||||
mem_pool_discard(&ce_mem_pool, should_validate_cache_entries());
|
||||
disable_fscache();
|
||||
remove_marked_cache_entries(&the_index, 1);
|
||||
remove_scheduled_dirs();
|
||||
errs |= finish_delayed_checkout(&state, opts->show_progress);
|
||||
|
||||
@@ -34,10 +34,6 @@ 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");
|
||||
static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n");
|
||||
@@ -179,29 +175,6 @@ 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(path->buf, prefix, "ed, 0);
|
||||
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(path->buf, prefix, "ed, 0);
|
||||
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 */
|
||||
@@ -211,9 +184,6 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
|
||||
quote_path(path->buf, prefix, "ed, 0);
|
||||
errno = saved_errno;
|
||||
warning_errno(_(msg_warn_remove_failed), quoted.buf);
|
||||
if (saved_errno == ENAMETOOLONG) {
|
||||
advise_if_enabled(ADVICE_NAME_TOO_LONG, _("Setting `core.longPaths` may allow the deletion to succeed."));
|
||||
}
|
||||
*dir_gone = 0;
|
||||
}
|
||||
ret = res;
|
||||
@@ -249,9 +219,6 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
|
||||
quote_path(path->buf, prefix, "ed, 0);
|
||||
errno = saved_errno;
|
||||
warning_errno(_(msg_warn_remove_failed), quoted.buf);
|
||||
if (saved_errno == ENAMETOOLONG) {
|
||||
advise_if_enabled(ADVICE_NAME_TOO_LONG, _("Setting `core.longPaths` may allow the deletion to succeed."));
|
||||
}
|
||||
*dir_gone = 0;
|
||||
ret = 1;
|
||||
}
|
||||
@@ -295,9 +262,6 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
|
||||
quote_path(path->buf, prefix, "ed, 0);
|
||||
errno = saved_errno;
|
||||
warning_errno(_(msg_warn_remove_failed), quoted.buf);
|
||||
if (saved_errno == ENAMETOOLONG) {
|
||||
advise_if_enabled(ADVICE_NAME_TOO_LONG, _("Setting `core.longPaths` may allow the deletion to succeed."));
|
||||
}
|
||||
*dir_gone = 0;
|
||||
ret = 1;
|
||||
}
|
||||
@@ -1050,7 +1014,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (read_cache() < 0)
|
||||
die(_("index file corrupt"));
|
||||
enable_fscache(active_nr);
|
||||
|
||||
pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
|
||||
for (i = 0; i < exclude_list.nr; i++)
|
||||
@@ -1117,9 +1080,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
qname = quote_path(item->string, NULL, &buf, 0);
|
||||
errno = saved_errno;
|
||||
warning_errno(_(msg_warn_remove_failed), qname);
|
||||
if (saved_errno == ENAMETOOLONG) {
|
||||
advise_if_enabled(ADVICE_NAME_TOO_LONG, _("Setting `core.longPaths` may allow the deletion to succeed."));
|
||||
}
|
||||
errors++;
|
||||
} else if (!quiet) {
|
||||
qname = quote_path(item->string, NULL, &buf, 0);
|
||||
@@ -1128,7 +1088,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
}
|
||||
|
||||
disable_fscache();
|
||||
strbuf_release(&abs_path);
|
||||
strbuf_release(&buf);
|
||||
string_list_clear(&del_list, 0);
|
||||
|
||||
@@ -900,8 +900,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
struct transport_ls_refs_options transport_ls_refs_options =
|
||||
TRANSPORT_LS_REFS_OPTIONS_INIT;
|
||||
|
||||
git_config(git_default_core_config, NULL);
|
||||
|
||||
packet_trace_identity("clone");
|
||||
|
||||
git_config(git_clone_config, NULL);
|
||||
|
||||
@@ -34,8 +34,6 @@ int cmd_column(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_core_config, NULL);
|
||||
|
||||
/* This one is special and must be the first one */
|
||||
if (argc > 1 && starts_with(argv[1], "--command=")) {
|
||||
command = argv[1] + 10;
|
||||
|
||||
@@ -1540,7 +1540,6 @@ int cmd_status(int argc, const char **argv, const char *prefix)
|
||||
PATHSPEC_PREFER_FULL,
|
||||
prefix, argv);
|
||||
|
||||
enable_fscache(0);
|
||||
if (status_format != STATUS_FORMAT_PORCELAIN &&
|
||||
status_format != STATUS_FORMAT_PORCELAIN_V2)
|
||||
progress_flag = REFRESH_PROGRESS;
|
||||
@@ -1581,7 +1580,6 @@ int cmd_status(int argc, const char **argv, const char *prefix)
|
||||
wt_status_print(&s);
|
||||
wt_status_collect_free_buffers(&s);
|
||||
|
||||
disable_fscache();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "credential.h"
|
||||
#include "string-list.h"
|
||||
#include "parse-options.h"
|
||||
#include "config.h"
|
||||
|
||||
static struct lock_file credential_lock;
|
||||
|
||||
@@ -166,8 +165,6 @@ int cmd_credential_store(int argc, const char **argv, const char *prefix)
|
||||
|
||||
umask(077);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
argc = parse_options(argc, (const char **)argv, prefix, options, usage, 0);
|
||||
if (argc != 1)
|
||||
usage_with_options(usage, options);
|
||||
|
||||
@@ -513,7 +513,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
||||
}
|
||||
add_path(&wtdir, wtdir_len, dst_path);
|
||||
if (symlinks) {
|
||||
if (create_symlink(lstate.istate, wtdir.buf, rdir.buf)) {
|
||||
if (symlink(wtdir.buf, rdir.buf)) {
|
||||
ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "connect.h"
|
||||
#include "oid-array.h"
|
||||
#include "protocol.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char fetch_pack_usage[] =
|
||||
"git fetch-pack [--all] [--stdin] [--quiet | -q] [--keep | -k] [--thin] "
|
||||
@@ -58,7 +57,6 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
||||
struct packet_reader reader;
|
||||
enum protocol_version version;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
fetch_if_missing = 0;
|
||||
|
||||
packet_trace_identity("fetch-pack");
|
||||
|
||||
@@ -1969,7 +1969,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
|
||||
"</Settings>\n"
|
||||
"<Actions Context=\"Author\">\n"
|
||||
"<Exec>\n"
|
||||
"<Command>\"%s\\headless-git.exe\"</Command>\n"
|
||||
"<Command>\"%s\\git.exe\"</Command>\n"
|
||||
"<Arguments>--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
|
||||
"</Exec>\n"
|
||||
"</Actions>\n"
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "tar.h"
|
||||
#include "builtin.h"
|
||||
#include "quote.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char builtin_get_tar_commit_id_usage[] =
|
||||
"git get-tar-commit-id";
|
||||
@@ -28,7 +27,6 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
|
||||
if (argc != 1)
|
||||
usage(builtin_get_tar_commit_id_usage);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
n = read_in_full(0, buffer, HEADERSIZE);
|
||||
if (n < 0)
|
||||
die_errno("git get-tar-commit-id: read error");
|
||||
|
||||
@@ -78,7 +78,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
|
||||
if (strbuf_readlink(&lnk, template_path->buf,
|
||||
st_template.st_size) < 0)
|
||||
die_errno(_("cannot readlink '%s'"), template_path->buf);
|
||||
if (create_symlink(NULL, lnk.buf, path->buf))
|
||||
if (symlink(lnk.buf, path->buf))
|
||||
die_errno(_("cannot symlink '%s' '%s'"),
|
||||
lnk.buf, path->buf);
|
||||
strbuf_release(&lnk);
|
||||
@@ -300,7 +300,7 @@ static int create_default_files(const char *template_path,
|
||||
path = git_path_buf(&buf, "tXXXXXX");
|
||||
if (!close(xmkstemp(path)) &&
|
||||
!unlink(path) &&
|
||||
!create_symlink(NULL, "testing", path) &&
|
||||
!symlink("testing", path) &&
|
||||
!lstat(path, &st1) &&
|
||||
S_ISLNK(st1.st_mode))
|
||||
unlink(path); /* good */
|
||||
@@ -410,7 +410,7 @@ int init_db(const char *git_dir, const char *real_git_dir,
|
||||
startup_info->have_repository = 1;
|
||||
|
||||
/* Ensure `core.hidedotfiles` is processed */
|
||||
git_config(git_default_core_config, NULL);
|
||||
git_config(platform_core_config, NULL);
|
||||
|
||||
safe_create_dir(git_dir, 0);
|
||||
|
||||
|
||||
@@ -2364,7 +2364,6 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, options, cherry_usage, 0);
|
||||
|
||||
switch (argc) {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "ref-filter.h"
|
||||
#include "remote.h"
|
||||
#include "refs.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char * const ls_remote_usage[] = {
|
||||
N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
|
||||
@@ -87,7 +86,6 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
|
||||
|
||||
packet_trace_identity("ls-remote");
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
if (argc > 1) {
|
||||
int i;
|
||||
CALLOC_ARRAY(pattern, argc);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "strbuf.h"
|
||||
#include "mailinfo.h"
|
||||
#include "parse-options.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char * const mailinfo_usage[] = {
|
||||
/* TRANSLATORS: keep <> in "<" mail ">" info. */
|
||||
@@ -79,7 +78,6 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
setup_mailinfo(&mi);
|
||||
meta_charset.policy = CHARSET_DEFAULT;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "builtin.h"
|
||||
#include "string-list.h"
|
||||
#include "strbuf.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char git_mailsplit_usage[] =
|
||||
"git mailsplit [-d<prec>] [-f<n>] [-b] [--keep-cr] -o<directory> [(<mbox>|<Maildir>)...]";
|
||||
@@ -278,7 +277,6 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
|
||||
const char **argp;
|
||||
static const char *stdin_only[] = { "-", NULL };
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
for (argp = argv+1; *argp; argp++) {
|
||||
const char *arg = *argp;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#define USE_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "builtin.h"
|
||||
#include "run-command.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char *pgm;
|
||||
static int one_shot, quiet;
|
||||
@@ -78,8 +77,6 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix)
|
||||
*/
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
if (argc < 3)
|
||||
usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])");
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "blob.h"
|
||||
#include "exec-cmd.h"
|
||||
#include "merge-blobs.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char merge_tree_usage[] = "git merge-tree <base-tree> <branch1> <branch2>";
|
||||
|
||||
@@ -376,7 +375,6 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
|
||||
if (argc != 4)
|
||||
usage(merge_tree_usage);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
buf1 = get_tree_descriptor(r, t+0, argv[1]);
|
||||
buf2 = get_tree_descriptor(r, t+1, argv[2]);
|
||||
buf3 = get_tree_descriptor(r, t+2, argv[3]);
|
||||
|
||||
@@ -84,7 +84,6 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
|
||||
builtin_mktag_options,
|
||||
builtin_mktag_usage, 0);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
if (strbuf_read(&buf, 0, 0) < 0)
|
||||
die_errno(_("could not read from stdin"));
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "tree.h"
|
||||
#include "parse-options.h"
|
||||
#include "object-store.h"
|
||||
#include "config.h"
|
||||
|
||||
static struct treeent {
|
||||
unsigned mode;
|
||||
@@ -165,7 +164,6 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
|
||||
getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "parse-options.h"
|
||||
#include "refs.h"
|
||||
#include "repository.h"
|
||||
#include "config.h"
|
||||
|
||||
static char const * const pack_refs_usage[] = {
|
||||
N_("git pack-refs [<options>]"),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "builtin.h"
|
||||
#include "parse-options.h"
|
||||
#include "prune-packed.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char * const prune_packed_usage[] = {
|
||||
"git prune-packed [-n | --dry-run] [-q | --quiet]",
|
||||
@@ -19,7 +18,6 @@ int cmd_prune_packed(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, prune_packed_options,
|
||||
prune_packed_usage, 0);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "prune-packed.h"
|
||||
#include "object-store.h"
|
||||
#include "shallow.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char * const prune_usage[] = {
|
||||
N_("git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"),
|
||||
@@ -153,8 +152,6 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
char *s;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
expire = TIME_MAX;
|
||||
save_commit_buffer = 0;
|
||||
read_replace_refs = 0;
|
||||
|
||||
@@ -408,7 +408,6 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, options, reflog_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |
|
||||
PARSE_OPT_KEEP_UNKNOWN |
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "transport.h"
|
||||
#include "run-command.h"
|
||||
#include "pkt-line.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char usage_msg[] =
|
||||
"git remote-ext <remote> <url>";
|
||||
@@ -199,6 +198,5 @@ int cmd_remote_ext(int argc, const char **argv, const char *prefix)
|
||||
if (argc != 3)
|
||||
usage(usage_msg);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
return command_loop(argv[2]);
|
||||
}
|
||||
|
||||
@@ -1736,7 +1736,6 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
int result;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "submodule.h"
|
||||
#include "submodule-config.h"
|
||||
#include "dir.h"
|
||||
#include "strbuf.h"
|
||||
#include "quote.h"
|
||||
|
||||
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
|
||||
|
||||
@@ -36,7 +34,6 @@ static const char * const git_reset_usage[] = {
|
||||
N_("git reset [-q] [<tree-ish>] [--] <pathspec>..."),
|
||||
N_("git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"),
|
||||
N_("git reset --patch [<tree-ish>] [--] [<pathspec>...]"),
|
||||
N_("DEPRECATED: git reset [-q] [--stdin [-z]] [<tree-ish>]"),
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -401,7 +398,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
struct object_id oid;
|
||||
struct pathspec pathspec;
|
||||
int intent_to_add = 0;
|
||||
int nul_term_line = 0, read_from_stdin = 0;
|
||||
const struct option options[] = {
|
||||
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
|
||||
OPT_BOOL(0, "no-refresh", &no_refresh,
|
||||
@@ -423,10 +419,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
N_("record only the fact that removed paths will be added later")),
|
||||
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||
OPT_BOOL('z', NULL, &nul_term_line,
|
||||
N_("DEPRECATED (use --pathspec-file-nul instead): paths are separated with NUL character")),
|
||||
OPT_BOOL(0, "stdin", &read_from_stdin,
|
||||
N_("DEPRECATED (use --pathspec-from-file=- instead): read paths from <stdin>")),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -436,12 +428,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
|
||||
|
||||
if (read_from_stdin) {
|
||||
pathspec_from_file = "-";
|
||||
if (nul_term_line)
|
||||
pathspec_file_nul = 1;
|
||||
}
|
||||
|
||||
if (pathspec_from_file) {
|
||||
if (patch_mode)
|
||||
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
|
||||
|
||||
@@ -426,7 +426,6 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
|
||||
struct option *opts = NULL;
|
||||
int onb = 0, osz = 0, unb = 0, usz = 0;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
strbuf_addstr(&parsed, "set --");
|
||||
argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "cache.h"
|
||||
#include "pack.h"
|
||||
#include "parse-options.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char *const show_index_usage[] = {
|
||||
"git show-index [--object-format=<hash-algorithm>]",
|
||||
@@ -24,7 +23,6 @@ int cmd_show_index(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, show_index_options, show_index_usage, 0);
|
||||
|
||||
if (hash_name) {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "tag.h"
|
||||
#include "string-list.h"
|
||||
#include "parse-options.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char * const show_ref_usage[] = {
|
||||
N_("git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]"),
|
||||
|
||||
@@ -46,9 +46,10 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix)
|
||||
if (argc)
|
||||
usage_with_options(stripspace_usage, options);
|
||||
|
||||
if (mode == STRIP_COMMENTS || mode == COMMENT_LINES)
|
||||
if (mode == STRIP_COMMENTS || mode == COMMENT_LINES) {
|
||||
setup_git_directory_gently(&nongit);
|
||||
git_config(git_default_config, NULL);
|
||||
git_config(git_default_config, NULL);
|
||||
}
|
||||
|
||||
if (strbuf_read(&buf, 0, 1024) < 0)
|
||||
die_errno("could not read the input");
|
||||
|
||||
@@ -3399,7 +3399,6 @@ static struct cmd_struct commands[] = {
|
||||
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i;
|
||||
git_config(git_default_config, NULL);
|
||||
if (argc < 2 || !strcmp(argv[1], "-h"))
|
||||
usage("git submodule--helper <command>");
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "sideband.h"
|
||||
#include "run-command.h"
|
||||
#include "strvec.h"
|
||||
#include "config.h"
|
||||
|
||||
static const char upload_archive_usage[] =
|
||||
"git upload-archive <repo>";
|
||||
@@ -29,7 +28,6 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
|
||||
if (!enter_repo(argv[1], 0))
|
||||
die("'%s' does not appear to be a git repository", argv[1]);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
init_archivers();
|
||||
|
||||
/* put received options in sent_argv[] */
|
||||
@@ -81,7 +79,6 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct child_process writer = CHILD_PROCESS_INIT;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage(upload_archive_usage);
|
||||
|
||||
|
||||
1
cache.h
1
cache.h
@@ -1306,7 +1306,6 @@ 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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -161,12 +161,6 @@ then
|
||||
MAKEFLAGS="$MAKEFLAGS --jobs=10"
|
||||
test windows_nt != "$CI_OS_NAME" ||
|
||||
GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS"
|
||||
case "$CI_OS_NAME" in
|
||||
linux) runs_on_pool=ubuntu-latest;;
|
||||
macos|osx) runs_on_pool=macos-latest;;
|
||||
windows_nt) runs_on_pool=windows-latest;;
|
||||
*) echo "Unhandled OS: $CI_OS_NAME" >&2; exit 1;;
|
||||
esac
|
||||
elif test true = "$GITHUB_ACTIONS"
|
||||
then
|
||||
CI_TYPE=github-actions
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
|
||||
. ${0%/*}/lib.sh
|
||||
|
||||
case "$CI_OS_NAME" in
|
||||
windows*) cmd //c mklink //j t\\.prove "$(cygpath -aw "$cache_dir/.prove")";;
|
||||
*) ln -s "$cache_dir/.prove" t/.prove;;
|
||||
esac
|
||||
|
||||
run_tests=t
|
||||
|
||||
case "$jobname" in
|
||||
@@ -48,8 +53,4 @@ then
|
||||
fi
|
||||
check_unignored_build_artifacts
|
||||
|
||||
case " $MAKE_TARGETS " in
|
||||
*" all "*) make -C contrib/subtree test;;
|
||||
esac
|
||||
|
||||
save_good_tree
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
|
||||
. ${0%/*}/lib.sh
|
||||
|
||||
case "$CI_OS_NAME" in
|
||||
windows*) cmd //c mklink //j t\\.prove "$(cygpath -aw "$cache_dir/.prove")";;
|
||||
*) ln -s "$cache_dir/.prove" t/.prove;;
|
||||
esac
|
||||
|
||||
group "Run tests" make --quiet -C t T="$(cd t &&
|
||||
./helper/test-tool path-utils slice-tests "$1" "$2" t[0-9]*.sh |
|
||||
tr '\n' ' ')" ||
|
||||
handle_failed_tests
|
||||
|
||||
# Run the git subtree tests only if main tests succeeded
|
||||
test 0 != "$1" || make -C contrib/subtree test
|
||||
|
||||
check_unignored_build_artifacts
|
||||
|
||||
@@ -32,7 +32,7 @@ struct fsm_health_data
|
||||
|
||||
struct wt_moved
|
||||
{
|
||||
wchar_t wpath[MAX_LONG_PATH + 1];
|
||||
wchar_t wpath[MAX_PATH + 1];
|
||||
BY_HANDLE_FILE_INFORMATION bhfi;
|
||||
} wt_moved;
|
||||
};
|
||||
@@ -141,8 +141,8 @@ static int has_worktree_moved(struct fsmonitor_daemon_state *state,
|
||||
return 0;
|
||||
|
||||
case CTX_INIT:
|
||||
if (xutftowcs_long_path(data->wt_moved.wpath,
|
||||
state->path_worktree_watch.buf) < 0) {
|
||||
if (xutftowcs_path(data->wt_moved.wpath,
|
||||
state->path_worktree_watch.buf) < 0) {
|
||||
error(_("could not convert to wide characters: '%s'"),
|
||||
state->path_worktree_watch.buf);
|
||||
return -1;
|
||||
|
||||
@@ -25,7 +25,7 @@ struct one_watch
|
||||
DWORD count;
|
||||
|
||||
struct strbuf path;
|
||||
wchar_t wpath_longname[MAX_LONG_PATH + 1];
|
||||
wchar_t wpath_longname[MAX_PATH + 1];
|
||||
DWORD wpath_longname_len;
|
||||
|
||||
HANDLE hDir;
|
||||
@@ -128,8 +128,8 @@ normalize:
|
||||
*/
|
||||
static void check_for_shortnames(struct one_watch *watch)
|
||||
{
|
||||
wchar_t buf_in[MAX_LONG_PATH + 1];
|
||||
wchar_t buf_out[MAX_LONG_PATH + 1];
|
||||
wchar_t buf_in[MAX_PATH + 1];
|
||||
wchar_t buf_out[MAX_PATH + 1];
|
||||
wchar_t *last;
|
||||
wchar_t *p;
|
||||
|
||||
@@ -194,8 +194,8 @@ static enum get_relative_result get_relative_longname(
|
||||
const wchar_t *wpath, DWORD wpath_len,
|
||||
wchar_t *wpath_longname, size_t bufsize_wpath_longname)
|
||||
{
|
||||
wchar_t buf_in[2 * MAX_LONG_PATH + 1];
|
||||
wchar_t buf_out[MAX_LONG_PATH + 1];
|
||||
wchar_t buf_in[2 * MAX_PATH + 1];
|
||||
wchar_t buf_out[MAX_PATH + 1];
|
||||
DWORD root_len;
|
||||
DWORD out_len;
|
||||
|
||||
@@ -296,10 +296,10 @@ static struct one_watch *create_watch(struct fsmonitor_daemon_state *state,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE;
|
||||
HANDLE hDir;
|
||||
DWORD len_longname;
|
||||
wchar_t wpath[MAX_LONG_PATH + 1];
|
||||
wchar_t wpath_longname[MAX_LONG_PATH + 1];
|
||||
wchar_t wpath[MAX_PATH + 1];
|
||||
wchar_t wpath_longname[MAX_PATH + 1];
|
||||
|
||||
if (xutftowcs_long_path(wpath, path) < 0) {
|
||||
if (xutftowcs_path(wpath, path) < 0) {
|
||||
error(_("could not convert to wide characters: '%s'"), path);
|
||||
return NULL;
|
||||
}
|
||||
@@ -544,7 +544,7 @@ static int process_worktree_events(struct fsmonitor_daemon_state *state)
|
||||
struct string_list cookie_list = STRING_LIST_INIT_DUP;
|
||||
struct fsmonitor_batch *batch = NULL;
|
||||
const char *p = watch->buffer;
|
||||
wchar_t wpath_longname[MAX_LONG_PATH + 1];
|
||||
wchar_t wpath_longname[MAX_PATH + 1];
|
||||
|
||||
/*
|
||||
* If the kernel gets more events than will fit in the kernel
|
||||
|
||||
@@ -76,8 +76,8 @@ static enum fsmonitor_reason check_vfs4git(struct repository *r)
|
||||
*/
|
||||
static enum fsmonitor_reason check_remote(struct repository *r)
|
||||
{
|
||||
wchar_t wpath[MAX_LONG_PATH];
|
||||
wchar_t wfullpath[MAX_LONG_PATH];
|
||||
wchar_t wpath[MAX_PATH];
|
||||
wchar_t wfullpath[MAX_PATH];
|
||||
size_t wlen;
|
||||
UINT driveType;
|
||||
|
||||
@@ -85,7 +85,7 @@ static enum fsmonitor_reason check_remote(struct repository *r)
|
||||
* Do everything in wide chars because the drive letter might be
|
||||
* a multi-byte sequence. See win32_has_dos_drive_prefix().
|
||||
*/
|
||||
if (xutftowcs_long_path(wpath, r->worktree) < 0)
|
||||
if (xutftowcs_path(wpath, r->worktree) < 0)
|
||||
return FSMONITOR_REASON_ERROR;
|
||||
|
||||
/*
|
||||
@@ -103,7 +103,7 @@ static enum fsmonitor_reason check_remote(struct repository *r)
|
||||
* slashes to backslashes. This is essential to get GetDriveTypeW()
|
||||
* correctly handle some UNC "\\server\share\..." paths.
|
||||
*/
|
||||
if (!GetFullPathNameW(wpath, MAX_LONG_PATH, wfullpath, NULL))
|
||||
if (!GetFullPathNameW(wpath, MAX_PATH, wfullpath, NULL))
|
||||
return FSMONITOR_REASON_ERROR;
|
||||
|
||||
driveType = GetDriveTypeW(wfullpath);
|
||||
|
||||
1533
compat/mingw.c
1533
compat/mingw.c
File diff suppressed because it is too large
Load Diff
118
compat/mingw.h
118
compat/mingw.h
@@ -11,9 +11,6 @@ typedef _sigset_t sigset_t;
|
||||
#undef _POSIX_THREAD_SAFE_FUNCTIONS
|
||||
#endif
|
||||
|
||||
extern int core_fscache;
|
||||
extern int core_long_paths;
|
||||
|
||||
int mingw_core_config(const char *var, const char *value, void *cb);
|
||||
#define platform_core_config mingw_core_config
|
||||
|
||||
@@ -123,6 +120,10 @@ struct utsname {
|
||||
* trivial stubs
|
||||
*/
|
||||
|
||||
static inline int readlink(const char *path, char *buf, size_t bufsiz)
|
||||
{ errno = ENOSYS; return -1; }
|
||||
static inline int symlink(const char *oldpath, const char *newpath)
|
||||
{ errno = ENOSYS; return -1; }
|
||||
static inline int fchmod(int fildes, mode_t mode)
|
||||
{ errno = ENOSYS; return -1; }
|
||||
#ifndef __MINGW64_VERSION_MAJOR
|
||||
@@ -213,10 +214,6 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
|
||||
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
|
||||
int link(const char *oldpath, const char *newpath);
|
||||
int uname(struct utsname *buf);
|
||||
int readlink(const char *path, char *buf, size_t bufsiz);
|
||||
struct index_state;
|
||||
int mingw_create_symlink(struct index_state *index, const char *target, const char *link);
|
||||
#define create_symlink mingw_create_symlink
|
||||
|
||||
/*
|
||||
* replacements of existing functions
|
||||
@@ -354,17 +351,6 @@ static inline int getrlimit(int resource, struct rlimit *rlp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
|
||||
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
|
||||
*/
|
||||
static inline long long filetime_to_hnsec(const FILETIME *ft)
|
||||
{
|
||||
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
|
||||
/* Windows to Unix Epoch conversion */
|
||||
return winTime - 116444736000000000LL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use mingw specific stat()/lstat()/fstat() implementations on Windows,
|
||||
* including our own struct stat with 64 bit st_size and nanosecond-precision
|
||||
@@ -381,13 +367,6 @@ struct timespec {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
|
||||
{
|
||||
long long hnsec = filetime_to_hnsec(ft);
|
||||
ts->tv_sec = (time_t)(hnsec / 10000000);
|
||||
ts->tv_nsec = (hnsec % 10000000) * 100;
|
||||
}
|
||||
|
||||
struct mingw_stat {
|
||||
_dev_t st_dev;
|
||||
_ino_t st_ino;
|
||||
@@ -420,7 +399,7 @@ int mingw_fstat(int fd, struct stat *buf);
|
||||
#ifdef lstat
|
||||
#undef lstat
|
||||
#endif
|
||||
extern int (*lstat)(const char *file_name, struct stat *buf);
|
||||
#define lstat mingw_lstat
|
||||
|
||||
|
||||
int mingw_utime(const char *file_name, const struct utimbuf *times);
|
||||
@@ -470,17 +449,9 @@ static inline void convert_slashes(char *path)
|
||||
if (*path == '\\')
|
||||
*path = '/';
|
||||
}
|
||||
struct strbuf;
|
||||
int mingw_is_mount_point(struct strbuf *path);
|
||||
extern int (*win32_is_mount_point)(struct strbuf *path);
|
||||
#define is_mount_point win32_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
|
||||
struct strbuf;
|
||||
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"
|
||||
@@ -516,42 +487,6 @@ int is_path_owned_by_current_sid(const char *path);
|
||||
int is_valid_win32_path(const char *path, int allow_literal_nul);
|
||||
#define is_valid_path(path) is_valid_win32_path(path, 0)
|
||||
|
||||
/**
|
||||
* Max length of long paths (exceeding MAX_PATH). The actual maximum supported
|
||||
* by NTFS is 32,767 (* sizeof(wchar_t)), but we choose an arbitrary smaller
|
||||
* value to limit required stack memory.
|
||||
*/
|
||||
#define MAX_LONG_PATH 4096
|
||||
|
||||
/**
|
||||
* Handles paths that would exceed the MAX_PATH limit of Windows Unicode APIs.
|
||||
*
|
||||
* With expand == false, the function checks for over-long paths and fails
|
||||
* with ENAMETOOLONG. The path parameter is not modified, except if cwd + path
|
||||
* exceeds max_path, but the resulting absolute path doesn't (e.g. due to
|
||||
* eliminating '..' components). The path parameter must point to a buffer
|
||||
* of max_path wide characters.
|
||||
*
|
||||
* With expand == true, an over-long path is automatically converted in place
|
||||
* to an absolute path prefixed with '\\?\', and the new length is returned.
|
||||
* The path parameter must point to a buffer of MAX_LONG_PATH wide characters.
|
||||
*
|
||||
* Parameters:
|
||||
* path: path to check and / or convert
|
||||
* len: size of path on input (number of wide chars without \0)
|
||||
* max_path: max short path length to check (usually MAX_PATH = 260, but just
|
||||
* 248 for CreateDirectoryW)
|
||||
* expand: false to only check the length, true to expand the path to a
|
||||
* '\\?\'-prefixed absolute path
|
||||
*
|
||||
* Return:
|
||||
* length of the resulting path, or -1 on failure
|
||||
*
|
||||
* Errors:
|
||||
* ENAMETOOLONG if path is too long
|
||||
*/
|
||||
int handle_long_path(wchar_t *path, int len, int max_path, int expand);
|
||||
|
||||
/**
|
||||
* Converts UTF-8 encoded string to UTF-16LE.
|
||||
*
|
||||
@@ -609,45 +544,17 @@ static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
|
||||
return xutftowcsn(wcs, utf, wcslen, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified file system specific wrapper of xutftowcsn and handle_long_path.
|
||||
* Converts ERANGE to ENAMETOOLONG. If expand is true, wcs must be at least
|
||||
* MAX_LONG_PATH wide chars (see handle_long_path).
|
||||
*/
|
||||
static inline int xutftowcs_path_ex(wchar_t *wcs, const char *utf,
|
||||
size_t wcslen, int utflen, int max_path, int expand)
|
||||
{
|
||||
int result = xutftowcsn(wcs, utf, wcslen, utflen);
|
||||
if (result < 0 && errno == ERANGE)
|
||||
errno = ENAMETOOLONG;
|
||||
if (result >= 0)
|
||||
result = handle_long_path(wcs, result, max_path, expand);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified file system specific variant of xutftowcsn, assumes output
|
||||
* buffer size is MAX_PATH wide chars and input string is \0-terminated,
|
||||
* fails with ENAMETOOLONG if input string is too long. Typically used for
|
||||
* Windows APIs that don't support long paths, e.g. SetCurrentDirectory,
|
||||
* LoadLibrary, CreateProcess...
|
||||
* fails with ENAMETOOLONG if input string is too long.
|
||||
*/
|
||||
static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
|
||||
{
|
||||
return xutftowcs_path_ex(wcs, utf, MAX_PATH, -1, MAX_PATH, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified file system specific variant of xutftowcsn for Windows APIs
|
||||
* that support long paths via '\\?\'-prefix, assumes output buffer size is
|
||||
* MAX_LONG_PATH wide chars, fails with ENAMETOOLONG if input string is too
|
||||
* long. The 'core.longpaths' git-config option controls whether the path
|
||||
* is only checked or expanded to a long path.
|
||||
*/
|
||||
static inline int xutftowcs_long_path(wchar_t *wcs, const char *utf)
|
||||
{
|
||||
return xutftowcs_path_ex(wcs, utf, MAX_LONG_PATH, -1, MAX_PATH,
|
||||
core_long_paths);
|
||||
int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
|
||||
if (result < 0 && errno == ERANGE)
|
||||
errno = ENAMETOOLONG;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -719,8 +626,3 @@ void open_in_gdb(void);
|
||||
* Used by Pthread API implementation for Windows
|
||||
*/
|
||||
int err_win_to_posix(DWORD winerr);
|
||||
|
||||
/*
|
||||
* Check current process is inside Windows Container.
|
||||
*/
|
||||
int is_inside_windows_container(void);
|
||||
|
||||
@@ -418,55 +418,6 @@ static int getchar_with_timeout(int timeout)
|
||||
return getchar();
|
||||
}
|
||||
|
||||
static char *shell_prompt(const char *prompt, int echo)
|
||||
{
|
||||
const char *read_input[] = {
|
||||
/* Note: call 'bash' explicitly, as 'read -s' is bash-specific */
|
||||
"bash", "-c", echo ?
|
||||
"cat >/dev/tty && read -r line </dev/tty && echo \"$line\"" :
|
||||
"cat >/dev/tty && read -r -s line </dev/tty && echo \"$line\" && echo >/dev/tty",
|
||||
NULL
|
||||
};
|
||||
struct child_process child = CHILD_PROCESS_INIT;
|
||||
static struct strbuf buffer = STRBUF_INIT;
|
||||
int prompt_len = strlen(prompt), len = -1, code;
|
||||
|
||||
strvec_pushv(&child.args, read_input);
|
||||
child.in = -1;
|
||||
child.out = -1;
|
||||
child.silent_exec_failure = 1;
|
||||
|
||||
if (start_command(&child))
|
||||
return NULL;
|
||||
|
||||
if (write_in_full(child.in, prompt, prompt_len) != prompt_len) {
|
||||
error("could not write to prompt script");
|
||||
close(child.in);
|
||||
goto ret;
|
||||
}
|
||||
close(child.in);
|
||||
|
||||
strbuf_reset(&buffer);
|
||||
len = strbuf_read(&buffer, child.out, 1024);
|
||||
if (len < 0) {
|
||||
error("could not read from prompt script");
|
||||
goto ret;
|
||||
}
|
||||
|
||||
strbuf_strip_suffix(&buffer, "\n");
|
||||
strbuf_strip_suffix(&buffer, "\r");
|
||||
|
||||
ret:
|
||||
close(child.out);
|
||||
code = finish_command(&child);
|
||||
if (code) {
|
||||
error("failed to execute prompt script (exit code %d)", code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return len < 0 ? NULL : buffer.buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef FORCE_TEXT
|
||||
@@ -479,15 +430,6 @@ char *git_terminal_prompt(const char *prompt, int echo)
|
||||
int r;
|
||||
FILE *input_fh, *output_fh;
|
||||
|
||||
#ifdef GIT_WINDOWS_NATIVE
|
||||
|
||||
/* try shell_prompt first, fall back to CONIN/OUT if bash is missing */
|
||||
char *result = shell_prompt(prompt, echo);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
#endif
|
||||
|
||||
input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);
|
||||
if (!input_fh)
|
||||
return NULL;
|
||||
|
||||
@@ -6,11 +6,7 @@ The Steps to Build Git with VS2015 or VS2017 from the command line.
|
||||
Prompt or from an SDK bash window:
|
||||
|
||||
$ cd <repo_root>
|
||||
$ ./compat/vcbuild/vcpkg_install.bat x64-windows
|
||||
|
||||
or
|
||||
|
||||
$ ./compat/vcbuild/vcpkg_install.bat arm64-windows
|
||||
$ ./compat/vcbuild/vcpkg_install.bat
|
||||
|
||||
The vcpkg tools and all of the third-party sources will be installed
|
||||
in this folder:
|
||||
@@ -41,17 +37,27 @@ The Steps to Build Git with VS2015 or VS2017 from the command line.
|
||||
|
||||
================================================================
|
||||
|
||||
Alternatively, just open Git's top-level directory in Visual Studio, via
|
||||
`File>Open>Folder...`. This will use CMake internally to generate the
|
||||
project definitions. It will also install the vcpkg system and build the
|
||||
Alternatively, run `make vcxproj` and then load the generated `git.sln` in
|
||||
Visual Studio. The initial build will install the vcpkg system and build the
|
||||
dependencies automatically. This will take a while.
|
||||
|
||||
You can also generate the Visual Studio solution manually by downloading
|
||||
and running CMake explicitly rather than letting Visual Studio doing
|
||||
that implicitly.
|
||||
Instead of generating the `git.sln` file yourself (which requires a full Git
|
||||
for Windows SDK), you may want to consider fetching the `vs/master` branch of
|
||||
https://github.com/git-for-windows/git instead (which is updated automatically
|
||||
via CI running `make vcxproj`). The `vs/master` branch does not require a Git
|
||||
for Windows to build, but you can run the test scripts in a regular Git Bash.
|
||||
|
||||
Another, deprecated option is to run `make vcxproj`. This option is
|
||||
superseded by the CMake-based build, and will be removed at some point.
|
||||
Note that `make vcxproj` will automatically add and commit the generated `.sln`
|
||||
and `.vcxproj` files to the repo. This is necessary to allow building a
|
||||
fully-testable Git in Visual Studio, where a regular Git Bash can be used to
|
||||
run the test scripts (as opposed to a full Git for Windows SDK): a number of
|
||||
build targets, such as Git commands implemented as Unix shell scripts (where
|
||||
`@@SHELL_PATH@@` and other placeholders are interpolated) require a full-blown
|
||||
Git for Windows SDK (which is about 10x the size of a regular Git for Windows
|
||||
installation).
|
||||
|
||||
If your plan is to open a Pull Request with Git for Windows, it is a good idea
|
||||
to drop this commit before submitting.
|
||||
|
||||
================================================================
|
||||
The Steps of Build Git with VS2008
|
||||
|
||||
@@ -99,7 +99,6 @@ REM ================================================================
|
||||
|
||||
SET sdk_dir=%WindowsSdkDir%
|
||||
SET sdk_ver=%WindowsSDKVersion%
|
||||
SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%%tgt%
|
||||
SET si=%sdk_dir%Include\%sdk_ver%
|
||||
SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared"
|
||||
SET sl=%sdk_dir%lib\%sdk_ver%
|
||||
@@ -131,7 +130,6 @@ REM ================================================================
|
||||
|
||||
SET sdk_dir=%WindowsSdkDir%
|
||||
SET sdk_ver=%WindowsSDKVersion%
|
||||
SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%bin\amd64
|
||||
SET si=%sdk_dir%Include\%sdk_ver%
|
||||
SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared" -I"%si%winrt"
|
||||
SET sl=%sdk_dir%lib\%sdk_ver%
|
||||
@@ -162,11 +160,6 @@ REM ================================================================
|
||||
echo msvc_includes=%msvc_includes%
|
||||
echo msvc_libs=%msvc_libs%
|
||||
|
||||
echo sdk_ver_bin_dir=%sdk_ver_bin_dir%
|
||||
SET X1=%sdk_ver_bin_dir:C:=/C%
|
||||
SET X2=%X1:\=/%
|
||||
echo sdk_ver_bin_dir_msys=%X2%
|
||||
|
||||
echo sdk_includes=%sdk_includes%
|
||||
echo sdk_libs=%sdk_libs%
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ my @cflags = ();
|
||||
my @lflags = ();
|
||||
my $is_linking = 0;
|
||||
my $is_debug = 0;
|
||||
my $is_gui = 0;
|
||||
while (@ARGV) {
|
||||
my $arg = shift @ARGV;
|
||||
if ("$arg" eq "-DDEBUG") {
|
||||
@@ -57,8 +56,7 @@ while (@ARGV) {
|
||||
# need to use that instead?
|
||||
foreach my $flag (@lflags) {
|
||||
if ($flag =~ /^-LIBPATH:(.*)/) {
|
||||
my $libcurl = $is_debug ? "libcurl-d.lib" : "libcurl.lib";
|
||||
foreach my $l ("libcurl_imp.lib", $libcurl) {
|
||||
foreach my $l ("libcurl_imp.lib", "libcurl.lib") {
|
||||
if (-f "$1/$l") {
|
||||
$lib = $l;
|
||||
last;
|
||||
@@ -68,11 +66,7 @@ while (@ARGV) {
|
||||
}
|
||||
push(@args, $lib);
|
||||
} elsif ("$arg" eq "-lexpat") {
|
||||
if ($is_debug) {
|
||||
push(@args, "libexpatd.lib");
|
||||
} else {
|
||||
push(@args, "libexpat.lib");
|
||||
}
|
||||
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
|
||||
$arg =~ s/^-L/-LIBPATH:/;
|
||||
push(@lflags, $arg);
|
||||
@@ -124,23 +118,11 @@ while (@ARGV) {
|
||||
push(@cflags, "-wd4996");
|
||||
} elsif ("$arg" =~ /^-W[a-z]/) {
|
||||
# let's ignore those
|
||||
} elsif ("$arg" eq "-fno-stack-protector") {
|
||||
# eat this
|
||||
} elsif ("$arg" eq "-mwindows") {
|
||||
$is_gui = 1;
|
||||
} else {
|
||||
push(@args, $arg);
|
||||
}
|
||||
}
|
||||
if ($is_linking) {
|
||||
if ($is_gui) {
|
||||
push(@args, "-ENTRY:wWinMainCRTStartup");
|
||||
push(@args, "-SUBSYSTEM:WINDOWS");
|
||||
} else {
|
||||
push(@args, "-ENTRY:wmainCRTStartup");
|
||||
push(@args, "-SUBSYSTEM:CONSOLE");
|
||||
}
|
||||
|
||||
push(@args, @lflags);
|
||||
unshift(@args, "link.exe");
|
||||
} else {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
# Compile Resources on Windows
|
||||
#
|
||||
# This is a wrapper to facilitate the compilation of Git with MSVC
|
||||
# using GNU Make as the build system. So, instead of manipulating the
|
||||
# Makefile into something nasty, just to support non-space arguments
|
||||
# etc, we use this wrapper to fix the command line options
|
||||
#
|
||||
######################################################################
|
||||
use strict;
|
||||
my @args = ();
|
||||
my @input = ();
|
||||
|
||||
while (@ARGV) {
|
||||
my $arg = shift @ARGV;
|
||||
if ("$arg" =~ /^-[dD]/) {
|
||||
# GIT_VERSION gets passed with too many
|
||||
# layers of dquote escaping.
|
||||
$arg =~ s/\\"/"/g;
|
||||
|
||||
push(@args, $arg);
|
||||
|
||||
} elsif ("$arg" eq "-i") {
|
||||
my $arg = shift @ARGV;
|
||||
# TODO complain if NULL or is dashed ??
|
||||
push(@input, $arg);
|
||||
|
||||
} elsif ("$arg" eq "-o") {
|
||||
my $arg = shift @ARGV;
|
||||
# TODO complain if NULL or is dashed ??
|
||||
push(@args, "-fo$arg");
|
||||
|
||||
} else {
|
||||
push(@args, $arg);
|
||||
}
|
||||
}
|
||||
|
||||
push(@args, "-nologo");
|
||||
push(@args, "-v");
|
||||
push(@args, @input);
|
||||
|
||||
unshift(@args, "rc.exe");
|
||||
printf("**** @args\n");
|
||||
|
||||
exit (system(@args) != 0);
|
||||
@@ -15,12 +15,7 @@ REM ================================================================
|
||||
@FOR /F "delims=" %%D IN ("%~dp0") DO @SET cwd=%%~fD
|
||||
cd %cwd%
|
||||
|
||||
SET arch=%2
|
||||
IF NOT DEFINED arch (
|
||||
echo defaulting to 'x64-windows`. Invoke %0 with 'x86-windows', 'x64-windows', or 'arm64-windows'
|
||||
set arch=x64-windows
|
||||
)
|
||||
|
||||
SET arch=x64-windows
|
||||
SET inst=%cwd%vcpkg\installed\%arch%
|
||||
|
||||
IF [%1]==[release] (
|
||||
|
||||
@@ -31,24 +31,11 @@ REM ================================================================
|
||||
|
||||
SETLOCAL EnableDelayedExpansion
|
||||
|
||||
SET arch=%1
|
||||
IF NOT DEFINED arch (
|
||||
echo defaulting to 'x64-windows`. Invoke %0 with 'x86-windows', 'x64-windows', or 'arm64-windows'
|
||||
set arch=x64-windows
|
||||
)
|
||||
|
||||
@FOR /F "delims=" %%D IN ("%~dp0") DO @SET cwd=%%~fD
|
||||
cd %cwd%
|
||||
|
||||
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 )
|
||||
@@ -61,8 +48,9 @@ REM ================================================================
|
||||
echo Successfully installed %cwd%vcpkg\vcpkg.exe
|
||||
|
||||
:install_libraries
|
||||
SET arch=x64-windows
|
||||
|
||||
echo Installing third-party libraries(%arch%)...
|
||||
echo Installing third-party libraries...
|
||||
FOR %%i IN (zlib expat libiconv openssl libssh2 curl) DO (
|
||||
cd %cwd%vcpkg
|
||||
IF NOT EXIST "packages\%%i_%arch%" CALL :sub__install_one %%i
|
||||
@@ -85,47 +73,8 @@ REM ================================================================
|
||||
:sub__install_one
|
||||
echo Installing package %1...
|
||||
|
||||
call :%1_features
|
||||
|
||||
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%features%:%arch%
|
||||
.\vcpkg.exe install %1:%arch%
|
||||
IF ERRORLEVEL 1 ( EXIT /B 1 )
|
||||
|
||||
echo Finished %1
|
||||
goto :EOF
|
||||
|
||||
::
|
||||
:: features for each vcpkg to install
|
||||
:: there should be an entry here for each package to install
|
||||
:: 'set features=' means use the default otherwise
|
||||
:: 'set features=[comma-delimited-feature-set]' is the syntax
|
||||
::
|
||||
|
||||
:zlib_features
|
||||
set features=
|
||||
goto :EOF
|
||||
|
||||
:expat_features
|
||||
set features=
|
||||
goto :EOF
|
||||
|
||||
:libiconv_features
|
||||
set features=
|
||||
goto :EOF
|
||||
|
||||
:openssl_features
|
||||
set features=
|
||||
goto :EOF
|
||||
|
||||
:libssh2_features
|
||||
set features=
|
||||
goto :EOF
|
||||
|
||||
:curl_features
|
||||
set features=[core,openssl,schannel]
|
||||
goto :EOF
|
||||
|
||||
@@ -6,7 +6,17 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
extern int file_attr_to_st_mode (DWORD attr, DWORD tag, const char *path);
|
||||
static inline int file_attr_to_st_mode (DWORD attr)
|
||||
{
|
||||
int fMode = S_IREAD;
|
||||
if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
fMode |= S_IFDIR;
|
||||
else
|
||||
fMode |= S_IFREG;
|
||||
if (!(attr & FILE_ATTRIBUTE_READONLY))
|
||||
fMode |= S_IWRITE;
|
||||
return fMode;
|
||||
}
|
||||
|
||||
static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
|
||||
{
|
||||
|
||||
@@ -1,33 +1,58 @@
|
||||
#include "../../git-compat-util.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
typedef struct dirent_DIR {
|
||||
struct DIR base_dir; /* extend base struct DIR */
|
||||
struct DIR {
|
||||
struct dirent dd_dir; /* includes d_type */
|
||||
HANDLE dd_handle; /* FindFirstFile handle */
|
||||
int dd_stat; /* 0-based index */
|
||||
struct dirent dd_dir; /* includes d_type */
|
||||
} dirent_DIR;
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
DIR *(*opendir)(const char *dirname) = dirent_opendir;
|
||||
};
|
||||
|
||||
static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
|
||||
{
|
||||
/* convert UTF-16 name to UTF-8 (d_name points to dirent_DIR.dd_name) */
|
||||
xwcstoutf(ent->d_name, fdata->cFileName, MAX_PATH * 3);
|
||||
/* convert UTF-16 name to UTF-8 */
|
||||
xwcstoutf(ent->d_name, fdata->cFileName, sizeof(ent->d_name));
|
||||
|
||||
/* Set file type, based on WIN32_FIND_DATA */
|
||||
if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
&& fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
|
||||
ent->d_type = DT_LNK;
|
||||
else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
ent->d_type = DT_DIR;
|
||||
else
|
||||
ent->d_type = DT_REG;
|
||||
}
|
||||
|
||||
static struct dirent *dirent_readdir(dirent_DIR *dir)
|
||||
DIR *opendir(const char *name)
|
||||
{
|
||||
wchar_t pattern[MAX_PATH + 2]; /* + 2 for '/' '*' */
|
||||
WIN32_FIND_DATAW fdata;
|
||||
HANDLE h;
|
||||
int len;
|
||||
DIR *dir;
|
||||
|
||||
/* convert name to UTF-16 and check length < MAX_PATH */
|
||||
if ((len = xutftowcs_path(pattern, name)) < 0)
|
||||
return NULL;
|
||||
|
||||
/* append optional '/' and wildcard '*' */
|
||||
if (len && !is_dir_sep(pattern[len - 1]))
|
||||
pattern[len++] = '/';
|
||||
pattern[len++] = '*';
|
||||
pattern[len] = 0;
|
||||
|
||||
/* open find handle */
|
||||
h = FindFirstFileW(pattern, &fdata);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD err = GetLastError();
|
||||
errno = (err == ERROR_DIRECTORY) ? ENOTDIR : err_win_to_posix(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize DIR structure and copy first dir entry */
|
||||
dir = xmalloc(sizeof(DIR));
|
||||
dir->dd_handle = h;
|
||||
dir->dd_stat = 0;
|
||||
finddata2dirent(&dir->dd_dir, &fdata);
|
||||
return dir;
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *dir)
|
||||
{
|
||||
if (!dir) {
|
||||
errno = EBADF; /* No set_errno for mingw */
|
||||
@@ -54,7 +79,7 @@ static struct dirent *dirent_readdir(dirent_DIR *dir)
|
||||
return &dir->dd_dir;
|
||||
}
|
||||
|
||||
static int dirent_closedir(dirent_DIR *dir)
|
||||
int closedir(DIR *dir)
|
||||
{
|
||||
if (!dir) {
|
||||
errno = EBADF;
|
||||
@@ -65,43 +90,3 @@ static int dirent_closedir(dirent_DIR *dir)
|
||||
free(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR *dirent_opendir(const char *name)
|
||||
{
|
||||
wchar_t pattern[MAX_LONG_PATH + 2]; /* + 2 for "\*" */
|
||||
WIN32_FIND_DATAW fdata;
|
||||
HANDLE h;
|
||||
int len;
|
||||
dirent_DIR *dir;
|
||||
|
||||
/* convert name to UTF-16 and check length */
|
||||
if ((len = xutftowcs_path_ex(pattern, name, MAX_LONG_PATH, -1,
|
||||
MAX_PATH - 2, core_long_paths)) < 0)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* append optional '\' and wildcard '*'. Note: we need to use '\' as
|
||||
* Windows doesn't translate '/' to '\' for "\\?\"-prefixed paths.
|
||||
*/
|
||||
if (len && !is_dir_sep(pattern[len - 1]))
|
||||
pattern[len++] = '\\';
|
||||
pattern[len++] = '*';
|
||||
pattern[len] = 0;
|
||||
|
||||
/* open find handle */
|
||||
h = FindFirstFileW(pattern, &fdata);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD err = GetLastError();
|
||||
errno = (err == ERROR_DIRECTORY) ? ENOTDIR : err_win_to_posix(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize DIR structure and copy first dir entry */
|
||||
dir = xmalloc(sizeof(dirent_DIR) + MAX_LONG_PATH);
|
||||
dir->base_dir.preaddir = (struct dirent *(*)(DIR *dir)) dirent_readdir;
|
||||
dir->base_dir.pclosedir = (int (*)(DIR *dir)) dirent_closedir;
|
||||
dir->dd_handle = h;
|
||||
dir->dd_stat = 0;
|
||||
finddata2dirent(&dir->dd_dir, &fdata);
|
||||
return (DIR*) dir;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,20 @@
|
||||
#ifndef DIRENT_H
|
||||
#define DIRENT_H
|
||||
|
||||
typedef struct DIR DIR;
|
||||
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_DIR 1
|
||||
#define DT_REG 2
|
||||
#define DT_LNK 3
|
||||
|
||||
struct dirent {
|
||||
unsigned char d_type; /* file type to prevent lstat after readdir */
|
||||
char d_name[FLEX_ARRAY]; /* file name */
|
||||
unsigned char d_type; /* file type to prevent lstat after readdir */
|
||||
char d_name[MAX_PATH * 3]; /* file name (* 3 for UTF-8 conversion) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Base DIR structure, contains pointers to readdir/closedir implementations so
|
||||
* that opendir may choose a concrete implementation on a call-by-call basis.
|
||||
*/
|
||||
typedef struct DIR {
|
||||
struct dirent *(*preaddir)(struct DIR *dir);
|
||||
int (*pclosedir)(struct DIR *dir);
|
||||
} DIR;
|
||||
|
||||
/* default dirent implementation */
|
||||
extern DIR *dirent_opendir(const char *dirname);
|
||||
|
||||
/* current dirent implementation */
|
||||
extern DIR *(*opendir)(const char *dirname);
|
||||
|
||||
#define readdir(dir) (dir->preaddir(dir))
|
||||
#define closedir(dir) (dir->pclosedir(dir))
|
||||
DIR *opendir(const char *dirname);
|
||||
struct dirent *readdir(DIR *dir);
|
||||
int closedir(DIR *dir);
|
||||
|
||||
#endif /* DIRENT_H */
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
#ifndef EXIT_PROCESS_H
|
||||
#define EXIT_PROCESS_H
|
||||
|
||||
/*
|
||||
* This file contains functions to terminate a Win32 process, as gently as
|
||||
* possible.
|
||||
*
|
||||
* At first, we will attempt to inject a thread that calls ExitProcess(). If
|
||||
* that fails, we will fall back to terminating the entire process tree.
|
||||
*
|
||||
* For simplicity, these functions are marked as file-local.
|
||||
*/
|
||||
|
||||
#include <tlhelp32.h>
|
||||
|
||||
/*
|
||||
* Terminates the process corresponding to the process ID and all of its
|
||||
* directly and indirectly spawned subprocesses.
|
||||
*
|
||||
* This way of terminating the processes is not gentle: the processes get
|
||||
* no chance of cleaning up after themselves (closing file handles, removing
|
||||
* .lock files, terminating spawned processes (if any), etc).
|
||||
*/
|
||||
static int terminate_process_tree(HANDLE main_process, int exit_status)
|
||||
{
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 entry;
|
||||
DWORD pids[16384];
|
||||
int max_len = sizeof(pids) / sizeof(*pids), i, len, ret = 0;
|
||||
pid_t pid = GetProcessId(main_process);
|
||||
|
||||
pids[0] = (DWORD)pid;
|
||||
len = 1;
|
||||
|
||||
/*
|
||||
* Even if Process32First()/Process32Next() seem to traverse the
|
||||
* processes in topological order (i.e. parent processes before
|
||||
* child processes), there is nothing in the Win32 API documentation
|
||||
* suggesting that this is guaranteed.
|
||||
*
|
||||
* Therefore, run through them at least twice and stop when no more
|
||||
* process IDs were added to the list.
|
||||
*/
|
||||
for (;;) {
|
||||
int orig_len = len;
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.dwSize = sizeof(entry);
|
||||
|
||||
if (!Process32First(snapshot, &entry))
|
||||
break;
|
||||
|
||||
do {
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if (pids[i] == entry.th32ProcessID)
|
||||
break;
|
||||
if (pids[i] == entry.th32ParentProcessID)
|
||||
pids[len++] = entry.th32ProcessID;
|
||||
}
|
||||
} while (len < max_len && Process32Next(snapshot, &entry));
|
||||
|
||||
if (orig_len == len || len >= max_len)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = len - 1; i > 0; i--) {
|
||||
HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, pids[i]);
|
||||
|
||||
if (process) {
|
||||
if (!TerminateProcess(process, exit_status))
|
||||
ret = -1;
|
||||
CloseHandle(process);
|
||||
}
|
||||
}
|
||||
if (!TerminateProcess(main_process, exit_status))
|
||||
ret = -1;
|
||||
CloseHandle(main_process);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a process runs in the same architecture as the current
|
||||
* one. That test is required before we assume that GetProcAddress() returns
|
||||
* a valid address *for the target process*.
|
||||
*/
|
||||
static inline int process_architecture_matches_current(HANDLE process)
|
||||
{
|
||||
static BOOL current_is_wow = -1;
|
||||
BOOL is_wow;
|
||||
|
||||
if (current_is_wow == -1 &&
|
||||
!IsWow64Process (GetCurrentProcess(), ¤t_is_wow))
|
||||
current_is_wow = -2;
|
||||
if (current_is_wow == -2)
|
||||
return 0; /* could not determine current process' WoW-ness */
|
||||
if (!IsWow64Process (process, &is_wow))
|
||||
return 0; /* cannot determine */
|
||||
return is_wow == current_is_wow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a thread into the given process that runs ExitProcess().
|
||||
*
|
||||
* Note: as kernel32.dll is loaded before any process, the other process and
|
||||
* this process will have ExitProcess() at the same address.
|
||||
*
|
||||
* This function expects the process handle to have the access rights for
|
||||
* CreateRemoteThread(): PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION,
|
||||
* PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ.
|
||||
*
|
||||
* The idea comes from the Dr Dobb's article "A Safer Alternative to
|
||||
* TerminateProcess()" by Andrew Tucker (July 1, 1999),
|
||||
* http://www.drdobbs.com/a-safer-alternative-to-terminateprocess/184416547
|
||||
*
|
||||
* If this method fails, we fall back to running terminate_process_tree().
|
||||
*/
|
||||
static int exit_process(HANDLE process, int exit_code)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
if (GetExitCodeProcess(process, &code) && code == STILL_ACTIVE) {
|
||||
static int initialized;
|
||||
static LPTHREAD_START_ROUTINE exit_process_address;
|
||||
PVOID arg = (PVOID)(intptr_t)exit_code;
|
||||
DWORD thread_id;
|
||||
HANDLE thread = NULL;
|
||||
|
||||
if (!initialized) {
|
||||
HINSTANCE kernel32 = GetModuleHandleA("kernel32");
|
||||
if (!kernel32)
|
||||
die("BUG: cannot find kernel32");
|
||||
exit_process_address =
|
||||
(LPTHREAD_START_ROUTINE)(void (*)(void))
|
||||
GetProcAddress(kernel32, "ExitProcess");
|
||||
initialized = 1;
|
||||
}
|
||||
if (!exit_process_address ||
|
||||
!process_architecture_matches_current(process))
|
||||
return terminate_process_tree(process, exit_code);
|
||||
|
||||
thread = CreateRemoteThread(process, NULL, 0,
|
||||
exit_process_address,
|
||||
arg, 0, &thread_id);
|
||||
if (thread) {
|
||||
CloseHandle(thread);
|
||||
/*
|
||||
* If the process survives for 10 seconds (a completely
|
||||
* arbitrary value picked from thin air), fall back to
|
||||
* killing the process tree via TerminateProcess().
|
||||
*/
|
||||
if (WaitForSingleObject(process, 10000) ==
|
||||
WAIT_OBJECT_0) {
|
||||
CloseHandle(process);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return terminate_process_tree(process, exit_code);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,787 +0,0 @@
|
||||
#include "../../cache.h"
|
||||
#include "../../hashmap.h"
|
||||
#include "../win32.h"
|
||||
#include "fscache.h"
|
||||
#include "../../dir.h"
|
||||
#include "config.h"
|
||||
#include "../../mem-pool.h"
|
||||
#include "ntifs.h"
|
||||
|
||||
static volatile long initialized;
|
||||
static DWORD dwTlsIndex;
|
||||
CRITICAL_SECTION fscache_cs;
|
||||
|
||||
/*
|
||||
* Store one fscache per thread to avoid thread contention and locking.
|
||||
* This is ok because multi-threaded access is 1) uncommon and 2) always
|
||||
* splitting up the cache entries across multiple threads so there isn't
|
||||
* any overlap between threads anyway.
|
||||
*/
|
||||
struct fscache {
|
||||
volatile long enabled;
|
||||
struct hashmap map;
|
||||
struct mem_pool mem_pool;
|
||||
unsigned int lstat_requests;
|
||||
unsigned int opendir_requests;
|
||||
unsigned int fscache_requests;
|
||||
unsigned int fscache_misses;
|
||||
/*
|
||||
* 32k wide characters translates to 64kB, which is the maximum that
|
||||
* Windows 8.1 and earlier can handle. On network drives, not only
|
||||
* the client's Windows version matters, but also the server's,
|
||||
* therefore we need to keep this to 64kB.
|
||||
*/
|
||||
WCHAR buffer[32 * 1024];
|
||||
};
|
||||
static struct trace_key trace_fscache = TRACE_KEY_INIT(FSCACHE);
|
||||
|
||||
/*
|
||||
* An entry in the file system cache. Used for both entire directory listings
|
||||
* and file entries.
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
struct fsentry {
|
||||
struct hashmap_entry ent;
|
||||
mode_t st_mode;
|
||||
ULONG reparse_tag;
|
||||
/* Pointer to the directory listing, or NULL for the listing itself. */
|
||||
struct fsentry *list;
|
||||
/* Pointer to the next file entry of the list. */
|
||||
struct fsentry *next;
|
||||
|
||||
union {
|
||||
/* Reference count of the directory listing. */
|
||||
volatile long refcnt;
|
||||
struct {
|
||||
/* More stat members (only used for file entries). */
|
||||
off64_t st_size;
|
||||
struct timespec st_atim;
|
||||
struct timespec st_mtim;
|
||||
struct timespec st_ctim;
|
||||
} s;
|
||||
} u;
|
||||
|
||||
/* Length of name. */
|
||||
unsigned short len;
|
||||
/*
|
||||
* Name of the entry. For directory listings: relative path of the
|
||||
* directory, without trailing '/' (empty for cwd()). For file entries:
|
||||
* name of the file. Typically points to the end of the structure if
|
||||
* the fsentry is allocated on the heap (see fsentry_alloc), or to a
|
||||
* local variable if on the stack (see fsentry_init).
|
||||
*/
|
||||
struct dirent dirent;
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
struct heap_fsentry {
|
||||
union {
|
||||
struct fsentry ent;
|
||||
char dummy[sizeof(struct fsentry) + MAX_LONG_PATH];
|
||||
} u;
|
||||
};
|
||||
|
||||
/*
|
||||
* Compares the paths of two fsentry structures for equality.
|
||||
*/
|
||||
static int fsentry_cmp(void *unused_cmp_data,
|
||||
const struct fsentry *fse1, const struct fsentry *fse2,
|
||||
void *unused_keydata)
|
||||
{
|
||||
int res;
|
||||
if (fse1 == fse2)
|
||||
return 0;
|
||||
|
||||
/* compare the list parts first */
|
||||
if (fse1->list != fse2->list &&
|
||||
(res = fsentry_cmp(NULL, fse1->list ? fse1->list : fse1,
|
||||
fse2->list ? fse2->list : fse2, NULL)))
|
||||
return res;
|
||||
|
||||
/* if list parts are equal, compare len and name */
|
||||
if (fse1->len != fse2->len)
|
||||
return fse1->len - fse2->len;
|
||||
return fspathncmp(fse1->dirent.d_name, fse2->dirent.d_name, fse1->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculates the hash code of an fsentry structure's path.
|
||||
*/
|
||||
static unsigned int fsentry_hash(const struct fsentry *fse)
|
||||
{
|
||||
unsigned int hash = fse->list ? fse->list->ent.hash : 0;
|
||||
return hash ^ memihash(fse->dirent.d_name, fse->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an fsentry structure for use by fsentry_hash and fsentry_cmp.
|
||||
*/
|
||||
static void fsentry_init(struct fsentry *fse, struct fsentry *list,
|
||||
const char *name, size_t len)
|
||||
{
|
||||
fse->list = list;
|
||||
if (len > MAX_LONG_PATH)
|
||||
BUG("Trying to allocate fsentry for long path '%.*s'",
|
||||
(int)len, name);
|
||||
memcpy(fse->dirent.d_name, name, len);
|
||||
fse->dirent.d_name[len] = 0;
|
||||
fse->len = len;
|
||||
hashmap_entry_init(&fse->ent, fsentry_hash(fse));
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an fsentry structure on the heap.
|
||||
*/
|
||||
static struct fsentry *fsentry_alloc(struct fscache *cache, struct fsentry *list, const char *name,
|
||||
size_t len)
|
||||
{
|
||||
/* overallocate fsentry and copy the name to the end */
|
||||
struct fsentry *fse =
|
||||
mem_pool_alloc(&cache->mem_pool, sizeof(*fse) + len + 1);
|
||||
/* init the rest of the structure */
|
||||
fsentry_init(fse, list, name, len);
|
||||
fse->next = NULL;
|
||||
fse->u.refcnt = 1;
|
||||
return fse;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a reference to an fsentry.
|
||||
*/
|
||||
inline static void fsentry_addref(struct fsentry *fse)
|
||||
{
|
||||
if (fse->list)
|
||||
fse = fse->list;
|
||||
|
||||
InterlockedIncrement(&(fse->u.refcnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the reference to an fsentry.
|
||||
*/
|
||||
static void fsentry_release(struct fsentry *fse)
|
||||
{
|
||||
if (fse->list)
|
||||
fse = fse->list;
|
||||
|
||||
InterlockedDecrement(&(fse->u.refcnt));
|
||||
}
|
||||
|
||||
static int xwcstoutfn(char *utf, int utflen, const wchar_t *wcs, int wcslen)
|
||||
{
|
||||
if (!wcs || !utf || utflen < 1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
utflen = WideCharToMultiByte(CP_UTF8, 0, wcs, wcslen, utf, utflen, NULL, NULL);
|
||||
if (utflen)
|
||||
return utflen;
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialize an fsentry from a FILE_FULL_DIR_INFORMATION structure.
|
||||
*/
|
||||
static struct fsentry *fseentry_create_entry(struct fscache *cache,
|
||||
struct fsentry *list,
|
||||
PFILE_FULL_DIR_INFORMATION fdata)
|
||||
{
|
||||
char buf[MAX_PATH * 3];
|
||||
int len;
|
||||
struct fsentry *fse;
|
||||
|
||||
len = xwcstoutfn(buf, ARRAY_SIZE(buf), fdata->FileName, fdata->FileNameLength / sizeof(wchar_t));
|
||||
|
||||
fse = fsentry_alloc(cache, list, buf, len);
|
||||
|
||||
fse->reparse_tag =
|
||||
fdata->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ?
|
||||
fdata->EaSize : 0;
|
||||
|
||||
/*
|
||||
* On certain Windows versions, host directories mapped into
|
||||
* Windows Containers ("Volumes", see https://docs.docker.com/storage/volumes/)
|
||||
* look like symbolic links, but their targets are paths that
|
||||
* are valid only in kernel mode.
|
||||
*
|
||||
* Let's work around this by detecting that situation and
|
||||
* telling Git that these are *not* symbolic links.
|
||||
*/
|
||||
if (fse->reparse_tag == IO_REPARSE_TAG_SYMLINK &&
|
||||
sizeof(buf) > (list ? list->len + 1 : 0) + fse->len + 1 &&
|
||||
is_inside_windows_container()) {
|
||||
size_t off = 0;
|
||||
if (list) {
|
||||
memcpy(buf, list->dirent.d_name, list->len);
|
||||
buf[list->len] = '/';
|
||||
off = list->len + 1;
|
||||
}
|
||||
memcpy(buf + off, fse->dirent.d_name, fse->len);
|
||||
buf[off + fse->len] = '\0';
|
||||
}
|
||||
|
||||
fse->st_mode = file_attr_to_st_mode(fdata->FileAttributes,
|
||||
fdata->EaSize, buf);
|
||||
fse->dirent.d_type = S_ISREG(fse->st_mode) ? DT_REG :
|
||||
S_ISDIR(fse->st_mode) ? DT_DIR : DT_LNK;
|
||||
fse->u.s.st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
|
||||
fdata->EndOfFile.LowPart |
|
||||
(((off_t)fdata->EndOfFile.HighPart) << 32);
|
||||
filetime_to_timespec((FILETIME *)&(fdata->LastAccessTime),
|
||||
&(fse->u.s.st_atim));
|
||||
filetime_to_timespec((FILETIME *)&(fdata->LastWriteTime),
|
||||
&(fse->u.s.st_mtim));
|
||||
filetime_to_timespec((FILETIME *)&(fdata->CreationTime),
|
||||
&(fse->u.s.st_ctim));
|
||||
|
||||
return fse;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an fsentry-based directory listing (similar to opendir / readdir).
|
||||
* Dir should not contain trailing '/'. Use an empty string for the current
|
||||
* directory (not "."!).
|
||||
*/
|
||||
static struct fsentry *fsentry_create_list(struct fscache *cache, const struct fsentry *dir,
|
||||
int *dir_not_found)
|
||||
{
|
||||
wchar_t pattern[MAX_LONG_PATH];
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
PFILE_FULL_DIR_INFORMATION di;
|
||||
HANDLE h;
|
||||
int wlen;
|
||||
struct fsentry *list, **phead;
|
||||
DWORD err;
|
||||
|
||||
*dir_not_found = 0;
|
||||
|
||||
/* convert name to UTF-16 and check length */
|
||||
if ((wlen = xutftowcs_path_ex(pattern, dir->dirent.d_name,
|
||||
MAX_LONG_PATH, dir->len, MAX_PATH - 2,
|
||||
core_long_paths)) < 0)
|
||||
return NULL;
|
||||
|
||||
/* handle CWD */
|
||||
if (!wlen) {
|
||||
wlen = GetCurrentDirectoryW(ARRAY_SIZE(pattern), pattern);
|
||||
if (!wlen || wlen >= ARRAY_SIZE(pattern)) {
|
||||
errno = wlen ? ENAMETOOLONG : err_win_to_posix(GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
h = CreateFileW(pattern, FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
*dir_not_found = 1; /* or empty directory */
|
||||
errno = (err == ERROR_DIRECTORY) ? ENOTDIR : err_win_to_posix(err);
|
||||
trace_printf_key(&trace_fscache, "fscache: error(%d) '%s'\n",
|
||||
errno, dir->dirent.d_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* allocate object to hold directory listing */
|
||||
list = fsentry_alloc(cache, NULL, dir->dirent.d_name, dir->len);
|
||||
list->st_mode = S_IFDIR;
|
||||
list->dirent.d_type = DT_DIR;
|
||||
|
||||
/* walk directory and build linked list of fsentry structures */
|
||||
phead = &list->next;
|
||||
status = NtQueryDirectoryFile(h, NULL, 0, 0, &iosb, cache->buffer,
|
||||
sizeof(cache->buffer), FileFullDirectoryInformation, FALSE, NULL, FALSE);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
/*
|
||||
* NtQueryDirectoryFile returns STATUS_INVALID_PARAMETER when
|
||||
* asked to enumerate an invalid directory (ie it is a file
|
||||
* instead of a directory). Verify that is the actual cause
|
||||
* of the error.
|
||||
*/
|
||||
if (status == STATUS_INVALID_PARAMETER) {
|
||||
DWORD attributes = GetFileAttributesW(pattern);
|
||||
if (!(attributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
status = ERROR_DIRECTORY;
|
||||
}
|
||||
goto Error;
|
||||
}
|
||||
di = (PFILE_FULL_DIR_INFORMATION)(cache->buffer);
|
||||
for (;;) {
|
||||
|
||||
*phead = fseentry_create_entry(cache, list, di);
|
||||
phead = &(*phead)->next;
|
||||
|
||||
/* If there is no offset in the entry, the buffer has been exhausted. */
|
||||
if (di->NextEntryOffset == 0) {
|
||||
status = NtQueryDirectoryFile(h, NULL, 0, 0, &iosb, cache->buffer,
|
||||
sizeof(cache->buffer), FileFullDirectoryInformation, FALSE, NULL, FALSE);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (status == STATUS_NO_MORE_FILES)
|
||||
break;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
di = (PFILE_FULL_DIR_INFORMATION)(cache->buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Advance to the next entry. */
|
||||
di = (PFILE_FULL_DIR_INFORMATION)(((PUCHAR)di) + di->NextEntryOffset);
|
||||
}
|
||||
|
||||
CloseHandle(h);
|
||||
return list;
|
||||
|
||||
Error:
|
||||
trace_printf_key(&trace_fscache,
|
||||
"fscache: status(%ld) unable to query directory "
|
||||
"contents '%s'\n", status, dir->dirent.d_name);
|
||||
CloseHandle(h);
|
||||
fsentry_release(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a directory listing to the cache.
|
||||
*/
|
||||
static void fscache_add(struct fscache *cache, struct fsentry *fse)
|
||||
{
|
||||
if (fse->list)
|
||||
fse = fse->list;
|
||||
|
||||
for (; fse; fse = fse->next)
|
||||
hashmap_add(&cache->map, &fse->ent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clears the cache.
|
||||
*/
|
||||
static void fscache_clear(struct fscache *cache)
|
||||
{
|
||||
mem_pool_discard(&cache->mem_pool, 0);
|
||||
mem_pool_init(&cache->mem_pool, 0);
|
||||
hashmap_clear(&cache->map);
|
||||
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
|
||||
cache->lstat_requests = cache->opendir_requests = 0;
|
||||
cache->fscache_misses = cache->fscache_requests = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the cache is enabled for the given path.
|
||||
*/
|
||||
static int do_fscache_enabled(struct fscache *cache, const char *path)
|
||||
{
|
||||
return cache->enabled > 0 && !is_absolute_path(path);
|
||||
}
|
||||
|
||||
int fscache_enabled(const char *path)
|
||||
{
|
||||
struct fscache *cache = fscache_getcache();
|
||||
|
||||
return cache ? do_fscache_enabled(cache, path) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks up or creates a cache entry for the specified key.
|
||||
*/
|
||||
static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
|
||||
{
|
||||
struct fsentry *fse;
|
||||
int dir_not_found;
|
||||
|
||||
cache->fscache_requests++;
|
||||
/* check if entry is in cache */
|
||||
fse = hashmap_get_entry(&cache->map, key, ent, NULL);
|
||||
if (fse) {
|
||||
if (fse->st_mode)
|
||||
fsentry_addref(fse);
|
||||
else
|
||||
fse = NULL; /* non-existing directory */
|
||||
return fse;
|
||||
}
|
||||
/* if looking for a file, check if directory listing is in cache */
|
||||
if (!fse && key->list) {
|
||||
fse = hashmap_get_entry(&cache->map, key->list, ent, NULL);
|
||||
if (fse) {
|
||||
/*
|
||||
* dir entry without file entry, or dir does not
|
||||
* exist -> file doesn't exist
|
||||
*/
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* create the directory listing */
|
||||
fse = fsentry_create_list(cache, key->list ? key->list : key, &dir_not_found);
|
||||
|
||||
/* leave on error (errno set by fsentry_create_list) */
|
||||
if (!fse) {
|
||||
if (dir_not_found && key->list) {
|
||||
/*
|
||||
* Record that the directory does not exist (or is
|
||||
* empty, which for all practical matters is the same
|
||||
* thing as far as fscache is concerned).
|
||||
*/
|
||||
fse = fsentry_alloc(cache, key->list->list,
|
||||
key->list->dirent.d_name,
|
||||
key->list->len);
|
||||
fse->st_mode = 0;
|
||||
hashmap_add(&cache->map, &fse->ent);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add directory listing to the cache */
|
||||
cache->fscache_misses++;
|
||||
fscache_add(cache, fse);
|
||||
|
||||
/* lookup file entry if requested (fse already points to directory) */
|
||||
if (key->list)
|
||||
fse = hashmap_get_entry(&cache->map, key, ent, NULL);
|
||||
|
||||
if (fse && !fse->st_mode)
|
||||
fse = NULL; /* non-existing directory */
|
||||
|
||||
/* return entry or ENOENT */
|
||||
if (fse)
|
||||
fsentry_addref(fse);
|
||||
else
|
||||
errno = ENOENT;
|
||||
|
||||
return fse;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enables the cache. Note that the cache is read-only, changes to
|
||||
* the working directory are NOT reflected in the cache while enabled.
|
||||
*/
|
||||
int fscache_enable(size_t initial_size)
|
||||
{
|
||||
int fscache;
|
||||
struct fscache *cache;
|
||||
int result = 0;
|
||||
|
||||
/* allow the cache to be disabled entirely */
|
||||
fscache = git_env_bool("GIT_TEST_FSCACHE", -1);
|
||||
if (fscache != -1)
|
||||
core_fscache = fscache;
|
||||
if (!core_fscache)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* refcount the global fscache initialization so that the
|
||||
* opendir and lstat function pointers are redirected if
|
||||
* any threads are using the fscache.
|
||||
*/
|
||||
EnterCriticalSection(&fscache_cs);
|
||||
if (!initialized) {
|
||||
if (!dwTlsIndex) {
|
||||
dwTlsIndex = TlsAlloc();
|
||||
if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
|
||||
LeaveCriticalSection(&fscache_cs);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* redirect opendir and lstat to the fscache implementations */
|
||||
opendir = fscache_opendir;
|
||||
lstat = fscache_lstat;
|
||||
win32_is_mount_point = fscache_is_mount_point;
|
||||
}
|
||||
initialized++;
|
||||
LeaveCriticalSection(&fscache_cs);
|
||||
|
||||
/* refcount the thread specific initialization */
|
||||
cache = fscache_getcache();
|
||||
if (cache) {
|
||||
cache->enabled++;
|
||||
} else {
|
||||
cache = (struct fscache *)xcalloc(1, sizeof(*cache));
|
||||
cache->enabled = 1;
|
||||
/*
|
||||
* avoid having to rehash by leaving room for the parent dirs.
|
||||
* '4' was determined empirically by testing several repos
|
||||
*/
|
||||
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
|
||||
mem_pool_init(&cache->mem_pool, 0);
|
||||
if (!TlsSetValue(dwTlsIndex, cache))
|
||||
BUG("TlsSetValue error");
|
||||
}
|
||||
|
||||
trace_printf_key(&trace_fscache, "fscache: enable\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables the cache.
|
||||
*/
|
||||
void fscache_disable(void)
|
||||
{
|
||||
struct fscache *cache;
|
||||
|
||||
if (!core_fscache)
|
||||
return;
|
||||
|
||||
/* update the thread specific fscache initialization */
|
||||
cache = fscache_getcache();
|
||||
if (!cache)
|
||||
BUG("fscache_disable() called on a thread where fscache has not been initialized");
|
||||
if (!cache->enabled)
|
||||
BUG("fscache_disable() called on an fscache that is already disabled");
|
||||
cache->enabled--;
|
||||
if (!cache->enabled) {
|
||||
TlsSetValue(dwTlsIndex, NULL);
|
||||
trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, "
|
||||
"total requests/misses %u/%u\n",
|
||||
cache->lstat_requests, cache->opendir_requests,
|
||||
cache->fscache_requests, cache->fscache_misses);
|
||||
mem_pool_discard(&cache->mem_pool, 0);
|
||||
hashmap_clear(&cache->map);
|
||||
free(cache);
|
||||
}
|
||||
|
||||
/* update the global fscache initialization */
|
||||
EnterCriticalSection(&fscache_cs);
|
||||
initialized--;
|
||||
if (!initialized) {
|
||||
/* reset opendir and lstat to the original implementations */
|
||||
opendir = dirent_opendir;
|
||||
lstat = mingw_lstat;
|
||||
win32_is_mount_point = mingw_is_mount_point;
|
||||
}
|
||||
LeaveCriticalSection(&fscache_cs);
|
||||
|
||||
trace_printf_key(&trace_fscache, "fscache: disable\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush cached stats result when fscache is enabled.
|
||||
*/
|
||||
void fscache_flush(void)
|
||||
{
|
||||
struct fscache *cache = fscache_getcache();
|
||||
|
||||
if (cache && cache->enabled) {
|
||||
fscache_clear(cache);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lstat replacement, uses the cache if enabled, otherwise redirects to
|
||||
* mingw_lstat.
|
||||
*/
|
||||
int fscache_lstat(const char *filename, struct stat *st)
|
||||
{
|
||||
int dirlen, base, len;
|
||||
struct heap_fsentry key[2];
|
||||
struct fsentry *fse;
|
||||
struct fscache *cache = fscache_getcache();
|
||||
|
||||
if (!cache || !do_fscache_enabled(cache, filename))
|
||||
return mingw_lstat(filename, st);
|
||||
|
||||
cache->lstat_requests++;
|
||||
/* split filename into path + name */
|
||||
len = strlen(filename);
|
||||
if (len && is_dir_sep(filename[len - 1]))
|
||||
len--;
|
||||
base = len;
|
||||
while (base && !is_dir_sep(filename[base - 1]))
|
||||
base--;
|
||||
dirlen = base ? base - 1 : 0;
|
||||
|
||||
/* lookup entry for path + name in cache */
|
||||
fsentry_init(&key[0].u.ent, NULL, filename, dirlen);
|
||||
fsentry_init(&key[1].u.ent, &key[0].u.ent, filename + base, len - base);
|
||||
fse = fscache_get(cache, &key[1].u.ent);
|
||||
if (!fse) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case symbolic links: FindFirstFile()/FindNextFile() did not
|
||||
* provide us with the length of the target path.
|
||||
*/
|
||||
if (fse->u.s.st_size == MAX_LONG_PATH && S_ISLNK(fse->st_mode)) {
|
||||
char buf[MAX_LONG_PATH];
|
||||
int len = readlink(filename, buf, sizeof(buf) - 1);
|
||||
|
||||
if (len > 0)
|
||||
fse->u.s.st_size = len;
|
||||
}
|
||||
|
||||
/* copy stat data */
|
||||
st->st_ino = 0;
|
||||
st->st_gid = 0;
|
||||
st->st_uid = 0;
|
||||
st->st_dev = 0;
|
||||
st->st_rdev = 0;
|
||||
st->st_nlink = 1;
|
||||
st->st_mode = fse->st_mode;
|
||||
st->st_size = fse->u.s.st_size;
|
||||
st->st_atim = fse->u.s.st_atim;
|
||||
st->st_mtim = fse->u.s.st_mtim;
|
||||
st->st_ctim = fse->u.s.st_ctim;
|
||||
|
||||
/* don't forget to release fsentry */
|
||||
fsentry_release(fse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* is_mount_point() replacement, uses cache if enabled, otherwise falls
|
||||
* back to mingw_is_mount_point().
|
||||
*/
|
||||
int fscache_is_mount_point(struct strbuf *path)
|
||||
{
|
||||
int dirlen, base, len;
|
||||
struct heap_fsentry key[2];
|
||||
struct fsentry *fse;
|
||||
struct fscache *cache = fscache_getcache();
|
||||
|
||||
if (!cache || !do_fscache_enabled(cache, path->buf))
|
||||
return mingw_is_mount_point(path);
|
||||
|
||||
cache->lstat_requests++;
|
||||
/* split path into path + name */
|
||||
len = path->len;
|
||||
if (len && is_dir_sep(path->buf[len - 1]))
|
||||
len--;
|
||||
base = len;
|
||||
while (base && !is_dir_sep(path->buf[base - 1]))
|
||||
base--;
|
||||
dirlen = base ? base - 1 : 0;
|
||||
|
||||
/* lookup entry for path + name in cache */
|
||||
fsentry_init(&key[0].u.ent, NULL, path->buf, dirlen);
|
||||
fsentry_init(&key[1].u.ent, &key[0].u.ent, path->buf + base, len - base);
|
||||
fse = fscache_get(cache, &key[1].u.ent);
|
||||
if (!fse)
|
||||
return mingw_is_mount_point(path);
|
||||
return fse->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
|
||||
}
|
||||
|
||||
typedef struct fscache_DIR {
|
||||
struct DIR base_dir; /* extend base struct DIR */
|
||||
struct fsentry *pfsentry;
|
||||
struct dirent *dirent;
|
||||
} fscache_DIR;
|
||||
|
||||
/*
|
||||
* Readdir replacement.
|
||||
*/
|
||||
static struct dirent *fscache_readdir(DIR *base_dir)
|
||||
{
|
||||
fscache_DIR *dir = (fscache_DIR*) base_dir;
|
||||
struct fsentry *next = dir->pfsentry->next;
|
||||
if (!next)
|
||||
return NULL;
|
||||
dir->pfsentry = next;
|
||||
dir->dirent = &next->dirent;
|
||||
return dir->dirent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closedir replacement.
|
||||
*/
|
||||
static int fscache_closedir(DIR *base_dir)
|
||||
{
|
||||
fscache_DIR *dir = (fscache_DIR*) base_dir;
|
||||
fsentry_release(dir->pfsentry);
|
||||
free(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opendir replacement, uses a directory listing from the cache if enabled,
|
||||
* otherwise calls original dirent implementation.
|
||||
*/
|
||||
DIR *fscache_opendir(const char *dirname)
|
||||
{
|
||||
struct heap_fsentry key;
|
||||
struct fsentry *list;
|
||||
fscache_DIR *dir;
|
||||
int len;
|
||||
struct fscache *cache = fscache_getcache();
|
||||
|
||||
if (!cache || !do_fscache_enabled(cache, dirname))
|
||||
return dirent_opendir(dirname);
|
||||
|
||||
cache->opendir_requests++;
|
||||
/* prepare name (strip trailing '/', replace '.') */
|
||||
len = strlen(dirname);
|
||||
if ((len == 1 && dirname[0] == '.') ||
|
||||
(len && is_dir_sep(dirname[len - 1])))
|
||||
len--;
|
||||
|
||||
/* get directory listing from cache */
|
||||
fsentry_init(&key.u.ent, NULL, dirname, len);
|
||||
list = fscache_get(cache, &key.u.ent);
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
/* alloc and return DIR structure */
|
||||
dir = (fscache_DIR*) xmalloc(sizeof(fscache_DIR));
|
||||
dir->base_dir.preaddir = fscache_readdir;
|
||||
dir->base_dir.pclosedir = fscache_closedir;
|
||||
dir->pfsentry = list;
|
||||
return (DIR*) dir;
|
||||
}
|
||||
|
||||
struct fscache *fscache_getcache(void)
|
||||
{
|
||||
return (struct fscache *)TlsGetValue(dwTlsIndex);
|
||||
}
|
||||
|
||||
void fscache_merge(struct fscache *dest)
|
||||
{
|
||||
struct hashmap_iter iter;
|
||||
struct hashmap_entry *e;
|
||||
struct fscache *cache = fscache_getcache();
|
||||
|
||||
/*
|
||||
* Only do the merge if fscache was enabled and we have a dest
|
||||
* cache to merge into.
|
||||
*/
|
||||
if (!dest) {
|
||||
fscache_enable(0);
|
||||
return;
|
||||
}
|
||||
if (!cache)
|
||||
BUG("fscache_merge() called on a thread where fscache has not been initialized");
|
||||
|
||||
TlsSetValue(dwTlsIndex, NULL);
|
||||
trace_printf_key(&trace_fscache, "fscache_merge: lstat %u, opendir %u, "
|
||||
"total requests/misses %u/%u\n",
|
||||
cache->lstat_requests, cache->opendir_requests,
|
||||
cache->fscache_requests, cache->fscache_misses);
|
||||
|
||||
/*
|
||||
* This is only safe because the primary thread we're merging into
|
||||
* isn't being used so the critical section only needs to prevent
|
||||
* the the child threads from stomping on each other.
|
||||
*/
|
||||
EnterCriticalSection(&fscache_cs);
|
||||
|
||||
hashmap_iter_init(&cache->map, &iter);
|
||||
while ((e = hashmap_iter_next(&iter)))
|
||||
hashmap_add(&dest->map, e);
|
||||
|
||||
mem_pool_combine(&dest->mem_pool, &cache->mem_pool);
|
||||
|
||||
dest->lstat_requests += cache->lstat_requests;
|
||||
dest->opendir_requests += cache->opendir_requests;
|
||||
dest->fscache_requests += cache->fscache_requests;
|
||||
dest->fscache_misses += cache->fscache_misses;
|
||||
initialized--;
|
||||
LeaveCriticalSection(&fscache_cs);
|
||||
|
||||
free(cache);
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef FSCACHE_H
|
||||
#define FSCACHE_H
|
||||
|
||||
/*
|
||||
* The fscache is thread specific. enable_fscache() must be called
|
||||
* for each thread where caching is desired.
|
||||
*/
|
||||
|
||||
extern CRITICAL_SECTION fscache_cs;
|
||||
|
||||
int fscache_enable(size_t initial_size);
|
||||
#define enable_fscache(initial_size) fscache_enable(initial_size)
|
||||
|
||||
void fscache_disable(void);
|
||||
#define disable_fscache() fscache_disable()
|
||||
|
||||
int fscache_enabled(const char *path);
|
||||
#define is_fscache_enabled(path) fscache_enabled(path)
|
||||
|
||||
void fscache_flush(void);
|
||||
#define flush_fscache() fscache_flush()
|
||||
|
||||
DIR *fscache_opendir(const char *dir);
|
||||
int fscache_lstat(const char *file_name, struct stat *buf);
|
||||
int fscache_is_mount_point(struct strbuf *path);
|
||||
|
||||
/* opaque fscache structure */
|
||||
struct fscache;
|
||||
|
||||
struct fscache *fscache_getcache(void);
|
||||
#define getcache_fscache() fscache_getcache()
|
||||
|
||||
void fscache_merge(struct fscache *dest);
|
||||
#define merge_fscache(dest) fscache_merge(dest)
|
||||
|
||||
#endif
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* headless Git - run Git without opening a console window on Windows
|
||||
*/
|
||||
|
||||
#define STRICT
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/*
|
||||
* If `dir` contains the path to a Git exec directory, extend `PATH` to
|
||||
* include the corresponding `bin/` directory (which is where all those
|
||||
* `.dll` files needed by `git.exe` are, on Windows).
|
||||
*/
|
||||
static int extend_path(wchar_t *dir, size_t dir_len)
|
||||
{
|
||||
const wchar_t *suffix = L"\\libexec\\git-core";
|
||||
size_t suffix_len = wcslen(suffix);
|
||||
wchar_t *env;
|
||||
DWORD len;
|
||||
|
||||
if (dir_len < suffix_len)
|
||||
return 0;
|
||||
|
||||
dir_len -= suffix_len;
|
||||
if (memcmp(dir + dir_len, suffix, suffix_len * sizeof(wchar_t)))
|
||||
return 0;
|
||||
|
||||
len = GetEnvironmentVariableW(L"PATH", NULL, 0);
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
env = _alloca((dir_len + 5 + len) * sizeof(wchar_t));
|
||||
wcsncpy(env, dir, dir_len);
|
||||
wcscpy(env + dir_len, L"\\bin;");
|
||||
if (!GetEnvironmentVariableW(L"PATH", env + dir_len + 5, len))
|
||||
return 0;
|
||||
|
||||
SetEnvironmentVariableW(L"PATH", env);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(_In_ HINSTANCE instance,
|
||||
_In_opt_ HINSTANCE previous_instance,
|
||||
_In_ LPWSTR command_line, _In_ int show)
|
||||
{
|
||||
wchar_t git_command_line[32768];
|
||||
size_t size = sizeof(git_command_line) / sizeof(wchar_t);
|
||||
const wchar_t *needs_quotes = L"";
|
||||
int slash = 0, i;
|
||||
|
||||
STARTUPINFO startup_info = {
|
||||
.cb = sizeof(STARTUPINFO),
|
||||
.dwFlags = STARTF_USESHOWWINDOW,
|
||||
.wShowWindow = SW_HIDE,
|
||||
};
|
||||
PROCESS_INFORMATION process_info = { 0 };
|
||||
DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT |
|
||||
CREATE_NEW_CONSOLE | CREATE_NO_WINDOW;
|
||||
DWORD exit_code;
|
||||
|
||||
/* First, determine the full path of argv[0] */
|
||||
for (i = 0; _wpgmptr[i]; i++)
|
||||
if (_wpgmptr[i] == L' ')
|
||||
needs_quotes = L"\"";
|
||||
else if (_wpgmptr[i] == L'\\')
|
||||
slash = i;
|
||||
|
||||
if (slash >= size - 11)
|
||||
return 127; /* Too long path */
|
||||
|
||||
/* If it is in Git's exec path, add the bin/ directory to the PATH */
|
||||
extend_path(_wpgmptr, slash);
|
||||
|
||||
/* Then, add the full path of `git.exe` as argv[0] */
|
||||
i = swprintf_s(git_command_line, size, L"%ls%.*ls\\git.exe%ls",
|
||||
needs_quotes, slash, _wpgmptr, needs_quotes);
|
||||
if (i < 0)
|
||||
return 127; /* Too long path */
|
||||
|
||||
if (*command_line) {
|
||||
/* Now, append the command-line arguments */
|
||||
i = swprintf_s(git_command_line + i, size - i,
|
||||
L" %ls", command_line);
|
||||
if (i < 0)
|
||||
return 127;
|
||||
}
|
||||
|
||||
startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
if (!CreateProcess(NULL, /* infer argv[0] from the command line */
|
||||
git_command_line, /* modified command line */
|
||||
NULL, /* inherit process handles? */
|
||||
NULL, /* inherit thread handles? */
|
||||
FALSE, /* handles inheritable? */
|
||||
creation_flags,
|
||||
NULL, /* use this process' environment */
|
||||
NULL, /* use this process' working directory */
|
||||
&startup_info, &process_info))
|
||||
return 129; /* could not start */
|
||||
WaitForSingleObject(process_info.hProcess, INFINITE);
|
||||
if (!GetExitCodeProcess(process_info.hProcess, &exit_code))
|
||||
exit_code = 130; /* Could not determine exit code? */
|
||||
|
||||
CloseHandle(process_info.hProcess);
|
||||
CloseHandle(process_info.hThread);
|
||||
|
||||
return (int)exit_code;
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
#ifndef _NTIFS_
|
||||
#define _NTIFS_
|
||||
|
||||
/*
|
||||
* Copy necessary structures and definitions out of the Windows DDK
|
||||
* to enable calling NtQueryDirectoryFile()
|
||||
*/
|
||||
|
||||
typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
|
||||
#if !defined(_NTSECAPI_) && !defined(_WINTERNL_) && \
|
||||
!defined(__UNICODE_STRING_DEFINED)
|
||||
#define __UNICODE_STRING_DEFINED
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING;
|
||||
typedef UNICODE_STRING *PUNICODE_STRING;
|
||||
typedef const UNICODE_STRING *PCUNICODE_STRING;
|
||||
#endif /* !_NTSECAPI_ && !_WINTERNL_ && !__UNICODE_STRING_DEFINED */
|
||||
|
||||
typedef enum _FILE_INFORMATION_CLASS {
|
||||
FileDirectoryInformation = 1,
|
||||
FileFullDirectoryInformation,
|
||||
FileBothDirectoryInformation,
|
||||
FileBasicInformation,
|
||||
FileStandardInformation,
|
||||
FileInternalInformation,
|
||||
FileEaInformation,
|
||||
FileAccessInformation,
|
||||
FileNameInformation,
|
||||
FileRenameInformation,
|
||||
FileLinkInformation,
|
||||
FileNamesInformation,
|
||||
FileDispositionInformation,
|
||||
FilePositionInformation,
|
||||
FileFullEaInformation,
|
||||
FileModeInformation,
|
||||
FileAlignmentInformation,
|
||||
FileAllInformation,
|
||||
FileAllocationInformation,
|
||||
FileEndOfFileInformation,
|
||||
FileAlternateNameInformation,
|
||||
FileStreamInformation,
|
||||
FilePipeInformation,
|
||||
FilePipeLocalInformation,
|
||||
FilePipeRemoteInformation,
|
||||
FileMailslotQueryInformation,
|
||||
FileMailslotSetInformation,
|
||||
FileCompressionInformation,
|
||||
FileObjectIdInformation,
|
||||
FileCompletionInformation,
|
||||
FileMoveClusterInformation,
|
||||
FileQuotaInformation,
|
||||
FileReparsePointInformation,
|
||||
FileNetworkOpenInformation,
|
||||
FileAttributeTagInformation,
|
||||
FileTrackingInformation,
|
||||
FileIdBothDirectoryInformation,
|
||||
FileIdFullDirectoryInformation,
|
||||
FileValidDataLengthInformation,
|
||||
FileShortNameInformation,
|
||||
FileIoCompletionNotificationInformation,
|
||||
FileIoStatusBlockRangeInformation,
|
||||
FileIoPriorityHintInformation,
|
||||
FileSfioReserveInformation,
|
||||
FileSfioVolumeInformation,
|
||||
FileHardLinkInformation,
|
||||
FileProcessIdsUsingFileInformation,
|
||||
FileNormalizedNameInformation,
|
||||
FileNetworkPhysicalNameInformation,
|
||||
FileIdGlobalTxDirectoryInformation,
|
||||
FileIsRemoteDeviceInformation,
|
||||
FileAttributeCacheInformation,
|
||||
FileNumaNodeInformation,
|
||||
FileStandardLinkInformation,
|
||||
FileRemoteProtocolInformation,
|
||||
FileMaximumInformation
|
||||
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _FILE_FULL_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
WCHAR FileName[1];
|
||||
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
|
||||
|
||||
typedef struct _IO_STATUS_BLOCK {
|
||||
union {
|
||||
NTSTATUS Status;
|
||||
PVOID Pointer;
|
||||
} u;
|
||||
ULONG_PTR Information;
|
||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||
|
||||
typedef VOID
|
||||
(NTAPI *PIO_APC_ROUTINE)(
|
||||
IN PVOID ApcContext,
|
||||
IN PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN ULONG Reserved);
|
||||
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQueryDirectoryFile(
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_opt_ HANDLE Event,
|
||||
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
|
||||
_In_opt_ PVOID ApcContext,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_Out_writes_bytes_(Length) PVOID FileInformation,
|
||||
_In_ ULONG Length,
|
||||
_In_ FILE_INFORMATION_CLASS FileInformationClass,
|
||||
_In_ BOOLEAN ReturnSingleEntry,
|
||||
_In_opt_ PUNICODE_STRING FileName,
|
||||
_In_ BOOLEAN RestartScan
|
||||
);
|
||||
|
||||
#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
|
||||
|
||||
#endif
|
||||
@@ -573,9 +573,6 @@ static void detect_msys_tty(int fd)
|
||||
if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation,
|
||||
buffer, sizeof(buffer) - 2, &result)))
|
||||
return;
|
||||
if (result < sizeof(*nameinfo) || !nameinfo->Name.Buffer ||
|
||||
!nameinfo->Name.Length)
|
||||
return;
|
||||
name = nameinfo->Name.Buffer;
|
||||
name[nameinfo->Name.Length / sizeof(*name)] = 0;
|
||||
|
||||
|
||||
2
config.c
2
config.c
@@ -1463,7 +1463,7 @@ int git_config_color(char *dest, const char *var, const char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_default_core_config(const char *var, const char *value, void *cb)
|
||||
static int git_default_core_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
/* This needs a better name */
|
||||
if (!strcmp(var, "core.filemode")) {
|
||||
|
||||
1
config.h
1
config.h
@@ -131,7 +131,6 @@ struct config_options {
|
||||
typedef int (*config_fn_t)(const char *, const char *, void *);
|
||||
|
||||
int git_default_config(const char *, const char *, void *);
|
||||
int git_default_core_config(const char *var, const char *value, void *cb);
|
||||
|
||||
/**
|
||||
* Read a specific file in git-config format.
|
||||
|
||||
@@ -425,7 +425,7 @@ ifeq ($(uname_S),Windows)
|
||||
# link.exe next to, and required by, cl.exe, we have to prepend this
|
||||
# onto the existing $PATH.
|
||||
#
|
||||
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys):$(sdk_ver_bin_dir_msys)
|
||||
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys)
|
||||
HAVE_ALLOCA_H = YesPlease
|
||||
NO_PREAD = YesPlease
|
||||
NEEDS_CRYPTO_WITH_SSL = YesPlease
|
||||
@@ -486,16 +486,14 @@ endif
|
||||
compat/win32/path-utils.o \
|
||||
compat/win32/pthread.o compat/win32/syslog.o \
|
||||
compat/win32/trace2_win32_process_info.o \
|
||||
compat/win32/dirent.o compat/win32/fscache.o
|
||||
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
|
||||
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\"
|
||||
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
|
||||
# See https://msdn.microsoft.com/en-us/library/ms235330.aspx
|
||||
EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib
|
||||
GITLIBS += git.res
|
||||
PTHREAD_LIBS =
|
||||
RC = compat/vcbuild/scripts/rc.pl
|
||||
lib =
|
||||
BASIC_CFLAGS += $(vcpkg_inc) $(sdk_includes) $(msvc_includes)
|
||||
ifndef DEBUG
|
||||
@@ -527,8 +525,6 @@ else
|
||||
endif
|
||||
X = .exe
|
||||
|
||||
EXTRA_PROGRAMS += headless-git$X
|
||||
|
||||
compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
|
||||
endif
|
||||
ifeq ($(uname_S),Interix)
|
||||
@@ -674,7 +670,7 @@ ifeq ($(uname_S),MINGW)
|
||||
compat/win32/flush.o \
|
||||
compat/win32/path-utils.o \
|
||||
compat/win32/pthread.o compat/win32/syslog.o \
|
||||
compat/win32/dirent.o compat/win32/fscache.o
|
||||
compat/win32/dirent.o
|
||||
BASIC_CFLAGS += -DWIN32
|
||||
EXTLIBS += -lws2_32
|
||||
GITLIBS += git.res
|
||||
@@ -682,7 +678,6 @@ ifeq ($(uname_S),MINGW)
|
||||
RC = windres -O coff
|
||||
NATIVE_CRLF = YesPlease
|
||||
X = .exe
|
||||
EXTRA_PROGRAMS += headless-git$X
|
||||
ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
|
||||
htmldir = doc/git/html/
|
||||
prefix =
|
||||
@@ -717,7 +712,7 @@ else
|
||||
endif
|
||||
CC = gcc
|
||||
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \
|
||||
-DENSURE_MSYSTEM_IS_SET -fstack-protector-strong
|
||||
-fstack-protector-strong
|
||||
EXTLIBS += -lntdll
|
||||
INSTALL = /bin/install
|
||||
INTERNAL_QSORT = YesPlease
|
||||
@@ -727,7 +722,6 @@ else
|
||||
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
|
||||
@@ -738,62 +732,6 @@ else
|
||||
NO_CURL = YesPlease
|
||||
endif
|
||||
endif
|
||||
ifeq (i686,$(uname_M))
|
||||
MINGW_PREFIX := mingw32
|
||||
endif
|
||||
ifeq (x86_64,$(uname_M))
|
||||
MINGW_PREFIX := mingw64
|
||||
endif
|
||||
|
||||
DESTDIR_WINDOWS = $(shell cygpath -aw '$(DESTDIR_SQ)')
|
||||
DESTDIR_MIXED = $(shell cygpath -am '$(DESTDIR_SQ)')
|
||||
install-mingit-test-artifacts:
|
||||
install -m755 -d '$(DESTDIR_SQ)/usr/bin'
|
||||
printf '%s\n%s\n' >'$(DESTDIR_SQ)/usr/bin/perl' \
|
||||
"#!/mingw64/bin/busybox sh" \
|
||||
"exec \"$(shell cygpath -am /usr/bin/perl.exe)\" \"\$$@\""
|
||||
|
||||
install -m755 -d '$(DESTDIR_SQ)'
|
||||
printf '%s%s\n%s\n%s\n%s\n%s\n' >'$(DESTDIR_SQ)/init.bat' \
|
||||
"PATH=$(DESTDIR_WINDOWS)\\$(MINGW_PREFIX)\\bin;" \
|
||||
"C:\\WINDOWS;C:\\WINDOWS\\system32" \
|
||||
"@set GIT_TEST_INSTALLED=$(DESTDIR_MIXED)/$(MINGW_PREFIX)/bin" \
|
||||
"@`echo "$(DESTDIR_WINDOWS)" | sed 's/:.*/:/'`" \
|
||||
"@cd `echo "$(DESTDIR_WINDOWS)" | sed 's/^.://'`\\test-git\\t" \
|
||||
"@echo Now, run 'helper\\test-run-command testsuite'"
|
||||
|
||||
install -m755 -d '$(DESTDIR_SQ)/test-git'
|
||||
sed 's/^\(NO_PERL\|NO_PYTHON\)=.*/\1=YesPlease/' \
|
||||
<GIT-BUILD-OPTIONS >'$(DESTDIR_SQ)/test-git/GIT-BUILD-OPTIONS'
|
||||
|
||||
install -m755 -d '$(DESTDIR_SQ)/test-git/t/helper'
|
||||
install -m755 $(TEST_PROGRAMS) '$(DESTDIR_SQ)/test-git/t/helper'
|
||||
(cd t && $(TAR) cf - t[0-9][0-9][0-9][0-9] lib-diff) | \
|
||||
(cd '$(DESTDIR_SQ)/test-git/t' && $(TAR) xf -)
|
||||
install -m755 t/t556x_common t/*.sh '$(DESTDIR_SQ)/test-git/t'
|
||||
|
||||
install -m755 -d '$(DESTDIR_SQ)/test-git/templates'
|
||||
(cd templates && $(TAR) cf - blt) | \
|
||||
(cd '$(DESTDIR_SQ)/test-git/templates' && $(TAR) xf -)
|
||||
|
||||
# po/build/locale for t0200
|
||||
install -m755 -d '$(DESTDIR_SQ)/test-git/po/build/locale'
|
||||
(cd po/build/locale && $(TAR) cf - .) | \
|
||||
(cd '$(DESTDIR_SQ)/test-git/po/build/locale' && $(TAR) xf -)
|
||||
|
||||
# git-daemon.exe for t5802, git-http-backend.exe for t5560
|
||||
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
|
||||
install -m755 git-daemon.exe git-http-backend.exe \
|
||||
'$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
|
||||
|
||||
# git-upload-archive (dashed) for t5000
|
||||
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
|
||||
install -m755 git-upload-archive.exe '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
|
||||
|
||||
# git-difftool--helper for t7800
|
||||
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
|
||||
install -m755 git-difftool--helper \
|
||||
'$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
|
||||
endif
|
||||
ifeq ($(uname_S),QNX)
|
||||
COMPAT_CFLAGS += -DSA_RESTART=0
|
||||
@@ -818,7 +756,7 @@ vcxproj:
|
||||
|
||||
# Make .vcxproj files and add them
|
||||
perl contrib/buildsystems/generate -g Vcxproj
|
||||
git add -f git.sln {*,*/lib.proj,t/helper/*,reftable/libreftable{,_test}.proj}/*.vcxproj
|
||||
git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj
|
||||
|
||||
# Generate the LinkOrCopyBuiltins.targets and LinkOrCopyRemoteHttp.targets file
|
||||
(echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \
|
||||
@@ -828,7 +766,7 @@ vcxproj:
|
||||
echo ' <Copy SourceFiles="$$(OutDir)\git.exe" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
|
||||
done && \
|
||||
echo ' </Target>' && \
|
||||
echo '</Project>') >git.proj/LinkOrCopyBuiltins.targets
|
||||
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); \
|
||||
@@ -836,8 +774,8 @@ vcxproj:
|
||||
echo ' <Copy SourceFiles="$$(OutDir)\'"$(REMOTE_CURL_PRIMARY)"'" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \
|
||||
done && \
|
||||
echo ' </Target>' && \
|
||||
echo '</Project>') >git-remote-http.proj/LinkOrCopyRemoteHttp.targets
|
||||
git add -f git.proj/LinkOrCopyBuiltins.targets git-remote-http.proj/LinkOrCopyRemoteHttp.targets
|
||||
echo '</Project>') >git-remote-http/LinkOrCopyRemoteHttp.targets
|
||||
git add -f git/LinkOrCopyBuiltins.targets git-remote-http/LinkOrCopyRemoteHttp.targets
|
||||
|
||||
# Add generated headers
|
||||
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(GENERATED_H)
|
||||
@@ -850,11 +788,9 @@ vcxproj:
|
||||
sed -i '/^git_broken_path_fix ".*/d' git-sh-setup
|
||||
git add -f $(SCRIPT_LIB) $(SCRIPTS)
|
||||
|
||||
ifndef NO_PERL
|
||||
# Add Perl module
|
||||
$(MAKE) $(LIB_PERL_GEN)
|
||||
git add -f perl/build
|
||||
endif
|
||||
|
||||
# Add bin-wrappers, for testing
|
||||
rm -rf bin-wrappers/
|
||||
|
||||
@@ -14,11 +14,6 @@ Note: Visual Studio also has the option of opening `CMakeLists.txt`
|
||||
directly; Using this option, Visual Studio will not find the source code,
|
||||
though, therefore the `File>Open>Folder...` option is preferred.
|
||||
|
||||
Visual Studio does not produce a .sln solution file nor the .vcxproj files
|
||||
that may be required by VS extension tools.
|
||||
|
||||
To generate the .sln/.vcxproj files run CMake manually, as described below.
|
||||
|
||||
Instructions to run CMake manually:
|
||||
|
||||
mkdir -p contrib/buildsystems/out
|
||||
@@ -27,7 +22,7 @@ Instructions to run CMake manually:
|
||||
|
||||
This will build the git binaries in contrib/buildsystems/out
|
||||
directory (our top-level .gitignore file knows to ignore contents of
|
||||
this directory). The project .sln and .vcxproj files are also generated.
|
||||
this directory).
|
||||
|
||||
Possible build configurations(-DCMAKE_BUILD_TYPE) with corresponding
|
||||
compiler flags
|
||||
@@ -40,16 +35,17 @@ empty(default) :
|
||||
NOTE: -DCMAKE_BUILD_TYPE is optional. For multi-config generators like Visual Studio
|
||||
this option is ignored
|
||||
|
||||
This process generates a Makefile(Linux/*BSD/MacOS), Visual Studio solution(Windows) by default.
|
||||
This process generates a Makefile(Linux/*BSD/MacOS) , Visual Studio solution(Windows) by default.
|
||||
Run `make` to build Git on Linux/*BSD/MacOS.
|
||||
Open git.sln on Windows and build Git.
|
||||
|
||||
NOTE: By default CMake uses Makefile as the build tool on Linux and Visual Studio in Windows,
|
||||
to use another tool say `ninja` add this to the command line when configuring.
|
||||
`-G Ninja`
|
||||
|
||||
NOTE: By default CMake will install vcpkg locally to your source tree on configuration,
|
||||
to avoid this, add `-DNO_VCPKG=TRUE` to the command line when configuring.
|
||||
|
||||
The Visual Studio default generator changed in v16.6 from its Visual Studio
|
||||
implemenation to `Ninja` This required changes to many CMake scripts.
|
||||
|
||||
]]
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
@@ -63,29 +59,15 @@ endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
||||
message("settting CMAKE_EXPORT_COMPILE_COMMANDS: ${CMAKE_EXPORT_COMPILE_COMMANDS}")
|
||||
endif()
|
||||
|
||||
if(USE_VCPKG)
|
||||
set(VCPKG_DIR "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg")
|
||||
message("WIN32: ${WIN32}") # show its underlying text values
|
||||
message("VCPKG_DIR: ${VCPKG_DIR}")
|
||||
message("VCPKG_ARCH: ${VCPKG_ARCH}") # maybe unset
|
||||
message("MSVC: ${MSVC}")
|
||||
message("CMAKE_GENERATOR: ${CMAKE_GENERATOR}")
|
||||
message("CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}")
|
||||
message("CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}")
|
||||
message("CMAKE_EXPORT_COMPILE_COMMANDS: ${CMAKE_EXPORT_COMPILE_COMMANDS}")
|
||||
message("ENV(CMAKE_EXPORT_COMPILE_COMMANDS): $ENV{CMAKE_EXPORT_COMPILE_COMMANDS}")
|
||||
if(NOT EXISTS ${VCPKG_DIR})
|
||||
message("Initializing vcpkg and building the Git's dependencies (this will take a while...)")
|
||||
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg_install.bat ${VCPKG_ARCH})
|
||||
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg_install.bat)
|
||||
endif()
|
||||
if(NOT EXISTS ${VCPKG_ARCH})
|
||||
message("VCPKG_ARCH: unset, using 'x64-windows'")
|
||||
set(VCPKG_ARCH "x64-windows") # default from vcpkg_install.bat
|
||||
endif()
|
||||
list(APPEND CMAKE_PREFIX_PATH "${VCPKG_DIR}/installed/${VCPKG_ARCH}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${VCPKG_DIR}/installed/x64-windows")
|
||||
|
||||
# In the vcpkg edition, we need this to be able to link to libcurl
|
||||
set(CURL_NO_CURL_CMAKE ON)
|
||||
@@ -95,7 +77,7 @@ if(USE_VCPKG)
|
||||
set(CMAKE_TOOLCHAIN_FILE ${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake CACHE STRING "Vcpkg toolchain file")
|
||||
endif()
|
||||
|
||||
find_program(SH_EXE sh PATHS "C:/Program Files/Git/bin" "$ENV{LOCALAPPDATA}/Programs/Git/bin")
|
||||
find_program(SH_EXE sh PATHS "C:/Program Files/Git/bin")
|
||||
if(NOT SH_EXE)
|
||||
message(FATAL_ERROR "sh: shell interpreter was not found in your path, please install one."
|
||||
"On Windows, you can get it as part of 'Git for Windows' install at https://gitforwindows.org/")
|
||||
@@ -241,14 +223,7 @@ endif()
|
||||
|
||||
#default behaviour
|
||||
include_directories(${CMAKE_SOURCE_DIR})
|
||||
|
||||
# When cross-compiling, define HOST_CPU as the canonical name of the CPU on
|
||||
# which the built Git will run (for instance "x86_64").
|
||||
if(NOT HOST_CPU)
|
||||
add_compile_definitions(GIT_HOST_CPU="${CMAKE_SYSTEM_PROCESSOR}")
|
||||
else()
|
||||
add_compile_definitions(GIT_HOST_CPU="${HOST_CPU}")
|
||||
endif()
|
||||
add_compile_definitions(GIT_HOST_CPU="${CMAKE_SYSTEM_PROCESSOR}")
|
||||
add_compile_definitions(SHA256_BLK INTERNAL_QSORT RUNTIME_PREFIX)
|
||||
add_compile_definitions(NO_OPENSSL SHA1_DC SHA1DC_NO_STANDARD_INCLUDES
|
||||
SHA1DC_INIT_SAFE_HASH_DEFAULT=0
|
||||
@@ -307,8 +282,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
compat/win32/trace2_win32_process_info.c
|
||||
compat/win32/dirent.c
|
||||
compat/nedmalloc/nedmalloc.c
|
||||
compat/strdup.c
|
||||
compat/win32/fscache.c)
|
||||
compat/strdup.c)
|
||||
set(NO_UNIX_SOCKETS 1)
|
||||
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
@@ -760,15 +734,6 @@ if(WIN32)
|
||||
else()
|
||||
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
|
||||
endif()
|
||||
|
||||
add_executable(headless-git ${CMAKE_SOURCE_DIR}/compat/win32/headless.c)
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
target_link_options(headless-git PUBLIC -municode -Wl,-subsystem,windows)
|
||||
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||
target_link_options(headless-git PUBLIC /NOLOGO /ENTRY:wWinMainCRTStartup /SUBSYSTEM:WINDOWS)
|
||||
else()
|
||||
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
target_link_libraries(common-main pthread rt)
|
||||
endif()
|
||||
@@ -1096,7 +1061,7 @@ file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "RUNTIME_PREFIX='${RUNTIME_PRE
|
||||
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PYTHON='${NO_PYTHON}'\n")
|
||||
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "SUPPORTS_SIMPLE_IPC='${SUPPORTS_SIMPLE_IPC}'\n")
|
||||
if(USE_VCPKG)
|
||||
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/${VCPKG_ARCH}/bin\"\n")
|
||||
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\"\n")
|
||||
endif()
|
||||
|
||||
#Make the tests work when building out of the source tree
|
||||
|
||||
@@ -58,8 +58,8 @@ sub createProject {
|
||||
my $uuid = generate_guid($name);
|
||||
$$build_structure{"$prefix${target}_GUID"} = $uuid;
|
||||
my $vcxproj = $target;
|
||||
$vcxproj =~ s/(.*\/)?(.*)/$&.proj\/$2.vcxproj/;
|
||||
$vcxproj =~ s/([^\/]*)(\/lib\.proj)\/(lib.vcxproj)/$1$2\/$1_$3/;
|
||||
$vcxproj =~ s/(.*\/)?(.*)/$&\/$2.vcxproj/;
|
||||
$vcxproj =~ s/([^\/]*)(\/lib)\/(lib.vcxproj)/$1$2\/$1_$3/;
|
||||
$$build_structure{"$prefix${target}_VCXPROJ"} = $vcxproj;
|
||||
|
||||
my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"$prefix${name}_SOURCES"}}));
|
||||
@@ -76,8 +76,8 @@ sub createProject {
|
||||
|
||||
my $libs_release = "\n ";
|
||||
my $libs_debug = "\n ";
|
||||
if (!$static_library && $name ne 'headless-git') {
|
||||
$libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|reftable\/libreftable(_test)?\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
|
||||
if (!$static_library) {
|
||||
$libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|reftable\/libreftable\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
|
||||
$libs_debug = $libs_release;
|
||||
$libs_debug =~ s/zlib\.lib/zlibd\.lib/g;
|
||||
$libs_debug =~ s/libexpat\.lib/libexpatd\.lib/g;
|
||||
@@ -88,21 +88,8 @@ sub createProject {
|
||||
$defines =~ s/</</g;
|
||||
$defines =~ s/>/>/g;
|
||||
$defines =~ s/\'//g;
|
||||
$defines =~ s/\\"/"/g;
|
||||
|
||||
my $rcdefines = $defines;
|
||||
$rcdefines =~ s/(?<!\\)"/\\$&/g;
|
||||
|
||||
my $entrypoint = 'wmainCRTStartup';
|
||||
my $subsystem = 'Console';
|
||||
if (grep /^-mwindows$/, @{$$build_structure{"$prefix${name}_LFLAGS"}}) {
|
||||
$entrypoint = 'wWinMainCRTStartup';
|
||||
$subsystem = 'Windows';
|
||||
}
|
||||
|
||||
my $dir = $vcxproj;
|
||||
$dir =~ s/\/[^\/]*$//;
|
||||
die "Could not create the directory $dir for $label project!\n" unless (-d "$dir" || mkdir "$dir");
|
||||
die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
|
||||
|
||||
open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
|
||||
binmode F, ":crlf :utf8";
|
||||
@@ -127,21 +114,12 @@ sub createProject {
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>$uuid</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch>
|
||||
<VCPKGArch Condition="'\$(Platform)'=='x64'">x64-windows</VCPKGArch>
|
||||
<VCPKGArch Condition="'\$(Platform)'=='ARM64'">arm64-windows</VCPKGArch>
|
||||
<VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch>
|
||||
<VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory>
|
||||
<VCPKGBinDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory>
|
||||
<VCPKGLibDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory>
|
||||
@@ -162,7 +140,7 @@ sub createProject {
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>$config_type</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<!-- <CharacterSet>UTF-8</CharacterSet> -->
|
||||
<OutDir>..\\</OutDir>
|
||||
<!-- <IntDir>\$(ProjectDir)\$(Configuration)\\</IntDir> -->
|
||||
@@ -188,7 +166,6 @@ sub createProject {
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<PrecompiledHeader />
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard_C>stdc11</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
@@ -197,9 +174,9 @@ sub createProject {
|
||||
<AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions>
|
||||
<EntryPointSymbol>$entrypoint</EntryPointSymbol>
|
||||
<EntryPointSymbol>wmainCRTStartup</EntryPointSymbol>
|
||||
<ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile>
|
||||
<SubSystem>$subsystem</SubSystem>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
EOM
|
||||
if ($target eq 'libgit') {
|
||||
@@ -207,7 +184,7 @@ EOM
|
||||
<PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)\\include\\openssl\\ssl.h')">
|
||||
<Message>Initialize VCPKG</Message>
|
||||
<Command>del "$cdup\\compat\\vcbuild\\vcpkg"</Command>
|
||||
<Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat" \$(VCPKGArch)</Command>
|
||||
<Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat"</Command>
|
||||
</PreBuildEvent>
|
||||
EOM
|
||||
}
|
||||
@@ -224,9 +201,6 @@ EOM
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;$rcdefines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
@@ -240,9 +214,6 @@ EOM
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;$rcdefines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
@@ -252,47 +223,36 @@ EOM
|
||||
<ItemGroup>
|
||||
EOM
|
||||
foreach(@sources) {
|
||||
if (/\.rc$/) {
|
||||
print F << "EOM";
|
||||
<ResourceCompile Include="$_" />
|
||||
EOM
|
||||
} else {
|
||||
print F << "EOM";
|
||||
print F << "EOM";
|
||||
<ClCompile Include="$_" />
|
||||
EOM
|
||||
}
|
||||
}
|
||||
print F << "EOM";
|
||||
</ItemGroup>
|
||||
EOM
|
||||
if ((!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') && !($name =~ /headless-git/)) {
|
||||
if (!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') {
|
||||
my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"};
|
||||
my $uuid_libreftable = $$build_structure{"LIBS_reftable/libreftable_GUID"};
|
||||
my $uuid_libreftable_test = $$build_structure{"LIBS_reftable/libreftable_test_GUID"};
|
||||
my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"};
|
||||
|
||||
print F << "EOM";
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$cdup\\libgit.proj\\libgit.vcxproj">
|
||||
<ProjectReference Include="$cdup\\libgit\\libgit.vcxproj">
|
||||
<Project>$uuid_libgit</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
EOM
|
||||
if (!($name =~ /xdiff|libreftable/)) {
|
||||
print F << "EOM";
|
||||
<ProjectReference Include="$cdup\\reftable\\libreftable.proj\\libreftable.vcxproj">
|
||||
<ProjectReference Include="$cdup\\reftable\\libreftable\\libreftable.vcxproj">
|
||||
<Project>$uuid_libreftable</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$cdup\\reftable\\libreftable_test.proj\\libreftable_test.vcxproj">
|
||||
<Project>$uuid_libreftable_test</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
EOM
|
||||
}
|
||||
if (!($name =~ 'xdiff')) {
|
||||
print F << "EOM";
|
||||
<ProjectReference Include="$cdup\\xdiff\\lib.proj\\xdiff_lib.vcxproj">
|
||||
<ProjectReference Include="$cdup\\xdiff\\lib\\xdiff_lib.vcxproj">
|
||||
<Project>$uuid_xdiff_lib</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
@@ -301,7 +261,7 @@ EOM
|
||||
if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) {
|
||||
my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"};
|
||||
print F << "EOM";
|
||||
<ProjectReference Include="$cdup\\vcs-svn\\lib.proj\\vcs-svn_lib.vcxproj">
|
||||
<ProjectReference Include="$cdup\\vcs-svn\\lib\\vcs-svn_lib.vcxproj">
|
||||
<Project>$uuid_vcs_svn_lib</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
@@ -378,7 +338,7 @@ sub createGlueProject {
|
||||
my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"};
|
||||
$vcxproj =~ s/\//\\/g;
|
||||
$appname =~ s/.*\///;
|
||||
print F "\"${appname}.proj\", \"${vcxproj}\", \"${uuid}\"";
|
||||
print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\"";
|
||||
print F "$SLN_POST";
|
||||
}
|
||||
foreach (@libs) {
|
||||
@@ -388,17 +348,15 @@ sub createGlueProject {
|
||||
my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"};
|
||||
$vcxproj =~ s/\//\\/g;
|
||||
$libname =~ s/\//_/g;
|
||||
print F "\"${libname}.proj\", \"${vcxproj}\", \"${uuid}\"";
|
||||
print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\"";
|
||||
print F "$SLN_POST";
|
||||
}
|
||||
|
||||
print F << "EOM";
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
@@ -409,14 +367,10 @@ EOM
|
||||
foreach (@apps) {
|
||||
my $appname = $_;
|
||||
my $uuid = $build_structure{"APPS_${appname}_GUID"};
|
||||
print F "\t\t${uuid}.Debug|ARM64.ActiveCfg = Debug|ARM64\n";
|
||||
print F "\t\t${uuid}.Debug|ARM64.Build.0 = Debug|ARM64\n";
|
||||
print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
|
||||
print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
|
||||
print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
|
||||
print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
|
||||
print F "\t\t${uuid}.Release|ARM64.ActiveCfg = Release|ARM64\n";
|
||||
print F "\t\t${uuid}.Release|ARM64.Build.0 = Release|ARM64\n";
|
||||
print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
|
||||
print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
|
||||
print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
|
||||
@@ -425,14 +379,10 @@ EOM
|
||||
foreach (@libs) {
|
||||
my $libname = $_;
|
||||
my $uuid = $build_structure{"LIBS_${libname}_GUID"};
|
||||
print F "\t\t${uuid}.Debug|ARM64.ActiveCfg = Debug|ARM64\n";
|
||||
print F "\t\t${uuid}.Debug|ARM64.Build.0 = Debug|ARM64\n";
|
||||
print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
|
||||
print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
|
||||
print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
|
||||
print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
|
||||
print F "\t\t${uuid}.Release|ARM64.ActiveCfg = Release|ARM64\n";
|
||||
print F "\t\t${uuid}.Release|ARM64.Build.0 = Release|ARM64\n";
|
||||
print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
|
||||
print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
|
||||
print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
|
||||
|
||||
@@ -165,7 +165,7 @@ sub parseMakeOutput
|
||||
next;
|
||||
}
|
||||
|
||||
if($text =~ / -c / || $text =~ / -i \S+\.rc /) {
|
||||
if($text =~ / -c /) {
|
||||
# compilation
|
||||
handleCompileLine($text, $line);
|
||||
|
||||
@@ -263,15 +263,16 @@ sub handleCompileLine
|
||||
if ("$part" eq "-o") {
|
||||
# ignore object file
|
||||
shift @parts;
|
||||
} elsif ("$part" eq "-c" || "$part" eq "-i" || "$part" =~ /^-fno-/ || "$part" eq '-pedantic') {
|
||||
} elsif ("$part" eq "-c") {
|
||||
# ignore compile flag
|
||||
} elsif ("$part" eq "-c") {
|
||||
} elsif ($part =~ /^.?-I/) {
|
||||
push(@incpaths, $part);
|
||||
} elsif ($part =~ /^.?-D/) {
|
||||
push(@defines, $part);
|
||||
} elsif ($part =~ /^-/) {
|
||||
push(@cflags, $part);
|
||||
} elsif ($part =~ /\.(c|cc|cpp|rc)$/) {
|
||||
} elsif ($part =~ /\.(c|cc|cpp)$/) {
|
||||
$sourcefile = $part;
|
||||
} else {
|
||||
die "Unhandled compiler option @ line $lineno: $part";
|
||||
@@ -358,7 +359,7 @@ sub handleLinkLine
|
||||
push(@libs, $part);
|
||||
} elsif ($part eq 'invalidcontinue.obj') {
|
||||
# ignore - known to MSVC
|
||||
} elsif ($part =~ /\.(o|res)$/) {
|
||||
} elsif ($part =~ /\.o$/) {
|
||||
push(@objfiles, $part);
|
||||
} elsif ($part =~ /\.obj$/) {
|
||||
# do nothing, 'make' should not be producing .obj, only .o files
|
||||
@@ -370,9 +371,7 @@ sub handleLinkLine
|
||||
# exit(1);
|
||||
foreach (@objfiles) {
|
||||
my $sourcefile = $_;
|
||||
$sourcefile =~ s/^headless-git\.o$/compat\/win32\/headless.c/;
|
||||
$sourcefile =~ s/\.o$/.c/;
|
||||
$sourcefile =~ s/\.res$/.rc/;
|
||||
push(@sources, $sourcefile);
|
||||
push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}});
|
||||
push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}});
|
||||
|
||||
@@ -94,7 +94,7 @@ $(GIT_SUBTREE_TEST): $(GIT_SUBTREE)
|
||||
cp $< $@
|
||||
|
||||
test: $(GIT_SUBTREE_TEST)
|
||||
$(MAKE) -C t/ all
|
||||
$(MAKE) -C t/ test
|
||||
|
||||
clean:
|
||||
$(RM) $(GIT_SUBTREE)
|
||||
|
||||
61
dir.c
61
dir.c
@@ -1063,59 +1063,16 @@ static int add_patterns(const char *fname, const char *base, int baselen,
|
||||
size_t size = 0;
|
||||
char *buf;
|
||||
|
||||
/*
|
||||
* A performance optimization for status.
|
||||
*
|
||||
* During a status scan, git looks in each directory for a .gitignore
|
||||
* file before scanning the directory. Since .gitignore files are not
|
||||
* that common, we can waste a lot of time looking for files that are
|
||||
* not there. Fortunately, the fscache already knows if the directory
|
||||
* contains a .gitignore file, since it has already read the directory
|
||||
* and it already has the stat-data.
|
||||
*
|
||||
* If the fscache is enabled, use the fscache-lstat() interlude to see
|
||||
* if the file exists (in the fscache hash maps) before trying to open()
|
||||
* it.
|
||||
*
|
||||
* This causes problem when the .gitignore file is a symlink, because
|
||||
* we call lstat() rather than stat() on the symlnk and the resulting
|
||||
* stat-data is for the symlink itself rather than the target file.
|
||||
* We CANNOT use stat() here because the fscache DOES NOT install an
|
||||
* interlude for stat() and mingw_stat() always calls "open-fstat-close"
|
||||
* on the file and defeats the purpose of the optimization here. Since
|
||||
* symlinks are even more rare than .gitignore files, we force a fstat()
|
||||
* after our open() to get stat-data for the target file.
|
||||
*/
|
||||
if (is_fscache_enabled(fname)) {
|
||||
if (lstat(fname, &st) < 0) {
|
||||
fd = -1;
|
||||
} else {
|
||||
fd = open(fname, O_RDONLY);
|
||||
if (fd < 0)
|
||||
warn_on_fopen_errors(fname);
|
||||
else if (S_ISLNK(st.st_mode) && fstat(fd, &st) < 0) {
|
||||
warn_on_fopen_errors(fname);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (flags & PATTERN_NOFOLLOW)
|
||||
fd = open_nofollow(fname, O_RDONLY);
|
||||
if (flags & PATTERN_NOFOLLOW)
|
||||
fd = open_nofollow(fname, O_RDONLY);
|
||||
else
|
||||
fd = open(fname, O_RDONLY);
|
||||
|
||||
if (fd < 0 || fstat(fd, &st) < 0) {
|
||||
if (fd < 0)
|
||||
warn_on_fopen_errors(fname);
|
||||
else
|
||||
fd = open(fname, O_RDONLY);
|
||||
|
||||
if (fd < 0 || fstat(fd, &st) < 0) {
|
||||
if (fd < 0)
|
||||
warn_on_fopen_errors(fname);
|
||||
else {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
close(fd);
|
||||
if (!istate)
|
||||
return -1;
|
||||
r = read_skip_worktree_file_from_index(istate, fname,
|
||||
|
||||
8
editor.c
8
editor.c
@@ -4,7 +4,6 @@
|
||||
#include "strvec.h"
|
||||
#include "run-command.h"
|
||||
#include "sigchain.h"
|
||||
#include "compat/terminal.h"
|
||||
|
||||
#ifndef DEFAULT_EDITOR
|
||||
#define DEFAULT_EDITOR "vi"
|
||||
@@ -56,7 +55,6 @@ static int launch_specified_editor(const char *editor, const char *path,
|
||||
return error("Terminal is dumb, but EDITOR unset");
|
||||
|
||||
if (strcmp(editor, ":")) {
|
||||
int save_and_restore_term = !strcmp(editor, "vi") || !strcmp(editor, "vim");
|
||||
struct strbuf realpath = STRBUF_INIT;
|
||||
struct child_process p = CHILD_PROCESS_INIT;
|
||||
int ret, sig;
|
||||
@@ -85,11 +83,7 @@ static int launch_specified_editor(const char *editor, const char *path,
|
||||
strvec_pushv(&p.env, (const char **)env);
|
||||
p.use_shell = 1;
|
||||
p.trace2_child_class = "editor";
|
||||
if (save_and_restore_term)
|
||||
save_and_restore_term = !save_term(1);
|
||||
if (start_command(&p) < 0) {
|
||||
if (save_and_restore_term)
|
||||
restore_term();
|
||||
strbuf_release(&realpath);
|
||||
return error("unable to start editor '%s'", editor);
|
||||
}
|
||||
@@ -97,8 +91,6 @@ static int launch_specified_editor(const char *editor, const char *path,
|
||||
sigchain_push(SIGINT, SIG_IGN);
|
||||
sigchain_push(SIGQUIT, SIG_IGN);
|
||||
ret = finish_command(&p);
|
||||
if (save_and_restore_term)
|
||||
restore_term();
|
||||
strbuf_release(&realpath);
|
||||
sig = ret - 128;
|
||||
sigchain_pop(SIGINT);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user