From a76d18c668291ef9ed27334ce1a6212ed9264629 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Fri, 2 Aug 2024 13:03:50 +0000 Subject: [PATCH 01/70] ci: refactor jobs into a single job with matrix --- .github/workflows/ci.yml | 137 ++++++++++----------------------------- 1 file changed, 33 insertions(+), 104 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e462a55..9b1cd88e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,107 +1,32 @@ name: Continuous Integration on: push: - branches: - - develop + branches: [develop] pull_request: branches: [develop] workflow_dispatch: jobs: - build-windows: - name: Build Windows x64 - runs-on: windows-2019 - steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - name: Build - run: dotnet build -c Release - - name: Publish - run: dotnet publish src/SourceGit.csproj -c Release -o publish -r win-x64 - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: sourcegit.win-x64 - path: publish - build-macos-intel: - name: Build macOS (Intel) - runs-on: macos-13 - steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - name: Build - run: dotnet build -c Release - - name: Publish - run: dotnet publish src/SourceGit.csproj -c Release -o publish -r osx-x64 - - name: Packing Program - run: tar -cvf sourcegit.osx-x64.tar -C publish/ . - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: sourcegit.osx-x64 - path: sourcegit.osx-x64.tar - build-macos-arm64: - name: Build macOS (Apple Silicon) - runs-on: macos-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - name: Build - run: dotnet build -c Release - - name: Publish - run: dotnet publish src/SourceGit.csproj -c Release -o publish -r osx-arm64 - - name: Packing Program - run: tar -cvf sourcegit.osx-arm64.tar -C publish/ . - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: sourcegit.osx-arm64 - path: sourcegit.osx-arm64.tar - build-linux: - name: Build Linux - runs-on: ubuntu-20.04 - steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - name: Build - run: dotnet build -c Release - - name: Publish - run: dotnet publish src/SourceGit.csproj -c Release -o publish -r linux-x64 - - name: Rename Executable File - run: mv publish/SourceGit publish/sourcegit - - name: Packing Program - run: tar -cvf sourcegit.linux-x64.tar -C publish/ . - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: sourcegit.linux-x64 - path: sourcegit.linux-x64.tar - build-linux-arm64: - name: Build Linux (arm64) - runs-on: ubuntu-20.04 + build: + strategy: + matrix: + include: + - name : Windows x64 + os: windows-2019 + runtime: win-x64 + - name : macOS (Intel) + os: macos-13 + runtime: osx-x64 + - name : macOS (Apple Silicon) + os: macos-latest + runtime: osx-arm64 + - name : Linux + os: ubuntu-20.04 + runtime: linux-x64 + - name : Linux (arm64) + os: ubuntu-20.04 + runtime: linux-arm64 + name: Build ${{ matrix.name }} + runs-on: ${{ matrix.os }} steps: - name: Checkout sources uses: actions/checkout@v4 @@ -112,6 +37,7 @@ jobs: with: dotnet-version: 8.0.x - name: Configure arm64 packages + if: ${{ matrix.runtime == 'linux-arm64' }} run: | sudo dpkg --add-architecture arm64 echo 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main restricted @@ -121,19 +47,22 @@ jobs: sudo sed -i -e 's/^deb http/deb [arch=amd64] http/g' /etc/apt/sources.list sudo sed -i -e 's/^deb mirror/deb [arch=amd64] mirror/g' /etc/apt/sources.list - name: Install cross-compiling dependencies + if: ${{ matrix.runtime == 'linux-arm64' }} run: | sudo apt-get update sudo apt-get install clang llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64 - name: Build run: dotnet build -c Release - name: Publish - run: dotnet publish src/SourceGit.csproj -c Release -o publish -r linux-arm64 - - name: Rename Executable File + run: dotnet publish src/SourceGit.csproj -c Release -o publish -r ${{ matrix.runtime }} + - name: Rename executable file + if: ${{ startsWith(matrix.runtime, 'linux-') }} run: mv publish/SourceGit publish/sourcegit - - name: Packing Program - run: tar -cvf sourcegit.linux-arm64.tar -C publish/ . - - name: Upload Artifact + - name: Package program + if: ${{ ! startsWith(matrix.runtime, 'win-') }} + run: tar -cvf sourcegit.${{ matrix.runtime }}.tar -C publish/ . + - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: sourcegit.linux-arm64 - path: sourcegit.linux-arm64.tar + name: sourcegit.${{ matrix.runtime }} + path: ${{ startsWith(matrix.runtime, 'win-') && 'publish' || format('sourcegit.{0}.tar', matrix.runtime) }} From 0492f8e75e15e3ad7a0961f789fe1209fa71624f Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Fri, 2 Aug 2024 14:25:25 +0000 Subject: [PATCH 02/70] ci: add win-arm64 job --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b1cd88e..84b7558a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ jobs: - name : Windows x64 os: windows-2019 runtime: win-x64 + - name : Windows ARM64 + os: windows-2019 + runtime: win-arm64 - name : macOS (Intel) os: macos-13 runtime: osx-x64 From 08aa96f1c5d8c42a5ae7de1df05f8201cf1b9d64 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Fri, 2 Aug 2024 15:06:42 +0000 Subject: [PATCH 03/70] ci: don't tar the artifacts since GitHub will archive it anyway --- .github/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84b7558a..253df156 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,11 +61,8 @@ jobs: - name: Rename executable file if: ${{ startsWith(matrix.runtime, 'linux-') }} run: mv publish/SourceGit publish/sourcegit - - name: Package program - if: ${{ ! startsWith(matrix.runtime, 'win-') }} - run: tar -cvf sourcegit.${{ matrix.runtime }}.tar -C publish/ . - name: Upload artifact uses: actions/upload-artifact@v4 with: name: sourcegit.${{ matrix.runtime }} - path: ${{ startsWith(matrix.runtime, 'win-') && 'publish' || format('sourcegit.{0}.tar', matrix.runtime) }} + path: publish From 646f7f90cfdaa2ec625c919a7598730a8da42125 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Fri, 2 Aug 2024 19:22:38 +0000 Subject: [PATCH 04/70] ci: allow build to be triggered by call --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 253df156..3a12b9e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: pull_request: branches: [develop] workflow_dispatch: + workflow_call: jobs: build: strategy: @@ -33,8 +34,6 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup .NET uses: actions/setup-dotnet@v4 with: From 6bea4b42a2a1951266ce416ede0be50b64aba8b8 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Fri, 2 Aug 2024 20:49:08 +0000 Subject: [PATCH 05/70] build: refactor build scripts use right way to include symlinks and some other minor changes --- build/build.linux.sh | 3 ++- build/resources/deb/DEBIAN/control | 2 +- build/resources/deb/DEBIAN/postinst | 5 ----- build/resources/deb/DEBIAN/postrm | 4 ---- build/resources/rpm/SPECS/build.spec | 33 ++++++++++++++-------------- 5 files changed, 19 insertions(+), 28 deletions(-) delete mode 100755 build/resources/deb/DEBIAN/postinst delete mode 100755 build/resources/deb/DEBIAN/postrm diff --git a/build/build.linux.sh b/build/build.linux.sh index 55bc2f62..21280527 100755 --- a/build/build.linux.sh +++ b/build/build.linux.sh @@ -16,12 +16,13 @@ cd ../../ # Debain/Ubuntu package mkdir -p resources/deb/opt/sourcegit/ +mkdir -p resources/deb/usr/bin mkdir -p resources/deb/usr/share/applications mkdir -p resources/deb/usr/share/icons cp -f SourceGit/* resources/deb/opt/sourcegit/ +ln -sf ../../opt/sourcegit/sourcegit resources/deb/usr/bin cp -r resources/_common/applications resources/deb/usr/share/ cp -r resources/_common/icons resources/deb/usr/share/ -chmod +x -R resources/deb/opt/sourcegit sed -i "2s/.*/Version: ${version}/g" resources/deb/DEBIAN/control dpkg-deb --build resources/deb ./sourcegit_${version}-1_amd64.deb diff --git a/build/resources/deb/DEBIAN/control b/build/resources/deb/DEBIAN/control index 44dbf397..7cfed330 100755 --- a/build/resources/deb/DEBIAN/control +++ b/build/resources/deb/DEBIAN/control @@ -1,5 +1,5 @@ Package: sourcegit -Version: 8.18 +Version: 8.23 Priority: optional Depends: libx11-6, libice6, libsm6 Architecture: amd64 diff --git a/build/resources/deb/DEBIAN/postinst b/build/resources/deb/DEBIAN/postinst deleted file mode 100755 index 56aba83b..00000000 --- a/build/resources/deb/DEBIAN/postinst +++ /dev/null @@ -1,5 +0,0 @@ -#!bin/sh - -echo 'Create link on /usr/bin' -ln -s /opt/sourcegit/sourcegit /usr/bin/sourcegit -exit 0 \ No newline at end of file diff --git a/build/resources/deb/DEBIAN/postrm b/build/resources/deb/DEBIAN/postrm deleted file mode 100755 index 5a600118..00000000 --- a/build/resources/deb/DEBIAN/postrm +++ /dev/null @@ -1,4 +0,0 @@ -#!bin/sh - -rm -f /usr/bin/sourcegit -exit 0 \ No newline at end of file diff --git a/build/resources/rpm/SPECS/build.spec b/build/resources/rpm/SPECS/build.spec index ddafcfb8..86a7cfdd 100644 --- a/build/resources/rpm/SPECS/build.spec +++ b/build/resources/rpm/SPECS/build.spec @@ -14,24 +14,23 @@ Requires: libSM.so.6 Open-source & Free Git Gui Client %install -mkdir -p $RPM_BUILD_ROOT/opt/sourcegit -mkdir -p $RPM_BUILD_ROOT/usr/share/applications -mkdir -p $RPM_BUILD_ROOT/usr/share/icons -cp -r ../../_common/applications $RPM_BUILD_ROOT/usr/share/ -cp -r ../../_common/icons $RPM_BUILD_ROOT/usr/share/ -cp -f ../../../SourceGit/* $RPM_BUILD_ROOT/opt/sourcegit/ -chmod 755 -R $RPM_BUILD_ROOT/opt/sourcegit -chmod 755 $RPM_BUILD_ROOT/usr/share/applications/sourcegit.desktop +mkdir -p %{buildroot}/opt/sourcegit +mkdir -p %{buildroot}/%{_bindir} +mkdir -p %{buildroot}/usr/share/applications +mkdir -p %{buildroot}/usr/share/icons +cp -f ../../../SourceGit/* %{buildroot}/opt/sourcegit/ +ln -sf ../../opt/sourcegit/sourcegit %{buildroot}/%{_bindir} +cp -r ../../_common/applications %{buildroot}/%{_datadir} +cp -r ../../_common/icons %{buildroot}/%{_datadir} +chmod 755 -R %{buildroot}/opt/sourcegit +chmod 755 %{buildroot}/%{_datadir}/applications/sourcegit.desktop %files -/opt/sourcegit -/usr/share - -%post -ln -s /opt/sourcegit/sourcegit /usr/bin/sourcegit - -%postun -rm -f /usr/bin/sourcegit +%dir /opt/sourcegit/ +/opt/sourcegit/* +/usr/share/applications/sourcegit.desktop +/usr/share/icons/* +%{_bindir}/sourcegit %changelog -# skip \ No newline at end of file +# skip From 97d622a8b711861c5b7b07b6e0828f00e5b3b3a6 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sat, 3 Aug 2024 05:55:36 +0000 Subject: [PATCH 06/70] build: fix some AppStream metadata warnings --- build/resources/appimage/sourcegit.appdata.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build/resources/appimage/sourcegit.appdata.xml b/build/resources/appimage/sourcegit.appdata.xml index ca304b4b..012c82d3 100644 --- a/build/resources/appimage/sourcegit.appdata.xml +++ b/build/resources/appimage/sourcegit.appdata.xml @@ -1,6 +1,6 @@ - com.sourcegit-scm.SourceGit + com.sourcegit_scm.SourceGit MIT MIT SourceGit @@ -8,8 +8,9 @@

Open-source GUI client for git users

- com.sourcegit-scm.SourceGit.desktop + https://github.com/sourcegit-scm/sourcegit + com.sourcegit_scm.SourceGit.desktop - com.sourcegit-scm.SourceGit.desktop + com.sourcegit_scm.SourceGit.desktop -
\ No newline at end of file + From 455ad657a7fbb0285bc9fd19689b90b4ecb26a3a Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sat, 3 Aug 2024 06:43:17 +0000 Subject: [PATCH 07/70] build: force root owner for deb package --- build/build.linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build.linux.sh b/build/build.linux.sh index 21280527..585dcfb3 100755 --- a/build/build.linux.sh +++ b/build/build.linux.sh @@ -24,7 +24,7 @@ ln -sf ../../opt/sourcegit/sourcegit resources/deb/usr/bin cp -r resources/_common/applications resources/deb/usr/share/ cp -r resources/_common/icons resources/deb/usr/share/ sed -i "2s/.*/Version: ${version}/g" resources/deb/DEBIAN/control -dpkg-deb --build resources/deb ./sourcegit_${version}-1_amd64.deb +dpkg-deb --root-owner-group --build resources/deb ./sourcegit_${version}-1_amd64.deb # Redhat/CentOS/Fedora package rpmbuild -bb --target=x86_64 resources/rpm/SPECS/build.spec --define "_topdir `pwd`/resources/rpm" --define "_version ${version}" From 073b5aaf9e0833acdbe6df34191a0213baca00a3 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sat, 3 Aug 2024 10:01:02 +0000 Subject: [PATCH 08/70] ci: add automatic releases --- .github/workflows/package.yml | 95 ++++++++++++++++++++++++++++ .github/workflows/release.yml | 49 ++++++++++++++ build/ci/package.linux.sh | 78 +++++++++++++++++++++++ build/ci/package.osx-app.sh | 22 +++++++ build/ci/package.windows-portable.sh | 19 ++++++ 5 files changed, 263 insertions(+) create mode 100644 .github/workflows/package.yml create mode 100644 .github/workflows/release.yml create mode 100755 build/ci/package.linux.sh create mode 100755 build/ci/package.osx-app.sh create mode 100755 build/ci/package.windows-portable.sh diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml new file mode 100644 index 00000000..8ffcf88e --- /dev/null +++ b/.github/workflows/package.yml @@ -0,0 +1,95 @@ +name: Package +on: + workflow_call: + inputs: + version: + description: Source Git package version + required: true + type: string +jobs: + build: + name: Build + uses: ./.github/workflows/ci.yml + windows-portable: + name: Package portable Windows app + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + runtime: [win-x64, win-arm64] + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Download build + uses: actions/download-artifact@v4 + with: + name: sourcegit.${{ matrix.runtime }} + path: build/SourceGit + - name: Package + env: + VERSION: ${{ inputs.version }} + RUNTIME: ${{ matrix.runtime }} + run: ./build/ci/package.windows-portable.sh + - name: Upload package artifact + uses: actions/upload-artifact@v4 + with: + name: package.${{ matrix.runtime }} + path: build/sourcegit_*.zip + osx-app: + name: Package OSX app + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + runtime: [osx-x64, osx-arm64] + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Download build + uses: actions/download-artifact@v4 + with: + name: sourcegit.${{ matrix.runtime }} + path: build/SourceGit + - name: Package + env: + VERSION: ${{ inputs.version }} + RUNTIME: ${{ matrix.runtime }} + run: ./build/ci/package.osx-app.sh + - name: Upload package artifact + uses: actions/upload-artifact@v4 + with: + name: package.${{ matrix.runtime }} + path: build/sourcegit_*.zip + linux: + name: Package Linux + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + runtime: [linux-x64, linux-arm64] + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Download package dependencies + run: | + sudo add-apt-repository universe + sudo apt-get update + sudo apt-get install desktop-file-utils rpm libfuse2 + - name: Download build + uses: actions/download-artifact@v4 + with: + name: sourcegit.${{ matrix.runtime }} + path: build/SourceGit + - name: Package + env: + VERSION: ${{ inputs.version }} + RUNTIME: ${{ matrix.runtime }} + run: ./build/ci/package.linux.sh + - name: Upload package artifacts + uses: actions/upload-artifact@v4 + with: + name: package.${{ matrix.runtime }} + path: | + build/sourcegit-*.AppImage + build/sourcegit_*.deb + build/sourcegit-*.rpm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..51e247d2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: Release +on: + push: + tags: + - v* +jobs: + version: + name: Prepare version string + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Output version string + id: version + env: + TAG: ${{ github.ref_name }} + run: echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + package: + needs: version + name: Package + uses: ./.github/workflows/package.yml + with: + version: ${{ needs.version.outputs.version }} + release: + needs: [version, package] + name: Release + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Create release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + run: gh release create "$TAG" -t "Release ${TAG#v}" --notes-from-tag + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + pattern: package.* + path: packages + merge-multiple: true + - name: Upload assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + VERSION: ${{ needs.version.outputs.version }} + run: gh release upload "$TAG" packages/* diff --git a/build/ci/package.linux.sh b/build/ci/package.linux.sh new file mode 100755 index 00000000..c4c23d14 --- /dev/null +++ b/build/ci/package.linux.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +set -e + +if [ -z "$VERSION" ]; then + echo "Provide the version as environment variable VERSION" + exit 1 +fi + +if [ -z "$RUNTIME" ]; then + echo "Provide the runtime as environment variable RUNTIME" + exit 1 +fi + +arch= +appimage_arch= +appimage_runtime= +target= +case "$RUNTIME" in + linux-x64) + arch=amd64 + appimage_arch=x86_64 + appimage_runtime=runtime-fuse2-x86_64 + target=x86_64;; + linux-arm64) + arch=arm64 + appimage_arch=arm_aarch64 + appimage_runtime=runtime-fuse2-aarch64 + target=aarch64;; + *) + echo "Unknown runtime $RUNTIME" + exit 1;; +esac + +APPIMAGETOOL_URL=https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage +APPIMAGE_RUNTIME_URL=https://github.com/AppImage/type2-runtime/releases/download/old/$appimage_runtime + +cd build + +if [ ! -f "appimagetool" ]; then + curl -o appimagetool -L "$APPIMAGETOOL_URL" + chmod +x appimagetool +fi + +if [ ! -f "appimage_runtime" ]; then + curl -o appimage_runtime -L "$APPIMAGE_RUNTIME_URL" +fi + +rm -f SourceGit/*.dbg + +mkdir -p SourceGit.AppDir/opt +mkdir -p SourceGit.AppDir/usr/share/metainfo +mkdir -p SourceGit.AppDir/usr/share/applications + +cp -r SourceGit SourceGit.AppDir/opt/sourcegit +desktop-file-install resources/_common/applications/sourcegit.desktop --dir SourceGit.AppDir/usr/share/applications \ + --set-icon com.sourcegit_scm.SourceGit --set-key=Exec --set-value=AppRun +mv SourceGit.AppDir/usr/share/applications/{sourcegit,com.sourcegit_scm.SourceGit}.desktop +cp resources/appimage/sourcegit.png SourceGit.AppDir/com.sourcegit_scm.SourceGit.png +ln -sf /opt/sourcegit/sourcegit SourceGit.AppDir/AppRun +ln -rsf SourceGit.AppDir/usr/share/applications/com.sourcegit_scm.SourceGit.desktop SourceGit.AppDir +cp resources/appimage/sourcegit.appdata.xml SourceGit.AppDir/usr/share/metainfo/com.sourcegit_scm.SourceGit.appdata.xml + +ARCH="$appimage_arch" ./appimagetool -v --runtime-file appimage_runtime SourceGit.AppDir "sourcegit-$VERSION.linux.$arch.AppImage" + +mkdir -p resources/deb/opt/sourcegit/ +mkdir -p resources/deb/usr/bin +mkdir -p resources/deb/usr/share/applications +mkdir -p resources/deb/usr/share/icons +cp -f SourceGit/* resources/deb/opt/sourcegit +ln -sf ../../opt/sourcegit/sourcegit resources/deb/usr/bin +cp -r resources/_common/applications resources/deb/usr/share +cp -r resources/_common/icons resources/deb/usr/share +sed -i -e "s/^Version:.*/Version: $VERSION/" -e "s/^Architecture:.*/Architecture: $arch/" resources/deb/DEBIAN/control +dpkg-deb --root-owner-group --build resources/deb "sourcegit_$VERSION-1_$arch.deb" + +rpmbuild -bb --target="$target" resources/rpm/SPECS/build.spec --define "_topdir $(pwd)/resources/rpm" --define "_version $VERSION" +mv "resources/rpm/RPMS/$target/sourcegit-$VERSION-1.$target.rpm" ./ diff --git a/build/ci/package.osx-app.sh b/build/ci/package.osx-app.sh new file mode 100755 index 00000000..80e66a08 --- /dev/null +++ b/build/ci/package.osx-app.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +if [ -z "$VERSION" ]; then + echo "Provide the version as environment variable VERSION" + exit 1 +fi + +if [ -z "$RUNTIME" ]; then + echo "Provide the runtime as environment variable RUNTIME" + exit 1 +fi + +cd build + +mkdir -p SourceGit.app/Contents/Resources +mv SourceGit SourceGit.app/Contents/MacOS +cp resources/app/App.icns SourceGit.app/Contents/Resources/App.icns +sed "s/SOURCE_GIT_VERSION/$VERSION/g" resources/app/App.plist > SourceGit.app/Contents/Info.plist + +zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit.app -x "*/*\.dsym/*" diff --git a/build/ci/package.windows-portable.sh b/build/ci/package.windows-portable.sh new file mode 100755 index 00000000..cc5ee1bd --- /dev/null +++ b/build/ci/package.windows-portable.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +if [ -z "$VERSION" ]; then + echo "Provide the version as environment variable VERSION" + exit 1 +fi + +if [ -z "$RUNTIME" ]; then + echo "Provide the runtime as environment variable RUNTIME" + exit 1 +fi + +cd build + +rm -rf SourceGit/*.pdb + +zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit From 822d6ec88e0774e23fae8e7ca31c07b35c450057 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sat, 3 Aug 2024 13:50:57 +0000 Subject: [PATCH 09/70] ci: tar artifact to keep permissions --- .github/workflows/ci.yml | 6 ++++++ .github/workflows/package.yml | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a12b9e1..87d460c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,12 @@ jobs: - name: Rename executable file if: ${{ startsWith(matrix.runtime, 'linux-') }} run: mv publish/SourceGit publish/sourcegit + - name: Tar artifact + if: ${{ startsWith(matrix.runtime, 'linux-') }} + run: | + tar -cvf "sourcegit.${{ matrix.runtime }}.tar" -C publish . + rm -r publish/* + mv "sourcegit.${{ matrix.runtime }}.tar" publish - name: Upload artifact uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 8ffcf88e..404c909e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -79,12 +79,15 @@ jobs: uses: actions/download-artifact@v4 with: name: sourcegit.${{ matrix.runtime }} - path: build/SourceGit + path: build - name: Package env: VERSION: ${{ inputs.version }} RUNTIME: ${{ matrix.runtime }} - run: ./build/ci/package.linux.sh + run: | + mkdir build/SourceGit + tar -xf "build/sourcegit.${{ matrix.runtime }}.tar" -C build/SourceGit + ./build/ci/package.linux.sh - name: Upload package artifacts uses: actions/upload-artifact@v4 with: From 00a11fbd02566bc0cc74e7c59b512058ebbff5e4 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Wed, 7 Aug 2024 03:26:57 +0000 Subject: [PATCH 10/70] ci: use relative link for AppImage's AppRun --- build/ci/package.linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/ci/package.linux.sh b/build/ci/package.linux.sh index c4c23d14..b9a86551 100755 --- a/build/ci/package.linux.sh +++ b/build/ci/package.linux.sh @@ -57,7 +57,7 @@ desktop-file-install resources/_common/applications/sourcegit.desktop --dir Sour --set-icon com.sourcegit_scm.SourceGit --set-key=Exec --set-value=AppRun mv SourceGit.AppDir/usr/share/applications/{sourcegit,com.sourcegit_scm.SourceGit}.desktop cp resources/appimage/sourcegit.png SourceGit.AppDir/com.sourcegit_scm.SourceGit.png -ln -sf /opt/sourcegit/sourcegit SourceGit.AppDir/AppRun +ln -rsf SourceGit.AppDir/opt/sourcegit/sourcegit SourceGit.AppDir/AppRun ln -rsf SourceGit.AppDir/usr/share/applications/com.sourcegit_scm.SourceGit.desktop SourceGit.AppDir cp resources/appimage/sourcegit.appdata.xml SourceGit.AppDir/usr/share/metainfo/com.sourcegit_scm.SourceGit.appdata.xml From 05ddd42604c893ab4cf1396f18c69adaf1155933 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sun, 11 Aug 2024 15:43:36 +0000 Subject: [PATCH 11/70] ci: use new AppImage runtime --- build/ci/package.linux.sh | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/build/ci/package.linux.sh b/build/ci/package.linux.sh index b9a86551..04309018 100755 --- a/build/ci/package.linux.sh +++ b/build/ci/package.linux.sh @@ -14,18 +14,15 @@ fi arch= appimage_arch= -appimage_runtime= target= case "$RUNTIME" in linux-x64) arch=amd64 appimage_arch=x86_64 - appimage_runtime=runtime-fuse2-x86_64 target=x86_64;; linux-arm64) arch=arm64 appimage_arch=arm_aarch64 - appimage_runtime=runtime-fuse2-aarch64 target=aarch64;; *) echo "Unknown runtime $RUNTIME" @@ -33,7 +30,6 @@ case "$RUNTIME" in esac APPIMAGETOOL_URL=https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -APPIMAGE_RUNTIME_URL=https://github.com/AppImage/type2-runtime/releases/download/old/$appimage_runtime cd build @@ -42,10 +38,6 @@ if [ ! -f "appimagetool" ]; then chmod +x appimagetool fi -if [ ! -f "appimage_runtime" ]; then - curl -o appimage_runtime -L "$APPIMAGE_RUNTIME_URL" -fi - rm -f SourceGit/*.dbg mkdir -p SourceGit.AppDir/opt @@ -61,7 +53,7 @@ ln -rsf SourceGit.AppDir/opt/sourcegit/sourcegit SourceGit.AppDir/AppRun ln -rsf SourceGit.AppDir/usr/share/applications/com.sourcegit_scm.SourceGit.desktop SourceGit.AppDir cp resources/appimage/sourcegit.appdata.xml SourceGit.AppDir/usr/share/metainfo/com.sourcegit_scm.SourceGit.appdata.xml -ARCH="$appimage_arch" ./appimagetool -v --runtime-file appimage_runtime SourceGit.AppDir "sourcegit-$VERSION.linux.$arch.AppImage" +ARCH="$appimage_arch" ./appimagetool -v SourceGit.AppDir "sourcegit-$VERSION.linux.$arch.AppImage" mkdir -p resources/deb/opt/sourcegit/ mkdir -p resources/deb/usr/bin From 2e1271723545170fc94a31963f46059db19e3482 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 12 Aug 2024 12:03:30 +0800 Subject: [PATCH 12/70] ux: removes padding when calculate layouts --- src/Views/Repository.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index 0e500b2c..f6230f02 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -164,7 +164,7 @@ namespace SourceGit.Views if (!IsLoaded) return; - var leftHeight = LeftSidebarGroups.Bounds.Height - 28.0 * 5; + var leftHeight = LeftSidebarGroups.Bounds.Height - 28.0 * 5 - 4; var localBranchRows = vm.IsLocalBranchGroupExpanded ? LocalBranchTree.Rows.Count : 0; var remoteBranchRows = vm.IsRemoteGroupExpanded ? RemoteBranchTree.Rows.Count : 0; var desiredBranches = (localBranchRows + remoteBranchRows) * 24.0; From 9c6bd87dd6096a78f54298fa2b48ee3cb2e7fdd0 Mon Sep 17 00:00:00 2001 From: NilsPvR Date: Sun, 11 Aug 2024 21:19:20 +0200 Subject: [PATCH 13/70] enhance: review suggestions for German translation --- src/Resources/Locales/de_DE.axaml | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 4a0abd37..ae4a69e2 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -6,9 +6,9 @@ Über SourceGit • Erstellt mit © 2024 sourcegit-scm - • Text Editor von + • Texteditor von • Monospace-Schriftarten von - • Quelltext findest du unter + • Quelltext findest du auf Open Source & freier Git GUI Client Worktree hinzufügen Was auschecken: @@ -29,7 +29,7 @@ Wähle die anzuwendende .patch-Datei Ignoriere Leerzeichenänderungen Keine Warnungen - Schaltet die Warnung vor nachgestellte Leerzeichen aus + Keine Warnung vor Leerzeichen am Zeilenende Patch anwenden Warnen Gibt eine Warnung für ein paar solcher Fehler aus, aber wendet es an @@ -41,12 +41,12 @@ Archiv erstellen SourceGit Askpass ALS UNVERÄNDERT ANGENOMMENE DATEIEN - KEINE UNVERÄNDERT ANGENOMMENEN DATEIEN GEFUNDEN + KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN ENTFERNEN BINÄRE DATEI NICHT UNTERSTÜTZT!!! Blame BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!! - ${0}$ auschecken... + Auscheken von ${0}$... Mit Branch vergleichen Mit HEAD vergleichen Mit Worktree vergleichen @@ -218,7 +218,7 @@ Fetch Alle Remotes fetchen Ohne Tags fetchen - Alle toten remote Branches entfernen + Alle verwaisten Branches entfernen Remote: Remote-Änderungen fetchen Als unverändert annehmen @@ -240,7 +240,7 @@ Datei Historie FILTER Git-Flow - Entwicklungs-Branch: + Development-Branch: Feature: Feature-Prefix: FLOW - Finish Feature @@ -251,7 +251,7 @@ Hotfix-Prefix: Git-Flow initialisieren Branch behalten - Produktions-Branch: + Production-Branch: Release: Release-Prefix: Feature starten... @@ -286,9 +286,9 @@ LFS Objekte pushen Pushe große Dateien in der Warteschlange zum Git LFS Endpunkt Remote: - Verfolge '{0}' benannte Dateien + Verfolge alle '{0}' Dateien Verfolge alle *{0} Dateien - Historien + Verlauf Wechsle zwischen horizontalem und vertikalem Layout Wechsle zwischen Kurven- und Konturgraphenmodus AUTOR @@ -314,9 +314,9 @@ Ausgewählte Änderungen stagen/unstagen Commit-Suchmodus Wechsle zu 'Änderungen' - Wechsle zu 'Historien' + Wechsle zu 'Verlauf' Wechsle zu 'Stashes' - TEXT EDITOR + TEXTEDITOR Suchpanel schließen Suche nächste Übereinstimmung Suche vorherige Übereinstimmung @@ -334,8 +334,8 @@ Interaktiver Rebase Ziel Branch: Auf: - Hoch schieben - Runter schieben + Hochschieben + Runterschieben Source Git FEHLER INFO @@ -353,8 +353,8 @@ Neue Seite erstellen Lesezeichen Tab schließen - Schließe andere Tabs - Schließe Rechte Tabs + Andere Tabs schließen + Rechte Tabs schließen Kopiere Repository-Pfad Repositories Einfügen @@ -368,11 +368,11 @@ Leztes Jahr Vor {0} Jahren Einstellungen - ERSCHEINUNGSBILD + DARSTELLUNG Standardschriftart Standardschriftgröße Monospace-Schriftart - Verwende nur die Monospace-Schriftart im Text Editor + Verwende nur die Monospace-Schriftart im Texteditor Design Design-Anpassungen ALLGEMEIN @@ -381,7 +381,7 @@ Sprache Commit-Historie Zuletzt geöffnete Tabs beim Starten wiederherstellen - Commit-Nachricht Hinweislänge + Längenvorgabe für Commit-Nachrichten Fixe Tab-Breite in Titelleiste Sichtbare Vergleichskontextzeilen GIT @@ -403,12 +403,12 @@ Tag-Signierung GPG Format GPG Installationspfad - Gebe Installationspfad zu installiertem GPG Programm an + Installationspfad zum GPG Programm Benutzer Signierungsschlüssel GPG Benutzer Signierungsschlüssel DIFF/MERGE TOOL Installationspfad - Gebe Installationspfad zum Diff/Merge Tool an + Installationspfad zum Diff/Merge Tool Tool Remote löschen Ziel: @@ -480,7 +480,7 @@ Aktualisiern REMOTES REMOTE HINZUFÜGEN - LÖSEN + KONFLIKTE BEHEBEN Commit suchen Suche über Dateiname From 965a4b21aef1040ce538e69132910c3c6fa8db0d Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 12 Aug 2024 15:01:00 +0800 Subject: [PATCH 14/70] feature: use `Ctrl` + click to start fetch/pull/push automatically with default options (#351) --- src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/Resources/Styles.axaml | 3 +++ src/ViewModels/Repository.cs | 21 +++++++++++++----- src/Views/RepositoryToolbar.axaml | 27 ++++++++++++++++++++--- src/Views/RepositoryToolbar.axaml.cs | 33 ++++++++++++++++++++++++++++ 7 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 364494f0..c3ce9f2a 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -163,6 +163,7 @@ Kind: annotated lightweight + Hold Ctrl to start directly Cut Delete Branch Branch: diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 58e915db..1603caf4 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -166,6 +166,7 @@ 类型 : 附注标签 轻量标签 + 按住Ctrl键点击将以默认参数运行 剪切 删除分支确认 分支名 : diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 167933da..859a0136 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -166,6 +166,7 @@ 型別 : 附註標籤 輕量標籤 + 按住Ctrl鍵點擊將以預設參數運行 剪下 刪除分支確認 分支名 : diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index f40e88f6..9ff41264 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -253,6 +253,9 @@ + diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 5ef34d5b..7f5a1232 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -420,7 +420,7 @@ namespace SourceGit.ViewModels return menu; } - public void Fetch() + public void Fetch(bool autoStart) { if (!PopupHost.CanCreatePopup()) return; @@ -431,10 +431,13 @@ namespace SourceGit.ViewModels return; } - PopupHost.ShowPopup(new Fetch(this)); + if (autoStart) + PopupHost.ShowAndStartPopup(new Fetch(this)); + else + PopupHost.ShowPopup(new Fetch(this)); } - public void Pull() + public void Pull(bool autoStart) { if (!PopupHost.CanCreatePopup()) return; @@ -445,10 +448,13 @@ namespace SourceGit.ViewModels return; } - PopupHost.ShowPopup(new Pull(this, null)); + if (autoStart) + PopupHost.ShowAndStartPopup(new Pull(this, null)); + else + PopupHost.ShowPopup(new Pull(this, null)); } - public void Push() + public void Push(bool autoStart) { if (!PopupHost.CanCreatePopup()) return; @@ -465,7 +471,10 @@ namespace SourceGit.ViewModels return; } - PopupHost.ShowPopup(new Push(this, null)); + if (autoStart) + PopupHost.ShowAndStartPopup(new Push(this, null)); + else + PopupHost.ShowPopup(new Push(this, null)); } public void ApplyPatch() diff --git a/src/Views/RepositoryToolbar.axaml b/src/Views/RepositoryToolbar.axaml index 2f7a1d48..45186fa7 100644 --- a/src/Views/RepositoryToolbar.axaml +++ b/src/Views/RepositoryToolbar.axaml @@ -31,15 +31,36 @@ - - - diff --git a/src/Views/RepositoryToolbar.axaml.cs b/src/Views/RepositoryToolbar.axaml.cs index 57fed44b..37963d99 100644 --- a/src/Views/RepositoryToolbar.axaml.cs +++ b/src/Views/RepositoryToolbar.axaml.cs @@ -1,4 +1,5 @@ using Avalonia.Controls; +using Avalonia.Input; using Avalonia.Interactivity; namespace SourceGit.Views @@ -10,6 +11,18 @@ namespace SourceGit.Views InitializeComponent(); } + protected override void OnKeyDown(KeyEventArgs e) + { + base.OnKeyDown(e); + _hasCtrl = e.KeyModifiers.HasFlag(KeyModifiers.Control); + } + + protected override void OnKeyUp(KeyEventArgs e) + { + base.OnKeyUp(e); + _hasCtrl = false; + } + private void OpenWithExternalTools(object sender, RoutedEventArgs e) { if (sender is Button button && DataContext is ViewModels.Repository repo) @@ -40,6 +53,24 @@ namespace SourceGit.Views } } + private void Fetch(object _, RoutedEventArgs e) + { + (DataContext as ViewModels.Repository)?.Fetch(_hasCtrl); + e.Handled = true; + } + + private void Pull(object _, RoutedEventArgs e) + { + (DataContext as ViewModels.Repository)?.Pull(_hasCtrl); + e.Handled = true; + } + + private void Push(object _, RoutedEventArgs e) + { + (DataContext as ViewModels.Repository)?.Push(_hasCtrl); + e.Handled = true; + } + private void OpenGitFlowMenu(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.Repository repo) @@ -61,6 +92,8 @@ namespace SourceGit.Views e.Handled = true; } + + private bool _hasCtrl = false; } } From 429e037adbdcbdf723021105e6fe600c23379dd1 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 12 Aug 2024 15:11:49 +0800 Subject: [PATCH 15/70] feature: use `Ctrl` + click to stash all changes automatically with default options (#351) --- src/ViewModels/Repository.cs | 10 ++-------- src/ViewModels/WorkingCopy.cs | 11 +++++++++++ src/Views/RepositoryToolbar.axaml | 9 ++++++++- src/Views/RepositoryToolbar.axaml.cs | 6 ++++++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 7f5a1232..e248967a 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -616,15 +616,9 @@ namespace SourceGit.ViewModels Task.Run(RefreshCommits); } - public void StashAll() + public void StashAll(bool autoStart) { - if (PopupHost.CanCreatePopup()) - { - var changes = new List(); - changes.AddRange(_workingCopy.Unstaged); - changes.AddRange(_workingCopy.Staged); - PopupHost.ShowPopup(new StashChanges(this, changes, true)); - } + _workingCopy?.StashAll(autoStart); } public void GotoResolve() diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 3e93d82b..c72900ec 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -317,6 +317,17 @@ namespace SourceGit.ViewModels dialog.ShowDialog(toplevel); } + public void StashAll(bool autoStart) + { + if (!PopupHost.CanCreatePopup()) + return; + + if (autoStart) + PopupHost.ShowAndStartPopup(new StashChanges(_repo, _cached, true)); + else + PopupHost.ShowPopup(new StashChanges(_repo, _cached, true)); + } + public void StageSelected() { StageChanges(_selectedUnstaged); diff --git a/src/Views/RepositoryToolbar.axaml b/src/Views/RepositoryToolbar.axaml index 45186fa7..b76cfd63 100644 --- a/src/Views/RepositoryToolbar.axaml +++ b/src/Views/RepositoryToolbar.axaml @@ -64,7 +64,14 @@ - diff --git a/src/Views/RepositoryToolbar.axaml.cs b/src/Views/RepositoryToolbar.axaml.cs index 37963d99..6fad104d 100644 --- a/src/Views/RepositoryToolbar.axaml.cs +++ b/src/Views/RepositoryToolbar.axaml.cs @@ -71,6 +71,12 @@ namespace SourceGit.Views e.Handled = true; } + private void StashAll(object _, RoutedEventArgs e) + { + (DataContext as ViewModels.Repository)?.StashAll(_hasCtrl); + e.Handled = true; + } + private void OpenGitFlowMenu(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.Repository repo) From d98ec5db7583650a3dd026f6e2dc685a3f48055e Mon Sep 17 00:00:00 2001 From: van Rijsinge Date: Mon, 12 Aug 2024 09:33:25 +0200 Subject: [PATCH 16/70] feature: add German translations for new features --- src/Resources/Locales/de_DE.axaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index ae4a69e2..ec138390 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -166,6 +166,7 @@ Art: Mit Anmerkung Ohne Anmerkung + Halte Strg gedrückt, um direkt auszuführen Ausschneiden Branch löschen Branch: @@ -488,6 +489,7 @@ SHA Autor & Committer Suche Branches & Tags + Zeige Tags als Baum Statistiken SUBMODULE SUBMODUL HINZUFÜGEN From 0646db36a4c15762fd838e2095527e7ed7adebfd Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 12 Aug 2024 16:14:39 +0800 Subject: [PATCH 17/70] fix: `KeyDown` event won't be triggered unless toolbar got focus (#351) --- src/Views/Launcher.axaml.cs | 18 ++++++++++++++++++ src/Views/RepositoryToolbar.axaml.cs | 27 +++++++++------------------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index dc9f91d2..95fbee7e 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -20,6 +20,11 @@ namespace SourceGit.Views InitializeComponent(); } + public bool HasKeyModifier(KeyModifiers modifier) + { + return _unhandledModifiers.HasFlag(modifier); + } + protected override void OnOpened(EventArgs e) { base.OnOpened(e); @@ -147,6 +152,17 @@ namespace SourceGit.Views } base.OnKeyDown(e); + + if (!e.Handled) + { + _unhandledModifiers = e.KeyModifiers; + } + } + + protected override void OnKeyUp(KeyEventArgs e) + { + base.OnKeyUp(e); + _unhandledModifiers = KeyModifiers.None; } protected override void OnClosing(WindowClosingEventArgs e) @@ -178,5 +194,7 @@ namespace SourceGit.Views e.Handled = true; } + + private KeyModifiers _unhandledModifiers = KeyModifiers.None; } } diff --git a/src/Views/RepositoryToolbar.axaml.cs b/src/Views/RepositoryToolbar.axaml.cs index 6fad104d..27ac43cd 100644 --- a/src/Views/RepositoryToolbar.axaml.cs +++ b/src/Views/RepositoryToolbar.axaml.cs @@ -1,6 +1,7 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.VisualTree; namespace SourceGit.Views { @@ -11,18 +12,6 @@ namespace SourceGit.Views InitializeComponent(); } - protected override void OnKeyDown(KeyEventArgs e) - { - base.OnKeyDown(e); - _hasCtrl = e.KeyModifiers.HasFlag(KeyModifiers.Control); - } - - protected override void OnKeyUp(KeyEventArgs e) - { - base.OnKeyUp(e); - _hasCtrl = false; - } - private void OpenWithExternalTools(object sender, RoutedEventArgs e) { if (sender is Button button && DataContext is ViewModels.Repository repo) @@ -55,25 +44,29 @@ namespace SourceGit.Views private void Fetch(object _, RoutedEventArgs e) { - (DataContext as ViewModels.Repository)?.Fetch(_hasCtrl); + var launcher = this.FindAncestorOfType(); + (DataContext as ViewModels.Repository)?.Fetch(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false); e.Handled = true; } private void Pull(object _, RoutedEventArgs e) { - (DataContext as ViewModels.Repository)?.Pull(_hasCtrl); + var launcher = this.FindAncestorOfType(); + (DataContext as ViewModels.Repository)?.Pull(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false); e.Handled = true; } private void Push(object _, RoutedEventArgs e) { - (DataContext as ViewModels.Repository)?.Push(_hasCtrl); + var launcher = this.FindAncestorOfType(); + (DataContext as ViewModels.Repository)?.Push(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false); e.Handled = true; } private void StashAll(object _, RoutedEventArgs e) { - (DataContext as ViewModels.Repository)?.StashAll(_hasCtrl); + var launcher = this.FindAncestorOfType(); + (DataContext as ViewModels.Repository)?.StashAll(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false); e.Handled = true; } @@ -98,8 +91,6 @@ namespace SourceGit.Views e.Handled = true; } - - private bool _hasCtrl = false; } } From 69178838be109ee7dcacb014789d32e2d510220a Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 12 Aug 2024 16:51:37 +0800 Subject: [PATCH 18/70] fix: always trait `Atl/Ctrl/Shift` as key modifers (#351) --- src/Views/Launcher.axaml.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index 95fbee7e..e73ad1a9 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -153,9 +153,19 @@ namespace SourceGit.Views base.OnKeyDown(e); + // Record unhandled key modifers. if (!e.Handled) { _unhandledModifiers = e.KeyModifiers; + + if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && (e.Key == Key.LeftAlt || e.Key == Key.RightAlt)) + _unhandledModifiers |= KeyModifiers.Alt; + + if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)) + _unhandledModifiers |= KeyModifiers.Control; + + if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && (e.Key == Key.LeftShift || e.Key == Key.RightShift)) + _unhandledModifiers |= KeyModifiers.Shift; } } From 04c9214fc056617a7bb377126df4c0255b600f29 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 12 Aug 2024 19:28:01 +0800 Subject: [PATCH 19/70] fix: remove null-check of sshKey in EditRemote --- src/ViewModels/EditRemote.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ViewModels/EditRemote.cs b/src/ViewModels/EditRemote.cs index 0004cca4..0a514324 100644 --- a/src/ViewModels/EditRemote.cs +++ b/src/ViewModels/EditRemote.cs @@ -93,11 +93,8 @@ namespace SourceGit.ViewModels public static ValidationResult ValidateSSHKey(string sshkey, ValidationContext ctx) { - if (ctx.ObjectInstance is EditRemote edit && edit.UseSSH) + if (ctx.ObjectInstance is EditRemote { _useSSH: true } && !string.IsNullOrEmpty(sshkey)) { - if (string.IsNullOrEmpty(sshkey)) - return new ValidationResult("SSH private key is required"); - if (!File.Exists(sshkey)) return new ValidationResult("Given SSH private key can NOT be found!"); } From f1d43d94a4368fb26a0cdbdde0bd00986dc04902 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sun, 11 Aug 2024 15:50:47 +0000 Subject: [PATCH 20/70] ci: disable unsupported platforms --- .github/workflows/ci.yml | 6 +++--- .github/workflows/package.yml | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87d460c6..40dd41b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,9 +26,9 @@ jobs: - name : Linux os: ubuntu-20.04 runtime: linux-x64 - - name : Linux (arm64) - os: ubuntu-20.04 - runtime: linux-arm64 + # - name : Linux (arm64) + # os: ubuntu-20.04 + # runtime: linux-arm64 name: Build ${{ matrix.name }} runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 404c909e..a3063813 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -66,7 +66,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - runtime: [linux-x64, linux-arm64] + # runtime: [linux-x64, linux-arm64] + runtime: [linux-x64] steps: - name: Checkout sources uses: actions/checkout@v4 From 38665a61cb9660a0668b8cee485c5e258de3bb47 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 12 Aug 2024 21:29:18 +0800 Subject: [PATCH 21/70] fix: `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)` returns an empty string on some linux distro * fallback the storage folder to `~/.sourcegit` --- README.md | 10 +++++----- src/App.axaml.cs | 2 ++ src/Native/OS.cs | 17 +++++++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0af00613..d9ce8f03 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,11 @@ You can download the latest stable from [Releases](https://github.com/sourcegit- This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs. -| OS | PATH | -|---------|-------------------------------------------------| -| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` | -| Linux | `${HOME}/.config/SourceGit` | -| macOS | `${HOME}/Library/Application Support/SourceGit` | +| OS | PATH | +|---------|-----------------------------------------------------| +| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` | +| Linux | `${HOME}/.config/SourceGit` or `${HOME}/.Sourcegit` | +| macOS | `${HOME}/Library/Application Support/SourceGit` | For **Windows** users: diff --git a/src/App.axaml.cs b/src/App.axaml.cs index a8f1e32e..be379e54 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -44,6 +44,8 @@ namespace SourceGit [STAThread] public static void Main(string[] args) { + Native.OS.SetupDataDir(); + AppDomain.CurrentDomain.UnhandledException += (_, e) => { LogException(e.ExceptionObject as Exception); diff --git a/src/Native/OS.cs b/src/Native/OS.cs index 8c2a3ada..ea2b14e6 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -21,9 +21,9 @@ namespace SourceGit.Native void OpenWithDefaultEditor(string file); } - public static readonly string DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SourceGit"); + public static string DataDir { get; private set; } = string.Empty; public static string GitExecutable { get; set; } = string.Empty; - public static List ExternalTools { get; set; } = new List(); + public static List ExternalTools { get; set; } = []; static OS() { @@ -70,10 +70,19 @@ namespace SourceGit.Native public static void SetupApp(AppBuilder builder) { + _backend.SetupApp(builder); + } + + public static void SetupDataDir() + { + var osAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + if (string.IsNullOrEmpty(osAppDataDir)) + DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".SourceGit"); + else + DataDir = Path.Combine(osAppDataDir, "SourceGit"); + if (!Directory.Exists(DataDir)) Directory.CreateDirectory(DataDir); - - _backend.SetupApp(builder); } public static void SetupEnternalTools() From 19cb5678a77b3ca3dc9cd11ba41fa8b9255e4ec9 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 10:08:44 +0800 Subject: [PATCH 22/70] project: upgrade `TextMateSharp` to `1.0.61` to support arm64 platforms (#312) --- src/SourceGit.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index c1fb8a4a..ee376f3a 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -45,7 +45,8 @@ - + + From d1b236b090d7b0c12ced23e3b048f8ab4edec413 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 10:19:16 +0800 Subject: [PATCH 23/70] enhance: usually we create hidden sub-directories in $HOME with lowercase names --- README.md | 2 +- src/Native/OS.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d9ce8f03..54765165 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationD | OS | PATH | |---------|-----------------------------------------------------| | Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` | -| Linux | `${HOME}/.config/SourceGit` or `${HOME}/.Sourcegit` | +| Linux | `${HOME}/.config/SourceGit` or `${HOME}/.sourcegit` | | macOS | `${HOME}/Library/Application Support/SourceGit` | For **Windows** users: diff --git a/src/Native/OS.cs b/src/Native/OS.cs index ea2b14e6..0e1b8522 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -77,7 +77,7 @@ namespace SourceGit.Native { var osAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); if (string.IsNullOrEmpty(osAppDataDir)) - DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".SourceGit"); + DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".sourcegit"); else DataDir = Path.Combine(osAppDataDir, "SourceGit"); From 202aa379f89f1da343d467981969382a825b80c9 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 12:08:33 +0800 Subject: [PATCH 24/70] fix: can not select the entire content of commit message --- src/Models/IssueTrackerRule.cs | 3 +- src/Resources/Styles.axaml | 6 +-- src/Views/CommitMessagePresenter.cs | 81 ++++++++++++++++++++++++----- src/Views/Histories.axaml.cs | 81 ++++++++++++++++++++++++----- 4 files changed, 141 insertions(+), 30 deletions(-) diff --git a/src/Models/IssueTrackerRule.cs b/src/Models/IssueTrackerRule.cs index 127cfa98..618fa166 100644 --- a/src/Models/IssueTrackerRule.cs +++ b/src/Models/IssueTrackerRule.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Text.RegularExpressions; - +using Avalonia.Controls.Documents; using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.Models @@ -10,6 +10,7 @@ namespace SourceGit.Models public int Start { get; set; } = 0; public int Length { get; set; } = 0; public string URL { get; set; } = ""; + public Run Link { get; set; } = null; public bool Intersect(int start, int length) { diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index 9ff41264..d05e2ed9 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -280,11 +280,11 @@ - - diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index 116442d9..1ab93ecd 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -6,6 +6,7 @@ using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.Documents; using Avalonia.Input; +using Avalonia.Utilities; namespace SourceGit.Views { @@ -38,6 +39,8 @@ namespace SourceGit.Views if (change.Property == MessageProperty || change.Property == IssueTrackerRulesProperty) { Inlines.Clear(); + _matches = null; + ClearHoveredIssueLink(); var message = Message; if (string.IsNullOrEmpty(message)) @@ -61,6 +64,7 @@ namespace SourceGit.Views } matches.Sort((l, r) => l.Start - r.Start); + _matches = matches; int pos = 0; foreach (var match in matches) @@ -68,12 +72,9 @@ namespace SourceGit.Views if (match.Start > pos) Inlines.Add(new Run(message.Substring(pos, match.Start - pos))); - var link = new TextBlock(); - link.SetValue(TextProperty, message.Substring(match.Start, match.Length)); - link.SetValue(ToolTip.TipProperty, match.URL); - link.Classes.Add("issue_link"); - link.PointerPressed += OnLinkPointerPressed; - Inlines.Add(link); + match.Link = new Run(message.Substring(match.Start, match.Length)); + match.Link.Classes.Add("issue_link"); + Inlines.Add(match.Link); pos = match.Start + match.Length; } @@ -83,16 +84,70 @@ namespace SourceGit.Views } } - private void OnLinkPointerPressed(object sender, PointerPressedEventArgs e) + protected override void OnPointerMoved(PointerEventArgs e) { - if (sender is TextBlock text) - { - var tooltip = text.GetValue(ToolTip.TipProperty) as string; - if (!string.IsNullOrEmpty(tooltip)) - Native.OS.OpenBrowser(tooltip); + base.OnPointerMoved(e); - e.Handled = true; + if (e.Pointer.Captured == null && _matches != null) + { + var padding = Padding; + var point = e.GetPosition(this) - new Point(padding.Left, padding.Top); + point = new Point( + MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)), + MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Height, 0))); + + var pos = TextLayout.HitTestPoint(point).TextPosition; + foreach (var match in _matches) + { + if (!match.Intersect(pos, 1)) + continue; + + if (match == _lastHover) + return; + + _lastHover = match; + SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); + ToolTip.SetTip(this, match.URL); + ToolTip.SetIsOpen(this, true); + return; + } + + ClearHoveredIssueLink(); } } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + if (_lastHover != null) + { + SetCurrentValue(SelectionEndProperty, SelectionStart); + Native.OS.OpenBrowser(_lastHover.URL); + ClearHoveredIssueLink(); + e.Handled = true; + return; + } + + base.OnPointerPressed(e); + } + + protected override void OnPointerExited(PointerEventArgs e) + { + base.OnPointerExited(e); + ClearHoveredIssueLink(); + } + + private void ClearHoveredIssueLink() + { + if (_lastHover != null) + { + ToolTip.SetTip(this, null); + SetCurrentValue(CursorProperty, Cursor.Parse("IBeam")); + _lastHover.Link.Classes.Remove("issue_link_hovered"); + _lastHover = null; + } + } + + private List _matches = null; + private Models.IssueTrackerMatch _lastHover = null; } } diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index f104a3ea..5ac31695 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -11,6 +11,7 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Threading; +using Avalonia.Utilities; using Avalonia.VisualTree; namespace SourceGit.Views @@ -185,6 +186,8 @@ namespace SourceGit.Views if (change.Property == SubjectProperty || change.Property == IssueTrackerRulesProperty) { Inlines.Clear(); + _matches = null; + ClearHoveredIssueLink(); var subject = Subject; if (string.IsNullOrEmpty(subject)) @@ -208,6 +211,7 @@ namespace SourceGit.Views } matches.Sort((l, r) => l.Start - r.Start); + _matches = matches; int pos = 0; foreach (var match in matches) @@ -215,12 +219,9 @@ namespace SourceGit.Views if (match.Start > pos) Inlines.Add(new Run(subject.Substring(pos, match.Start - pos))); - var link = new TextBlock(); - link.SetValue(TextProperty, subject.Substring(match.Start, match.Length)); - link.SetValue(ToolTip.TipProperty, match.URL); - link.Classes.Add("issue_link"); - link.PointerPressed += OnLinkPointerPressed; - Inlines.Add(link); + match.Link = new Run(subject.Substring(match.Start, match.Length)); + match.Link.Classes.Add("issue_link"); + Inlines.Add(match.Link); pos = match.Start + match.Length; } @@ -230,17 +231,71 @@ namespace SourceGit.Views } } - private void OnLinkPointerPressed(object sender, PointerPressedEventArgs e) + protected override void OnPointerMoved(PointerEventArgs e) { - if (sender is TextBlock text) - { - var tooltip = text.GetValue(ToolTip.TipProperty) as string; - if (!string.IsNullOrEmpty(tooltip)) - Native.OS.OpenBrowser(tooltip); + base.OnPointerMoved(e); - e.Handled = true; + if (_matches != null) + { + var padding = Padding; + var point = e.GetPosition(this) - new Point(padding.Left, padding.Top); + point = new Point( + MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)), + MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Height, 0))); + + var textPosition = TextLayout.HitTestPoint(point).TextPosition; + foreach (var match in _matches) + { + if (!match.Intersect(textPosition, 1)) + continue; + + if (match == _lastHover) + return; + + _lastHover = match; + SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); + ToolTip.SetTip(this, match.URL); + ToolTip.SetIsOpen(this, true); + e.Handled = true; + return; + } + + ClearHoveredIssueLink(); } } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + if (_lastHover != null) + { + Native.OS.OpenBrowser(_lastHover.URL); + ClearHoveredIssueLink(); + e.Handled = true; + return; + } + + base.OnPointerPressed(e); + } + + protected override void OnPointerExited(PointerEventArgs e) + { + base.OnPointerExited(e); + ClearHoveredIssueLink(); + } + + private void ClearHoveredIssueLink() + { + if (_lastHover != null) + { + ToolTip.SetTip(this, null); + SetCurrentValue(CursorProperty, Cursor.Parse("Arrow")); + _lastHover.Link.Classes.Remove("issue_link_hovered"); + _lastHover = null; + } + } + + private List _matches = null; + private Models.IssueTrackerMatch _lastHover = null; } public class CommitTimeTextBlock : TextBlock From 08fc069281486c36cca575fac6478521f425a2d2 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 12:18:26 +0800 Subject: [PATCH 25/70] enhance: disable selection while click issue link --- src/Views/CommitMessagePresenter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index 1ab93ecd..f540b272 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -120,7 +120,7 @@ namespace SourceGit.Views { if (_lastHover != null) { - SetCurrentValue(SelectionEndProperty, SelectionStart); + e.Pointer.Capture(null); Native.OS.OpenBrowser(_lastHover.URL); ClearHoveredIssueLink(); e.Handled = true; From 435c12b340bef19b1a44aaaf6a9361743bc6490b Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 12:25:06 +0800 Subject: [PATCH 26/70] ux: add style for issue link hovered --- src/Views/CommitMessagePresenter.cs | 2 ++ src/Views/Histories.axaml.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index f540b272..22386cbf 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -106,6 +106,8 @@ namespace SourceGit.Views return; _lastHover = match; + _lastHover.Link.Classes.Add("issue_link_hovered"); + SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); ToolTip.SetTip(this, match.URL); ToolTip.SetIsOpen(this, true); diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 5ac31695..33ba0c37 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -253,6 +253,8 @@ namespace SourceGit.Views return; _lastHover = match; + _lastHover.Link.Classes.Add("issue_link_hovered"); + SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); ToolTip.SetTip(this, match.URL); ToolTip.SetIsOpen(this, true); From 70f2bda0973ebd992397898bf277aef73f8fe19c Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 14:47:59 +0800 Subject: [PATCH 27/70] revert:ci: disable unsupported platforms This reverts commit f1d43d94a4368fb26a0cdbdde0bd00986dc04902. --- .github/workflows/ci.yml | 6 +++--- .github/workflows/package.yml | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40dd41b4..87d460c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,9 +26,9 @@ jobs: - name : Linux os: ubuntu-20.04 runtime: linux-x64 - # - name : Linux (arm64) - # os: ubuntu-20.04 - # runtime: linux-arm64 + - name : Linux (arm64) + os: ubuntu-20.04 + runtime: linux-arm64 name: Build ${{ matrix.name }} runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index a3063813..404c909e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -66,8 +66,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # runtime: [linux-x64, linux-arm64] - runtime: [linux-x64] + runtime: [linux-x64, linux-arm64] steps: - name: Checkout sources uses: actions/checkout@v4 From d601ca6b235569ff7d1c2bc0c568ec054ae6f112 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 14:57:05 +0800 Subject: [PATCH 28/70] enhance: force InvalidateVisual --- src/Views/CommitRefsPresenter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Views/CommitRefsPresenter.cs b/src/Views/CommitRefsPresenter.cs index f941d4a5..da842182 100644 --- a/src/Views/CommitRefsPresenter.cs +++ b/src/Views/CommitRefsPresenter.cs @@ -191,9 +191,11 @@ namespace SourceGit.Views requiredWidth += label.Width + 16 /* icon */ + 8 /* label margin */ + 4 /* item right margin */; } + InvalidateVisual(); return new Size(requiredWidth, 16); } + InvalidateVisual(); return new Size(0, 0); } From a145d6e4c379ce0cce81d1db96ef2ffda2987e7b Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 15:58:34 +0800 Subject: [PATCH 29/70] revert: remove issue link support in commit list * improve render performance * the links in commit list are very easy to click by mistake --- src/ViewModels/Histories.cs | 6 -- src/Views/Histories.axaml | 9 +- src/Views/Histories.axaml.cs | 157 ----------------------------------- 3 files changed, 4 insertions(+), 168 deletions(-) diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 5a943e04..8f21bf70 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Platform.Storage; using Avalonia.VisualTree; @@ -55,11 +54,6 @@ namespace SourceGit.ViewModels set => SetProperty(ref _detailContext, value); } - public AvaloniaList IssueTrackerRules - { - get => _repo.Settings.IssueTrackerRules; - } - public Histories(Repository repo) { _repo = repo; diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 91190315..6859d510 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -77,11 +77,10 @@ FontSize="10" VerticalAlignment="Center"/> - + diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 33ba0c37..7a3fef28 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -1,17 +1,13 @@ using System; -using System.Collections.Generic; using System.Text; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; -using Avalonia.Controls.Documents; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Threading; -using Avalonia.Utilities; using Avalonia.VisualTree; namespace SourceGit.Views @@ -157,149 +153,6 @@ namespace SourceGit.Views private Status _status = Status.Normal; } - public class CommitSubjectPresenter : TextBlock - { - public static readonly StyledProperty SubjectProperty = - AvaloniaProperty.Register(nameof(Subject)); - - public string Subject - { - get => GetValue(SubjectProperty); - set => SetValue(SubjectProperty, value); - } - - public static readonly StyledProperty> IssueTrackerRulesProperty = - AvaloniaProperty.Register>(nameof(IssueTrackerRules)); - - public AvaloniaList IssueTrackerRules - { - get => GetValue(IssueTrackerRulesProperty); - set => SetValue(IssueTrackerRulesProperty, value); - } - - protected override Type StyleKeyOverride => typeof(TextBlock); - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - - if (change.Property == SubjectProperty || change.Property == IssueTrackerRulesProperty) - { - Inlines.Clear(); - _matches = null; - ClearHoveredIssueLink(); - - var subject = Subject; - if (string.IsNullOrEmpty(subject)) - return; - - var rules = IssueTrackerRules; - if (rules == null || rules.Count == 0) - { - Inlines.Add(new Run(subject)); - return; - } - - var matches = new List(); - foreach (var rule in rules) - rule.Matches(matches, subject); - - if (matches.Count == 0) - { - Inlines.Add(new Run(subject)); - return; - } - - matches.Sort((l, r) => l.Start - r.Start); - _matches = matches; - - int pos = 0; - foreach (var match in matches) - { - if (match.Start > pos) - Inlines.Add(new Run(subject.Substring(pos, match.Start - pos))); - - match.Link = new Run(subject.Substring(match.Start, match.Length)); - match.Link.Classes.Add("issue_link"); - Inlines.Add(match.Link); - - pos = match.Start + match.Length; - } - - if (pos < subject.Length) - Inlines.Add(new Run(subject.Substring(pos))); - } - } - - protected override void OnPointerMoved(PointerEventArgs e) - { - base.OnPointerMoved(e); - - if (_matches != null) - { - var padding = Padding; - var point = e.GetPosition(this) - new Point(padding.Left, padding.Top); - point = new Point( - MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)), - MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Height, 0))); - - var textPosition = TextLayout.HitTestPoint(point).TextPosition; - foreach (var match in _matches) - { - if (!match.Intersect(textPosition, 1)) - continue; - - if (match == _lastHover) - return; - - _lastHover = match; - _lastHover.Link.Classes.Add("issue_link_hovered"); - - SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); - ToolTip.SetTip(this, match.URL); - ToolTip.SetIsOpen(this, true); - e.Handled = true; - return; - } - - ClearHoveredIssueLink(); - } - } - - protected override void OnPointerPressed(PointerPressedEventArgs e) - { - if (_lastHover != null) - { - Native.OS.OpenBrowser(_lastHover.URL); - ClearHoveredIssueLink(); - e.Handled = true; - return; - } - - base.OnPointerPressed(e); - } - - protected override void OnPointerExited(PointerEventArgs e) - { - base.OnPointerExited(e); - ClearHoveredIssueLink(); - } - - private void ClearHoveredIssueLink() - { - if (_lastHover != null) - { - ToolTip.SetTip(this, null); - SetCurrentValue(CursorProperty, Cursor.Parse("Arrow")); - _lastHover.Link.Classes.Remove("issue_link_hovered"); - _lastHover = null; - } - } - - private List _matches = null; - private Models.IssueTrackerMatch _lastHover = null; - } - public class CommitTimeTextBlock : TextBlock { public static readonly StyledProperty ShowAsDateTimeProperty = @@ -607,16 +460,6 @@ namespace SourceGit.Views set => SetValue(NavigationIdProperty, value); } - public AvaloniaList IssueTrackerRules - { - get - { - if (DataContext is ViewModels.Histories histories) - return histories.IssueTrackerRules; - return null; - } - } - static Histories() { NavigationIdProperty.Changed.AddClassHandler((h, _) => From 34a598d4213ff54b9a2f382548d6581d0b395ae6 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 17:15:17 +0800 Subject: [PATCH 30/70] feature: add commit web links (#357) --- src/Models/CommitLink.cs | 8 ++++ src/Resources/Icons.axaml | 1 + src/ViewModels/CommitDetail.cs | 52 +++++++++++++------------- src/ViewModels/FileHistories.cs | 12 +++--- src/ViewModels/Histories.cs | 4 +- src/ViewModels/InteractiveRebase.cs | 2 +- src/ViewModels/Repository.cs | 19 ++++++++++ src/ViewModels/WorkingCopy.cs | 2 +- src/Views/CommitBaseInfo.axaml | 12 +++++- src/Views/CommitBaseInfo.axaml.cs | 57 +++++++++++++++++++++++------ src/Views/CommitDetail.axaml | 1 + src/Views/DiffView.axaml | 4 +- src/Views/RevisionFiles.axaml | 2 +- 13 files changed, 124 insertions(+), 52 deletions(-) create mode 100644 src/Models/CommitLink.cs diff --git a/src/Models/CommitLink.cs b/src/Models/CommitLink.cs new file mode 100644 index 00000000..6a421797 --- /dev/null +++ b/src/Models/CommitLink.cs @@ -0,0 +1,8 @@ +namespace SourceGit.Models +{ + public class CommitLink + { + public string Name { get; set; } = null; + public string URLTemplate { get; set; } = null; + } +} diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index a159d764..5f148b50 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -59,6 +59,7 @@ M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l132 0 0-128 64 0 0 128 132 0 0 64-132 0 0 128-64 0 0-128-132 0Z M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z + M 968 418 l -95 94 c -59 59 -146 71 -218 37 L 874 331 a 64 64 0 0 0 0 -90 L 783 150 a 64 64 0 0 0 -90 0 L 475 368 c -34 -71 -22 -159 37 -218 l 94 -94 c 75 -75 196 -75 271 0 l 90 90 c 75 75 75 196 0 271 z M 332 693 a 64 64 0 0 1 0 -90 l 271 -271 c 25 -25 65 -25 90 0 s 25 65 0 90 L 422 693 a 64 64 0 0 1 -90 0 z M 151 783 l 90 90 a 64 64 0 0 0 90 0 l 218 -218 c 34 71 22 159 -37 218 l -86 94 a 192 192 0 0 1 -271 0 l -98 -98 a 192 192 0 0 1 0 -271 l 94 -86 c 59 -59 146 -71 218 -37 L 151 693 a 64 64 0 0 0 0 90 z M0 33h1024v160H0zM0 432h1024v160H0zM0 831h1024v160H0z M512 0C233 0 7 223 0 500C6 258 190 64 416 64c230 0 416 200 416 448c0 53 43 96 96 96s96-43 96-96c0-283-229-512-512-512zm0 1023c279 0 505-223 512-500c-6 242-190 436-416 436c-230 0-416-200-416-448c0-53-43-96-96-96s-96 43-96 96c0 283 229 512 512 512z M976 0h-928A48 48 0 000 48v652a48 48 0 0048 48h416V928H200a48 48 0 000 96h624a48 48 0 000-96H560v-180h416a48 48 0 0048-48V48A48 48 0 00976 0zM928 652H96V96h832v556z diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index ae0e2cb9..04fe4d06 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -66,7 +66,7 @@ namespace SourceGit.ViewModels if (value == null || value.Count != 1) DiffContext = null; else - DiffContext = new DiffContext(_repo, new Models.DiffOption(_commit, value[0]), _diffContext); + DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_commit, value[0]), _diffContext); } } } @@ -89,15 +89,19 @@ namespace SourceGit.ViewModels set => SetProperty(ref _viewRevisionFileContent, value); } - public AvaloniaList IssueTrackerRules + public AvaloniaList WebLinks { - get => _issueTrackerRules; + get => _repo.TryGetCommitLinks(); } - public CommitDetail(string repo, AvaloniaList issueTrackerRules) + public AvaloniaList IssueTrackerRules + { + get => _repo.Settings?.IssueTrackerRules; + } + + public CommitDetail(Repository repo) { _repo = repo; - _issueTrackerRules = issueTrackerRules; } public void Cleanup() @@ -118,8 +122,7 @@ namespace SourceGit.ViewModels public void NavigateTo(string commitSHA) { - var repo = App.FindOpenedRepository(_repo); - repo?.NavigateToCommit(commitSHA); + _repo?.NavigateToCommit(commitSHA); } public void ClearSearchChangeFilter() @@ -129,7 +132,7 @@ namespace SourceGit.ViewModels public List GetRevisionFilesUnderFolder(string parentFolder) { - return new Commands.QueryRevisionObjects(_repo, _commit.SHA, parentFolder).Result(); + return new Commands.QueryRevisionObjects(_repo.FullPath, _commit.SHA, parentFolder).Result(); } public void ViewRevisionFile(Models.Object file) @@ -145,13 +148,13 @@ namespace SourceGit.ViewModels case Models.ObjectType.Blob: Task.Run(() => { - var isBinary = new Commands.IsBinary(_repo, _commit.SHA, file.Path).Result(); + var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result(); if (isBinary) { var ext = Path.GetExtension(file.Path); if (IMG_EXTS.Contains(ext)) { - var stream = Commands.QueryFileContent.Run(_repo, _commit.SHA, file.Path); + var stream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path); var bitmap = stream.Length > 0 ? new Bitmap(stream) : null; Dispatcher.UIThread.Invoke(() => { @@ -160,7 +163,7 @@ namespace SourceGit.ViewModels } else { - var size = new Commands.QueryFileSize(_repo, file.Path, _commit.SHA).Result(); + var size = new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).Result(); Dispatcher.UIThread.Invoke(() => { ViewRevisionFileContent = new Models.RevisionBinaryFile() { Size = size }; @@ -170,7 +173,7 @@ namespace SourceGit.ViewModels return; } - var contentStream = Commands.QueryFileContent.Run(_repo, _commit.SHA, file.Path); + var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path); var content = new StreamReader(contentStream).ReadToEnd(); var matchLFS = REG_LFS_FORMAT().Match(content); if (matchLFS.Success) @@ -191,7 +194,7 @@ namespace SourceGit.ViewModels case Models.ObjectType.Commit: Task.Run(() => { - var submoduleRoot = Path.Combine(_repo, file.Path); + var submoduleRoot = Path.Combine(_repo.FullPath, file.Path); var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result(); if (commit != null) { @@ -237,7 +240,7 @@ namespace SourceGit.ViewModels var toolPath = Preference.Instance.ExternalMergeToolPath; var opt = new Models.DiffOption(_commit, change); - Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, opt)); + Task.Run(() => Commands.MergeTool.OpenForDiff(_repo.FullPath, toolType, toolPath, opt)); ev.Handled = true; }; menu.Items.Add(diffWithMerger); @@ -249,7 +252,7 @@ namespace SourceGit.ViewModels history.Icon = App.CreateMenuIcon("Icons.Histories"); history.Click += (_, ev) => { - var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, change.Path, _issueTrackerRules) }; + var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, change.Path) }; window.Show(); ev.Handled = true; }; @@ -259,12 +262,12 @@ namespace SourceGit.ViewModels blame.Icon = App.CreateMenuIcon("Icons.Blame"); blame.Click += (_, ev) => { - var window = new Views.Blame() { DataContext = new Blame(_repo, change.Path, _commit.SHA) }; + var window = new Views.Blame() { DataContext = new Blame(_repo.FullPath, change.Path, _commit.SHA) }; window.Show(); ev.Handled = true; }; - var full = Path.GetFullPath(Path.Combine(_repo, change.Path)); + var full = Path.GetFullPath(Path.Combine(_repo.FullPath, change.Path)); var explore = new MenuItem(); explore.Header = App.Text("RevealFile"); explore.Icon = App.CreateMenuIcon("Icons.Explore"); @@ -312,7 +315,7 @@ namespace SourceGit.ViewModels history.Icon = App.CreateMenuIcon("Icons.Histories"); history.Click += (_, ev) => { - var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, file.Path, _issueTrackerRules) }; + var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, file.Path) }; window.Show(); ev.Handled = true; }; @@ -323,12 +326,12 @@ namespace SourceGit.ViewModels blame.IsEnabled = file.Type == Models.ObjectType.Blob; blame.Click += (_, ev) => { - var window = new Views.Blame() { DataContext = new Blame(_repo, file.Path, _commit.SHA) }; + var window = new Views.Blame() { DataContext = new Blame(_repo.FullPath, file.Path, _commit.SHA) }; window.Show(); ev.Handled = true; }; - var full = Path.GetFullPath(Path.Combine(_repo, file.Path)); + var full = Path.GetFullPath(Path.Combine(_repo.FullPath, file.Path)); var explore = new MenuItem(); explore.Header = App.Text("RevealFile"); explore.Icon = App.CreateMenuIcon("Icons.Explore"); @@ -353,7 +356,7 @@ namespace SourceGit.ViewModels if (selected.Count == 1) { var saveTo = Path.Combine(selected[0].Path.LocalPath, Path.GetFileName(file.Path)); - Commands.SaveRevisionFile.Run(_repo, _commit.SHA, file.Path, saveTo); + Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo); } ev.Handled = true; @@ -406,9 +409,9 @@ namespace SourceGit.ViewModels Task.Run(() => { - var fullMessage = new Commands.QueryCommitFullMessage(_repo, _commit.SHA).Result(); + var fullMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0]; - var cmdChanges = new Commands.CompareRevisions(_repo, parent, _commit.SHA) { Cancel = _cancelToken }; + var cmdChanges = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { Cancel = _cancelToken }; var changes = cmdChanges.Result(); var visible = changes; if (!string.IsNullOrWhiteSpace(_searchChangeFilter)) @@ -463,8 +466,7 @@ namespace SourceGit.ViewModels ".ico", ".bmp", ".jpg", ".png", ".jpeg" }; - private string _repo; - private AvaloniaList _issueTrackerRules = null; + private Repository _repo = null; private int _activePageIndex = 0; private Models.Commit _commit = null; private string _fullMessage = string.Empty; diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 79696a7e..e1284b2f 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Avalonia.Collections; using Avalonia.Threading; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -35,7 +33,7 @@ namespace SourceGit.ViewModels } else { - DiffContext = new DiffContext(_repo, new Models.DiffOption(value, _file), _diffContext); + DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(value, _file), _diffContext); DetailContext.Commit = value; } } @@ -54,15 +52,15 @@ namespace SourceGit.ViewModels set => SetProperty(ref _detailContext, value); } - public FileHistories(string repo, string file, AvaloniaList issueTrackerRules) + public FileHistories(Repository repo, string file) { _repo = repo; _file = file; - _detailContext = new CommitDetail(repo, issueTrackerRules); + _detailContext = new CommitDetail(repo); Task.Run(() => { - var commits = new Commands.QueryCommits(_repo, $"-n 10000 -- \"{file}\"", false).Result(); + var commits = new Commands.QueryCommits(_repo.FullPath, $"-n 10000 -- \"{file}\"", false).Result(); Dispatcher.UIThread.Invoke(() => { IsLoading = false; @@ -73,7 +71,7 @@ namespace SourceGit.ViewModels }); } - private readonly string _repo = null; + private readonly Repository _repo = null; private readonly string _file = null; private bool _isLoading = true; private List _commits = null; diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 8f21bf70..4a0a05a0 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -93,7 +93,7 @@ namespace SourceGit.ViewModels } else { - var commitDetail = new CommitDetail(_repo.FullPath, _repo.Settings.IssueTrackerRules); + var commitDetail = new CommitDetail(_repo); commitDetail.Commit = commit; DetailContext = commitDetail; } @@ -121,7 +121,7 @@ namespace SourceGit.ViewModels } else { - var commitDetail = new CommitDetail(_repo.FullPath, _repo.Settings.IssueTrackerRules); + var commitDetail = new CommitDetail(_repo); commitDetail.Commit = commit; DetailContext = commitDetail; } diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index 32417e01..0c8838e0 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -114,7 +114,7 @@ namespace SourceGit.ViewModels Current = current; On = on; IsLoading = true; - DetailContext = new CommitDetail(repoPath, repo.Settings.IssueTrackerRules); + DetailContext = new CommitDetail(repo); Task.Run(() => { diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index e248967a..6cbe9576 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -491,6 +491,25 @@ namespace SourceGit.ViewModels PopupHost.ShowAndStartPopup(new Cleanup(this)); } + public AvaloniaList TryGetCommitLinks() + { + var rs = new AvaloniaList(); + foreach (var remote in _remotes) + { + if (remote.TryGetVisitURL(out var url)) + { + if (url.StartsWith("https://github.com/", StringComparison.Ordinal)) + rs.Add(new Models.CommitLink() { Name = "Github", URLTemplate = $"{url}/commit/SOURCEGIT_COMMIT_HASH_CODE" }); + else if (url.StartsWith("https://gitlab.com/", StringComparison.Ordinal)) + rs.Add(new Models.CommitLink() { Name = "GitLab", URLTemplate = $"{url}/-/commit/SOURCEGIT_COMMIT_HASH_CODE" }); + else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal)) + rs.Add(new Models.CommitLink() { Name = "Gitee", URLTemplate = $"{url}/commit/SOURCEGIT_COMMIT_HASH_CODE" }); + } + } + + return rs; + } + public void ClearHistoriesFilter() { _settings.Filters.Clear(); diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index c72900ec..9658eb48 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -567,7 +567,7 @@ namespace SourceGit.ViewModels history.Icon = App.CreateMenuIcon("Icons.Histories"); history.Click += (_, e) => { - var window = new Views.FileHistories() { DataContext = new FileHistories(_repo.FullPath, change.Path, _repo.Settings.IssueTrackerRules) }; + var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, change.Path) }; window.Show(); e.Handled = true; }; diff --git a/src/Views/CommitBaseInfo.axaml b/src/Views/CommitBaseInfo.axaml index d2c57810..53e194ff 100644 --- a/src/Views/CommitBaseInfo.axaml +++ b/src/Views/CommitBaseInfo.axaml @@ -54,7 +54,17 @@ - + + + + + + diff --git a/src/Views/CommitBaseInfo.axaml.cs b/src/Views/CommitBaseInfo.axaml.cs index 86451dfe..8c5e3d98 100644 --- a/src/Views/CommitBaseInfo.axaml.cs +++ b/src/Views/CommitBaseInfo.axaml.cs @@ -2,20 +2,12 @@ using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Input; +using Avalonia.Interactivity; namespace SourceGit.Views { public partial class CommitBaseInfo : UserControl { - public static readonly StyledProperty CanNavigateProperty = - AvaloniaProperty.Register(nameof(CanNavigate), true); - - public bool CanNavigate - { - get => GetValue(CanNavigateProperty); - set => SetValue(CanNavigateProperty, value); - } - public static readonly StyledProperty MessageProperty = AvaloniaProperty.Register(nameof(Message), string.Empty); @@ -25,6 +17,15 @@ namespace SourceGit.Views set => SetValue(MessageProperty, value); } + public static readonly StyledProperty> WebLinksProperty = + AvaloniaProperty.Register>(nameof(WebLinks)); + + public AvaloniaList WebLinks + { + get => GetValue(WebLinksProperty); + set => SetValue(WebLinksProperty, value); + } + public static readonly StyledProperty> IssueTrackerRulesProperty = AvaloniaProperty.Register>(nameof(IssueTrackerRules)); @@ -39,11 +40,43 @@ namespace SourceGit.Views InitializeComponent(); } + private void OnOpenWebLink(object sender, RoutedEventArgs e) + { + if (DataContext is ViewModels.CommitDetail detail) + { + var links = WebLinks; + if (links.Count > 1) + { + var menu = new ContextMenu(); + + foreach (var link in links) + { + var url = link.URLTemplate.Replace("SOURCEGIT_COMMIT_HASH_CODE", detail.Commit.SHA); + var item = new MenuItem() { Header = link.Name }; + item.Click += (_, ev) => + { + Native.OS.OpenBrowser(url); + ev.Handled = true; + }; + + menu.Items.Add(item); + } + + (sender as Control)?.OpenContextMenu(menu); + } + else if (links.Count == 1) + { + var url = links[0].URLTemplate.Replace("SOURCEGIT_COMMIT_HASH_CODE", detail.Commit.SHA); + Native.OS.OpenBrowser(url); + } + } + + e.Handled = true; + } + private void OnParentSHAPressed(object sender, PointerPressedEventArgs e) { - if (sender is Control { DataContext: string sha } && - DataContext is ViewModels.CommitDetail detail && - CanNavigate) + if (DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha }) { detail.NavigateTo(sha); } diff --git a/src/Views/CommitDetail.axaml b/src/Views/CommitDetail.axaml index af733f49..432fa737 100644 --- a/src/Views/CommitDetail.axaml +++ b/src/Views/CommitDetail.axaml @@ -21,6 +21,7 @@ diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index b573a32d..9e927205 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -176,7 +176,7 @@ - + @@ -190,7 +190,7 @@ - + diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml index 5066195d..aef71e19 100644 --- a/src/Views/RevisionFiles.axaml +++ b/src/Views/RevisionFiles.axaml @@ -73,7 +73,7 @@ - + From f3406e93fc906d937985e41d30f3a30991515bef Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 17:38:58 +0800 Subject: [PATCH 31/70] fix: try to fix issue #338 * upgrade Avalonia to `11.1.3` * use reactive property instead of simple getter --- src/SourceGit.csproj | 10 +++++----- src/ViewModels/Histories.cs | 8 ++++---- src/ViewModels/Repository.cs | 29 +++++++++++++++++++---------- src/ViewModels/WorkingCopy.cs | 2 -- src/Views/Repository.axaml | 4 ++-- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index ee376f3a..468d55e9 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -37,11 +37,11 @@ - - - - - + + + + + diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 4a0a05a0..85be27af 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -243,7 +243,7 @@ namespace SourceGit.ViewModels reword.Icon = App.CreateMenuIcon("Icons.Edit"); reword.Click += (_, e) => { - if (_repo.WorkingCopyChangesCount > 0) + if (_repo.LocalChangesCount > 0) { App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); return; @@ -261,7 +261,7 @@ namespace SourceGit.ViewModels squash.IsEnabled = commit.Parents.Count == 1; squash.Click += (_, e) => { - if (_repo.WorkingCopyChangesCount > 0) + if (_repo.LocalChangesCount > 0) { App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); return; @@ -322,7 +322,7 @@ namespace SourceGit.ViewModels interactiveRebase.IsVisible = current.Head != commit.SHA; interactiveRebase.Click += (_, e) => { - if (_repo.WorkingCopyChangesCount > 0) + if (_repo.LocalChangesCount > 0) { App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); return; @@ -379,7 +379,7 @@ namespace SourceGit.ViewModels }; menu.Items.Add(compareWithHead); - if (_repo.WorkingCopyChangesCount > 0) + if (_repo.LocalChangesCount > 0) { var compareWithWorktree = new MenuItem(); compareWithWorktree.Header = App.Text("CommitCM.CompareWithWorktree"); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 6cbe9576..0ba1c51d 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -142,14 +142,16 @@ namespace SourceGit.ViewModels private set => SetProperty(ref _submodules, value); } - public int WorkingCopyChangesCount + public int LocalChangesCount { - get => _workingCopy == null ? 0 : _workingCopy.Count; + get => _localChangesCount; + private set => SetProperty(ref _localChangesCount, value); } public int StashesCount { - get => _stashesPage == null ? 0 : _stashesPage.Stashes.Count; + get => _stashesCount; + private set => SetProperty(ref _stashesCount, value); } public bool IncludeUntracked @@ -350,6 +352,9 @@ namespace SourceGit.ViewModels _stashesPage = null; _inProgressContext = null; + _localChangesCount = 0; + _stashesCount = 0; + _remotes.Clear(); _branches.Clear(); _localBranchTrees.Clear(); @@ -834,7 +839,7 @@ namespace SourceGit.ViewModels { InProgressContext = inProgress; HasUnsolvedConflicts = hasUnsolvedConflict; - OnPropertyChanged(nameof(WorkingCopyChangesCount)); + LocalChangesCount = changes.Count; }); } @@ -845,7 +850,8 @@ namespace SourceGit.ViewModels { if (_stashesPage != null) _stashesPage.Stashes = stashes; - OnPropertyChanged(nameof(StashesCount)); + + StashesCount = stashes.Count; }); } @@ -878,7 +884,7 @@ namespace SourceGit.ViewModels if (branch.IsLocal) { - if (WorkingCopyChangesCount > 0) + if (_localChangesCount > 0) PopupHost.ShowPopup(new Checkout(this, branch.Name)); else PopupHost.ShowAndStartPopup(new Checkout(this, branch.Name)); @@ -1215,7 +1221,7 @@ namespace SourceGit.ViewModels var discard = new MenuItem(); discard.Header = App.Text("BranchCM.DiscardAll"); discard.Icon = App.CreateMenuIcon("Icons.Undo"); - discard.IsEnabled = _workingCopy.Count > 0; + discard.IsEnabled = _localChangesCount > 0; discard.Click += (_, e) => { if (PopupHost.CanCreatePopup()) @@ -1319,7 +1325,7 @@ namespace SourceGit.ViewModels menu.Items.Add(merge); menu.Items.Add(rebase); - if (WorkingCopyChangesCount > 0) + if (_localChangesCount > 0) { var compareWithWorktree = new MenuItem(); compareWithWorktree.Header = App.Text("BranchCM.CompareWithWorktree"); @@ -1342,7 +1348,7 @@ namespace SourceGit.ViewModels var compareWithBranch = CreateMenuItemToCompareBranches(branch); if (compareWithBranch != null) { - if (WorkingCopyChangesCount == 0) + if (_localChangesCount == 0) menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(compareWithBranch); @@ -1619,7 +1625,7 @@ namespace SourceGit.ViewModels } var hasCompare = false; - if (WorkingCopyChangesCount > 0) + if (_localChangesCount > 0) { var compareWithWorktree = new MenuItem(); compareWithWorktree.Header = App.Text("BranchCM.CompareWithWorktree"); @@ -1981,6 +1987,9 @@ namespace SourceGit.ViewModels private int _selectedViewIndex = 0; private object _selectedView = null; + private int _localChangesCount = 0; + private int _stashesCount = 0; + private bool _isSearching = false; private bool _isSearchLoadingVisible = false; private bool _isSearchCommitSuggestionOpen = false; diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 9658eb48..36ab33ca 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -177,8 +177,6 @@ namespace SourceGit.ViewModels } } - public int Count => _count; - public object DetailContext { get => _detailContext; diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 9c111eb7..65747a57 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -97,8 +97,8 @@ CornerRadius="9" VerticalAlignment="Center" Background="{DynamicResource Brush.Badge}" - IsVisible="{Binding WorkingCopyChangesCount, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> - + IsVisible="{Binding LocalChangesCount, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> + From 59a7c74fd1ee7c56907633bccabcfd984e4d7ab2 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 18:24:28 +0800 Subject: [PATCH 32/70] fix: try to fix issue #338 * use custom control to draw badges --- src/ViewModels/BranchTreeNode.cs | 5 -- src/Views/BranchTree.axaml | 21 +++---- src/Views/BranchTree.axaml.cs | 94 +++++++++++++++++++++++++++++++ src/Views/Repository.axaml | 34 ++++++----- src/Views/Repository.axaml.cs | 97 ++++++++++++++++++++++++++++++++ 5 files changed, 214 insertions(+), 37 deletions(-) diff --git a/src/ViewModels/BranchTreeNode.cs b/src/ViewModels/BranchTreeNode.cs index 33988725..71f96a90 100644 --- a/src/ViewModels/BranchTreeNode.cs +++ b/src/ViewModels/BranchTreeNode.cs @@ -36,11 +36,6 @@ namespace SourceGit.ViewModels get => Backend is Models.Branch; } - public string TrackStatus - { - get => Backend is Models.Branch { IsLocal: true } branch ? branch.TrackStatus.ToString() : string.Empty; - } - public FontWeight NameFontWeight { get => Backend is Models.Branch { IsCurrent: true } ? FontWeight.Bold : FontWeight.Regular; diff --git a/src/Views/BranchTree.axaml b/src/Views/BranchTree.axaml index 366814fe..59b0b609 100644 --- a/src/Views/BranchTree.axaml +++ b/src/Views/BranchTree.axaml @@ -83,20 +83,13 @@ FontWeight="{Binding NameFontWeight}"/> - - - + FontFamilyProperty = + TextBlock.FontFamilyProperty.AddOwner(); + + public FontFamily FontFamily + { + get => GetValue(FontFamilyProperty); + set => SetValue(FontFamilyProperty, value); + } + + public static readonly StyledProperty FontSizeProperty = + TextBlock.FontSizeProperty.AddOwner(); + + public double FontSize + { + get => GetValue(FontSizeProperty); + set => SetValue(FontSizeProperty, value); + } + + public static readonly StyledProperty ForegroundProperty = + AvaloniaProperty.Register(nameof(Foreground), Brushes.White); + + public IBrush Foreground + { + get => GetValue(ForegroundProperty); + set => SetValue(ForegroundProperty, value); + } + + public static readonly StyledProperty BackgroundProperty = + AvaloniaProperty.Register(nameof(Background), Brushes.White); + + public IBrush Background + { + get => GetValue(BackgroundProperty); + set => SetValue(BackgroundProperty, value); + } + + static BranchTreeNodeTrackStatusPresenter() + { + AffectsMeasure( + FontSizeProperty, + FontFamilyProperty, + ForegroundProperty); + + AffectsRender( + ForegroundProperty, + BackgroundProperty); + } + + public override void Render(DrawingContext context) + { + base.Render(context); + + if (_label != null) + { + context.DrawRectangle(Background, null, new RoundedRect(new Rect(0, 0, _label.Width + 18, 18), new CornerRadius(9))); + context.DrawText(_label, new Point(9, 9 - _label.Height * 0.5)); + } + } + + protected override void OnDataContextChanged(EventArgs e) + { + base.OnDataContextChanged(e); + InvalidateMeasure(); + InvalidateVisual(); + } + + protected override Size MeasureOverride(Size availableSize) + { + _label = null; + + if (DataContext is ViewModels.BranchTreeNode { Backend: Models.Branch branch }) + { + var status = branch.TrackStatus.ToString(); + if (!string.IsNullOrEmpty(status)) + { + _label = new FormattedText( + status, + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + new Typeface(FontFamily), + FontSize, + Foreground); + } + } + + return _label != null ? new Size(_label.Width + 18, 18) : new Size(0, 0); + } + + private FormattedText _label = null; + } + public partial class BranchTree : UserControl { public static readonly StyledProperty> NodesProperty = diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 65747a57..2bf003a7 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -91,15 +91,14 @@ - - - + @@ -107,15 +106,14 @@ - - - + diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index f6230f02..a83d24bd 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -1,12 +1,109 @@ using System; +using System.Globalization; using Avalonia; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.Media; namespace SourceGit.Views { + public class CounterPresenter : Control + { + public static readonly StyledProperty CountProperty = + AvaloniaProperty.Register(nameof(Count), 0); + + public int Count + { + get => GetValue(CountProperty); + set => SetValue(CountProperty, value); + } + + public static readonly StyledProperty FontFamilyProperty = + TextBlock.FontFamilyProperty.AddOwner(); + + public FontFamily FontFamily + { + get => GetValue(FontFamilyProperty); + set => SetValue(FontFamilyProperty, value); + } + + public static readonly StyledProperty FontSizeProperty = + TextBlock.FontSizeProperty.AddOwner(); + + public double FontSize + { + get => GetValue(FontSizeProperty); + set => SetValue(FontSizeProperty, value); + } + + public static readonly StyledProperty ForegroundProperty = + AvaloniaProperty.Register(nameof(Foreground), Brushes.White); + + public IBrush Foreground + { + get => GetValue(ForegroundProperty); + set => SetValue(ForegroundProperty, value); + } + + public static readonly StyledProperty BackgroundProperty = + AvaloniaProperty.Register(nameof(Background), Brushes.White); + + public IBrush Background + { + get => GetValue(BackgroundProperty); + set => SetValue(BackgroundProperty, value); + } + + static CounterPresenter() + { + AffectsMeasure( + FontSizeProperty, + FontFamilyProperty, + ForegroundProperty, + CountProperty); + + AffectsRender( + ForegroundProperty, + BackgroundProperty, + CountProperty); + } + + public override void Render(DrawingContext context) + { + base.Render(context); + + if (_label != null) + { + context.DrawRectangle(Background, null, new RoundedRect(new Rect(0, 0, _label.Width + 18, 18), new CornerRadius(9))); + context.DrawText(_label, new Point(9, 9 - _label.Height * 0.5)); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + if (Count > 0) + { + _label = new FormattedText( + Count.ToString(), + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + new Typeface(FontFamily), + FontSize, + Foreground); + } + else + { + _label = null; + } + + return _label != null ? new Size(_label.Width + 18, 18) : new Size(0, 0); + } + + private FormattedText _label = null; + } + public partial class Repository : UserControl { public Repository() From abdf9d7e75b88eb5a3df48fe759cbb77a8646212 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 19:30:10 +0800 Subject: [PATCH 33/70] refactor: rewrite commit web links --- src/ViewModels/CommitDetail.cs | 18 ++++++++++++++++-- src/ViewModels/Repository.cs | 19 ------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 04fe4d06..2cf549f2 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -91,8 +91,9 @@ namespace SourceGit.ViewModels public AvaloniaList WebLinks { - get => _repo.TryGetCommitLinks(); - } + get; + private set; + } = new AvaloniaList(); public AvaloniaList IssueTrackerRules { @@ -102,6 +103,19 @@ namespace SourceGit.ViewModels public CommitDetail(Repository repo) { _repo = repo; + + foreach (var remote in repo.Remotes) + { + if (remote.TryGetVisitURL(out var url)) + { + if (url.StartsWith("https://github.com/", StringComparison.Ordinal)) + WebLinks.Add(new Models.CommitLink() { Name = "Github", URLTemplate = $"{url}/commit/SOURCEGIT_COMMIT_HASH_CODE" }); + else if (url.StartsWith("https://gitlab.com/", StringComparison.Ordinal)) + WebLinks.Add(new Models.CommitLink() { Name = "GitLab", URLTemplate = $"{url}/-/commit/SOURCEGIT_COMMIT_HASH_CODE" }); + else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal)) + WebLinks.Add(new Models.CommitLink() { Name = "Gitee", URLTemplate = $"{url}/commit/SOURCEGIT_COMMIT_HASH_CODE" }); + } + } } public void Cleanup() diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 0ba1c51d..e304be0b 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -496,25 +496,6 @@ namespace SourceGit.ViewModels PopupHost.ShowAndStartPopup(new Cleanup(this)); } - public AvaloniaList TryGetCommitLinks() - { - var rs = new AvaloniaList(); - foreach (var remote in _remotes) - { - if (remote.TryGetVisitURL(out var url)) - { - if (url.StartsWith("https://github.com/", StringComparison.Ordinal)) - rs.Add(new Models.CommitLink() { Name = "Github", URLTemplate = $"{url}/commit/SOURCEGIT_COMMIT_HASH_CODE" }); - else if (url.StartsWith("https://gitlab.com/", StringComparison.Ordinal)) - rs.Add(new Models.CommitLink() { Name = "GitLab", URLTemplate = $"{url}/-/commit/SOURCEGIT_COMMIT_HASH_CODE" }); - else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal)) - rs.Add(new Models.CommitLink() { Name = "Gitee", URLTemplate = $"{url}/commit/SOURCEGIT_COMMIT_HASH_CODE" }); - } - } - - return rs; - } - public void ClearHistoriesFilter() { _settings.Filters.Clear(); From ec14d9d5333e34df59bf18d3c3b2a7ba2dfc8832 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 13 Aug 2024 20:40:05 +0800 Subject: [PATCH 34/70] refactor: remove binding errors --- src/ViewModels/Histories.cs | 5 +++++ src/Views/Repository.axaml | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 85be27af..86a211fa 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -10,6 +10,11 @@ namespace SourceGit.ViewModels { public class Histories : ObservableObject { + public Repository Repo + { + get => _repo; + } + public bool IsLoading { get => _isLoading; diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 2bf003a7..38c64c76 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -668,8 +668,7 @@ - + From 55da40f8dc04e7d682cb0cd96e17d5fed4646b4e Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 14 Aug 2024 11:06:37 +0800 Subject: [PATCH 35/70] fix: sometimes textblock with issue link will render nothing --- src/Resources/Styles.axaml | 3 - src/Views/CommitMessagePresenter.cs | 5 +- src/Views/Histories.axaml | 9 +- src/Views/Histories.axaml.cs | 153 ++++++++++++++++++++++++++++ src/Views/Repository.axaml | 4 +- 5 files changed, 163 insertions(+), 11 deletions(-) diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index d05e2ed9..843eefc7 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -284,9 +284,6 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/WorkingCopy.axaml b/src/Views/WorkingCopy.axaml index 4727ce20..7acba84a 100644 --- a/src/Views/WorkingCopy.axaml +++ b/src/Views/WorkingCopy.axaml @@ -176,10 +176,12 @@ Date: Thu, 15 Aug 2024 19:52:05 +0800 Subject: [PATCH 51/70] ux: style of commit message picker button --- src/Resources/Icons.axaml | 1 - src/Resources/Styles.axaml | 15 +++++++++++++++ src/Views/WorkingCopy.axaml | 10 +++++----- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 46f229b9..216a350c 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -14,7 +14,6 @@ M1280 704c0 141-115 256-256 256H288C129 960 0 831 0 672c0-126 80-232 192-272A327 327 0 01192 384c0-177 143-320 320-320 119 0 222 64 277 160C820 204 857 192 896 192c106 0 192 86 192 192 0 24-5 48-13 69C1192 477 1280 580 1280 704zm-493-128H656V352c0-18-14-32-32-32h-96c-18 0-32 14-32 32v224h-131c-29 0-43 34-23 55l211 211c12 12 33 12 45 0l211-211c20-20 6-55-23-55z M853 102H171C133 102 102 133 102 171v683C102 891 133 922 171 922h683C891 922 922 891 922 853V171C922 133 891 102 853 102zM390 600l-48 48L205 512l137-137 48 48L301 512l88 88zM465 819l-66-18L559 205l66 18L465 819zm218-171L634 600 723 512l-88-88 48-48L819 512 683 649z M796 471A292 292 0 00512 256a293 293 0 00-284 215H0v144h228A293 293 0 00512 832a291 291 0 00284-217H1024V471h-228M512 688A146 146 0 01366 544A145 145 0 01512 400c80 0 146 63 146 144A146 146 0 01512 688 - M796 561a5 5 0 014 7l-39 90a5 5 0 004 7h100a5 5 0 014 8l-178 247a5 5 0 01-9-4l32-148a5 5 0 00-5-6h-89a5 5 0 01-4-7l86-191a5 5 0 014-3h88zM731 122a73 73 0 0173 73v318a54 54 0 00-8-1h-88a54 54 0 00-49 32l-86 191a54 54 0 00-5 22l0 4a54 54 0 0053 50h35L636 902H244a73 73 0 01-73-73V195a73 73 0 0173-73h488zm-219 366h-195v73h195v-73zm146-146H317v73h341v-73z M645 448l64 64 220-221L704 64l-64 64 115 115H128v90h628zM375 576l-64-64-220 224L314 960l64-64-116-115H896v-90H262z M608 0q48 0 88 23t63 63 23 87v70h55q35 0 67 14t57 38 38 57 14 67V831q0 34-14 66t-38 57-57 38-67 13H426q-34 0-66-13t-57-38-38-57-14-66v-70h-56q-34 0-66-14t-57-38-38-57-13-67V174q0-47 23-87T109 23 196 0h412m175 244H426q-46 0-86 22T278 328t-26 85v348H608q47 0 86-22t63-62 25-85l1-348m-269 318q18 0 31 13t13 31-13 31-31 13-31-13-13-31 13-31 31-13m0-212q13 0 22 9t11 22v125q0 14-9 23t-22 10-23-7-11-22l-1-126q0-13 10-23t23-10z M896 811l-128 0c-23 0-43-19-43-43 0-23 19-43 43-43l107 0c13 0 21-9 21-21L896 107c0-13-9-21-21-21L448 85c-13 0-21 9-21 21l0 21c0 23-19 43-43 43-23 0-43-19-43-43L341 85c0-47 38-85 85-85l469 0c47 0 85 38 85 85l0 640C981 772 943 811 896 811zM683 299l0 640c0 47-38 85-85 85L128 1024c-47 0-85-38-85-85L43 299c0-47 38-85 85-85l469 0C644 213 683 252 683 299zM576 299 149 299c-13 0-21 9-21 21l0 597c0 13 9 21 21 21l427 0c13 0 21-9 21-21L597 320C597 307 589 299 576 299z diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index 843eefc7..8a39c49b 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -455,6 +455,21 @@ + + + + + + From addbb19728f7a07a67f6b2a8a9083f2e4389b079 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 15 Aug 2024 22:13:20 +0800 Subject: [PATCH 54/70] feature: add context menu items to revision changes to reset (checkout) selected file to this revision or to it's first parent file version (#359) --- src/Resources/Locales/en_US.axaml | 2 ++ src/Resources/Locales/zh_CN.axaml | 2 ++ src/Resources/Locales/zh_TW.axaml | 2 ++ src/ViewModels/CommitDetail.cs | 28 +++++++++++++++++++++++++++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 6f03ef06..75be560a 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -64,6 +64,8 @@ Branch Compare Bytes CANCEL + Reset to This Revision + Reset to Parent Revision CHANGE DISPLAY MODE Show as File and Dir List Show as Path List diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 96b85d7b..2bd21da2 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -67,6 +67,8 @@ 分支比较 字节 取 消 + 重置文件到该版本 + 重置文件到上一版本 切换变更显示模式 文件名+路径列表模式 全路径列表模式 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 1f49fe1b..ea4a2cde 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -67,6 +67,8 @@ 分支比較 位元組 取 消 + 重置檔案到該版本 + 重置檔案到上一版本 切換變更顯示模式 檔名+路徑列表模式 全路徑列表模式 diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 33a96022..dba0e7b2 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -260,6 +260,33 @@ namespace SourceGit.ViewModels ev.Handled = true; }; menu.Items.Add(diffWithMerger); + menu.Items.Add(new MenuItem { Header = "-" }); + + if (File.Exists(Path.Combine(_repo.FullPath, change.Path))) + { + var resetToThisRevision = new MenuItem(); + resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision"); + resetToThisRevision.Icon = App.CreateMenuIcon("Icons.Undo"); + resetToThisRevision.Click += (_, ev) => + { + new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}"); + ev.Handled = true; + }; + + var resetToFirstParent = new MenuItem(); + resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision"); + resetToFirstParent.Icon = App.CreateMenuIcon("Icons.Undo"); + resetToFirstParent.IsEnabled = _commit.Parents.Count > 0 && change.Index != Models.ChangeState.Added; + resetToFirstParent.Click += (_, ev) => + { + new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}~1"); + ev.Handled = true; + }; + + menu.Items.Add(resetToThisRevision); + menu.Items.Add(resetToFirstParent); + menu.Items.Add(new MenuItem { Header = "-" }); + } if (change.Index != Models.ChangeState.Deleted) { @@ -294,7 +321,6 @@ namespace SourceGit.ViewModels ev.Handled = true; }; - menu.Items.Add(new MenuItem { Header = "-" }); menu.Items.Add(history); menu.Items.Add(blame); menu.Items.Add(explore); From dd66e68ecd8fef6234bb1d7e9f0c48a2af3c131d Mon Sep 17 00:00:00 2001 From: Jean Date: Thu, 15 Aug 2024 19:02:09 -0300 Subject: [PATCH 55/70] fix: update pt-BR locale w/ new strings --- src/Resources/Locales/pt_BR.axaml | 34 +++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 4c471a0e..3a3bebad 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -67,19 +67,21 @@ Comparar Branch Bytes CANCELAR + Resetar para Esta Revisão + Resetar to Revisão Pai ALTERAR MODO DE EXIBIÇÃO - Mostrar como Lista de Arquivos e Diretórios + Mostrar como Grade Mostrar como Lista de Caminhos - Mostrar como Árvore de Sistema de Arquivos - Checar Branch - Checar Commit + Mostrar como Árvore de Arquivos do Sistema + Checkout Branch + Checkout Commit Aviso: Ao fazer o checkout de um commit, seu Head ficará desanexado Commit: Branch: Alterações Locais: Descartar - Não Fazer Nada - Guardar & Reaplicar + Nada + Stash & Reaplicar Cherry-Pick Este Commit Commit: Commitar todas as alterações @@ -125,8 +127,20 @@ Insira o assunto do commit Descrição Configurar Repositório + TEMPLATE DE COMMIT + Nome do Template: + Conteúdo do Template: Endereço de Email Endereço de email + GIT + RASTREADOR DE PROBLEMAS + Adicionar Regra de Exemplo do Github + Adicionar Regra de Exemplo do Jira + Nova Regra + Expressão Regex de Issue: + Nome da Regra: + URL de Resultado: + Por favor, use $1, $2 para acessar os valores de grupos do regex. Proxy HTTP Proxy HTTP usado por este repositório Nome de Usuário @@ -157,6 +171,7 @@ Tipo: anotada leve + Pressione Ctrl para iniciar diretamente Recortar Excluir Branch Branch: @@ -338,6 +353,7 @@ Nome: O Git NÃO foi configurado. Por favor, vá para [Preferências] e configure primeiro. AVISO + Abrir Pasta de Dados do Aplicativo SELECIONAR PASTA Abrir Com... Opcional. @@ -363,6 +379,7 @@ Fonte Padrão Tamanho da Fonte Padrão Fonte Monoespaçada + Usar apenas fonte monoespaçada no editor de texto Tema Sobrescrever Tema GERAL @@ -478,6 +495,7 @@ SHA Autor & Committer Pesquisar Branches & Tags + Mostrar Tags como Árvore Estatísticas SUBMÓDULOS ADICIONAR SUBMÓDULO @@ -555,6 +573,7 @@ Submódulo: Usar opção --remote Aviso + Página de Boas-vindas Criar Grupo Raíz Criar Subgrupo Clonar Repositório @@ -577,11 +596,13 @@ Você pode stagear este arquivo agora. COMMIT COMMIT & PUSH + Template/Histories CTRL + Enter CONFLITOS DETECTADOS CONFLITOS DE ARQUIVOS RESOLVIDOS INCLUIR ARQUIVOS NÃO RASTREADOS NENHUMA MENSAGEM DE ENTRADA RECENTE + NENHUM TEMPLATE DE COMMIT STAGED DESSTAGEAR DESSTAGEAR TODOS @@ -589,6 +610,7 @@ STAGEAR STAGEAR TODOS VER SUPOR NÃO ALTERADO + Template: ${0}$ Clique com o botão direito nos arquivos selecionados e escolha como resolver conflitos. WORKTREE Copiar Caminho From f7e0cbf989c0f129866258e8d7346715b0ead5bf Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 16 Aug 2024 10:14:08 +0800 Subject: [PATCH 56/70] ux: style for disabled menu item --- src/Resources/Locales/en_US.axaml | 4 +- src/Resources/Styles.axaml | 258 ++++++++++++++---------------- 2 files changed, 126 insertions(+), 136 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 75be560a..001d042a 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -200,13 +200,13 @@ NEW Syntax Highlighting Line Word Wrap - Open In Merge Tool + Open in Merge Tool Decrease Number of Visible Lines Increase Number of Visible Lines SELECT FILE TO VIEW CHANGES Show hidden symbols Swap - Open In Merge Tool + Open in Merge Tool Discard Changes All local changes in working copy. Changes: diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index defb1be6..e9477212 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -251,6 +251,7 @@ + - + + + + + - - - - - + - - - - - + - - - - - +