mirror of
https://github.com/Murmele/Gittyup.git
synced 2024-09-11 10:45:39 +03:00
Merge branch 'master'
This commit is contained in:
commit
231c3d3da4
80
.github/workflows/build.yml
vendored
80
.github/workflows/build.yml
vendored
@ -38,9 +38,18 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
# image: bilelmoussaoui/flatpak-github-actions:kde-5.15-21.08
|
# image: bilelmoussaoui/flatpak-github-actions:kde-5.15-21.08
|
||||||
image: exactlyonekas/gittyup-flatpak-builder:latest
|
image: archlinux:latest
|
||||||
options: --privileged
|
options: --privileged
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
- name: Update
|
||||||
|
run: |
|
||||||
|
pacman --noconfirm -Suy
|
||||||
|
pacman --noconfirm -S flatpak flatpak-builder xorg-server-xvfb
|
||||||
|
flatpak install --assumeyes org.kde.Sdk//5.15-21.08
|
||||||
|
flatpak install --assumeyes org.freedesktop.Sdk.Extension.golang//21.08
|
||||||
|
flatpak install --assumeyes org.kde.Platform//5.15-21.08
|
||||||
|
|
||||||
- name: Show environment variables
|
- name: Show environment variables
|
||||||
run: >
|
run: >
|
||||||
echo IS_RELEASE: ${{ env.IS_RELEASE }}
|
echo IS_RELEASE: ${{ env.IS_RELEASE }}
|
||||||
@ -67,7 +76,7 @@ jobs:
|
|||||||
- name: Replace git tag by the commit id on which it runs
|
- name: Replace git tag by the commit id on which it runs
|
||||||
if: github.ref_type != 'tag'
|
if: github.ref_type != 'tag'
|
||||||
run: >
|
run: >
|
||||||
sed -i 's@tag: gittyup_v[1-9]*.[0-9]*.[0-9]*@commit: "${{ (github.event.pull_request && github.event.pull_request.head.sha) || github.sha }}"@' com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
sed -i 's@tag: .*@commit: "${{ (github.event.pull_request && github.event.pull_request.head.sha) || github.sha }}"@' com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
||||||
|
|
||||||
- name: Use correct git tag
|
- name: Use correct git tag
|
||||||
if: github.ref_type == 'tag'
|
if: github.ref_type == 'tag'
|
||||||
@ -88,6 +97,11 @@ jobs:
|
|||||||
run: >
|
run: >
|
||||||
sed -i 's@desktop-file-name-suffix: ""@desktop-file-name-suffix: " (Development)"@' com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
sed -i 's@desktop-file-name-suffix: ""@desktop-file-name-suffix: " (Development)"@' com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
||||||
|
|
||||||
|
- name: Enable automatic update
|
||||||
|
if: github.ref_type != 'tag'
|
||||||
|
run: >
|
||||||
|
sed -i 's@-DENABLE_UPDATE_OVER_GUI=OFF@-DENABLE_UPDATE_OVER_GUI=ON@' com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
||||||
|
|
||||||
- name: Show Flatpak manifest
|
- name: Show Flatpak manifest
|
||||||
run: cat com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
run: cat com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
||||||
|
|
||||||
@ -123,8 +137,11 @@ jobs:
|
|||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
ninja_platform: linux
|
ninja_platform: linux
|
||||||
qt_platform: linux
|
qt_platform: linux
|
||||||
|
qt_arch: gcc_64
|
||||||
openssl_arch: linux-x86_64
|
openssl_arch: linux-x86_64
|
||||||
cmake_flags: "-DGENERATE_APPDATA=ON"
|
ld_library_arch: linux-x86-64
|
||||||
|
cmake_flags: "-DGENERATE_APPDATA=ON -DCMAKE_INSTALL_PREFIX=/usr -DUSE_SYSTEM_QT=ON -DENABLE_UPDATE_OVER_GUI=OFF"
|
||||||
|
pack: 0
|
||||||
cmake_env: {}
|
cmake_env: {}
|
||||||
|
|
||||||
- name: macos
|
- name: macos
|
||||||
@ -193,7 +210,7 @@ jobs:
|
|||||||
perl-version: '5.30'
|
perl-version: '5.30'
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
uses: jurplel/install-qt-action@v2.13.0
|
uses: jurplel/install-qt-action@v3.3.0
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
if: "!matrix.qt.check_only"
|
if: "!matrix.qt.check_only"
|
||||||
with:
|
with:
|
||||||
@ -205,7 +222,7 @@ jobs:
|
|||||||
modules: qtwebengine
|
modules: qtwebengine
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
uses: jurplel/install-qt-action@v2.13.0
|
uses: jurplel/install-qt-action@v3.3.0
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
if: matrix.qt.check_only
|
if: matrix.qt.check_only
|
||||||
with:
|
with:
|
||||||
@ -264,7 +281,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p build/release
|
mkdir -p build/release
|
||||||
cd build/release
|
cd build/release
|
||||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDEBUG_OUTPUT=OFF -DGITTYUP_CI_TESTS=ON ${{ env.CMAKE_FLAGS }} ${{ matrix.env.cmake_flags }} ../..
|
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DUPDATE_TRANSLATIONS=ON -DGITTYUP_CI_TESTS=ON ${{ env.CMAKE_FLAGS }} ${{ matrix.env.cmake_flags }} ../..
|
||||||
|
|
||||||
- name: Build Information
|
- name: Build Information
|
||||||
run: |
|
run: |
|
||||||
@ -301,15 +318,20 @@ jobs:
|
|||||||
if: matrix.env.pack && !matrix.qt.check_only
|
if: matrix.env.pack && !matrix.qt.check_only
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: build/release/VERSION.txt
|
path: build/release/Version.txt
|
||||||
name: Gittyup-VERSION
|
name: Gittyup-VERSION
|
||||||
|
|
||||||
|
- name: Check Version file
|
||||||
|
run: |
|
||||||
|
cd build/release
|
||||||
|
cat ./Version.txt
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
if: matrix.env.ninja_platform != 'win' && matrix.env.ninja_platform != 'mac'
|
if: matrix.env.ninja_platform != 'win' && matrix.env.ninja_platform != 'mac'
|
||||||
uses: GabrielBB/xvfb-action@v1
|
uses: GabrielBB/xvfb-action@v1
|
||||||
with:
|
with:
|
||||||
working-directory: build/release
|
working-directory: build/release
|
||||||
run: ninja check
|
run: ninja check --verbose
|
||||||
|
|
||||||
- name: Test (Windows)
|
- name: Test (Windows)
|
||||||
if: matrix.env.ninja_platform == 'win'
|
if: matrix.env.ninja_platform == 'win'
|
||||||
@ -317,6 +339,44 @@ jobs:
|
|||||||
cd build/release
|
cd build/release
|
||||||
ninja check_no_win32_offscreen
|
ninja check_no_win32_offscreen
|
||||||
|
|
||||||
|
- name: Build Appimage
|
||||||
|
if: matrix.env.ninja_platform == 'linux' && !matrix.qt.check_only
|
||||||
|
run: |
|
||||||
|
cd build/release
|
||||||
|
sudo apt -y install appstream
|
||||||
|
sudo apt -y install libfuse2
|
||||||
|
sudo apt -y install libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0
|
||||||
|
sudo apt -y install libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xinerama0 libxcb-xinput0 libxcb-xkb1 libxcb-xrm0 libxcb-xv0 libxcb-xvmc0 libxcb1
|
||||||
|
|
||||||
|
mkdir -p AppDir
|
||||||
|
DESTDIR=AppDir ninja install
|
||||||
|
|
||||||
|
export QTDIR=$RUNNER_WORKSPACE/Qt/${{ matrix.qt.version }}/${{ matrix.env.qt_arch }}
|
||||||
|
|
||||||
|
rm -rf ./AppDir/usr/include/
|
||||||
|
strip ./AppDir/usr/bin/cmark ./AppDir/usr/bin/gittyup ./AppDir/usr/bin/indexer ./AppDir/usr/bin/relauncher
|
||||||
|
|
||||||
|
wget -c https://github.com/$(wget -q https://github.com/probonopd/go-appimage/releases/expanded_assets/continuous -O - | grep "appimagetool-.*-x86_64.AppImage" | head -n 1 | cut -d '"' -f 2)
|
||||||
|
chmod +x appimagetool-*.AppImage
|
||||||
|
QTDIR=$QTDIR ./appimagetool-*.AppImage -s deploy ./AppDir/usr/share/applications/*.desktop --appimage-extract-and-run # Bundle EVERYTHING
|
||||||
|
|
||||||
|
# Modify the AppDir: move ld-linux into the same directory as the payload application
|
||||||
|
# and change AppRun accordingly; so that, e.g., Qt qApp->applicationDirPath() works
|
||||||
|
mv ./AppDir/lib64/ld-${{ matrix.env.ld_library_arch }}.so.2 ./AppDir/usr/bin/
|
||||||
|
sed -i -e 's@^LD_LINUX.*@LD_LINUX=$(find "$HERE/usr/bin" -name "ld-*.so.*" | head -n 1)@g' ./AppDir/AppRun
|
||||||
|
|
||||||
|
rm ./AppDir/usr/share/metainfo/gittyup.appdata.xml
|
||||||
|
VERSION=$(cat ./Version.txt)
|
||||||
|
VERSION="$VERSION" ./appimagetool-*.AppImage ./AppDir # turn AppDir into AppImage
|
||||||
|
#ls -lh Gittyup-*
|
||||||
|
|
||||||
|
- name: Publish Appimage
|
||||||
|
if: matrix.env.ninja_platform == 'linux' && !matrix.qt.check_only
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
path: build/release/*.AppImage
|
||||||
|
name: GittyupAppImage
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
# https://github.com/marvinpinto/actions/issues/177
|
# https://github.com/marvinpinto/actions/issues/177
|
||||||
needs: [flatpak, build]
|
needs: [flatpak, build]
|
||||||
@ -347,7 +407,7 @@ jobs:
|
|||||||
# version is exported from cmake to file
|
# version is exported from cmake to file
|
||||||
- name: Retrieve version
|
- name: Retrieve version
|
||||||
run: |
|
run: |
|
||||||
echo "::set-output name=VERSION::$(cat artifacts/Gittyup-VERSION/VERSION.txt)"
|
echo "::set-output name=VERSION::$(cat artifacts/Gittyup-VERSION/Version.txt)"
|
||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Update GitHub release (latest tag)
|
- name: Update GitHub release (latest tag)
|
||||||
@ -363,6 +423,7 @@ jobs:
|
|||||||
**/artifacts/Gittyup macos/Gittyup*.dmg
|
**/artifacts/Gittyup macos/Gittyup*.dmg
|
||||||
**/artifacts/Gittyup Flatpak/com.github.Murmele.Gittyup.yml
|
**/artifacts/Gittyup Flatpak/com.github.Murmele.Gittyup.yml
|
||||||
**/Gittyup-x86_64/*.flatpak
|
**/Gittyup-x86_64/*.flatpak
|
||||||
|
**/artifacts/GittyupAppImage/*
|
||||||
|
|
||||||
- name: Update GitHub release (version tag)
|
- name: Update GitHub release (version tag)
|
||||||
uses: marvinpinto/action-automatic-releases@latest
|
uses: marvinpinto/action-automatic-releases@latest
|
||||||
@ -378,6 +439,7 @@ jobs:
|
|||||||
**/artifacts/Gittyup macos/Gittyup*.dmg
|
**/artifacts/Gittyup macos/Gittyup*.dmg
|
||||||
**/artifacts/Gittyup Flatpak/com.github.Murmele.Gittyup.yml
|
**/artifacts/Gittyup Flatpak/com.github.Murmele.Gittyup.yml
|
||||||
**/Gittyup-x86_64/*.flatpak
|
**/Gittyup-x86_64/*.flatpak
|
||||||
|
**/artifacts/GittyupAppImage/*
|
||||||
|
|
||||||
# needed otherwise the docs folder is not available
|
# needed otherwise the docs folder is not available
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,5 +1,13 @@
|
|||||||
build
|
build
|
||||||
|
.cache
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.project
|
.project
|
||||||
.vscode/
|
.vscode/
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
|
cmake-build-debug/
|
||||||
|
cmake-build-release/
|
||||||
|
build
|
||||||
|
.idea/
|
||||||
|
.venv
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
7
.pre-commit-config.yaml
Normal file
7
.pre-commit-config.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
|
rev: v13.0.1
|
||||||
|
hooks:
|
||||||
|
- id: clang-format
|
||||||
|
args: [ -i ]
|
||||||
|
|
@ -1,15 +1,22 @@
|
|||||||
cmake_minimum_required(VERSION 3.6.2)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(Gittyup)
|
project(Gittyup)
|
||||||
|
|
||||||
# Set name and version.
|
# Set name and version.
|
||||||
set(GITTYUP_NAME "Gittyup")
|
set(GITTYUP_NAME "Gittyup")
|
||||||
|
set(GITTYUP_EXECUTABLE_NAME "gittyup")
|
||||||
|
set(GITTYUP_IDENTIFIER "com.github.Murmele.Gittyup")
|
||||||
set(GITTYUP_VERSION_MAJOR 1)
|
set(GITTYUP_VERSION_MAJOR 1)
|
||||||
set(GITTYUP_VERSION_MINOR 2)
|
set(GITTYUP_VERSION_MINOR 3)
|
||||||
set(GITTYUP_VERSION_PATCH 1)
|
set(GITTYUP_VERSION_PATCH 0)
|
||||||
set(GITTYUP_VERSION
|
set(GITTYUP_VERSION
|
||||||
"${GITTYUP_VERSION_MAJOR}.${GITTYUP_VERSION_MINOR}.${GITTYUP_VERSION_PATCH}"
|
"${GITTYUP_VERSION_MAJOR}.${GITTYUP_VERSION_MINOR}.${GITTYUP_VERSION_PATCH}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
string(TIMESTAMP CURR_YEAR "%Y")
|
||||||
|
add_compile_definitions(CURR_YEAR=${CURR_YEAR})
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/LICENSE.md.in ${CMAKE_SOURCE_DIR}/LICENSE.md
|
||||||
|
@ONLY NEWLINE_STYLE UNIX)
|
||||||
|
|
||||||
# Write version to file so it can be used also from external, for example in the
|
# Write version to file so it can be used also from external, for example in the
|
||||||
# github manifest
|
# github manifest
|
||||||
file(WRITE "${CMAKE_BINARY_DIR}/Version.txt" ${GITTYUP_VERSION})
|
file(WRITE "${CMAKE_BINARY_DIR}/Version.txt" ${GITTYUP_VERSION})
|
||||||
@ -45,6 +52,7 @@ set(BUILD_SHARED_LIBS OFF)
|
|||||||
|
|
||||||
option(FLATPAK "Building for flatpak" OFF)
|
option(FLATPAK "Building for flatpak" OFF)
|
||||||
option(DEBUG_FLATPAK "Building but using flatpak urls for testing" OFF)
|
option(DEBUG_FLATPAK "Building but using flatpak urls for testing" OFF)
|
||||||
|
option(ENABLE_UPDATE_OVER_GUI "Enable updating from the Gittyup gui" ON)
|
||||||
option(USE_SYSTEM_OPENSSL "Use the system-wide OpenSSL installation" OFF)
|
option(USE_SYSTEM_OPENSSL "Use the system-wide OpenSSL installation" OFF)
|
||||||
option(
|
option(
|
||||||
USE_SYSTEM_LIBGIT2
|
USE_SYSTEM_LIBGIT2
|
||||||
@ -68,7 +76,10 @@ set(LUA_MODULES_PATH
|
|||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(HAIKU)
|
||||||
|
# qsort_r in libgit2 requires this
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS -lgnu)
|
||||||
|
elseif(UNIX AND NOT APPLE)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS -ldl)
|
set(CMAKE_EXE_LINKER_FLAGS -ldl)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -86,9 +97,20 @@ if(UNIX)
|
|||||||
set(QT_MODULES ${QT_MODULES} DBus)
|
set(QT_MODULES ${QT_MODULES} DBus)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(DEBUG_OUTPUT "Print debug output" ON)
|
option(DEBUG_OUTPUT
|
||||||
|
"Print debug output (Only available if debug menu is enabled!)" ON)
|
||||||
|
option(DEBUG_OUTPUT_GENERAL "Enable general debug messages" ON)
|
||||||
|
option(DEBUG_OUTPUT_REFRESH "Enable debug messages to debug the refresh flow"
|
||||||
|
OFF)
|
||||||
if(NOT DEBUG_OUTPUT)
|
if(NOT DEBUG_OUTPUT)
|
||||||
add_compile_definitions(QT_NO_DEBUG_OUTPUT)
|
add_compile_definitions(QT_NO_DEBUG_OUTPUT)
|
||||||
|
else()
|
||||||
|
if(DEBUG_OUTPUT_GENERAL)
|
||||||
|
add_compile_definitions(DEBUG_OUTPUT_GENERAL)
|
||||||
|
endif()
|
||||||
|
if(DEBUG_OUTPUT_REFRESH)
|
||||||
|
add_compile_definitions(DEBUG_OUTPUT_REFRESH)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(
|
find_package(
|
||||||
@ -103,6 +125,10 @@ if(FLATPAK)
|
|||||||
add_compile_definitions(FLATPAK)
|
add_compile_definitions(FLATPAK)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_UPDATE_OVER_GUI)
|
||||||
|
add_compile_definitions(ENABLE_UPDATE_OVER_GUI)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(DEBUG_FLATPAK)
|
if(DEBUG_FLATPAK)
|
||||||
add_compile_definitions(DEBUG_FLATPAK)
|
add_compile_definitions(DEBUG_FLATPAK)
|
||||||
endif()
|
endif()
|
||||||
@ -125,6 +151,18 @@ if(APPLE)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
set(CONTENTS_DIR ${GITTYUP_EXECUTABLE_NAME}.app/Contents)
|
||||||
|
set(RESOURCES_DIR ${CONTENTS_DIR}/Resources)
|
||||||
|
set(L10N_INSTALL_DIR ${RESOURCES_DIR}/l10n)
|
||||||
|
elseif(UNIX)
|
||||||
|
set(L10N_INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/${GITTYUP_NAME})
|
||||||
|
set(RESOURCES_DIR ${CMAKE_INSTALL_DATADIR}/${GITTYUP_NAME})
|
||||||
|
else()
|
||||||
|
set(L10N_INSTALL_DIR Resources/l10n)
|
||||||
|
set(RESOURCES_DIR Resources)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_subdirectory(dep)
|
add_subdirectory(dep)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(l10n)
|
add_subdirectory(l10n)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018 Scientific Toolworks, Inc.
|
Copyright (c) 2018 Scientific Toolworks, Inc.
|
||||||
Copyright (c) 2021-2022 Gittyup contributors
|
Copyright (c) 2021-2023 Gittyup contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
22
LICENSE.md.in
Normal file
22
LICENSE.md.in
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Scientific Toolworks, Inc.
|
||||||
|
Copyright (c) 2021-@CURR_YEAR@ Gittyup contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
15
README.md
15
README.md
@ -132,8 +132,11 @@ where `<path-to-qt>` points to the Qt install directory that contains
|
|||||||
`bin`, `lib`, etc.
|
`bin`, `lib`, etc.
|
||||||
|
|
||||||
**Build**
|
**Build**
|
||||||
|
```
|
||||||
ninja
|
ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
### A Convenient Shell Script for Ubuntu is available [here](https://raw.githubusercontent.com/Murmele/Gittyup/master/pack/buildUbuntu.sh), and will install all the necessary prerequisites, and build a release version for immediate use.
|
||||||
|
|
||||||
How to Install
|
How to Install
|
||||||
-----------------
|
-----------------
|
||||||
@ -177,7 +180,6 @@ function run_disown_silence(){
|
|||||||
run_disown_silence flatpak run com.github.Murmele.Gittyup
|
run_disown_silence flatpak run com.github.Murmele.Gittyup
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
How to Contribute
|
How to Contribute
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -192,6 +194,15 @@ branch. Create pull requests against the `master` branch. Follow the
|
|||||||
[seven guidelines](https://chris.beams.io/posts/git-commit/) to writing a
|
[seven guidelines](https://chris.beams.io/posts/git-commit/) to writing a
|
||||||
great commit message.
|
great commit message.
|
||||||
|
|
||||||
|
Prior to committing a change, please use `cl-format.sh` to ensure your code
|
||||||
|
adheres to the formatting conventions for this project. You can also use the
|
||||||
|
`setup-env.sh` script to install a pre-commit hook which will automatically
|
||||||
|
run `clang-format` against all modified files.
|
||||||
|
|
||||||
|
Prior to pushing a change, please ensure you run the unit tests to avoid any
|
||||||
|
regressions. These are found in `<build-dir>/test` and can be run using
|
||||||
|
`ctest`.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
35
cl-fmt.sh
35
cl-fmt.sh
@ -1,18 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
cd "`dirname "$0"`"
|
cd "`dirname "$0"`"
|
||||||
|
|
||||||
# Variable that will hold the name of the clang-format command
|
# Variable that will hold the name of the clang-format command
|
||||||
FMT=""
|
FMT=""
|
||||||
|
|
||||||
FOLDERS=("./src" "./test")
|
FOLDERS=("./src" "./test" "./l10n")
|
||||||
|
|
||||||
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
|
# We specifically require clang-format v13. Some distros include the version
|
||||||
# that the version number be part of the command. We prefer clang-format if
|
# number in the name, others don't. Prefer the specifically-named version.
|
||||||
# that's present, otherwise we work backwards from highest version to lowest
|
for clangfmt in clang-format-13 clang-format
|
||||||
# version but at least 13.
|
do
|
||||||
for clangfmt in clang-format{,-{1,2,3}{9,8,7,6,5,4,3}}; do
|
if command -v "$clangfmt" &>/dev/null; then
|
||||||
if which "$clangfmt" &>/dev/null; then
|
|
||||||
FMT="$clangfmt"
|
FMT="$clangfmt"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@ -24,6 +24,14 @@ if [ -z "$FMT" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check we have v13 of clang-format
|
||||||
|
VERSION=`$FMT --version | grep -Po 'version\s\K(\d+)'`
|
||||||
|
if [ "$VERSION" != "13" ]; then
|
||||||
|
echo "Found clang-format v$VERSION, but v13 is required. Please install v13 of clang-format and try again."
|
||||||
|
echo "On Debian-derived distributions, this can be done via: apt install clang-format-13"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
function format() {
|
function format() {
|
||||||
for f in $(find $@ \( -type d -path './test/dep/*' -prune \) -o \( -name '*.h' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \)); do
|
for f in $(find $@ \( -type d -path './test/dep/*' -prune \) -o \( -name '*.h' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \)); do
|
||||||
echo "format ${f}";
|
echo "format ${f}";
|
||||||
@ -41,9 +49,18 @@ for dir in ${FOLDERS[@]}; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Format cmake files
|
||||||
|
# NOTE: requires support for python venv; on Debian-like distros, this can be
|
||||||
|
# installed using apt install python3-venv
|
||||||
echo "Start formatting cmake files"
|
echo "Start formatting cmake files"
|
||||||
pip install cmake-format==0.6.13
|
CMAKE_FORMAT=${SCRIPT_DIR}/.venv/bin/cmake-format
|
||||||
|
if [ ! -f "$CMAKE_FORMAT" ]; then
|
||||||
|
pushd ${SCRIPT_DIR}
|
||||||
|
python3 -m venv .venv
|
||||||
|
.venv/bin/pip install cmake-format==0.6.13
|
||||||
|
popd
|
||||||
|
fi
|
||||||
find . \
|
find . \
|
||||||
\( -type d -path './test/dep/*' -prune \) \
|
\( -type d -path './test/dep/*' -prune \) \
|
||||||
-o \( -type d -path './dep/*/*' -prune \) \
|
-o \( -type d -path './dep/*/*' -prune \) \
|
||||||
-o \( -name CMakeLists.txt -exec cmake-format --in-place {} + \)
|
-o \( -name CMakeLists.txt -exec "$CMAKE_FORMAT" --in-place {} + \)
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
# For testing enable
|
||||||
|
#set(CMAKE_SOURCE_DIR <PATH TO SOURCE>)
|
||||||
|
#set(CMAKE_BINARY_DIR <PATH TO BINARY DIR>)
|
||||||
|
#set(DOC_SOURCE_DIR ${CMAKE_SOURCE_DIR}/docs)
|
||||||
|
#set(DOC_BINARY_DIR ${CMAKE_BINARY_DIR}/docs)
|
||||||
|
#set(CHANGELOG_HTML ${DOC_BINARY_DIR}/changelog.html)
|
||||||
|
#set(APPDATA_CONF ${CMAKE_SOURCE_DIR}/rsrc/linux/com.github.Murmele.Gittyup.appdata.xml.in)
|
||||||
|
#set(APPDATA ${CMAKE_BINARY_DIR}/rsrc/linux/com.github.Murmele.Gittyup.appdata.xml)
|
||||||
|
|
||||||
# add release notes to the appdata file
|
# add release notes to the appdata file
|
||||||
file(READ "${CHANGELOG_HTML}" HTML_CHANGELOGS)
|
file(READ "${CHANGELOG_HTML}" HTML_CHANGELOGS)
|
||||||
# it is not allowed to have multiple texts without being in an environment
|
# it is not allowed to have multiple texts without being in an environment
|
||||||
@ -5,6 +14,7 @@ file(READ "${CHANGELOG_HTML}" HTML_CHANGELOGS)
|
|||||||
string(REGEX REPLACE "<p>([^<]*)<\\/p>" "\\1" RELEASES ${HTML_CHANGELOGS}) # remove paragraph environment
|
string(REGEX REPLACE "<p>([^<]*)<\\/p>" "\\1" RELEASES ${HTML_CHANGELOGS}) # remove paragraph environment
|
||||||
string(REGEX REPLACE "<h4>([A-Za-z0-9]*)<\\/h4>" "<p>\\1</p>" RELEASES ${RELEASES}) # h4 is unknow to appdata so change it to a paragraph environment
|
string(REGEX REPLACE "<h4>([A-Za-z0-9]*)<\\/h4>" "<p>\\1</p>" RELEASES ${RELEASES}) # h4 is unknow to appdata so change it to a paragraph environment
|
||||||
string(REPLACE "\n" "\n\t" RELEASES ${RELEASES}) # add tabulator
|
string(REPLACE "\n" "\n\t" RELEASES ${RELEASES}) # add tabulator
|
||||||
string(REGEX REPLACE "<h3>(v[1-9]\\.[0-9]\\.[0-9]) - ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])<\\/h3>" "<release version='\\1' date='\\2'>\n\t<description>" RELEASES ${RELEASES})
|
# For Dev Version "vX.X.X - <current date> (DEV)" can be used to show in the changelog the current progress
|
||||||
|
string(REGEX REPLACE "<h3>(v[1-9]\\.[0-9]\\.[0-9]|vX\\.X\\.X) - ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])( \\(DEV\\))?<\\/h3>" "<release version='\\1' date='\\2'>\n\t<description>" RELEASES ${RELEASES})
|
||||||
string(REGEX REPLACE "<hr \\/>" "</description>\n\t</release>" RELEASES ${RELEASES})
|
string(REGEX REPLACE "<hr \\/>" "</description>\n\t</release>" RELEASES ${RELEASES})
|
||||||
configure_file(${APPDATA_CONF} ${APPDATA})
|
configure_file(${APPDATA_CONF} ${APPDATA})
|
||||||
|
@ -56,13 +56,13 @@ theme['button'] = {
|
|||||||
-- commit list colors
|
-- commit list colors
|
||||||
-- { default, active, inactive, disabled }
|
-- { default, active, inactive, disabled }
|
||||||
theme['commits'] = {
|
theme['commits'] = {
|
||||||
text = '#E1E5F2',
|
text = '#AAB2BE',
|
||||||
bright_text = '#AAB2BE',
|
bright_text = '#E1E5F2',
|
||||||
background = '#2D2E34',
|
background = '#2D2E34',
|
||||||
alternate = '#2D2E34', -- an alternate background color for list rows
|
alternate = '#2D2E34', -- an alternate background color for list rows
|
||||||
highlight = { active = '#2A82DA', inactive = '#1B5B9B' },
|
highlight = { active = '#2A82DA', inactive = '#1B5B9B' },
|
||||||
highlighted_text = { active = '#E1E5F2', inactive = '#E1E5F2' },
|
highlighted_text = { active = '#A6CBF0', inactive = '#E1E5F2' },
|
||||||
highlighted_bright_text = { active = '#A6CBF0', inactive = '#9090A5' }
|
highlighted_bright_text = { active = '#E1E5F2', inactive = '#9090A5' }
|
||||||
}
|
}
|
||||||
|
|
||||||
-- status badge colors
|
-- status badge colors
|
||||||
@ -77,7 +77,12 @@ theme['badge'] = {
|
|||||||
selected = '#E1E5F2', -- the color when a list item is selected
|
selected = '#E1E5F2', -- the color when a list item is selected
|
||||||
conflicted = '#DA2ADA', -- the color of conflicted items
|
conflicted = '#DA2ADA', -- the color of conflicted items
|
||||||
head = '#52A500', -- a bolder color to indicate the HEAD
|
head = '#52A500', -- a bolder color to indicate the HEAD
|
||||||
notification = '#8C2026' -- the color of toolbar notifications badges
|
notification = '#8C2026', -- the color of toolbar notifications badges
|
||||||
|
modified = '#91973A', -- (yellow) the color of the badge when the file is modified
|
||||||
|
added = '#394734', -- (green) the color of the badge when the file was newly added
|
||||||
|
deleted = '#5E3638', -- (red) the color of the badge when the file was deleted
|
||||||
|
untracked = '#2A4944', -- (green blue) the color of the badge when the file is untracked
|
||||||
|
renamed = '#23455E' -- (blue) the color of the badge when the file is renamed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ theme['commits'] = {
|
|||||||
-- { normal, selected, conflicted, head, notification }
|
-- { normal, selected, conflicted, head, notification }
|
||||||
theme['badge'] = {
|
theme['badge'] = {
|
||||||
foreground = {
|
foreground = {
|
||||||
normal = '#FFFFFF',
|
normal = '#000000',
|
||||||
selected = '#6C6C6C'
|
selected = '#6C6C6C'
|
||||||
},
|
},
|
||||||
background = {
|
background = {
|
||||||
@ -77,7 +77,12 @@ theme['badge'] = {
|
|||||||
selected = '#FFFFFF', -- the color when a list item is selected
|
selected = '#FFFFFF', -- the color when a list item is selected
|
||||||
conflicted = '#D22222', -- the color of conflicted items
|
conflicted = '#D22222', -- the color of conflicted items
|
||||||
head = '#6F7379', -- a bolder color to indicate the HEAD
|
head = '#6F7379', -- a bolder color to indicate the HEAD
|
||||||
notification = '#FF0000' -- the color of toolbar notifications badges
|
notification = '#FF0000', -- the color of toolbar notifications badges
|
||||||
|
modified = '#FFEEDB', -- (yellow) the color of the badge when the file is modified
|
||||||
|
added = '#DCFFDC', -- (green) the color of the badge when the file was newly added
|
||||||
|
deleted = '#FFDCDC', -- (red) the color of the badge when the file was deleted
|
||||||
|
untracked = '#d9ead2', -- (green blue) the color of the badge when the file is untracked
|
||||||
|
renamed = '#d2e8fc' -- (blue) the color of the badge when the file is renamed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ if(NOT USE_SYSTEM_GIT)
|
|||||||
macro(add_helper NAME)
|
macro(add_helper NAME)
|
||||||
set(TARGET git-credential-${NAME})
|
set(TARGET git-credential-${NAME})
|
||||||
add_executable(${TARGET} ${PATH}/${NAME}/${TARGET}.c)
|
add_executable(${TARGET} ${PATH}/${NAME}/${TARGET}.c)
|
||||||
set_target_properties(${TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
set_target_properties(
|
||||||
$<TARGET_FILE_DIR:gittyup>)
|
${TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||||
|
$<TARGET_FILE_DIR:gittyup>/credential-helpers)
|
||||||
|
|
||||||
if(${ARGC} GREATER 1)
|
if(${ARGC} GREATER 1)
|
||||||
target_link_libraries(${TARGET} ${ARGV1})
|
target_link_libraries(${TARGET} ${ARGV1})
|
||||||
@ -14,7 +15,7 @@ if(NOT USE_SYSTEM_GIT)
|
|||||||
if(NOT APPLE)
|
if(NOT APPLE)
|
||||||
install(
|
install(
|
||||||
TARGETS ${TARGET}
|
TARGETS ${TARGET}
|
||||||
DESTINATION .
|
DESTINATION ${CMAKE_INSTALL_BINDIR}/credential-helpers
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 29708a562a1887a91de0fa6ca668c71871accde9
|
Subproject commit 3f499b24f3bcd66db022074f7e8b4f6ee266a3ae
|
@ -59,5 +59,8 @@ target_link_libraries(scintilla Qt5::Widgets lexilla)
|
|||||||
set_target_properties(scintilla PROPERTIES AUTOMOC ON)
|
set_target_properties(scintilla PROPERTIES AUTOMOC ON)
|
||||||
|
|
||||||
set(SCINTILLUA_LEXERS_DIR
|
set(SCINTILLUA_LEXERS_DIR
|
||||||
|
${RESOURCES_DIR}/lexers
|
||||||
|
CACHE INTERNAL "")
|
||||||
|
set(SRC_SCINTILLUA_LEXERS_DIR
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scintillua/lexers
|
${CMAKE_CURRENT_SOURCE_DIR}/scintillua/lexers
|
||||||
CACHE INTERNAL "")
|
CACHE INTERNAL "")
|
||||||
|
@ -1,11 +1,74 @@
|
|||||||
### v1.2.1 - 2022-11-10
|
### vX.X.X - 2023-04-20 (DEV)
|
||||||
|
|
||||||
|
Description
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
* UI(Commit List): Added a right-click menu entry to rename branches.
|
||||||
|
* UI(Main Menu): Added a menu-entry to rename the current branch.
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
|
* UI(Commit List): Collapse multiple branch and tag right-click menu entries
|
||||||
|
into submenus. This affects the checkout and delete operations.
|
||||||
|
* Fix(Build System): Force usage of clang-format v13 to ensure consistent formatting.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
### v1.3.0 - 2023-04-20
|
||||||
|
|
||||||
|
Performance Improvement and feature release
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
* Colorized status badges
|
||||||
|
* Template: use first template as default template for the commit message
|
||||||
|
* Search function for the treeview
|
||||||
|
* Reworked credential store: add possibility to choose between different methods to store credentials
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
|
* Fix external diff in Flatpak build
|
||||||
|
* Fix windows credentials
|
||||||
|
* Fix force push to correct remote
|
||||||
|
* Fix tab title if more than three times a repository with the same name is opened
|
||||||
|
* Fix storing repository settings correctly, because otherwise they are not applied
|
||||||
|
* Fix language support
|
||||||
|
* Improved refresh velocity
|
||||||
|
* Fix storing and restoring current opened file when Gittyup refreshes
|
||||||
|
* Improved velocity for files with many hunks
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
### v1.2.2 - 2023-01-22
|
||||||
|
|
||||||
Bug fix release
|
Bug fix release
|
||||||
|
|
||||||
#### Changed
|
#### Changed
|
||||||
|
|
||||||
|
* Fix flatpak install process
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
### v1.2.1 - 2023-01-22
|
||||||
|
|
||||||
|
Bug fix release
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
* Possibility to hide avatar (Settings - Window - View - Show Avatars)
|
||||||
|
* Show log entry when a conflict during rebase happens
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
* Fix download url for flatpak and macos
|
* Fix download url for flatpak and macos
|
||||||
* Fix Segmentation fault when ignoring files
|
* Fix Segmentation fault when ignoring files
|
||||||
|
* Fix discard of complete files and submodules
|
||||||
|
* Fix context menu entries
|
||||||
|
* Fix bytesize overflow
|
||||||
|
* Fix focus loose during scrolling in the Commitlist with the keyboard
|
||||||
|
* Do not crash when the repository is for some reason broken
|
||||||
|
* Fix crash if rebasing is not possible
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
### v1.2.0 - 2022-10-28
|
### v1.2.0 - 2022-10-28
|
||||||
|
@ -31,7 +31,26 @@ Report bugs in Gittyup by opening an issue in the
|
|||||||
Remember to search for existing issues before creating a new one.
|
Remember to search for existing issues before creating a new one.
|
||||||
|
|
||||||
If you still need help, check out our Matrix channel
|
If you still need help, check out our Matrix channel
|
||||||
[Gittyup:martix.org](https://matrix.to/#/#Gittyup:matrix.org).
|
[Gittyup:matrix.org](https://matrix.to/#/#Gittyup:matrix.org).
|
||||||
|
|
||||||
|
Multi language support
|
||||||
|
======================
|
||||||
|
|
||||||
|
Gittyup supports the following languages:
|
||||||
|
- English (en)
|
||||||
|
- German (de)
|
||||||
|
- Spanisch (es)
|
||||||
|
- Japanese (ja)
|
||||||
|
- Portuguese (pt)
|
||||||
|
- Portuguese Brazil (pt_BR)
|
||||||
|
- Chinese (zh_CN)
|
||||||
|
- Russian (ru)
|
||||||
|
|
||||||
|
By default the system language is used. To switch to another language execute the application with the following command
|
||||||
|
```
|
||||||
|
LANG=<lang> <executable>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
========
|
========
|
||||||
@ -74,9 +93,9 @@ Solving rebase conflicts and continuing after conflicts are solved
|
|||||||
|
|
||||||
![Rebase Conflicts](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/RebaseConflicts.png)
|
![Rebase Conflicts](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/RebaseConflicts.png)
|
||||||
|
|
||||||
### Staring commits
|
### Starring commits
|
||||||
to find specific commits much faster
|
to find specific commits much faster
|
||||||
![Staring commits](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/starring_commits.png)
|
![Starring commits](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/starring_commits.png)
|
||||||
|
|
||||||
### Tag selection
|
### Tag selection
|
||||||
Use an existing tag as template for your next tag. So you never have to look which is your latest tag
|
Use an existing tag as template for your next tag. So you never have to look which is your latest tag
|
||||||
@ -84,7 +103,7 @@ Use an existing tag as template for your next tag. So you never have to look whi
|
|||||||
![Tag selection](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/tag_selection.png)
|
![Tag selection](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/tag_selection.png)
|
||||||
|
|
||||||
### Commit message template
|
### Commit message template
|
||||||
Create you commit messages according a defined template
|
Create you commit messages according a defined template. The first template is automatically applied to the commit message editor.
|
||||||
|
|
||||||
![Commit message template selection](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/CommitMessageTemplateSelection.png)
|
![Commit message template selection](https://raw.githubusercontent.com/Murmele/Gittyup/master/rsrc/screenshots/CommitMessageTemplateSelection.png)
|
||||||
|
|
||||||
|
@ -14,10 +14,18 @@ set(LANGUAGES
|
|||||||
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
|
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
|
||||||
file(GLOB_RECURSE SOURCE_FILES ${SRC_DIR}/*.h ${SRC_DIR}/*.cpp ${SRC_DIR}/*.mm)
|
file(GLOB_RECURSE SOURCE_FILES ${SRC_DIR}/*.h ${SRC_DIR}/*.cpp ${SRC_DIR}/*.mm)
|
||||||
|
|
||||||
|
set(SYSTEM_LANG_KEY "System")
|
||||||
|
set(SUPPORTED_LANGUAGES "{\"${SYSTEM_LANG_KEY}\", \"${SYSTEM_LANG_KEY}\"},")
|
||||||
foreach(LANGUAGE ${LANGUAGES})
|
foreach(LANGUAGE ${LANGUAGES})
|
||||||
set(TS_FILES ${TS_FILES} gittyup_${LANGUAGE}.ts)
|
set(TS_FILES ${TS_FILES} gittyup_${LANGUAGE}.ts)
|
||||||
|
set(SUPPORTED_LANGUAGES
|
||||||
|
"${SUPPORTED_LANGUAGES} {\"${LANGUAGE}\", \"${LANGUAGE}\"},")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
set(LANGUAGE_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/languages.cpp")
|
||||||
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/languages.cpp.inc"
|
||||||
|
${LANGUAGE_SOURCE_FILE} @ONLY)
|
||||||
|
|
||||||
if(UPDATE_TRANSLATIONS)
|
if(UPDATE_TRANSLATIONS)
|
||||||
# FIXME: Clean removes the .ts files.
|
# FIXME: Clean removes the .ts files.
|
||||||
qt5_create_translation(QM_FILES ${SOURCE_FILES} ${TS_FILES})
|
qt5_create_translation(QM_FILES ${SOURCE_FILES} ${TS_FILES})
|
||||||
@ -28,12 +36,11 @@ endif()
|
|||||||
add_custom_target(translations DEPENDS ${QM_FILES})
|
add_custom_target(translations DEPENDS ${QM_FILES})
|
||||||
add_dependencies(gittyup translations)
|
add_dependencies(gittyup translations)
|
||||||
|
|
||||||
|
add_library(translation ${LANGUAGE_SOURCE_FILE})
|
||||||
|
target_include_directories(translation PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
target_link_libraries(translation Qt5::Core)
|
||||||
|
|
||||||
# install language files
|
# install language files
|
||||||
if(APPLE)
|
|
||||||
set(CONTENTS_DIR ${GITTYUP_NAME}.app/Contents)
|
|
||||||
elseif(UNIX)
|
|
||||||
set(CONTENTS_DIR ${CMAKE_INSTALL_DATADIR}/gittyup)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(LANGUAGE ${LANGUAGES})
|
foreach(LANGUAGE ${LANGUAGES})
|
||||||
set(QT_QM_FILES ${QT_QM_FILES} ${QT_TRANSLATIONS_DIR}/qtbase_${LANGUAGE}.qm)
|
set(QT_QM_FILES ${QT_QM_FILES} ${QT_TRANSLATIONS_DIR}/qtbase_${LANGUAGE}.qm)
|
||||||
@ -44,19 +51,22 @@ foreach(LANGUAGE ${LANGUAGES})
|
|||||||
TARGET translations
|
TARGET translations
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||||
${DIR}/${CONTENTS_DIR}/Resources/${LANGUAGE}.lproj)
|
${DIR}/${RESOURCES_DIR}/${LANGUAGE}.lproj)
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if(APPLE OR UNIX)
|
foreach(QM_FILE ${QT_QM_FILES})
|
||||||
set(RESOURCES_PREFIX ${CONTENTS_DIR}/)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(QM_FILE ${QM_FILES} ${QT_QM_FILES})
|
|
||||||
if(EXISTS ${QM_FILE})
|
if(EXISTS ${QM_FILE})
|
||||||
install(
|
install(
|
||||||
FILES ${QM_FILE}
|
FILES ${QM_FILE}
|
||||||
DESTINATION ${RESOURCES_PREFIX}Resources/l10n
|
DESTINATION ${L10N_INSTALL_DIR}
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
foreach(QM_FILE ${QM_FILES})
|
||||||
|
install(
|
||||||
|
FILES ${QM_FILE}
|
||||||
|
DESTINATION ${L10N_INSTALL_DIR}
|
||||||
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
endforeach()
|
||||||
|
3170
l10n/gittyup_de.ts
3170
l10n/gittyup_de.ts
File diff suppressed because it is too large
Load Diff
3230
l10n/gittyup_en.ts
3230
l10n/gittyup_en.ts
File diff suppressed because it is too large
Load Diff
3046
l10n/gittyup_es.ts
3046
l10n/gittyup_es.ts
File diff suppressed because it is too large
Load Diff
2960
l10n/gittyup_ja.ts
2960
l10n/gittyup_ja.ts
File diff suppressed because it is too large
Load Diff
2960
l10n/gittyup_pt.ts
2960
l10n/gittyup_pt.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3004
l10n/gittyup_ru.ts
3004
l10n/gittyup_ru.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
9
l10n/languages.cpp.inc
Normal file
9
l10n/languages.cpp.inc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "languages.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Languages {
|
||||||
|
const QString system = QStringLiteral("@SYSTEM_LANG_KEY@");
|
||||||
|
const QMap<const char*, const char*> languages = { @SUPPORTED_LANGUAGES@ };
|
||||||
|
}
|
11
l10n/languages.h
Normal file
11
l10n/languages.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef LANGUAGES_H
|
||||||
|
#define LANGUAGES_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
namespace Languages {
|
||||||
|
extern const QString system;
|
||||||
|
extern const QMap<const char *, const char *> languages;
|
||||||
|
} // namespace Languages
|
||||||
|
|
||||||
|
#endif // LANGUAGES_H
|
@ -2,7 +2,6 @@ set(CONF_DIR ${CMAKE_SOURCE_DIR}/conf)
|
|||||||
set(RSRC_DIR ${CMAKE_SOURCE_DIR}/rsrc)
|
set(RSRC_DIR ${CMAKE_SOURCE_DIR}/rsrc)
|
||||||
|
|
||||||
set(MAC $<PLATFORM_ID:Darwin>)
|
set(MAC $<PLATFORM_ID:Darwin>)
|
||||||
set(CONTENTS_DIR ${GITTYUP_NAME}.app/Contents)
|
|
||||||
|
|
||||||
# Install Qt plugins.
|
# Install Qt plugins.
|
||||||
set(QT_PLUGINS QJpegPlugin)
|
set(QT_PLUGINS QJpegPlugin)
|
||||||
@ -17,6 +16,14 @@ else()
|
|||||||
QComposePlatformInputContextPlugin)
|
QComposePlatformInputContextPlugin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(INSTALL_LIBDIR ${CMAKE_INSTALL_BINDIR})
|
||||||
|
elseif(NOT APPLE)
|
||||||
|
set(INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
else()
|
||||||
|
set(INSTALL_LIBDIR ${CONTENTS_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FLATPAK)
|
if(FLATPAK)
|
||||||
qt_import_plugins(gittyup INCLUDE ${QT_PLUGINS})
|
qt_import_plugins(gittyup INCLUDE ${QT_PLUGINS})
|
||||||
elseif(NOT USE_SYSTEM_QT)
|
elseif(NOT USE_SYSTEM_QT)
|
||||||
@ -35,7 +42,7 @@ elseif(NOT USE_SYSTEM_QT)
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${PLUGIN}
|
FILES ${PLUGIN}
|
||||||
DESTINATION $<${MAC}:${CONTENTS_DIR}/>Plugins/${DIR_NAME}
|
DESTINATION ${INSTALL_LIBDIR}/Plugins/${DIR_NAME}
|
||||||
PERMISSIONS
|
PERMISSIONS
|
||||||
OWNER_READ
|
OWNER_READ
|
||||||
OWNER_WRITE
|
OWNER_WRITE
|
||||||
@ -100,7 +107,7 @@ elseif(NOT USE_SYSTEM_QT)
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${QT_LIBRARY}
|
FILES ${QT_LIBRARY}
|
||||||
DESTINATION .
|
DESTINATION ${INSTALL_LIBDIR}
|
||||||
PERMISSIONS
|
PERMISSIONS
|
||||||
OWNER_READ
|
OWNER_READ
|
||||||
OWNER_WRITE
|
OWNER_WRITE
|
||||||
@ -131,7 +138,7 @@ if(UNIX AND NOT APPLE)
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES "${LIB_PATH}/${LIB_NAME}${LIB_EXT}"
|
FILES "${LIB_PATH}/${LIB_NAME}${LIB_EXT}"
|
||||||
DESTINATION .
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
PERMISSIONS
|
PERMISSIONS
|
||||||
OWNER_READ
|
OWNER_READ
|
||||||
OWNER_WRITE
|
OWNER_WRITE
|
||||||
@ -166,7 +173,7 @@ if(NOT APPLE)
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${SSL_LIB}
|
FILES ${SSL_LIB}
|
||||||
DESTINATION .
|
DESTINATION ${INSTALL_LIBDIR}
|
||||||
PERMISSIONS
|
PERMISSIONS
|
||||||
OWNER_READ
|
OWNER_READ
|
||||||
OWNER_WRITE
|
OWNER_WRITE
|
||||||
@ -186,16 +193,25 @@ if(NOT APPLE)
|
|||||||
set(QT_CONF ${CONF_DIR}/qt.conf)
|
set(QT_CONF ${CONF_DIR}/qt.conf)
|
||||||
install(
|
install(
|
||||||
FILES ${QT_CONF}
|
FILES ${QT_CONF}
|
||||||
DESTINATION $<${MAC}:${CONTENTS_DIR}/Resources/>.
|
DESTINATION
|
||||||
|
$<${MAC}:${RESOURCES_DIR}>$<$<PLATFORM_ID:Windows>:${INSTALL_LIBDIR}>
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
foreach(icon 16 32 64 128 256 512)
|
||||||
|
install(
|
||||||
|
FILES ${RSRC_DIR}/Gittyup.iconset/icon_${icon}x${icon}.png
|
||||||
|
DESTINATION share/icons/hicolor/${icon}x${icon}/apps
|
||||||
|
COMPONENT ${GITTYUP_NAME}
|
||||||
|
RENAME ${GITTYUP_EXECUTABLE_NAME}.png)
|
||||||
|
endforeach()
|
||||||
install(
|
install(
|
||||||
DIRECTORY ${RSRC_DIR}/Gittyup.iconset
|
FILES ${RSRC_DIR}/Gittyup.iconset/gittyup_logo.svg
|
||||||
DESTINATION "Resources"
|
DESTINATION share/icons/hicolor/scalable/apps
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME}
|
||||||
|
RENAME ${GITTYUP_EXECUTABLE_NAME}.svg)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Sign bundle on macOS.
|
# Sign bundle on macOS.
|
||||||
@ -204,7 +220,7 @@ if(APPLE AND CODESIGN_IDENTITY)
|
|||||||
CODE "execute_process(COMMAND
|
CODE "execute_process(COMMAND
|
||||||
codesign --deep --timestamp --options runtime
|
codesign --deep --timestamp --options runtime
|
||||||
-s \"${CODESIGN_IDENTITY}\"
|
-s \"${CODESIGN_IDENTITY}\"
|
||||||
\${CMAKE_INSTALL_PREFIX}/${GITTYUP_NAME}.app
|
\${CMAKE_INSTALL_PREFIX}/${GITTYUP_EXECUTABLE_NAME}.app
|
||||||
)"
|
)"
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
endif()
|
endif()
|
||||||
@ -220,9 +236,10 @@ elseif(WIN32)
|
|||||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||||
"CreateShortCut \
|
"CreateShortCut \
|
||||||
\\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${GITTYUP_NAME}.lnk\\\" \
|
\\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${GITTYUP_NAME}.lnk\\\" \
|
||||||
\\\"$INSTDIR\\\\${GITTYUP_NAME}.exe\\\"")
|
\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\""
|
||||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
)
|
||||||
set(CPACK_NSIS_MUI_FINISHPAGE_RUN ${GITTYUP_NAME}.exe)
|
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ${CMAKE_INSTALL_BINDIR})
|
||||||
|
set(CPACK_NSIS_MUI_FINISHPAGE_RUN ${GITTYUP_EXECUTABLE_NAME}.exe)
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
install(
|
install(
|
||||||
@ -262,11 +279,11 @@ if(WIN32)
|
|||||||
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
|
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
|
||||||
"${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
|
"${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
|
||||||
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup' '' 'Open with Gittyup'
|
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup' '' 'Open with Gittyup'
|
||||||
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup' 'Icon' '\\\"$INSTDIR\\\\gittyup.exe\\\"'
|
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup' 'Icon' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\"'
|
||||||
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\gittyup.exe\\\" \\\"%V\\\"'
|
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\" \\\"%V\\\"'
|
||||||
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup' '' 'Open with Gittyup'
|
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup' '' 'Open with Gittyup'
|
||||||
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup' 'Icon' '\\\"$INSTDIR\\\\gittyup.exe\\\"'
|
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup' 'Icon' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\"'
|
||||||
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\gittyup.exe\\\" \\\"%L\\\"'"
|
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\" \\\"%L\\\"'"
|
||||||
)
|
)
|
||||||
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
|
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
|
||||||
"${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
|
"${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
|
||||||
@ -277,13 +294,18 @@ endif(WIN32)
|
|||||||
set(CPACK_PACKAGE_FILE_NAME ${PACKAGE_FILE_NAME})
|
set(CPACK_PACKAGE_FILE_NAME ${PACKAGE_FILE_NAME})
|
||||||
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/pack)
|
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/pack)
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${GITTYUP_NAME})
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${GITTYUP_NAME})
|
||||||
set(CPACK_PACKAGE_VENDOR "Scientific Toolworks, Inc.")
|
set(CPACK_PACKAGE_VENDOR "Gittyup Contributors")
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${GITTYUP_VERSION_MAJOR})
|
set(CPACK_PACKAGE_VERSION_MAJOR ${GITTYUP_VERSION_MAJOR})
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${GITTYUP_VERSION_MINOR})
|
set(CPACK_PACKAGE_VERSION_MINOR ${GITTYUP_VERSION_MINOR})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${GITTYUP_VERSION_PATCH})
|
set(CPACK_PACKAGE_VERSION_PATCH ${GITTYUP_VERSION_PATCH})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.md)
|
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.md)
|
||||||
|
else()
|
||||||
|
install(
|
||||||
|
FILES ${CMAKE_SOURCE_DIR}/LICENSE.md
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/Gittyup
|
||||||
|
RENAME LICENSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
Flatpak manifest can be found at: https://github.com/flathub/com.github.Murmele.Gittyup
|
Flatpak manifest can be found at: https://github.com/flathub/com.github.Murmele.Gittyup
|
||||||
Arch PKGBUILD file can be found at: TODO (currently it is in #314)
|
Arch PKGBUILD file can be found at: TODO (currently it is in #314)
|
||||||
|
Linux (Tested On Ubuntu 22.04LTS) version is available in the buildUbuntu.sh file included in this directory.
|
||||||
|
26
pack/buildUbuntu.sh
Executable file
26
pack/buildUbuntu.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
sudo apt install build-essential libgl1-mesa-dev
|
||||||
|
sudo apt install cmake
|
||||||
|
sudo apt install libgit2-dev
|
||||||
|
sudo apt install cmark
|
||||||
|
sudo apt install git
|
||||||
|
sudo apt install libssh2-1-dev
|
||||||
|
sudo apt install openssl
|
||||||
|
sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools
|
||||||
|
sudo apt install qttools5-dev
|
||||||
|
sudo apt install ninja-build
|
||||||
|
cd ../../..
|
||||||
|
git fetch
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
git pull
|
||||||
|
git checkout deps
|
||||||
|
cd dep/openssl/openssl/
|
||||||
|
./config -fPIC
|
||||||
|
make
|
||||||
|
cd
|
||||||
|
mkdir -vp build/release
|
||||||
|
cd build/release
|
||||||
|
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../..
|
||||||
|
ninja
|
||||||
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
|||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleLongVersionString</key>
|
<key>CFBundleLongVersionString</key>
|
||||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
|
72
rsrc/github-repository-open-graph-Gittyup.png.xmp
Normal file
72
rsrc/github-repository-open-graph-Gittyup.png.xmp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
|
||||||
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:exif="http://ns.adobe.com/exif/1.0/"
|
||||||
|
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
|
||||||
|
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
|
||||||
|
xmlns:darktable="http://darktable.sf.net/"
|
||||||
|
exif:DateTimeOriginal=""
|
||||||
|
xmp:Rating="1"
|
||||||
|
xmpMM:DerivedFrom="github-repository-open-graph-Gittyup.png"
|
||||||
|
darktable:import_timestamp="63810317507625743"
|
||||||
|
darktable:change_timestamp="-1"
|
||||||
|
darktable:export_timestamp="-1"
|
||||||
|
darktable:print_timestamp="-1"
|
||||||
|
darktable:xmp_version="5"
|
||||||
|
darktable:raw_params="0"
|
||||||
|
darktable:auto_presets_applied="1"
|
||||||
|
darktable:history_end="4"
|
||||||
|
darktable:iop_order_version="2"
|
||||||
|
darktable:history_basic_hash="adf93e2c7aefb698a6ff153e3fa7f0b8"
|
||||||
|
darktable:history_current_hash="adf93e2c7aefb698a6ff153e3fa7f0b8">
|
||||||
|
<darktable:masks_history>
|
||||||
|
<rdf:Seq/>
|
||||||
|
</darktable:masks_history>
|
||||||
|
<darktable:history>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li
|
||||||
|
darktable:num="0"
|
||||||
|
darktable:operation="colorin"
|
||||||
|
darktable:enabled="1"
|
||||||
|
darktable:modversion="7"
|
||||||
|
darktable:params="gz48eJzjZBgFowABWAbaAaNgwAEAMNgADg=="
|
||||||
|
darktable:multi_name=""
|
||||||
|
darktable:multi_priority="0"
|
||||||
|
darktable:blendop_version="11"
|
||||||
|
darktable:blendop_params="gz14eJxjYIAACQYYOOHEgAZY0QVwggZ7CB6pfNoAAE8gGQg="/>
|
||||||
|
<rdf:li
|
||||||
|
darktable:num="1"
|
||||||
|
darktable:operation="colorout"
|
||||||
|
darktable:enabled="1"
|
||||||
|
darktable:modversion="5"
|
||||||
|
darktable:params="gz35eJxjZBgFo4CBAQAEEAAC"
|
||||||
|
darktable:multi_name=""
|
||||||
|
darktable:multi_priority="0"
|
||||||
|
darktable:blendop_version="11"
|
||||||
|
darktable:blendop_params="gz14eJxjYIAACQYYOOHEgAZY0QVwggZ7CB6pfNoAAE8gGQg="/>
|
||||||
|
<rdf:li
|
||||||
|
darktable:num="2"
|
||||||
|
darktable:operation="gamma"
|
||||||
|
darktable:enabled="1"
|
||||||
|
darktable:modversion="1"
|
||||||
|
darktable:params="0000000000000000"
|
||||||
|
darktable:multi_name=""
|
||||||
|
darktable:multi_priority="0"
|
||||||
|
darktable:blendop_version="11"
|
||||||
|
darktable:blendop_params="gz14eJxjYIAACQYYOOHEgAZY0QVwggZ7CB6pfNoAAE8gGQg="/>
|
||||||
|
<rdf:li
|
||||||
|
darktable:num="3"
|
||||||
|
darktable:operation="flip"
|
||||||
|
darktable:enabled="1"
|
||||||
|
darktable:modversion="2"
|
||||||
|
darktable:params="ffffffff"
|
||||||
|
darktable:multi_name=""
|
||||||
|
darktable:multi_priority="0"
|
||||||
|
darktable:blendop_version="11"
|
||||||
|
darktable:blendop_params="gz14eJxjYIAACQYYOOHEgAZY0QVwggZ7CB6pfNoAAE8gGQg="/>
|
||||||
|
</rdf:Seq>
|
||||||
|
</darktable:history>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</x:xmpmeta>
|
@ -45,7 +45,7 @@
|
|||||||
<url type="donation">https://liberapay.com/Gittyup/donate</url>
|
<url type="donation">https://liberapay.com/Gittyup/donate</url>
|
||||||
|
|
||||||
<provides>
|
<provides>
|
||||||
<binary>Gittyup</binary>
|
<binary>gittyup</binary>
|
||||||
<id>com.github.Murmele.Gittyup</id>
|
<id>com.github.Murmele.Gittyup</id>
|
||||||
</provides>
|
</provides>
|
||||||
|
|
||||||
|
@ -2,11 +2,10 @@
|
|||||||
Encoding=UTF-8
|
Encoding=UTF-8
|
||||||
Name=Gittyup
|
Name=Gittyup
|
||||||
Comment=Graphical Git client for Windows, Linux and macOS
|
Comment=Graphical Git client for Windows, Linux and macOS
|
||||||
Exec=Gittyup
|
Exec=gittyup
|
||||||
StartupWMClass=gittyup
|
StartupWMClass=com.github.Murmele.Gittyup
|
||||||
Icon=gittyup
|
Icon=gittyup
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Development;
|
Categories=Development;
|
||||||
X-Desktop-File-Install-Version=0.1
|
X-Desktop-File-Install-Version=0.1
|
||||||
Name[de_DE]=com.github.Murmele.Gittyup.desktop
|
|
||||||
|
BIN
rsrc/screenshots/ColorizedBadges.png
Normal file
BIN
rsrc/screenshots/ColorizedBadges.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
44
setup-env.sh
Executable file
44
setup-env.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
cd "`dirname "$0"`"
|
||||||
|
|
||||||
|
PRE_COMMIT=${SCRIPT_DIR}/.venv/bin/pre-commit
|
||||||
|
|
||||||
|
pre_commit() {
|
||||||
|
# Set up pre-commit hook
|
||||||
|
if [ ! -f "${PRE_COMMIT}" ]; then
|
||||||
|
pushd ${SCRIPT_DIR}
|
||||||
|
python3 -m venv .venv
|
||||||
|
.venv/bin/pip install pre-commit
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
${PRE_COMMIT} install
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_pre_commt() {
|
||||||
|
if [ -f "${PRE_COMMIT}" ]; then
|
||||||
|
${PRE_COMMIT} uninstall
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
set -- --help
|
||||||
|
fi
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
pre_commit | pre-commit | install_pre_commit | install-pre-commit)
|
||||||
|
pre_commit
|
||||||
|
;;
|
||||||
|
remove_pre_commit | remove-pre-commit | uninstall_pre_commit | uninstall-pre-commit)
|
||||||
|
remove_pre_commit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "USAGE $0 [commands]"
|
||||||
|
echo " Commands:"
|
||||||
|
echo " install-pre-commit - installs pre-commit hooks"
|
||||||
|
echo " uninstall-pre-commit - removes pre-commit hooks"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
@ -1,5 +1,13 @@
|
|||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
add_compile_options(-Werror=switch)
|
||||||
|
# Uncomment to compile with more warnings add_compile_options(-Wall) Uncomment
|
||||||
|
# to compile with even more warnings add_compile_options(-Wextra) TODO:
|
||||||
|
# currently there are too many unused parameters which overwhelms the warning
|
||||||
|
# output with `-Wall`. So let's leave fixing these for later.
|
||||||
|
add_compile_options(-Wno-unused-parameter)
|
||||||
|
|
||||||
|
add_subdirectory(util)
|
||||||
add_subdirectory(cli)
|
add_subdirectory(cli)
|
||||||
add_subdirectory(conf)
|
add_subdirectory(conf)
|
||||||
add_subdirectory(cred)
|
add_subdirectory(cred)
|
||||||
@ -13,7 +21,6 @@ add_subdirectory(plugins)
|
|||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
add_subdirectory(ui)
|
add_subdirectory(ui)
|
||||||
add_subdirectory(update)
|
add_subdirectory(update)
|
||||||
add_subdirectory(util)
|
|
||||||
add_subdirectory(watcher)
|
add_subdirectory(watcher)
|
||||||
|
|
||||||
# Add executable last.
|
# Add executable last.
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
#include "ui/RepoView.h"
|
#include "ui/RepoView.h"
|
||||||
#include "ui/TabWidget.h"
|
#include "ui/TabWidget.h"
|
||||||
#include "update/Updater.h"
|
#include "update/Updater.h"
|
||||||
|
#include "languages.h"
|
||||||
|
#include "util/Debug.h"
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
@ -132,6 +134,18 @@ Application::Application(int &argc, char **argv, bool haltOnParseError)
|
|||||||
// Set debug menu option.
|
// Set debug menu option.
|
||||||
MenuBar::setDebugMenuVisible(parser.isSet("debug-menu"));
|
MenuBar::setDebugMenuVisible(parser.isSet("debug-menu"));
|
||||||
|
|
||||||
|
Debug(QString("Root dir: %1").arg(Settings::rootDir().absolutePath()));
|
||||||
|
Debug(QString("App dir: %1").arg(Settings::appDir().absolutePath()));
|
||||||
|
Debug(QString("Doc dir: %1").arg(Settings::docDir().absolutePath()));
|
||||||
|
Debug(QString("Conf dir: %1").arg(Settings::confDir().absolutePath()));
|
||||||
|
Debug(QString("l10n dir: %1").arg(Settings::l10nDir().absolutePath()));
|
||||||
|
Debug(QString("dictionaries dir: %1")
|
||||||
|
.arg(Settings::dictionariesDir().absolutePath()));
|
||||||
|
Debug(QString("lexer dir: %1").arg(Settings::lexerDir().absolutePath()));
|
||||||
|
Debug(QString("themes dir: %1").arg(Settings::themesDir().absolutePath()));
|
||||||
|
Debug(
|
||||||
|
QString("pluginsDir dir: %1").arg(Settings::pluginsDir().absolutePath()));
|
||||||
|
|
||||||
// Set pathspec filter.
|
// Set pathspec filter.
|
||||||
mPathspec = parser.value("filter");
|
mPathspec = parser.value("filter");
|
||||||
|
|
||||||
@ -159,6 +173,12 @@ Application::Application(int &argc, char **argv, bool haltOnParseError)
|
|||||||
.toBool()) &&
|
.toBool()) &&
|
||||||
(!parser.isSet("no-translation"))) {
|
(!parser.isSet("no-translation"))) {
|
||||||
// Load translation files.
|
// Load translation files.
|
||||||
|
|
||||||
|
const auto &language =
|
||||||
|
Settings::instance()->value(Setting::Id::Language).toString();
|
||||||
|
if (language != Languages::system)
|
||||||
|
QLocale::setDefault(QLocale(language));
|
||||||
|
|
||||||
QLocale locale;
|
QLocale locale;
|
||||||
QDir l10n = Settings::l10nDir();
|
QDir l10n = Settings::l10nDir();
|
||||||
QString name = QString(GITTYUP_NAME).toLower();
|
QString name = QString(GITTYUP_NAME).toLower();
|
||||||
@ -310,9 +330,9 @@ static MainWindow *openOrSwitch(QDir repo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
#define DBUS_SERVICE_NAME "com.github.Murmele.Gittyup"
|
#define DBUS_SERVICE_NAME GITTYUP_IDENTIFIER
|
||||||
#define DBUS_INTERFACE_NAME "com.github.Murmele.Gittyup.Application"
|
#define DBUS_INTERFACE_NAME GITTYUP_DBUS_INTERFACE_NAME
|
||||||
#define DBUS_OBJECT_PATH "/com/github/Murmele/Gittyup/Application"
|
#define DBUS_OBJECT_PATH GITTYUP_DBUS_OBJECT_PATH
|
||||||
|
|
||||||
DBusGittyup::DBusGittyup(QObject *parent) : QObject(parent) {}
|
DBusGittyup::DBusGittyup(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
@ -488,4 +508,4 @@ void Application::handleSslErrors(QNetworkReply *reply,
|
|||||||
reply->ignoreSslErrors(errors);
|
reply->ignoreSslErrors(errors);
|
||||||
settings.setValue("ssl/ignore", true);
|
settings.setValue("ssl/ignore", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ file(GLOB CONFIG_FILES ${CONF_DIR}/*.lua)
|
|||||||
file(GLOB DICTIONARIES ${CONF_DIR}/dictionaries/*.aff
|
file(GLOB DICTIONARIES ${CONF_DIR}/dictionaries/*.aff
|
||||||
${CONF_DIR}/dictionaries/*.dic ${CONF_DIR}/dictionaries/*.txt)
|
${CONF_DIR}/dictionaries/*.dic ${CONF_DIR}/dictionaries/*.txt)
|
||||||
file(GLOB THEMES ${CONF_DIR}/themes/*.lua)
|
file(GLOB THEMES ${CONF_DIR}/themes/*.lua)
|
||||||
file(GLOB SCINTILLUA_LEXERS ${SCINTILLUA_LEXERS_DIR}/*.lua)
|
file(GLOB SCINTILLUA_LEXERS ${SRC_SCINTILLUA_LEXERS_DIR}/*.lua)
|
||||||
file(GLOB LUA_PLUGINS ${CONF_DIR}/plugins/*.lua ${CONF_DIR}/plugins/*.txt)
|
file(GLOB LUA_PLUGINS ${CONF_DIR}/plugins/*.lua ${CONF_DIR}/plugins/*.txt)
|
||||||
|
|
||||||
# Build resources.
|
# Build resources.
|
||||||
@ -59,11 +59,22 @@ endif()
|
|||||||
|
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
app
|
app
|
||||||
PUBLIC GITTYUP_NAME="${GITTYUP_NAME}" GITTYUP_VERSION="${GITTYUP_VERSION}"
|
PUBLIC GITTYUP_NAME="${GITTYUP_NAME}"
|
||||||
|
GITTYUP_VERSION="${GITTYUP_VERSION}"
|
||||||
|
GITTYUP_IDENTIFIER="${GITTYUP_IDENTIFIER}"
|
||||||
|
GITTYUP_DBUS_INTERFACE_NAME="${GITTYUP_IDENTIFIER}.Application"
|
||||||
|
GITTYUP_DBUS_OBJECT_PATH="/com/github/Murmele/Gittyup/Application"
|
||||||
PRIVATE QT_TRANSLATIONS_DIR="${QT_TRANSLATIONS_DIR}"
|
PRIVATE QT_TRANSLATIONS_DIR="${QT_TRANSLATIONS_DIR}"
|
||||||
BUILD_DESCRIPTION="${BUILD_DESCRIPTION}")
|
BUILD_DESCRIPTION="${BUILD_DESCRIPTION}")
|
||||||
|
|
||||||
target_link_libraries(app conf git ui update Qt5::Widgets)
|
target_link_libraries(
|
||||||
|
app
|
||||||
|
translation
|
||||||
|
conf
|
||||||
|
git
|
||||||
|
ui
|
||||||
|
update
|
||||||
|
Qt5::Widgets)
|
||||||
|
|
||||||
set_target_properties(app PROPERTIES AUTOMOC ON)
|
set_target_properties(app PROPERTIES AUTOMOC ON)
|
||||||
|
|
||||||
@ -103,8 +114,10 @@ endif()
|
|||||||
target_link_libraries(gittyup app)
|
target_link_libraries(gittyup app)
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
gittyup PROPERTIES OUTPUT_NAME ${GITTYUP_NAME} RUNTIME_OUTPUT_DIRECTORY
|
gittyup
|
||||||
${CMAKE_BINARY_DIR})
|
PROPERTIES OUTPUT_NAME ${GITTYUP_EXECUTABLE_NAME}
|
||||||
|
MACOSX_BUNDLE_BUNDLE_NAME ${GITTYUP_NAME}
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(app Dbghelp.lib)
|
target_link_libraries(app Dbghelp.lib)
|
||||||
@ -118,7 +131,7 @@ elseif(APPLE)
|
|||||||
MACOSX_BUNDLE_BUNDLE_VERSION ${GITTYUP_VERSION}
|
MACOSX_BUNDLE_BUNDLE_VERSION ${GITTYUP_VERSION}
|
||||||
MACOSX_BUNDLE_LONG_VERSION_STRING ${GITTYUP_VERSION}
|
MACOSX_BUNDLE_LONG_VERSION_STRING ${GITTYUP_VERSION}
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GITTYUP_VERSION}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GITTYUP_VERSION}
|
||||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.Murmele.Gittyup")
|
MACOSX_BUNDLE_GUI_IDENTIFIER ${GITTYUP_IDENTIFIER})
|
||||||
|
|
||||||
# Copy config files into bundle.
|
# Copy config files into bundle.
|
||||||
set_source_files_properties(
|
set_source_files_properties(
|
||||||
@ -152,19 +165,10 @@ endif()
|
|||||||
|
|
||||||
add_dependencies(gittyup indexer relauncher)
|
add_dependencies(gittyup indexer relauncher)
|
||||||
|
|
||||||
if(FLATPAK)
|
install(
|
||||||
# Install application.
|
TARGETS gittyup
|
||||||
install(
|
DESTINATION $<IF:$<PLATFORM_ID:Darwin>,.,${CMAKE_INSTALL_BINDIR}>
|
||||||
TARGETS gittyup
|
COMPONENT ${GITTYUP_NAME})
|
||||||
DESTINATION ./bin # otherwise the executable will not be found by flatpak
|
|
||||||
COMPONENT ${GITTYUP_NAME})
|
|
||||||
else()
|
|
||||||
# Install application.
|
|
||||||
install(
|
|
||||||
TARGETS gittyup
|
|
||||||
DESTINATION .
|
|
||||||
COMPONENT ${GITTYUP_NAME})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
get_target_property(QT_LIBRARY Qt5::Core LOCATION)
|
get_target_property(QT_LIBRARY Qt5::Core LOCATION)
|
||||||
@ -172,7 +176,7 @@ if(APPLE)
|
|||||||
get_filename_component(RPATH ${QT_FRAMEWORK} DIRECTORY)
|
get_filename_component(RPATH ${QT_FRAMEWORK} DIRECTORY)
|
||||||
|
|
||||||
# Fixup relauncher RPATH.
|
# Fixup relauncher RPATH.
|
||||||
set(RELAUNCHER ${GITTYUP_NAME}.app/Contents/MacOS/relauncher)
|
set(RELAUNCHER ${CONTENTS_DIR}/MacOS/relauncher)
|
||||||
install(
|
install(
|
||||||
CODE "execute_process(COMMAND
|
CODE "execute_process(COMMAND
|
||||||
${CMAKE_INSTALL_NAME_TOOL} -delete_rpath \"${RPATH}\"
|
${CMAKE_INSTALL_NAME_TOOL} -delete_rpath \"${RPATH}\"
|
||||||
@ -189,7 +193,7 @@ execute_process(COMMAND
|
|||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
# Fixup indexer RPATH.
|
# Fixup indexer RPATH.
|
||||||
set(INDEXER ${GITTYUP_NAME}.app/Contents/MacOS/indexer)
|
set(INDEXER ${CONTENTS_DIR}/MacOS/indexer)
|
||||||
install(
|
install(
|
||||||
CODE "execute_process(COMMAND
|
CODE "execute_process(COMMAND
|
||||||
${CMAKE_INSTALL_NAME_TOOL} -delete_rpath \"${RPATH}\"
|
${CMAKE_INSTALL_NAME_TOOL} -delete_rpath \"${RPATH}\"
|
||||||
@ -207,13 +211,16 @@ execute_process(COMMAND
|
|||||||
else()
|
else()
|
||||||
# Windows and UNIX must be ./ otherwise it is interpreted as absolute path
|
# Windows and UNIX must be ./ otherwise it is interpreted as absolute path
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
set(RESOURCES_INSTALL_DIR
|
install(
|
||||||
"${CMAKE_INSTALL_DATADIR}/gittyup/Resources"
|
FILES ${CMAKE_SOURCE_DIR}/rsrc/linux/com.github.Murmele.Gittyup.desktop
|
||||||
CACHE STRING "The path for installing resource files")
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
||||||
else()
|
RENAME ${GITTYUP_EXECUTABLE_NAME}.desktop)
|
||||||
set(RESOURCES_INSTALL_DIR
|
if(${GENERATE_APPDATA})
|
||||||
"Resources"
|
install(
|
||||||
CACHE STRING "The path for installing resource files")
|
FILES ${APPDATA}
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo
|
||||||
|
RENAME ${GITTYUP_EXECUTABLE_NAME}.appdata.xml)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Install config files.
|
# Install config files.
|
||||||
@ -224,13 +231,13 @@ else()
|
|||||||
install(
|
install(
|
||||||
FILES ${CHANGELOG_HTML} ${ACKNOWLEDGMENTS_HTML} ${PRIVACY_HTML}
|
FILES ${CHANGELOG_HTML} ${ACKNOWLEDGMENTS_HTML} ${PRIVACY_HTML}
|
||||||
${PLUGIN_HTML}
|
${PLUGIN_HTML}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}
|
DESTINATION ${RESOURCES_DIR}
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${EMOJI} ${MERGETOOLS}
|
FILES ${EMOJI} ${MERGETOOLS}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}
|
DESTINATION ${RESOURCES_DIR}
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EMOJI}
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EMOJI}
|
||||||
@ -241,7 +248,7 @@ else()
|
|||||||
foreach(CONFIG_FILE ${CONFIG_FILES})
|
foreach(CONFIG_FILE ${CONFIG_FILES})
|
||||||
install(
|
install(
|
||||||
FILES ${CONFIG_FILE}
|
FILES ${CONFIG_FILE}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}
|
DESTINATION ${RESOURCES_DIR}
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
file(RELATIVE_PATH CONFIG_FILE_DEST ${CONF_DIR} ${CONFIG_FILE})
|
file(RELATIVE_PATH CONFIG_FILE_DEST ${CONF_DIR} ${CONFIG_FILE})
|
||||||
@ -252,7 +259,7 @@ else()
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${DICTIONARIES}
|
FILES ${DICTIONARIES}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}/dictionaries
|
DESTINATION ${RESOURCES_DIR}/dictionaries
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
foreach(DICTIONARY ${DICTIONARIES})
|
foreach(DICTIONARY ${DICTIONARIES})
|
||||||
@ -263,7 +270,7 @@ else()
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${THEMES}
|
FILES ${THEMES}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}/themes
|
DESTINATION ${RESOURCES_DIR}/themes
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
foreach(THEME ${THEMES})
|
foreach(THEME ${THEMES})
|
||||||
@ -274,7 +281,7 @@ else()
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${LUA_PLUGINS}
|
FILES ${LUA_PLUGINS}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}/plugins
|
DESTINATION ${RESOURCES_DIR}/plugins
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
foreach(LUA_PLUGIN ${LUA_PLUGINS})
|
foreach(LUA_PLUGIN ${LUA_PLUGINS})
|
||||||
@ -286,7 +293,7 @@ else()
|
|||||||
foreach(SCINTILLUA_LEXER ${SCINTILLUA_LEXERS})
|
foreach(SCINTILLUA_LEXER ${SCINTILLUA_LEXERS})
|
||||||
install(
|
install(
|
||||||
FILES ${SCINTILLUA_LEXER}
|
FILES ${SCINTILLUA_LEXER}
|
||||||
DESTINATION ${RESOURCES_INSTALL_DIR}/lexers
|
DESTINATION ${RESOURCES_DIR}/lexers
|
||||||
COMPONENT ${GITTYUP_NAME})
|
COMPONENT ${GITTYUP_NAME})
|
||||||
|
|
||||||
get_filename_component(SCINTILLUA_LEXER_DEST ${SCINTILLUA_LEXER} NAME)
|
get_filename_component(SCINTILLUA_LEXER_DEST ${SCINTILLUA_LEXER} NAME)
|
||||||
|
@ -354,6 +354,21 @@ QColor CustomTheme::badge(BadgeRole role, BadgeState state) {
|
|||||||
case BadgeState::Notification:
|
case BadgeState::Notification:
|
||||||
stateKey = "notification";
|
stateKey = "notification";
|
||||||
break;
|
break;
|
||||||
|
case BadgeState::Modified:
|
||||||
|
stateKey = "modified";
|
||||||
|
break;
|
||||||
|
case BadgeState::Added:
|
||||||
|
stateKey = "added";
|
||||||
|
break;
|
||||||
|
case BadgeState::Deleted:
|
||||||
|
stateKey = "deleted";
|
||||||
|
break;
|
||||||
|
case BadgeState::Untracked:
|
||||||
|
stateKey = "untracked";
|
||||||
|
break;
|
||||||
|
case BadgeState::Renamed:
|
||||||
|
stateKey = "renamed";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap badge = mMap.value("badge").toMap();
|
QVariantMap badge = mMap.value("badge").toMap();
|
||||||
@ -421,6 +436,8 @@ QColor CustomTheme::commitEditor(CommitEditor color) {
|
|||||||
case CommitEditor::LengthWarning:
|
case CommitEditor::LengthWarning:
|
||||||
return commitEditor.value("lengthwarning").value<QColor>();
|
return commitEditor.value("lengthwarning").value<QColor>();
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor CustomTheme::diff(Diff color) {
|
QColor CustomTheme::diff(Diff color) {
|
||||||
@ -450,6 +467,8 @@ QColor CustomTheme::diff(Diff color) {
|
|||||||
case Diff::Error:
|
case Diff::Error:
|
||||||
return diff.value("error").value<QColor>();
|
return diff.value("error").value<QColor>();
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor CustomTheme::heatMap(HeatMap color) {
|
QColor CustomTheme::heatMap(HeatMap color) {
|
||||||
@ -461,6 +480,8 @@ QColor CustomTheme::heatMap(HeatMap color) {
|
|||||||
case HeatMap::Cold:
|
case HeatMap::Cold:
|
||||||
return QColor(heatmap.value("cold").toString());
|
return QColor(heatmap.value("cold").toString());
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor CustomTheme::remoteComment(Comment color) {
|
QColor CustomTheme::remoteComment(Comment color) {
|
||||||
@ -476,6 +497,8 @@ QColor CustomTheme::remoteComment(Comment color) {
|
|||||||
case Comment::Timestamp:
|
case Comment::Timestamp:
|
||||||
return QColor(comment.value("timestamp").toString());
|
return QColor(comment.value("timestamp").toString());
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor CustomTheme::star() {
|
QColor CustomTheme::star() {
|
||||||
|
@ -101,7 +101,14 @@ QColor Theme::badge(BadgeRole role, BadgeState state) {
|
|||||||
case BadgeState::Head:
|
case BadgeState::Head:
|
||||||
return QPalette().color(QPalette::HighlightedText);
|
return QPalette().color(QPalette::HighlightedText);
|
||||||
|
|
||||||
default:
|
case BadgeState::Normal: // fall through
|
||||||
|
case BadgeState::Conflicted: // fall through
|
||||||
|
case BadgeState::Notification: // fall through
|
||||||
|
case BadgeState::Modified: // fall through
|
||||||
|
case BadgeState::Added: // fall through
|
||||||
|
case BadgeState::Deleted: // fall through
|
||||||
|
case BadgeState::Untracked: // fall through
|
||||||
|
case BadgeState::Renamed: // fall through
|
||||||
return QPalette().color(QPalette::WindowText);
|
return QPalette().color(QPalette::WindowText);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +130,20 @@ QColor Theme::badge(BadgeRole role, BadgeState state) {
|
|||||||
|
|
||||||
case BadgeState::Notification:
|
case BadgeState::Notification:
|
||||||
return mDark ? "#8C2026" : "#FF0000";
|
return mDark ? "#8C2026" : "#FF0000";
|
||||||
|
case BadgeState::Modified:
|
||||||
|
return mDark ? "#91973A" : "#FFEEDB";
|
||||||
|
case BadgeState::Added:
|
||||||
|
return mDark ? "#394734" : "#DCFFDC";
|
||||||
|
case BadgeState::Deleted:
|
||||||
|
return mDark ? "#5E3638" : "#FFDCDC";
|
||||||
|
case BadgeState::Untracked:
|
||||||
|
return mDark ? "#2A4944" : "#C7FFF6";
|
||||||
|
case BadgeState::Renamed:
|
||||||
|
return mDark ? "#23455E" : "#D2E8FC";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(false);
|
||||||
|
return QStringLiteral("");
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QColor> Theme::branchTopologyEdges() {
|
QList<QColor> Theme::branchTopologyEdges() {
|
||||||
@ -152,6 +171,8 @@ QColor Theme::commitEditor(CommitEditor color) {
|
|||||||
case CommitEditor::LengthWarning:
|
case CommitEditor::LengthWarning:
|
||||||
return Qt::yellow;
|
return Qt::yellow;
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Theme::diff(Diff color) {
|
QColor Theme::diff(Diff color) {
|
||||||
@ -180,6 +201,8 @@ QColor Theme::diff(Diff color) {
|
|||||||
case Diff::Error:
|
case Diff::Error:
|
||||||
return "#7E494B";
|
return "#7E494B";
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (color) {
|
switch (color) {
|
||||||
@ -206,6 +229,8 @@ QColor Theme::diff(Diff color) {
|
|||||||
case Diff::Error:
|
case Diff::Error:
|
||||||
return "#FF0000";
|
return "#FF0000";
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Theme::heatMap(HeatMap color) {
|
QColor Theme::heatMap(HeatMap color) {
|
||||||
@ -216,6 +241,8 @@ QColor Theme::heatMap(HeatMap color) {
|
|||||||
return mDark ? QPalette().color(QPalette::Inactive, QPalette::Highlight)
|
return mDark ? QPalette().color(QPalette::Inactive, QPalette::Highlight)
|
||||||
: QPalette().color(QPalette::Mid);
|
: QPalette().color(QPalette::Mid);
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Theme::remoteComment(Comment color) {
|
QColor Theme::remoteComment(Comment color) {
|
||||||
@ -229,6 +256,8 @@ QColor Theme::remoteComment(Comment color) {
|
|||||||
case Comment::Timestamp:
|
case Comment::Timestamp:
|
||||||
return QPalette().color(QPalette::WindowText);
|
return QPalette().color(QPalette::WindowText);
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Theme::star() { return QPalette().color(QPalette::Highlight); }
|
QColor Theme::star() { return QPalette().color(QPalette::Highlight); }
|
||||||
|
@ -22,7 +22,18 @@ class Theme {
|
|||||||
public:
|
public:
|
||||||
enum class BadgeRole { Foreground, Background };
|
enum class BadgeRole { Foreground, Background };
|
||||||
|
|
||||||
enum class BadgeState { Normal, Selected, Conflicted, Head, Notification };
|
enum class BadgeState {
|
||||||
|
Normal,
|
||||||
|
Selected,
|
||||||
|
Conflicted,
|
||||||
|
Head,
|
||||||
|
Notification,
|
||||||
|
Modified,
|
||||||
|
Added,
|
||||||
|
Deleted,
|
||||||
|
Untracked,
|
||||||
|
Renamed
|
||||||
|
};
|
||||||
|
|
||||||
enum class CommitEditor { SpellError, SpellIgnore, LengthWarning };
|
enum class CommitEditor { SpellError, SpellIgnore, LengthWarning };
|
||||||
|
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
add_library(conf ConfFile.cpp Settings.cpp Setting.cpp RecentRepositories.cpp
|
add_library(conf ConfFile.cpp Settings.cpp Setting.cpp RecentRepositories.cpp
|
||||||
RecentRepository.cpp)
|
RecentRepository.cpp)
|
||||||
|
|
||||||
target_link_libraries(conf lua Qt5::Core util)
|
target_link_libraries(conf lua Qt5::Core util translation)
|
||||||
|
|
||||||
|
# SRC_ definitions point to the source directly
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
conf PRIVATE SCINTILLUA_LEXERS_DIR="${SCINTILLUA_LEXERS_DIR}")
|
conf
|
||||||
|
PRIVATE CONF_DIR="${RESOURCES_DIR}"
|
||||||
if(UNIX)
|
SRC_CONF_DIR="${CMAKE_SOURCE_DIR}/conf"
|
||||||
target_compile_definitions(
|
L10N_DIR="${L10N_INSTALL_DIR}"
|
||||||
conf
|
SRC_L10N_DIR="${CMAKE_BINARY_DIR}/l10n"
|
||||||
PRIVATE CONF_DIR="${CMAKE_INSTALL_FULL_DATADIR}/gittyup/Resources"
|
SCINTILLUA_LEXERS_DIR="${SCINTILLUA_LEXERS_DIR}"
|
||||||
L10N_DIR="${CMAKE_INSTALL_FULL_DATADIR}/gittyup/Resources/l10n")
|
SRC_SCINTILLUA_LEXERS_DIR="${SRC_SCINTILLUA_LEXERS_DIR}")
|
||||||
else()
|
|
||||||
|
|
||||||
target_compile_definitions(conf PRIVATE CONF_DIR="" L10N_DIR="")
|
|
||||||
endif()
|
|
||||||
set_target_properties(conf PROPERTIES AUTOMOC ON)
|
set_target_properties(conf PROPERTIES AUTOMOC ON)
|
||||||
|
@ -50,16 +50,20 @@ void RecentRepositories::remove(int index) {
|
|||||||
emit repositoryRemoved();
|
emit repositoryRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecentRepositories::add(QString path) {
|
/*!
|
||||||
|
* gitpath: path to the git repository, does not neccesarly need to be the
|
||||||
|
* workdir
|
||||||
|
*/
|
||||||
|
void RecentRepositories::add(QString gitpath) {
|
||||||
emit repositoryAboutToBeAdded();
|
emit repositoryAboutToBeAdded();
|
||||||
|
|
||||||
auto end = mRepos.end();
|
auto end = mRepos.end();
|
||||||
RecentRepository *repo = new RecentRepository(path, this);
|
RecentRepository *repo = new RecentRepository(gitpath, this);
|
||||||
auto it = std::remove_if(mRepos.begin(), end, [repo](RecentRepository *rhs) {
|
auto it = std::remove_if(mRepos.begin(), end, [repo](RecentRepository *rhs) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return repo->path().compare(rhs->path(), Qt::CaseInsensitive) == 0;
|
return repo->gitpath().compare(rhs->gitpath(), Qt::CaseInsensitive) == 0;
|
||||||
#else
|
#else
|
||||||
return (repo->path() == rhs->path());
|
return (repo->gitpath() == rhs->gitpath());
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,7 +86,7 @@ RecentRepositories *RecentRepositories::instance() {
|
|||||||
void RecentRepositories::store() {
|
void RecentRepositories::store() {
|
||||||
QStringList paths;
|
QStringList paths;
|
||||||
foreach (RecentRepository *repo, mRepos)
|
foreach (RecentRepository *repo, mRepos)
|
||||||
paths.append(repo->path());
|
paths.append(repo->gitpath());
|
||||||
|
|
||||||
QSettings().setValue(kRecentKey, paths);
|
QSettings().setValue(kRecentKey, paths);
|
||||||
|
|
||||||
@ -125,6 +129,13 @@ void RecentRepositories::load() {
|
|||||||
qDeleteAll(mRepos);
|
qDeleteAll(mRepos);
|
||||||
mRepos.clear();
|
mRepos.clear();
|
||||||
|
|
||||||
|
/* If two paths have the same name, increase the path segment so that they get
|
||||||
|
* unique For example: path1/anotherpath/repositoryname
|
||||||
|
* path2/anotherpath/repositoryname
|
||||||
|
*
|
||||||
|
* In this case the complete paths are shown and not only 'repositoryname',
|
||||||
|
* otherwise they are not distinguishable in the recent repository list:
|
||||||
|
*/
|
||||||
foreach (const QString &path, paths) {
|
foreach (const QString &path, paths) {
|
||||||
RecentRepository *repo = new RecentRepository(path, this);
|
RecentRepository *repo = new RecentRepository(path, this);
|
||||||
auto functor = [repo](RecentRepository *rhs) {
|
auto functor = [repo](RecentRepository *rhs) {
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
#include "RecentRepository.h"
|
#include "RecentRepository.h"
|
||||||
|
|
||||||
RecentRepository::RecentRepository(const QString &path, QObject *parent)
|
RecentRepository::RecentRepository(const QString &gitpath, QObject *parent)
|
||||||
: QObject(parent), mPath(path) {}
|
: QObject(parent), mGitPath(gitpath) {}
|
||||||
|
|
||||||
QString RecentRepository::path() const { return mPath; }
|
QString RecentRepository::gitpath() const { return mGitPath; }
|
||||||
|
|
||||||
QString RecentRepository::name() const {
|
QString RecentRepository::name() const {
|
||||||
return mPath.section('/', -mSections);
|
return mGitPath.section('/', -mSections, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecentRepository::increment() { ++mSections; }
|
void RecentRepository::increment() { ++mSections; }
|
||||||
|
@ -16,15 +16,15 @@ class RecentRepository : public QObject {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RecentRepository(const QString &path, QObject *parent = nullptr);
|
RecentRepository(const QString &gitpath, QObject *parent = nullptr);
|
||||||
|
|
||||||
QString path() const;
|
QString gitpath() const;
|
||||||
QString name() const;
|
QString name() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void increment();
|
void increment();
|
||||||
|
|
||||||
QString mPath;
|
QString mGitPath;
|
||||||
int mSections = 1;
|
int mSections = 1;
|
||||||
|
|
||||||
friend class RecentRepositories;
|
friend class RecentRepositories;
|
||||||
|
@ -26,7 +26,7 @@ void Setting::initialize(QMap<Id, QString> &keys) {
|
|||||||
keys[Id::TerminalName] = "terminal/name";
|
keys[Id::TerminalName] = "terminal/name";
|
||||||
keys[Id::TerminalPath] = "terminal/path";
|
keys[Id::TerminalPath] = "terminal/path";
|
||||||
keys[Id::DontTranslate] = "translation/disable";
|
keys[Id::DontTranslate] = "translation/disable";
|
||||||
keys[Id::StoreCredentials] = "credential/store";
|
keys[Id::Language] = "translation/language";
|
||||||
keys[Id::AllowSingleInstanceOnly] = "singleInstance";
|
keys[Id::AllowSingleInstanceOnly] = "singleInstance";
|
||||||
keys[Id::CheckForUpdatesAutomatically] = "update/check";
|
keys[Id::CheckForUpdatesAutomatically] = "update/check";
|
||||||
keys[Id::InstallUpdatesAutomatically] = "update/download";
|
keys[Id::InstallUpdatesAutomatically] = "update/download";
|
||||||
@ -35,8 +35,13 @@ void Setting::initialize(QMap<Id, QString> &keys) {
|
|||||||
keys[Id::SshKeyFilePath] = "ssh/keyFilePath";
|
keys[Id::SshKeyFilePath] = "ssh/keyFilePath";
|
||||||
keys[Id::CommitMergeImmediately] = "merge/commit";
|
keys[Id::CommitMergeImmediately] = "merge/commit";
|
||||||
keys[Id::ShowCommitsInCompactMode] = "commit/compact";
|
keys[Id::ShowCommitsInCompactMode] = "commit/compact";
|
||||||
|
keys[Id::ShowCommitsAuthor] = "commit/author";
|
||||||
|
keys[Id::ShowCommitsDate] = "commit/date";
|
||||||
|
keys[Id::ShowCommitsId] = "commit/id";
|
||||||
keys[Id::ShowChangedFilesAsList] = "doubletreeview/listview";
|
keys[Id::ShowChangedFilesAsList] = "doubletreeview/listview";
|
||||||
keys[Id::ShowChangedFilesInSingleView] = "doubletreeview/single";
|
keys[Id::ShowChangedFilesInSingleView] = "doubletreeview/single";
|
||||||
|
keys[Id::ShowChangedFilesMultiColumn] = "doubletreeview/listviewmulticolumn";
|
||||||
|
keys[Id::HideUntracked] = "untracked.hide";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prompt::initialize(QMap<Kind, QString> &keys) {
|
void Prompt::initialize(QMap<Kind, QString> &keys) {
|
||||||
|
@ -50,7 +50,6 @@ public:
|
|||||||
TerminalName,
|
TerminalName,
|
||||||
TerminalPath,
|
TerminalPath,
|
||||||
DontTranslate,
|
DontTranslate,
|
||||||
StoreCredentials,
|
|
||||||
AllowSingleInstanceOnly,
|
AllowSingleInstanceOnly,
|
||||||
CheckForUpdatesAutomatically,
|
CheckForUpdatesAutomatically,
|
||||||
InstallUpdatesAutomatically,
|
InstallUpdatesAutomatically,
|
||||||
@ -59,8 +58,14 @@ public:
|
|||||||
SshKeyFilePath,
|
SshKeyFilePath,
|
||||||
CommitMergeImmediately,
|
CommitMergeImmediately,
|
||||||
ShowCommitsInCompactMode,
|
ShowCommitsInCompactMode,
|
||||||
|
ShowCommitsAuthor,
|
||||||
|
ShowCommitsDate,
|
||||||
|
ShowCommitsId,
|
||||||
ShowChangedFilesAsList,
|
ShowChangedFilesAsList,
|
||||||
|
ShowChangedFilesMultiColumn, // For the list only
|
||||||
ShowChangedFilesInSingleView,
|
ShowChangedFilesInSingleView,
|
||||||
|
HideUntracked,
|
||||||
|
Language,
|
||||||
};
|
};
|
||||||
Q_ENUM(Id)
|
Q_ENUM(Id)
|
||||||
|
|
||||||
|
@ -9,13 +9,14 @@
|
|||||||
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "ConfFile.h"
|
#include "ConfFile.h"
|
||||||
|
#include "Debug.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
|
#include "languages.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#define CS Qt::CaseInsensitive
|
#define CS Qt::CaseInsensitive
|
||||||
#else
|
#else
|
||||||
@ -24,18 +25,20 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const QString kIgnoreWsKey = "diff/whitespace/ignore";
|
const QString kIgnoreWsKey("diff/whitespace/ignore");
|
||||||
const QString kLastPathKey = "lastpath";
|
const QString kLastPathKey("lastpath");
|
||||||
|
const QString kTranslation("translation");
|
||||||
|
const QString kTranslationLanguage("language");
|
||||||
|
|
||||||
// Look up variant at key relative to root.
|
// Look up variant at key relative to root.
|
||||||
QVariant lookup(const QVariantMap &root, const QString &key) {
|
QVariant lookup(const QVariantMap &root, const QString &key) {
|
||||||
QStringList list = key.split("/", QString::SkipEmptyParts);
|
QStringList list(key.split("/", Qt::SkipEmptyParts));
|
||||||
if (list.isEmpty())
|
if (list.isEmpty())
|
||||||
return root;
|
return root;
|
||||||
|
|
||||||
QVariantMap map = root;
|
QVariantMap map(root);
|
||||||
while (map.contains(list.first())) {
|
while (map.contains(list.first())) {
|
||||||
QVariant result = map.value(list.takeFirst());
|
QVariant result(map.value(list.takeFirst()));
|
||||||
if (list.isEmpty())
|
if (list.isEmpty())
|
||||||
return result;
|
return result;
|
||||||
map = result.toMap();
|
map = result.toMap();
|
||||||
@ -45,24 +48,16 @@ QVariant lookup(const QVariantMap &root, const QString &key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString promptKey(Prompt::Kind kind) { return Prompt::key(kind); }
|
QString promptKey(Prompt::Kind kind) { return Prompt::key(kind); }
|
||||||
|
|
||||||
QDir rootDir() {
|
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
dir.cdUp(); // Contents
|
|
||||||
#endif
|
|
||||||
qDebug() << "Root dir: " << dir;
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Settings::Settings(QObject *parent) : QObject(parent) {
|
Settings::Settings(QObject *parent) : QObject(parent) {
|
||||||
foreach (const QFileInfo &file, confDir().entryInfoList(QStringList("*.lua")))
|
foreach (const QFileInfo &file, confDir().entryInfoList(QStringList("*.lua")))
|
||||||
mDefaults[file.baseName()] = ConfFile(file.absoluteFilePath()).parse();
|
mDefaults[file.baseName()] = ConfFile(file.absoluteFilePath()).parse();
|
||||||
mDefaults[kLastPathKey] = QDir::homePath();
|
mDefaults[kLastPathKey] = QDir::homePath();
|
||||||
|
QVariantMap map;
|
||||||
|
map[kTranslationLanguage] = QVariant(Languages::system);
|
||||||
|
mDefaults[kTranslation] = map;
|
||||||
|
mDefaults[kTranslation].toMap()[kTranslationLanguage] = Languages::system;
|
||||||
mCurrentMap = mDefaults;
|
mCurrentMap = mDefaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +71,7 @@ QVariant Settings::value(const QString &key,
|
|||||||
const QVariant &defaultValue) const {
|
const QVariant &defaultValue) const {
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup(group());
|
settings.beginGroup(group());
|
||||||
QVariant result = settings.value(key, defaultValue);
|
QVariant result(settings.value(key, defaultValue));
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -120,13 +115,13 @@ QString Settings::lexer(const QString &filename) {
|
|||||||
return "null";
|
return "null";
|
||||||
|
|
||||||
QFileInfo info(filename);
|
QFileInfo info(filename);
|
||||||
QString name = info.fileName();
|
QString name(info.fileName());
|
||||||
QString suffix = info.suffix().toLower();
|
QString suffix(info.suffix().toLower());
|
||||||
|
|
||||||
// Try all patterns first.
|
// Try all patterns first.
|
||||||
QVariantMap lexers = mDefaults.value("lexers").toMap();
|
QVariantMap lexers(mDefaults.value("lexers").toMap());
|
||||||
foreach (const QString &key, lexers.keys()) {
|
foreach (const QString &key, lexers.keys()) {
|
||||||
QVariantMap map = lexers.value(key).toMap();
|
QVariantMap map(lexers.value(key).toMap());
|
||||||
if (map.contains("patterns")) {
|
if (map.contains("patterns")) {
|
||||||
foreach (QString pattern, map.value("patterns").toString().split(",")) {
|
foreach (QString pattern, map.value("patterns").toString().split(",")) {
|
||||||
QRegExp regExp(pattern, CS, QRegExp::Wildcard);
|
QRegExp regExp(pattern, CS, QRegExp::Wildcard);
|
||||||
@ -138,7 +133,7 @@ QString Settings::lexer(const QString &filename) {
|
|||||||
|
|
||||||
// Try to match by extension.
|
// Try to match by extension.
|
||||||
foreach (const QString &key, lexers.keys()) {
|
foreach (const QString &key, lexers.keys()) {
|
||||||
QVariantMap map = lexers.value(key).toMap();
|
QVariantMap map(lexers.value(key).toMap());
|
||||||
if (map.contains("extensions")) {
|
if (map.contains("extensions")) {
|
||||||
foreach (QString ext, map.value("extensions").toString().split(",")) {
|
foreach (QString ext, map.value("extensions").toString().split(",")) {
|
||||||
if (suffix == ext)
|
if (suffix == ext)
|
||||||
@ -151,8 +146,8 @@ QString Settings::lexer(const QString &filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::kind(const QString &filename) {
|
QString Settings::kind(const QString &filename) {
|
||||||
QString key = lexer(filename);
|
QString key(lexer(filename));
|
||||||
QVariantMap lexers = mDefaults.value("lexers").toMap();
|
QVariantMap lexers(mDefaults.value("lexers").toMap());
|
||||||
return lexers.value(key).toMap().value("name").toString();
|
return lexers.value(key).toMap().value("name").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +179,8 @@ QString Settings::promptDescription(Prompt::Kind kind) const {
|
|||||||
case Prompt::Kind::LargeFiles:
|
case Prompt::Kind::LargeFiles:
|
||||||
return tr("Prompt to stage large files");
|
return tr("Prompt to stage large files");
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(kind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setHotkey(const QString &action, const QString &hotkey) {
|
void Settings::setHotkey(const QString &action, const QString &hotkey) {
|
||||||
@ -208,6 +205,13 @@ void Settings::setLastPath(const QString &lastPath) {
|
|||||||
setValue(kLastPathKey, lastPath);
|
setValue(kLastPathKey, lastPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDir Settings::rootDir() {
|
||||||
|
QDir dir(QCoreApplication::applicationDirPath());
|
||||||
|
dir.cdUp();
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
QDir Settings::appDir() {
|
QDir Settings::appDir() {
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
QDir dir(QCoreApplication::applicationDirPath());
|
||||||
|
|
||||||
@ -223,48 +227,62 @@ QDir Settings::appDir() {
|
|||||||
QDir Settings::docDir() { return confDir(); }
|
QDir Settings::docDir() { return confDir(); }
|
||||||
|
|
||||||
QDir Settings::confDir() {
|
QDir Settings::confDir() {
|
||||||
QDir dir = rootDir();
|
|
||||||
if (!dir.cd("Resources"))
|
#if !defined(NDEBUG)
|
||||||
dir = QDir(CONF_DIR);
|
QDir dir(SRC_CONF_DIR);
|
||||||
qDebug() << "Conf dir: " << dir;
|
#else
|
||||||
|
QDir dir(rootDir());
|
||||||
|
if (!dir.cd("Resources")) {
|
||||||
|
if (!dir.cd(CONF_DIR))
|
||||||
|
dir.setPath(SRC_CONF_DIR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Settings::l10nDir() {
|
QDir Settings::l10nDir() {
|
||||||
QDir dir = confDir();
|
#if !defined(NDEBUG)
|
||||||
if (!dir.cd("l10n"))
|
QDir dir(QDir(SRC_L10N_DIR));
|
||||||
dir = QDir(L10N_DIR);
|
#else
|
||||||
|
QDir dir(confDir());
|
||||||
qDebug() << "l10n dir: " << dir;
|
if (!dir.cd("l10n")) {
|
||||||
|
dir = rootDir();
|
||||||
|
if (!dir.cd(L10N_DIR))
|
||||||
|
dir.setPath(SRC_L10N_DIR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Settings::dictionariesDir() {
|
QDir Settings::dictionariesDir() {
|
||||||
QDir dir = confDir();
|
QDir dir(confDir());
|
||||||
dir.cd("dictionaries");
|
dir.cd("dictionaries");
|
||||||
qDebug() << "Dictionaries dir: " << dir;
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Settings::lexerDir() {
|
QDir Settings::lexerDir() {
|
||||||
QDir dir = confDir();
|
#if !defined(NDEBUG)
|
||||||
if (!dir.cd("lexers"))
|
QDir dir(SRC_SCINTILLUA_LEXERS_DIR);
|
||||||
dir = QDir(SCINTILLUA_LEXERS_DIR);
|
#else
|
||||||
qDebug() << "Lexers dir: " << dir;
|
QDir dir(confDir());
|
||||||
|
if (!dir.cd("lexers")) {
|
||||||
|
dir = rootDir();
|
||||||
|
if (!dir.cd(SCINTILLUA_LEXERS_DIR))
|
||||||
|
dir.setPath(SRC_SCINTILLUA_LEXERS_DIR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Settings::themesDir() {
|
QDir Settings::themesDir() {
|
||||||
QDir dir = confDir();
|
QDir dir(confDir());
|
||||||
dir.cd("themes");
|
dir.cd("themes");
|
||||||
qDebug() << "Theme dir: " << dir;
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Settings::pluginsDir() {
|
QDir Settings::pluginsDir() {
|
||||||
QDir dir = confDir();
|
QDir dir(confDir());
|
||||||
dir.cd("plugins");
|
dir.cd("plugins");
|
||||||
qDebug() << "Plugins dir: " << dir;
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,8 +291,8 @@ QDir Settings::userDir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QDir Settings::tempDir() {
|
QDir Settings::tempDir() {
|
||||||
QString name = QCoreApplication::applicationName();
|
QString name(QCoreApplication::applicationName());
|
||||||
QDir dir = QDir::temp();
|
QDir dir(QDir::temp());
|
||||||
dir.mkpath(name);
|
dir.mkpath(name);
|
||||||
dir.cd(name);
|
dir.cd(name);
|
||||||
return dir;
|
return dir;
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
void setLastPath(const QString &lastPath);
|
void setLastPath(const QString &lastPath);
|
||||||
|
|
||||||
// settings directories
|
// settings directories
|
||||||
|
static QDir rootDir();
|
||||||
static QDir appDir();
|
static QDir appDir();
|
||||||
static QDir docDir();
|
static QDir docDir();
|
||||||
static QDir confDir();
|
static QDir confDir();
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
if(WIN32)
|
add_library(cred Cache.cpp Store.cpp CredentialHelper.cpp GitCredential.cpp)
|
||||||
set(CREDENTIAL_IMPL_FILE WinCred.cpp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(cred Cache.cpp CredentialHelper.cpp GitCredential.cpp
|
target_link_libraries(cred conf git Qt5::Core)
|
||||||
${CREDENTIAL_IMPL_FILE})
|
|
||||||
|
|
||||||
target_link_libraries(cred conf Qt5::Core)
|
|
||||||
|
|
||||||
set_target_properties(cred PROPERTIES AUTOMOC ON)
|
set_target_properties(cred PROPERTIES AUTOMOC ON)
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
#include "CredentialHelper.h"
|
#include "CredentialHelper.h"
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
#include "GitCredential.h"
|
#include "GitCredential.h"
|
||||||
#include "WinCred.h"
|
#include "qtsupport.h"
|
||||||
|
#include "Store.h"
|
||||||
#include "conf/Settings.h"
|
#include "conf/Settings.h"
|
||||||
|
#include "git/Config.h"
|
||||||
#include <QLibrary>
|
#include <QLibrary>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
@ -22,27 +24,30 @@ namespace {
|
|||||||
|
|
||||||
const QString kLogKey = "credential/log";
|
const QString kLogKey = "credential/log";
|
||||||
|
|
||||||
|
const QString cacheStoreName = "cache";
|
||||||
|
const QString storeStoreName = "store";
|
||||||
|
const QString osxKeyChainStoreName = "osxkeychain";
|
||||||
|
const QString winCredStoreName = "wincred";
|
||||||
|
const QString libSecretStoreName = "libsecret";
|
||||||
|
const QString gnomeKeyringStoreName = "gnome-keyring";
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CredentialHelper *CredentialHelper::instance() {
|
CredentialHelper *CredentialHelper::instance() {
|
||||||
static QPointer<CredentialHelper> instance;
|
static QPointer<CredentialHelper> instance;
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
if (Settings::instance()->value(Setting::Id::StoreCredentials).toBool()) {
|
git::Config config = git::Config::global();
|
||||||
#if defined(Q_OS_MAC)
|
auto helperName = config.value<QString>("credential.helper");
|
||||||
instance = new GitCredential("osxkeychain");
|
if (isHelperValid(helperName)) {
|
||||||
#elif defined(Q_OS_WIN)
|
if (helperName == cacheStoreName) {
|
||||||
// The git wincred helper fails for some users.
|
instance = new Cache;
|
||||||
instance = new WinCred;
|
} else if (helperName == storeStoreName) {
|
||||||
#else
|
auto path =
|
||||||
QLibrary lib("secret-1", 0);
|
QString::fromLocal8Bit(qgetenv("HOME") + "/.git-credentials");
|
||||||
if (lib.load()) {
|
instance = new Store(path);
|
||||||
instance = new GitCredential("libsecret");
|
|
||||||
} else {
|
} else {
|
||||||
QLibrary lib("gnome-keyring", 0);
|
instance = new GitCredential(helperName);
|
||||||
if (lib.load())
|
|
||||||
instance = new GitCredential("gnome-keyring");
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance)
|
if (!instance)
|
||||||
@ -52,6 +57,31 @@ CredentialHelper *CredentialHelper::instance() {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CredentialHelper::isHelperValid(const QString &name) {
|
||||||
|
return !name.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CredentialHelper::getAvailableHelperNames() {
|
||||||
|
QStringList list;
|
||||||
|
list.append(cacheStoreName);
|
||||||
|
list.append(storeStoreName);
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
list.append(osxKeyChainStoreName);
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
list.append(winCredStoreName);
|
||||||
|
#else
|
||||||
|
QLibrary lib("secret-1", 0);
|
||||||
|
if (lib.load()) {
|
||||||
|
list.append(libSecretStoreName);
|
||||||
|
}
|
||||||
|
QLibrary lib2(gnomeKeyringStoreName, 0);
|
||||||
|
if (lib2.load()) {
|
||||||
|
list.append(gnomeKeyringStoreName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
bool CredentialHelper::isLoggingEnabled() {
|
bool CredentialHelper::isLoggingEnabled() {
|
||||||
return QSettings().value(kLogKey).toBool();
|
return QSettings().value(kLogKey).toBool();
|
||||||
}
|
}
|
||||||
@ -69,5 +99,5 @@ void CredentialHelper::log(const QString &text) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
||||||
QTextStream(&file) << time << " - " << text << endl;
|
QTextStream(&file) << time << " - " << text << Qt::endl;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ public:
|
|||||||
static bool isLoggingEnabled();
|
static bool isLoggingEnabled();
|
||||||
static void setLoggingEnabled(bool enabled);
|
static void setLoggingEnabled(bool enabled);
|
||||||
|
|
||||||
|
static QStringList getAvailableHelperNames();
|
||||||
|
static bool isHelperValid(const QString &name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void log(const QString &text);
|
static void log(const QString &text);
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "GitCredential.h"
|
#include "GitCredential.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
|
#include <QStandardPaths>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
@ -44,11 +46,11 @@ bool GitCredential::get(const QString &url, QString &username,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
QTextStream out(&process);
|
QTextStream out(&process);
|
||||||
out << "protocol=" << protocol(url) << endl;
|
out << "protocol=" << protocol(url) << Qt::endl;
|
||||||
out << "host=" << host(url) << endl;
|
out << "host=" << host(url) << Qt::endl;
|
||||||
if (!username.isEmpty())
|
if (!username.isEmpty())
|
||||||
out << "username=" << username << endl;
|
out << "username=" << username << Qt::endl;
|
||||||
out << endl;
|
out << Qt::endl;
|
||||||
|
|
||||||
process.closeWriteChannel();
|
process.closeWriteChannel();
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
@ -79,11 +81,11 @@ bool GitCredential::store(const QString &url, const QString &username,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
QTextStream out(&process);
|
QTextStream out(&process);
|
||||||
out << "protocol=" << protocol(url) << endl;
|
out << "protocol=" << protocol(url) << Qt::endl;
|
||||||
out << "host=" << host(url) << endl;
|
out << "host=" << host(url) << Qt::endl;
|
||||||
out << "username=" << username << endl;
|
out << "username=" << username << Qt::endl;
|
||||||
out << "password=" << password << endl;
|
out << "password=" << password << Qt::endl;
|
||||||
out << endl;
|
out << Qt::endl;
|
||||||
|
|
||||||
process.closeWriteChannel();
|
process.closeWriteChannel();
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
@ -92,6 +94,46 @@ bool GitCredential::store(const QString &url, const QString &username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString GitCredential::command() const {
|
QString GitCredential::command() const {
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
QString name = QString("git-credential-%1").arg(mName);
|
||||||
return dir.filePath(QString("git-credential-%1").arg(mName));
|
QDir appDir = QCoreApplication::applicationDirPath();
|
||||||
|
appDir.cd("credential-helpers");
|
||||||
|
|
||||||
|
// Prefer credential helpers directly installed into Gittyup's app dir
|
||||||
|
QString candidate =
|
||||||
|
QStandardPaths::findExecutable(name, QStringList(appDir.path()));
|
||||||
|
if (!candidate.isEmpty()) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate = QStandardPaths::findExecutable(name);
|
||||||
|
if (!candidate.isEmpty()) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Look for GIT CLI installation path
|
||||||
|
QString gitPath = QStandardPaths::findExecutable("git");
|
||||||
|
if (!gitPath.isEmpty()) {
|
||||||
|
QDir gitDir = QFileInfo(gitPath).dir();
|
||||||
|
if (gitDir.dirName() == "cmd" || gitDir.dirName() == "bin") {
|
||||||
|
gitDir.cdUp();
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN64
|
||||||
|
gitDir.cd("mingw64");
|
||||||
|
#else
|
||||||
|
gitDir.cd("mingw32");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gitDir.cd("bin");
|
||||||
|
|
||||||
|
candidate =
|
||||||
|
QStandardPaths::findExecutable(name, QStringList(gitDir.path()));
|
||||||
|
if (!candidate.isEmpty()) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
111
src/cred/Store.cpp
Normal file
111
src/cred/Store.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2022, Gittyup Community
|
||||||
|
//
|
||||||
|
// This software is licensed under the MIT License. The LICENSE.md file
|
||||||
|
// describes the conditions under which this software may be distributed.
|
||||||
|
//
|
||||||
|
// Author: Hessamoddin Hediehloo(H-4ND-H)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Store.h"
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QString host(const QString &url) {
|
||||||
|
QString host = QUrl(url).host();
|
||||||
|
if (!host.isEmpty())
|
||||||
|
return host;
|
||||||
|
|
||||||
|
// Extract hostname from SSH URL.
|
||||||
|
int end = url.indexOf(':');
|
||||||
|
int begin = url.indexOf('@') + 1;
|
||||||
|
return url.mid(begin, end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString protocol(const QString &url) {
|
||||||
|
QString scheme = QUrl(url).scheme();
|
||||||
|
return !scheme.isEmpty() ? scheme : "ssh";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Store::Store(const QString &path) { mPath = path; }
|
||||||
|
|
||||||
|
QMap<QString, QMap<QString, QMap<QString, QString>>> Store::readCredFile() {
|
||||||
|
QMap<QString, QMap<QString, QMap<QString, QString>>> store;
|
||||||
|
|
||||||
|
QFile file(mPath);
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
return store;
|
||||||
|
|
||||||
|
while (!file.atEnd()) {
|
||||||
|
auto line = file.readLine();
|
||||||
|
auto urlStr = QUrl::fromPercentEncoding(line);
|
||||||
|
auto urlObj = QUrl::fromUserInput(urlStr);
|
||||||
|
store[urlObj.scheme()][urlObj.host()][urlObj.userName()] =
|
||||||
|
urlObj.password();
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Store::extractUserPass(const QMap<QString, QString> &map,
|
||||||
|
QString &username, QString &password) {
|
||||||
|
if (map.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (username.isEmpty())
|
||||||
|
username = map.keys().first();
|
||||||
|
|
||||||
|
if (!map.contains(username))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
password = map.value(username);
|
||||||
|
|
||||||
|
return !username.isEmpty() && !password.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Store::get(const QString &url, QString &username, QString &password) {
|
||||||
|
|
||||||
|
auto store = readCredFile();
|
||||||
|
const QMap<QString, QString> &map = store[protocol(url)][host(url)];
|
||||||
|
return extractUserPass(map, username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Store::store(const QString &url, const QString &username,
|
||||||
|
const QString &password) {
|
||||||
|
auto store = readCredFile();
|
||||||
|
store[protocol(url)][host(url)][username] = password;
|
||||||
|
|
||||||
|
QFile file(mPath);
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (const auto &protocolKey, store.keys()) {
|
||||||
|
auto protocol = store[protocolKey];
|
||||||
|
foreach (const auto &hostKey, protocol.keys()) {
|
||||||
|
auto host = protocol[hostKey];
|
||||||
|
foreach (const auto &usernameKey, host.keys()) {
|
||||||
|
QUrl temp;
|
||||||
|
temp.setScheme(protocolKey);
|
||||||
|
temp.setHost(hostKey);
|
||||||
|
temp.setUserName(usernameKey);
|
||||||
|
temp.setPassword(host[usernameKey]);
|
||||||
|
auto encoded = QUrl::toPercentEncoding(temp.toString(), "@:/");
|
||||||
|
QTextStream fout(&file);
|
||||||
|
fout << encoded << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Store::command() const { return ""; }
|
34
src/cred/Store.h
Normal file
34
src/cred/Store.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2022, Gittyup Community
|
||||||
|
//
|
||||||
|
// This software is licensed under the MIT License. The LICENSE.md file
|
||||||
|
// describes the conditions under which this software may be distributed.
|
||||||
|
//
|
||||||
|
// Author: Hessamoddin Hediehloo(H-4ND-H)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STORE_H
|
||||||
|
#define STORE_H
|
||||||
|
|
||||||
|
#include "CredentialHelper.h"
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
class Store : public CredentialHelper {
|
||||||
|
public:
|
||||||
|
Store(const QString &path);
|
||||||
|
|
||||||
|
bool get(const QString &url, QString &username, QString &password) override;
|
||||||
|
|
||||||
|
bool store(const QString &url, const QString &username,
|
||||||
|
const QString &password) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString command() const;
|
||||||
|
QMap<QString, QMap<QString, QMap<QString, QString>>> readCredFile();
|
||||||
|
bool extractUserPass(const QMap<QString, QString> &map, QString &username,
|
||||||
|
QString &password);
|
||||||
|
|
||||||
|
QString mPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,128 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018, Scientific Toolworks, Inc.
|
|
||||||
//
|
|
||||||
// This software is licensed under the MIT License. The LICENSE.md file
|
|
||||||
// describes the conditions under which this software may be distributed.
|
|
||||||
//
|
|
||||||
// Author: Jason Haslam
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "WinCred.h"
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <wincred.h>
|
|
||||||
|
|
||||||
// Attempt to be compatible with the git wincred helper by matching
|
|
||||||
// the target name and encoding the password in UTF-16.
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const QString kNameFmt = "%1@%2";
|
|
||||||
const QString kTargetFmt = "git:https://%1";
|
|
||||||
|
|
||||||
QString buildTarget(const QString &host, const QString &name) {
|
|
||||||
return kTargetFmt.arg(name.isEmpty() ? host : kNameFmt.arg(name, host));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString host(const QString &url) {
|
|
||||||
QString host = QUrl(url).host();
|
|
||||||
if (!host.isEmpty())
|
|
||||||
return host;
|
|
||||||
|
|
||||||
// Extract hostname from SSH URL.
|
|
||||||
int end = url.indexOf(':');
|
|
||||||
int begin = url.indexOf('@') + 1;
|
|
||||||
return url.mid(begin, end - begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
WinCred::WinCred() {}
|
|
||||||
|
|
||||||
bool WinCred::get(const QString &url, QString &username, QString &password) {
|
|
||||||
log(QString("get: %1 %2").arg(url, username));
|
|
||||||
|
|
||||||
PCREDENTIAL cred;
|
|
||||||
QString target = buildTarget(host(url), username);
|
|
||||||
if (!CredRead(target.toUtf8(), CRED_TYPE_GENERIC, 0, &cred)) {
|
|
||||||
switch (DWORD error = GetLastError()) {
|
|
||||||
case ERROR_NOT_FOUND:
|
|
||||||
log(QString("get: credential not found for '%1'").arg(target));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_NO_SUCH_LOGON_SESSION:
|
|
||||||
log("get: no such logon session");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_INVALID_FLAGS:
|
|
||||||
log("get: invalid flags");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log(QString("get: unknown error '%1'").arg(error));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
username = cred->UserName;
|
|
||||||
int size = cred->CredentialBlobSize / sizeof(ushort);
|
|
||||||
password = QString::fromUtf16((ushort *)cred->CredentialBlob, size);
|
|
||||||
|
|
||||||
CredFree(cred);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WinCred::store(const QString &url, const QString &username,
|
|
||||||
const QString &password) {
|
|
||||||
log(QString("store: %1 %2").arg(url, username));
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
QByteArray name = username.toUtf8();
|
|
||||||
QStringList names = {QString(), username};
|
|
||||||
foreach (const QString &tmp, names) {
|
|
||||||
QByteArray target = buildTarget(host(url), tmp).toUtf8();
|
|
||||||
|
|
||||||
CREDENTIAL cred;
|
|
||||||
cred.Flags = 0;
|
|
||||||
cred.Type = CRED_TYPE_GENERIC;
|
|
||||||
cred.TargetName = target.data();
|
|
||||||
cred.Comment = "Written by GitAhead";
|
|
||||||
cred.CredentialBlobSize = password.length() * sizeof(ushort);
|
|
||||||
cred.CredentialBlob = (LPBYTE)password.utf16();
|
|
||||||
cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
|
|
||||||
cred.AttributeCount = 0;
|
|
||||||
cred.Attributes = nullptr;
|
|
||||||
cred.TargetAlias = nullptr;
|
|
||||||
cred.UserName = name.data();
|
|
||||||
if (CredWrite(&cred, 0)) {
|
|
||||||
result = true;
|
|
||||||
} else {
|
|
||||||
switch (DWORD error = GetLastError()) {
|
|
||||||
case ERROR_NO_SUCH_LOGON_SESSION:
|
|
||||||
log("store: no such logon session");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_INVALID_PARAMETER:
|
|
||||||
log("store: invalid parameter");
|
|
||||||
|
|
||||||
case ERROR_INVALID_FLAGS:
|
|
||||||
log("store: invalid flags");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_BAD_USERNAME:
|
|
||||||
log(QString("store: bad username '%1'").arg(username));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log(QString("store: unknown error '%1'").arg(error));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018, Scientific Toolworks, Inc.
|
|
||||||
//
|
|
||||||
// This software is licensed under the MIT License. The LICENSE.md file
|
|
||||||
// describes the conditions under which this software may be distributed.
|
|
||||||
//
|
|
||||||
// Author: Jason Haslam
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef WINCRED_H
|
|
||||||
#define WINCRED_H
|
|
||||||
|
|
||||||
#include "CredentialHelper.h"
|
|
||||||
|
|
||||||
class WinCred : public CredentialHelper {
|
|
||||||
public:
|
|
||||||
WinCred();
|
|
||||||
|
|
||||||
bool get(const QString &url, QString &username, QString &password) override;
|
|
||||||
|
|
||||||
bool store(const QString &url, const QString &username,
|
|
||||||
const QString &password) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -42,7 +42,9 @@ const QString kSubtitleFmt = "<h4 style='margin-top: 0px; color: gray'>%2</h4>";
|
|||||||
|
|
||||||
const QString kTextFmt =
|
const QString kTextFmt =
|
||||||
"<p style='white-space: nowrap'><b style='font-size: large'>%1 v%2</b> "
|
"<p style='white-space: nowrap'><b style='font-size: large'>%1 v%2</b> "
|
||||||
"- %3 - %4<br>Copyright © 2021-2022 Gittyup contributors"
|
"- %3 - %4<br>Copyright © 2021-" +
|
||||||
|
QString::number(CURR_YEAR) +
|
||||||
|
" Gittyup contributors"
|
||||||
"<br>Copyright © 2016-2020 Scientific Toolworks, Inc. and "
|
"<br>Copyright © 2016-2020 Scientific Toolworks, Inc. and "
|
||||||
"contributors</p><p> If you have a question that might benefit the "
|
"contributors</p><p> If you have a question that might benefit the "
|
||||||
"community, consider asking it on <a href='%5'>Stack Overflow</a> by "
|
"community, consider asking it on <a href='%5'>Stack Overflow</a> by "
|
||||||
|
@ -172,7 +172,8 @@ AmendDialog::AmendDialog(const git::Signature &author,
|
|||||||
l->addWidget(m_committerInfo, Row::Committer, 0, 1, 2);
|
l->addWidget(m_committerInfo, Row::Committer, 0, 1, 2);
|
||||||
|
|
||||||
auto *lMessage = new QLabel(tr("Commit Message:"), this);
|
auto *lMessage = new QLabel(tr("Commit Message:"), this);
|
||||||
m_commitMessage = new QTextEdit(commitMessage, this);
|
m_commitMessage = new QTextEdit(this);
|
||||||
|
m_commitMessage->setPlainText(commitMessage);
|
||||||
m_commitMessage->setObjectName("Textlabel Commit Message");
|
m_commitMessage->setObjectName("Textlabel Commit Message");
|
||||||
l->addWidget(lMessage, Row::CommitMessageLabel, 0);
|
l->addWidget(lMessage, Row::CommitMessageLabel, 0);
|
||||||
l->addWidget(m_commitMessage, Row::CommitMessage, 0, 1, 2);
|
l->addWidget(m_commitMessage, Row::CommitMessage, 0, 1, 2);
|
||||||
|
@ -24,6 +24,7 @@ add_library(
|
|||||||
RebaseConflictDialog.cpp
|
RebaseConflictDialog.cpp
|
||||||
RemoteDialog.cpp
|
RemoteDialog.cpp
|
||||||
RemoteTableModel.cpp
|
RemoteTableModel.cpp
|
||||||
|
RenameBranchDialog.cpp
|
||||||
SettingsDialog.cpp
|
SettingsDialog.cpp
|
||||||
StartDialog.cpp
|
StartDialog.cpp
|
||||||
SubmoduleDelegate.cpp
|
SubmoduleDelegate.cpp
|
||||||
|
@ -100,17 +100,17 @@ public:
|
|||||||
|
|
||||||
// Connect signals after initializing fields.
|
// Connect signals after initializing fields.
|
||||||
connect(mName, &QLineEdit::textChanged, this, [this](const QString &text) {
|
connect(mName, &QLineEdit::textChanged, this, [this](const QString &text) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.gitConfig();
|
||||||
config.setValue("user.name", text);
|
config.setValue("user.name", text);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mEmail, &QLineEdit::textChanged, this, [this](const QString &text) {
|
connect(mEmail, &QLineEdit::textChanged, this, [this](const QString &text) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.gitConfig();
|
||||||
config.setValue("user.email", text);
|
config.setValue("user.email", text);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mFetch, &QCheckBox::toggled, view, [this, view](bool checked) {
|
connect(mFetch, &QCheckBox::toggled, view, [this, view](bool checked) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.appConfig();
|
||||||
config.setValue("autofetch.enable", checked);
|
config.setValue("autofetch.enable", checked);
|
||||||
view->startFetchTimer();
|
view->startFetchTimer();
|
||||||
});
|
});
|
||||||
@ -118,28 +118,28 @@ public:
|
|||||||
using Signal = void (QSpinBox::*)(int);
|
using Signal = void (QSpinBox::*)(int);
|
||||||
auto signal = static_cast<Signal>(&QSpinBox::valueChanged);
|
auto signal = static_cast<Signal>(&QSpinBox::valueChanged);
|
||||||
connect(mFetchMinutes, signal, this, [this](int value) {
|
connect(mFetchMinutes, signal, this, [this](int value) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.appConfig();
|
||||||
config.setValue("autofetch.minutes", value);
|
config.setValue("autofetch.minutes", value);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mPushCommit, &QCheckBox::toggled, this, [this](bool checked) {
|
connect(mPushCommit, &QCheckBox::toggled, this, [this](bool checked) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.appConfig();
|
||||||
config.setValue("autopush.enable", checked);
|
config.setValue("autopush.enable", checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mPullUpdate, &QCheckBox::toggled, this, [this](bool checked) {
|
connect(mPullUpdate, &QCheckBox::toggled, this, [this](bool checked) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.appConfig();
|
||||||
config.setValue("autoupdate.enable", checked);
|
config.setValue("autoupdate.enable", checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mAutoPrune, &QCheckBox::toggled, this, [this](bool checked) {
|
connect(mAutoPrune, &QCheckBox::toggled, this, [this](bool checked) {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.appConfig();
|
||||||
config.setValue("autoprune.enable", checked);
|
config.setValue("autoprune.enable", checked);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
git::Config config = mRepo.config();
|
git::Config config = mRepo.gitConfig();
|
||||||
mName->setText(config.value<QString>("user.name"));
|
mName->setText(config.value<QString>("user.name"));
|
||||||
mEmail->setText(config.value<QString>("user.email"));
|
mEmail->setText(config.value<QString>("user.email"));
|
||||||
|
|
||||||
@ -158,6 +158,7 @@ public:
|
|||||||
git::Config app = mRepo.appConfig();
|
git::Config app = mRepo.appConfig();
|
||||||
mFetch->setChecked(app.value<bool>("autofetch.enable", fetch));
|
mFetch->setChecked(app.value<bool>("autofetch.enable", fetch));
|
||||||
mFetchMinutes->setValue(app.value<int>("autofetch.minutes", minutes));
|
mFetchMinutes->setValue(app.value<int>("autofetch.minutes", minutes));
|
||||||
|
mFetchMinutes->setEnabled(mFetch->isChecked());
|
||||||
mPushCommit->setChecked(app.value<bool>("autopush.enable", push));
|
mPushCommit->setChecked(app.value<bool>("autopush.enable", push));
|
||||||
mPullUpdate->setChecked(app.value<bool>("autoupdate.enable", update));
|
mPullUpdate->setChecked(app.value<bool>("autoupdate.enable", update));
|
||||||
mAutoPrune->setChecked(app.value<bool>("autoprune.enable", prune));
|
mAutoPrune->setChecked(app.value<bool>("autoprune.enable", prune));
|
||||||
@ -605,7 +606,7 @@ public:
|
|||||||
QLineEdit *urlLineEdit =
|
QLineEdit *urlLineEdit =
|
||||||
new QLineEdit(map.value("Endpoint").section(" ", 0, 0));
|
new QLineEdit(map.value("Endpoint").section(" ", 0, 0));
|
||||||
connect(urlLineEdit, &QLineEdit::textChanged, [repo](const QString &text) {
|
connect(urlLineEdit, &QLineEdit::textChanged, [repo](const QString &text) {
|
||||||
git::Config config = repo.config();
|
git::Config config = repo.gitConfig();
|
||||||
config.setValue("lfs.url", text);
|
config.setValue("lfs.url", text);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -614,7 +615,7 @@ public:
|
|||||||
pruneOffsetDays->setValue(map.value("PruneOffsetDays").toInt());
|
pruneOffsetDays->setValue(map.value("PruneOffsetDays").toInt());
|
||||||
auto signal = QOverload<int>::of(&QSpinBox::valueChanged);
|
auto signal = QOverload<int>::of(&QSpinBox::valueChanged);
|
||||||
connect(pruneOffsetDays, signal, [repo](int value) {
|
connect(pruneOffsetDays, signal, [repo](int value) {
|
||||||
git::Config config = repo.config();
|
git::Config config = repo.gitConfig();
|
||||||
config.setValue("lfs.pruneoffsetdays", value);
|
config.setValue("lfs.pruneoffsetdays", value);
|
||||||
});
|
});
|
||||||
QHBoxLayout *pruneOffsetLayout = new QHBoxLayout;
|
QHBoxLayout *pruneOffsetLayout = new QHBoxLayout;
|
||||||
@ -628,7 +629,7 @@ public:
|
|||||||
bool fetchRecentEnabled = map.value("FetchRecentAlways").contains("true");
|
bool fetchRecentEnabled = map.value("FetchRecentAlways").contains("true");
|
||||||
fetchRecentAlways->setChecked(fetchRecentEnabled);
|
fetchRecentAlways->setChecked(fetchRecentEnabled);
|
||||||
connect(fetchRecentAlways, &QCheckBox::toggled, [repo](bool checked) {
|
connect(fetchRecentAlways, &QCheckBox::toggled, [repo](bool checked) {
|
||||||
git::Config config = repo.config();
|
git::Config config = repo.gitConfig();
|
||||||
config.setValue("lfs.fetchrecentalways", checked);
|
config.setValue("lfs.fetchrecentalways", checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -637,7 +638,7 @@ public:
|
|||||||
fetchRecentRefsDays->setValue(map.value("FetchRecentRefsDays").toInt());
|
fetchRecentRefsDays->setValue(map.value("FetchRecentRefsDays").toInt());
|
||||||
fetchRecentRefsDays->setEnabled(fetchRecentEnabled);
|
fetchRecentRefsDays->setEnabled(fetchRecentEnabled);
|
||||||
connect(fetchRecentRefsDays, signal, [repo](int value) {
|
connect(fetchRecentRefsDays, signal, [repo](int value) {
|
||||||
git::Config config = repo.config();
|
git::Config config = repo.gitConfig();
|
||||||
config.setValue("lfs.fetchrecentrefsdays", value);
|
config.setValue("lfs.fetchrecentrefsdays", value);
|
||||||
});
|
});
|
||||||
connect(fetchRecentAlways, &QCheckBox::toggled, this,
|
connect(fetchRecentAlways, &QCheckBox::toggled, this,
|
||||||
@ -655,7 +656,7 @@ public:
|
|||||||
map.value("FetchRecentCommitsDays").toInt());
|
map.value("FetchRecentCommitsDays").toInt());
|
||||||
fetchRecentCommitsDays->setEnabled(fetchRecentEnabled);
|
fetchRecentCommitsDays->setEnabled(fetchRecentEnabled);
|
||||||
connect(fetchRecentCommitsDays, signal, [repo](int value) {
|
connect(fetchRecentCommitsDays, signal, [repo](int value) {
|
||||||
git::Config config = repo.config();
|
git::Config config = repo.gitConfig();
|
||||||
config.setValue("lfs.fetchrecentcommitsdays", value);
|
config.setValue("lfs.fetchrecentcommitsdays", value);
|
||||||
});
|
});
|
||||||
connect(fetchRecentAlways, &QCheckBox::toggled, this,
|
connect(fetchRecentAlways, &QCheckBox::toggled, this,
|
||||||
|
@ -47,7 +47,7 @@ DeleteBranchDialog::DeleteBranchDialog(const git::Branch &branch,
|
|||||||
|
|
||||||
QString name = upstream.name().section('/', 1);
|
QString name = upstream.name().section('/', 1);
|
||||||
QString key = kBranchMergeFmt.arg(branch.name());
|
QString key = kBranchMergeFmt.arg(branch.name());
|
||||||
QString upstreamName = repo.config().value<QString>(key);
|
QString upstreamName = repo.gitConfig().value<QString>(key);
|
||||||
|
|
||||||
git::Remote remote = upstream.remote();
|
git::Remote remote = upstream.remote();
|
||||||
QString remoteName = remote.name();
|
QString remoteName = remote.name();
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
|
||||||
DiffPanel::DiffPanel(const git::Repository &repo, QWidget *parent)
|
DiffPanel::DiffPanel(const git::Repository &repo, QWidget *parent)
|
||||||
: QWidget(parent), mConfig(repo ? repo.config() : git::Config::global()) {
|
: QWidget(parent),
|
||||||
|
mConfig(repo ? repo.gitConfig() : git::Config::global()) {
|
||||||
// diff context
|
// diff context
|
||||||
QSpinBox *context = new QSpinBox(this);
|
QSpinBox *context = new QSpinBox(this);
|
||||||
QLabel *contextLabel = new QLabel(tr("lines"), this);
|
QLabel *contextLabel = new QLabel(tr("lines"), this);
|
||||||
|
@ -85,7 +85,7 @@ QVBoxLayout *ExternalToolsDialog::createUserDefinedLayout(const QString &type) {
|
|||||||
table->resizeColumnsToContents();
|
table->resizeColumnsToContents();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(footer, &Footer::minusClicked, [this, table, model] {
|
connect(footer, &Footer::minusClicked, [table, model] {
|
||||||
QModelIndexList indexes = table->selectionModel()->selectedRows(0);
|
QModelIndexList indexes = table->selectionModel()->selectedRows(0);
|
||||||
foreach (const QModelIndex &index, indexes)
|
foreach (const QModelIndex &index, indexes)
|
||||||
model->remove(index.data(Qt::DisplayRole).toString());
|
model->remove(index.data(Qt::DisplayRole).toString());
|
||||||
|
@ -90,7 +90,7 @@ RemoteDialog::RemoteDialog(Kind kind, RepoView *parent) : QDialog(parent) {
|
|||||||
if (ref.isValid()) {
|
if (ref.isValid()) {
|
||||||
QString key = QString("branch.%1.merge").arg(ref.name());
|
QString key = QString("branch.%1.merge").arg(ref.name());
|
||||||
git::Config config =
|
git::Config config =
|
||||||
RepoView::parentView(this)->repo().config();
|
RepoView::parentView(this)->repo().gitConfig();
|
||||||
value = config.value<QString>(key);
|
value = config.value<QString>(key);
|
||||||
}
|
}
|
||||||
mRemoteRef->setText(value);
|
mRemoteRef->setText(value);
|
||||||
|
58
src/dialogs/RenameBranchDialog.cpp
Normal file
58
src/dialogs/RenameBranchDialog.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// This software is licensed under the MIT License. The LICENSE.md file
|
||||||
|
// describes the conditions under which this software may be distributed.
|
||||||
|
//
|
||||||
|
// Author: Michael WERLE
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "RenameBranchDialog.h"
|
||||||
|
#include "git/Branch.h"
|
||||||
|
#include "ui/ExpandButton.h"
|
||||||
|
#include "ui/ReferenceList.h"
|
||||||
|
#include "ui/RepoView.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
RenameBranchDialog::RenameBranchDialog(const git::Repository &repo,
|
||||||
|
const git::Branch &branch,
|
||||||
|
QWidget *parent)
|
||||||
|
: QDialog(parent) {
|
||||||
|
Q_ASSERT(branch.isValid() && branch.isLocalBranch());
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
mName = new QLineEdit(branch.name(), this);
|
||||||
|
mName->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
|
||||||
|
mName->setMinimumWidth(QFontMetrics(mName->font()).averageCharWidth() * 40);
|
||||||
|
|
||||||
|
QFormLayout *form = new QFormLayout;
|
||||||
|
form->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||||
|
form->addRow(tr("Name:"), mName);
|
||||||
|
|
||||||
|
QDialogButtonBox *buttons = new QDialogButtonBox(this);
|
||||||
|
buttons->addButton(QDialogButtonBox::Cancel);
|
||||||
|
QPushButton *rename =
|
||||||
|
buttons->addButton(tr("Rename Branch"), QDialogButtonBox::AcceptRole);
|
||||||
|
rename->setEnabled(false);
|
||||||
|
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
|
layout->addLayout(form);
|
||||||
|
layout->addWidget(buttons);
|
||||||
|
|
||||||
|
// Update button when name text changes.
|
||||||
|
connect(mName, &QLineEdit::textChanged, [repo, rename](const QString &text) {
|
||||||
|
rename->setEnabled(git::Branch::isNameValid(text) &&
|
||||||
|
!repo.lookupBranch(text, GIT_BRANCH_LOCAL).isValid());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Perform the rename when the button is clicked
|
||||||
|
connect(rename, &QPushButton::clicked,
|
||||||
|
[this, branch] { git::Branch(branch).rename(mName->text()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RenameBranchDialog::name() const { return mName->text(); }
|
33
src/dialogs/RenameBranchDialog.h
Normal file
33
src/dialogs/RenameBranchDialog.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// This software is licensed under the MIT License. The LICENSE.md file
|
||||||
|
// describes the conditions under which this software may be distributed.
|
||||||
|
//
|
||||||
|
// Author: Michael WERLE
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RENAMEBRANCHDIALOG_H
|
||||||
|
#define RENAMEBRANCHDIALOG_H
|
||||||
|
|
||||||
|
#include "git/Branch.h"
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
|
||||||
|
namespace git {
|
||||||
|
class Reference;
|
||||||
|
class Repository;
|
||||||
|
} // namespace git
|
||||||
|
|
||||||
|
class RenameBranchDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenameBranchDialog(const git::Repository &repo, const git::Branch &branch,
|
||||||
|
QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLineEdit *mName;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -25,6 +25,7 @@
|
|||||||
#include "ui/MainWindow.h"
|
#include "ui/MainWindow.h"
|
||||||
#include "ui/MenuBar.h"
|
#include "ui/MenuBar.h"
|
||||||
#include "ui/RepoView.h"
|
#include "ui/RepoView.h"
|
||||||
|
#include "languages.h"
|
||||||
#include "update/Updater.h"
|
#include "update/Updater.h"
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -105,17 +106,23 @@ public:
|
|||||||
new QCheckBox(tr("Update submodules after pull and clone"), this);
|
new QCheckBox(tr("Update submodules after pull and clone"), this);
|
||||||
mAutoPrune = new QCheckBox(tr("Prune when fetching"), this);
|
mAutoPrune = new QCheckBox(tr("Prune when fetching"), this);
|
||||||
mNoTranslation = new QCheckBox(tr("No translation"), this);
|
mNoTranslation = new QCheckBox(tr("No translation"), this);
|
||||||
|
mLanguages = new QComboBox(this);
|
||||||
|
|
||||||
|
QMapIterator<const char *, const char *> i(Languages::languages);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
mLanguages->addItem(tr(i.key()), QVariant(i.value()));
|
||||||
|
}
|
||||||
|
|
||||||
mStoreCredentials =
|
mStoreCredentials =
|
||||||
new QCheckBox(tr("Store credentials in secure storage"), this);
|
new QCheckBox(tr("Store credentials in secure storage"), this);
|
||||||
|
|
||||||
|
mAvailableStores = new QComboBox(this);
|
||||||
|
|
||||||
QLabel *privacy = new QLabel(tr("<a href='view'>View privacy policy</a>"));
|
QLabel *privacy = new QLabel(tr("<a href='view'>View privacy policy</a>"));
|
||||||
connect(privacy, &QLabel::linkActivated,
|
connect(privacy, &QLabel::linkActivated,
|
||||||
[] { AboutDialog::openSharedInstance(AboutDialog::Privacy); });
|
[] { AboutDialog::openSharedInstance(AboutDialog::Privacy); });
|
||||||
|
|
||||||
mSingleInstance =
|
|
||||||
new QCheckBox(tr("Only allow a single running instance"), this);
|
|
||||||
|
|
||||||
QFormLayout *form = new QFormLayout;
|
QFormLayout *form = new QFormLayout;
|
||||||
form->addRow(tr("User name:"), mName);
|
form->addRow(tr("User name:"), mName);
|
||||||
form->addRow(tr("User email:"), mEmail);
|
form->addRow(tr("User email:"), mEmail);
|
||||||
@ -124,11 +131,18 @@ public:
|
|||||||
form->addRow(QString(), mPullUpdate);
|
form->addRow(QString(), mPullUpdate);
|
||||||
form->addRow(QString(), mAutoPrune);
|
form->addRow(QString(), mAutoPrune);
|
||||||
form->addRow(tr("Language:"), mNoTranslation);
|
form->addRow(tr("Language:"), mNoTranslation);
|
||||||
|
form->addRow(tr("Language:"), mLanguages);
|
||||||
form->addRow(tr("Credentials:"), mStoreCredentials);
|
form->addRow(tr("Credentials:"), mStoreCredentials);
|
||||||
|
form->addRow(tr("Credential store type:"), mAvailableStores);
|
||||||
form->addRow(QString(), privacy);
|
form->addRow(QString(), privacy);
|
||||||
|
|
||||||
|
mSingleInstance =
|
||||||
|
new QCheckBox(tr("Only allow a single running instance"), this);
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
||||||
form->addRow(tr("Single instance:"), mSingleInstance);
|
form->addRow(tr("Single instance:"), mSingleInstance);
|
||||||
|
#elif defined(Q_OS_MACX)
|
||||||
|
mSingleInstance->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
@ -179,11 +193,33 @@ public:
|
|||||||
Settings::instance()->setValue(Setting::Id::DontTranslate, checked);
|
Settings::instance()->setValue(Setting::Id::DontTranslate, checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(mStoreCredentials, &QCheckBox::toggled, [](bool checked) {
|
connect(mLanguages, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
Settings::instance()->setValue(Setting::Id::StoreCredentials, checked);
|
[this]() {
|
||||||
|
const auto &language = mLanguages->currentData().toString();
|
||||||
|
Settings::instance()->setValue(Setting::Id::Language, language);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(mStoreCredentials, &QCheckBox::toggled, [this](bool checked) {
|
||||||
|
git::Config config = git::Config::global();
|
||||||
|
mAvailableStores->setEnabled(checked);
|
||||||
|
if (checked) {
|
||||||
|
auto store = mAvailableStores->currentText();
|
||||||
|
config.setValue("credential.helper", store);
|
||||||
|
} else {
|
||||||
|
config.remove("credential.helper");
|
||||||
|
}
|
||||||
|
|
||||||
delete CredentialHelper::instance();
|
delete CredentialHelper::instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(mAvailableStores, &QComboBox::currentTextChanged,
|
||||||
|
[](const QString &text) {
|
||||||
|
git::Config config = git::Config::global();
|
||||||
|
config.setValue("credential.helper", text);
|
||||||
|
|
||||||
|
delete CredentialHelper::instance();
|
||||||
|
});
|
||||||
|
|
||||||
connect(mSingleInstance, &QCheckBox::toggled, [](bool checked) {
|
connect(mSingleInstance, &QCheckBox::toggled, [](bool checked) {
|
||||||
Settings::instance()->setValue(Setting::Id::AllowSingleInstanceOnly,
|
Settings::instance()->setValue(Setting::Id::AllowSingleInstanceOnly,
|
||||||
checked);
|
checked);
|
||||||
@ -196,6 +232,7 @@ public:
|
|||||||
mEmail->setText(config.value<QString>("user.email"));
|
mEmail->setText(config.value<QString>("user.email"));
|
||||||
|
|
||||||
Settings *settings = Settings::instance();
|
Settings *settings = Settings::instance();
|
||||||
|
|
||||||
mFetch->setChecked(
|
mFetch->setChecked(
|
||||||
settings->value(Setting::Id::FetchAutomatically).toBool());
|
settings->value(Setting::Id::FetchAutomatically).toBool());
|
||||||
mFetchMinutes->setValue(
|
mFetchMinutes->setValue(
|
||||||
@ -211,8 +248,25 @@ public:
|
|||||||
|
|
||||||
mNoTranslation->setChecked(
|
mNoTranslation->setChecked(
|
||||||
settings->value(Setting::Id::DontTranslate).toBool());
|
settings->value(Setting::Id::DontTranslate).toBool());
|
||||||
mStoreCredentials->setChecked(
|
|
||||||
settings->value(Setting::Id::StoreCredentials).toBool());
|
const auto &l = settings->value(Setting::Id::Language).toString();
|
||||||
|
for (int i = 0; i < mLanguages->count(); i++) {
|
||||||
|
if (mLanguages->itemData(i).toString() == l) {
|
||||||
|
mLanguages->setCurrentIndex(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto currentHelper = config.value<QString>("credential.helper");
|
||||||
|
auto checked = CredentialHelper::isHelperValid(currentHelper);
|
||||||
|
mStoreCredentials->setChecked(checked);
|
||||||
|
|
||||||
|
auto availableHelpers = CredentialHelper::getAvailableHelperNames();
|
||||||
|
foreach (auto helper, availableHelpers) {
|
||||||
|
mAvailableStores->addItem(helper);
|
||||||
|
}
|
||||||
|
mAvailableStores->setEditable(true);
|
||||||
|
mAvailableStores->setCurrentText(currentHelper);
|
||||||
|
|
||||||
mSingleInstance->setChecked(
|
mSingleInstance->setChecked(
|
||||||
settings->value(Setting::Id::AllowSingleInstanceOnly).toBool());
|
settings->value(Setting::Id::AllowSingleInstanceOnly).toBool());
|
||||||
@ -228,7 +282,9 @@ private:
|
|||||||
QCheckBox *mPullUpdate;
|
QCheckBox *mPullUpdate;
|
||||||
QCheckBox *mAutoPrune;
|
QCheckBox *mAutoPrune;
|
||||||
QCheckBox *mNoTranslation;
|
QCheckBox *mNoTranslation;
|
||||||
|
QComboBox *mLanguages;
|
||||||
QCheckBox *mStoreCredentials;
|
QCheckBox *mStoreCredentials;
|
||||||
|
QComboBox *mAvailableStores;
|
||||||
QCheckBox *mSingleInstance;
|
QCheckBox *mSingleInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,10 +117,10 @@ public:
|
|||||||
RecentRepository *repo = repos->repository(index.row());
|
RecentRepository *repo = repos->repository(index.row());
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
return mShowFullPath ? repo->path() : repo->name();
|
return mShowFullPath ? repo->gitpath() : repo->name();
|
||||||
|
|
||||||
case Qt::UserRole:
|
case Qt::UserRole:
|
||||||
return repo->path();
|
return repo->gitpath();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -698,7 +698,7 @@ void StartDialog::updateButtons() {
|
|||||||
open->setEnabled(false);
|
open->setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
Account *account = parent.data(AccountRole).value<Account *>();
|
Account *account = parent.data(AccountRole).value<Account *>();
|
||||||
if (Repository *repo = index.data(RepositoryRole).value<Repository *>()) {
|
if (nullptr != index.data(RepositoryRole).value<Repository *>()) {
|
||||||
if (account->repositoryPath(index.row()).isEmpty())
|
if (account->repositoryPath(index.row()).isEmpty())
|
||||||
clone = true;
|
clone = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
case Theme::Dark:
|
case Theme::Dark:
|
||||||
Settings::instance()->setValue(Setting::Id::ColorTheme, "Dark");
|
Settings::instance()->setValue(Setting::Id::ColorTheme, "Dark");
|
||||||
break;
|
break;
|
||||||
default:
|
case Theme::Default:
|
||||||
Settings::instance()->setValue(Setting::Id::ColorTheme, "Default");
|
Settings::instance()->setValue(Setting::Id::ColorTheme, "Default");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ public:
|
|||||||
virtual ~LexerLPeg() {}
|
virtual ~LexerLPeg() {}
|
||||||
|
|
||||||
/** Destroys the lexer object. */
|
/** Destroys the lexer object. */
|
||||||
void SCI_METHOD Release() {
|
void SCI_METHOD Release() override {
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexers");
|
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexers");
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
|
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
|
||||||
lua_pushnil(L), lua_settable(L, -3), lua_pop(L, 1); // sci_lexers
|
lua_pushnil(L), lua_settable(L, -3), lua_pop(L, 1); // sci_lexers
|
||||||
@ -429,7 +429,7 @@ public:
|
|||||||
* @param buffer The document interface.
|
* @param buffer The document interface.
|
||||||
*/
|
*/
|
||||||
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc,
|
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc,
|
||||||
int initStyle, IDocument *buffer) {
|
int initStyle, IDocument *buffer) override {
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(&props));
|
lua_pushlightuserdata(L, reinterpret_cast<void *>(&props));
|
||||||
lua_setfield(L, LUA_REGISTRYINDEX, "sci_props");
|
lua_setfield(L, LUA_REGISTRYINDEX, "sci_props");
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
|
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
|
||||||
@ -515,7 +515,7 @@ public:
|
|||||||
* @param buffer The document interface.
|
* @param buffer The document interface.
|
||||||
*/
|
*/
|
||||||
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc,
|
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc,
|
||||||
int initStyle, IDocument *buffer) {
|
int initStyle, IDocument *buffer) override {
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(&props));
|
lua_pushlightuserdata(L, reinterpret_cast<void *>(&props));
|
||||||
lua_setfield(L, LUA_REGISTRYINDEX, "sci_props");
|
lua_setfield(L, LUA_REGISTRYINDEX, "sci_props");
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
|
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
|
||||||
@ -552,7 +552,8 @@ public:
|
|||||||
* @param key The string keyword.
|
* @param key The string keyword.
|
||||||
* @param val The string value.
|
* @param val The string value.
|
||||||
*/
|
*/
|
||||||
Sci_Position SCI_METHOD PropertySet(const char *key, const char *value) {
|
Sci_Position SCI_METHOD PropertySet(const char *key,
|
||||||
|
const char *value) override {
|
||||||
const char *val = *value ? value : " ";
|
const char *val = *value ? value : " ";
|
||||||
props.Set(key, val, strlen(key), strlen(val)); // ensure property is cleared
|
props.Set(key, val, strlen(key), strlen(val)); // ensure property is cleared
|
||||||
return -1; // no need to re-lex
|
return -1; // no need to re-lex
|
||||||
@ -566,7 +567,7 @@ public:
|
|||||||
* @param arg The argument.
|
* @param arg The argument.
|
||||||
* @return void *data
|
* @return void *data
|
||||||
*/
|
*/
|
||||||
void *SCI_METHOD PrivateCall(int code, void *arg) {
|
void *SCI_METHOD PrivateCall(int code, void *arg) override {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case SCI_GETDIRECTFUNCTION:
|
case SCI_GETDIRECTFUNCTION:
|
||||||
fn = reinterpret_cast<SciFnDirect>(arg);
|
fn = reinterpret_cast<SciFnDirect>(arg);
|
||||||
@ -603,12 +604,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCI_METHOD Version() const { return 0; }
|
int SCI_METHOD Version() const override { return 0; }
|
||||||
const char *SCI_METHOD PropertyNames() { return ""; }
|
const char *SCI_METHOD PropertyNames() override { return ""; }
|
||||||
int SCI_METHOD PropertyType(const char *) { return 0; }
|
int SCI_METHOD PropertyType(const char *) override { return 0; }
|
||||||
const char *SCI_METHOD DescribeProperty(const char *) { return ""; }
|
const char *SCI_METHOD DescribeProperty(const char *) override { return ""; }
|
||||||
const char *SCI_METHOD DescribeWordListSets() { return ""; }
|
const char *SCI_METHOD DescribeWordListSets() override { return ""; }
|
||||||
Sci_Position SCI_METHOD WordListSet(int, const char *) { return -1; }
|
Sci_Position SCI_METHOD WordListSet(int, const char *) override { return -1; }
|
||||||
|
|
||||||
int SCI_METHOD LineEndTypesSupported() noexcept override {
|
int SCI_METHOD LineEndTypesSupported() noexcept override {
|
||||||
return SC_LINE_END_TYPE_UNICODE;
|
return SC_LINE_END_TYPE_UNICODE;
|
||||||
@ -636,7 +637,7 @@ public:
|
|||||||
|
|
||||||
int SCI_METHOD GetIdentifier() override { return 0; }
|
int SCI_METHOD GetIdentifier() override { return 0; }
|
||||||
|
|
||||||
const char *SCI_METHOD PropertyGet(const char *key) { return ""; }
|
const char *SCI_METHOD PropertyGet(const char *key) override { return ""; }
|
||||||
|
|
||||||
/** Constructs a new instance of the lexer. */
|
/** Constructs a new instance of the lexer. */
|
||||||
static ILexer5 *LexerFactoryLPeg() { return new LexerLPeg(); }
|
static ILexer5 *LexerFactoryLPeg() { return new LexerLPeg(); }
|
||||||
|
@ -128,7 +128,7 @@ void SurfaceImpl::Polygon(Point *pts, size_t npts, ColourDesired fore,
|
|||||||
PenColour(fore);
|
PenColour(fore);
|
||||||
|
|
||||||
QVarLengthArray<QPoint, 8> qpts(npts);
|
QVarLengthArray<QPoint, 8> qpts(npts);
|
||||||
for (int i = 0; i < npts; i++)
|
for (size_t i = 0; i < npts; i++)
|
||||||
qpts[i] = QPoint(pts[i].x, pts[i].y);
|
qpts[i] = QPoint(pts[i].x, pts[i].y);
|
||||||
|
|
||||||
QPainter *painter = GetPainter();
|
QPainter *painter = GetPainter();
|
||||||
@ -306,7 +306,7 @@ void SurfaceImpl::MeasureWidths(Font &font, std::string_view s,
|
|||||||
QTextLine tl = tlay.createLine();
|
QTextLine tl = tlay.createLine();
|
||||||
tlay.endLayout();
|
tlay.endLayout();
|
||||||
|
|
||||||
int i = 0;
|
size_t i = 0;
|
||||||
int ui = 0;
|
int ui = 0;
|
||||||
int fit = su.size();
|
int fit = su.size();
|
||||||
const unsigned char *us = reinterpret_cast<const unsigned char *>(s.data());
|
const unsigned char *us = reinterpret_cast<const unsigned char *>(s.data());
|
||||||
@ -468,9 +468,6 @@ void Window::SetCursor(Cursor curs) {
|
|||||||
case cursorText:
|
case cursorText:
|
||||||
shape = Qt::IBeamCursor;
|
shape = Qt::IBeamCursor;
|
||||||
break;
|
break;
|
||||||
case cursorArrow:
|
|
||||||
shape = Qt::ArrowCursor;
|
|
||||||
break;
|
|
||||||
case cursorUp:
|
case cursorUp:
|
||||||
shape = Qt::UpArrowCursor;
|
shape = Qt::UpArrowCursor;
|
||||||
break;
|
break;
|
||||||
|
@ -185,7 +185,7 @@ void ScintillaQt::paintEvent(QPaintEvent *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScintillaQt::wheelEvent(QWheelEvent *event) {
|
void ScintillaQt::wheelEvent(QWheelEvent *event) {
|
||||||
if (event->orientation() == Qt::Horizontal) {
|
if (event->angleDelta().x() != 0) {
|
||||||
if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
|
if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
|
||||||
event->ignore();
|
event->ignore();
|
||||||
else
|
else
|
||||||
@ -194,7 +194,7 @@ void ScintillaQt::wheelEvent(QWheelEvent *event) {
|
|||||||
if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
|
if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
|
||||||
// Zoom! We play with the font sizes in the styles.
|
// Zoom! We play with the font sizes in the styles.
|
||||||
// Number of steps/line is ignored, we just care if sizing up or down
|
// Number of steps/line is ignored, we just care if sizing up or down
|
||||||
if (event->delta() > 0) {
|
if (event->angleDelta().y() > 0) {
|
||||||
KeyCommand(SCI_ZOOMIN);
|
KeyCommand(SCI_ZOOMIN);
|
||||||
} else {
|
} else {
|
||||||
KeyCommand(SCI_ZOOMOUT);
|
KeyCommand(SCI_ZOOMOUT);
|
||||||
@ -327,8 +327,7 @@ void ScintillaQt::keyPressEvent(QKeyEvent *event) {
|
|||||||
|
|
||||||
QString text = event->text();
|
QString text = event->text();
|
||||||
if (input && !text.isEmpty() && text[0].isPrint()) {
|
if (input && !text.isEmpty() && text[0].isPrint()) {
|
||||||
QByteArray utext = text.toUtf8();
|
InsertCharacter(text.toStdString(), CharacterSource::directInput);
|
||||||
AddCharUTF(utext.data(), utext.size());
|
|
||||||
} else {
|
} else {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
@ -355,7 +354,7 @@ static int modifierTranslated(int sciModifier) {
|
|||||||
void ScintillaQt::mousePressEvent(QMouseEvent *event) {
|
void ScintillaQt::mousePressEvent(QMouseEvent *event) {
|
||||||
Point pos = PointFromQPoint(event->pos());
|
Point pos = PointFromQPoint(event->pos());
|
||||||
|
|
||||||
if (event->button() == Qt::MidButton &&
|
if (event->button() == Qt::MiddleButton &&
|
||||||
QApplication::clipboard()->supportsSelection()) {
|
QApplication::clipboard()->supportsSelection()) {
|
||||||
SelectionPosition selPos =
|
SelectionPosition selPos =
|
||||||
SPositionFromLocation(pos, false, false, UserVirtualSpace());
|
SPositionFromLocation(pos, false, false, UserVirtualSpace());
|
||||||
@ -440,6 +439,7 @@ void ScintillaQt::dragEnterEvent(QDragEnterEvent *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScintillaQt::dragLeaveEvent(QDragLeaveEvent *event) {
|
void ScintillaQt::dragLeaveEvent(QDragLeaveEvent *event) {
|
||||||
|
Q_UNUSED(event);
|
||||||
SetDragPosition(SelectionPosition(Sci::invalidPosition));
|
SetDragPosition(SelectionPosition(Sci::invalidPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,9 +520,8 @@ void ScintillaQt::inputMethodEvent(QInputMethodEvent *event) {
|
|||||||
const unsigned int ucWidth = commitStr.at(i).isHighSurrogate() ? 2 : 1;
|
const unsigned int ucWidth = commitStr.at(i).isHighSurrogate() ? 2 : 1;
|
||||||
const QString oneCharUTF16 = commitStr.mid(i, ucWidth);
|
const QString oneCharUTF16 = commitStr.mid(i, ucWidth);
|
||||||
const QByteArray oneChar = oneCharUTF16.toUtf8();
|
const QByteArray oneChar = oneCharUTF16.toUtf8();
|
||||||
const int oneCharLen = oneChar.length();
|
|
||||||
|
|
||||||
AddCharUTF(oneChar.data(), oneCharLen);
|
InsertCharacter(oneChar.toStdString(), CharacterSource::directInput);
|
||||||
i += ucWidth;
|
i += ucWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +567,7 @@ void ScintillaQt::inputMethodEvent(QInputMethodEvent *event) {
|
|||||||
indicator = SC_INDICATOR_CONVERTED;
|
indicator = SC_INDICATOR_CONVERTED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case QTextCharFormat::DashDotDotLine:
|
||||||
indicator = SC_INDICATOR_UNKNOWN;
|
indicator = SC_INDICATOR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +604,7 @@ void ScintillaQt::inputMethodEvent(QInputMethodEvent *event) {
|
|||||||
numBytes += oneCharLen;
|
numBytes += oneCharLen;
|
||||||
imeCharPos[i + 1] = numBytes;
|
imeCharPos[i + 1] = numBytes;
|
||||||
|
|
||||||
AddCharUTF(oneChar.data(), oneCharLen);
|
InsertCharacter(oneChar.toStdString(), CharacterSource::directInput);
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// Segment marked with imeCaretPos is for target input.
|
// Segment marked with imeCaretPos is for target input.
|
||||||
@ -642,7 +641,7 @@ QVariant ScintillaQt::inputMethodQuery(Qt::InputMethodQuery query) const {
|
|||||||
int line = send(SCI_LINEFROMPOSITION, pos);
|
int line = send(SCI_LINEFROMPOSITION, pos);
|
||||||
|
|
||||||
switch (query) {
|
switch (query) {
|
||||||
case Qt::ImMicroFocus: {
|
case Qt::ImCursorRectangle: {
|
||||||
int startPos = (preeditPos >= 0) ? preeditPos : pos;
|
int startPos = (preeditPos >= 0) ? preeditPos : pos;
|
||||||
Point pt =
|
Point pt =
|
||||||
const_cast<ScintillaQt *>(this)->LocationFromPosition(startPos);
|
const_cast<ScintillaQt *>(this)->LocationFromPosition(startPos);
|
||||||
@ -691,9 +690,23 @@ QVariant ScintillaQt::inputMethodQuery(Qt::InputMethodQuery query) const {
|
|||||||
return buffer.constData();
|
return buffer.constData();
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
case Qt::ImEnabled: // fall through
|
||||||
return QVariant();
|
case Qt::ImAnchorPosition: // fall through
|
||||||
|
case Qt::ImHints: // fall through
|
||||||
|
case Qt::ImMaximumTextLength: // fall through
|
||||||
|
case Qt::ImPreferredLanguage: // fall through
|
||||||
|
case Qt::ImAbsolutePosition: // fall through
|
||||||
|
case Qt::ImTextBeforeCursor: // fall through
|
||||||
|
case Qt::ImTextAfterCursor: // fall through
|
||||||
|
case Qt::ImEnterKeyType: // fall through
|
||||||
|
case Qt::ImAnchorRectangle: // fall through
|
||||||
|
case Qt::ImInputItemClipRectangle: // fall through
|
||||||
|
case Qt::ImPlatformData: // fall through
|
||||||
|
case Qt::ImQueryInput: // fall through
|
||||||
|
case Qt::ImQueryAll: // fall through
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScintillaQt::PasteFromMode(QClipboard::Mode clipboardMode) {
|
void ScintillaQt::PasteFromMode(QClipboard::Mode clipboardMode) {
|
||||||
|
@ -43,7 +43,9 @@ QPixmap stagedUnstagedIcon(const bool &checked, const QColor &background,
|
|||||||
QRect(QPoint(0, 0), QSize(fontHeight - 2, fontHeight - 2)));
|
QRect(QPoint(0, 0), QSize(fontHeight - 2, fontHeight - 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FLATPAK)
|
||||||
const float textHeightFactorCheckBoxSize = 2.0;
|
const float textHeightFactorCheckBoxSize = 2.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ public:
|
|||||||
|
|
||||||
QList<Diagnostic> diagnostics(int line);
|
QList<Diagnostic> diagnostics(int line);
|
||||||
void addDiagnostic(int line, const Diagnostic &diag);
|
void addDiagnostic(int line, const Diagnostic &diag);
|
||||||
sptr_t WndProc(unsigned int message, uptr_t wParam, sptr_t lParam);
|
sptr_t WndProc(unsigned int message, uptr_t wParam, sptr_t lParam) override;
|
||||||
|
|
||||||
// Make wheel event public.
|
// Make wheel event public.
|
||||||
// FIXME: This should be an event filter?
|
// FIXME: This should be an event filter?
|
||||||
@ -154,7 +154,7 @@ private:
|
|||||||
int diagnosticMarker(int line);
|
int diagnosticMarker(int line);
|
||||||
void loadMarkerIcon(Marker marker, const QIcon &icon);
|
void loadMarkerIcon(Marker marker, const QIcon &icon);
|
||||||
void loadMarkerPixmap(Marker marker, const QPixmap &pixmap);
|
void loadMarkerPixmap(Marker marker, const QPixmap &pixmap);
|
||||||
void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
|
void AddToPopUp(const char *label, int cmd = 0, bool enabled = true) override;
|
||||||
void ContextMenu(Scintilla::Point pt);
|
void ContextMenu(Scintilla::Point pt);
|
||||||
|
|
||||||
QString mPath;
|
QString mPath;
|
||||||
|
@ -129,11 +129,11 @@ void Branch::remove(bool force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Branch::isRebase() const {
|
bool Branch::isRebase() const {
|
||||||
return repo().config().value<bool>(kRebaseFmt.arg(name()));
|
return repo().gitConfig().value<bool>(kRebaseFmt.arg(name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Branch::setRebase(bool checked) {
|
void Branch::setRebase(bool checked) {
|
||||||
repo().config().setValue(kRebaseFmt.arg(name()), checked);
|
repo().gitConfig().setValue(kRebaseFmt.arg(name()), checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotatedCommit Branch::annotatedCommitFromFetchHead() const {
|
AnnotatedCommit Branch::annotatedCommitFromFetchHead() const {
|
||||||
|
@ -251,7 +251,8 @@ bool Commit::amend(const Signature &author, const Signature &committer,
|
|||||||
return !error;
|
return !error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Commit::reset(git_reset_t type, const QStringList &paths) const {
|
bool Commit::reset(git_reset_t type, const QStringList &paths,
|
||||||
|
bool triggerReferenceUpdated) const {
|
||||||
QVector<char *> rawPaths;
|
QVector<char *> rawPaths;
|
||||||
QVector<QByteArray> storage;
|
QVector<QByteArray> storage;
|
||||||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||||||
@ -271,7 +272,9 @@ bool Commit::reset(git_reset_t type, const QStringList &paths) const {
|
|||||||
Repository repo = this->repo();
|
Repository repo = this->repo();
|
||||||
int state = repo.state();
|
int state = repo.state();
|
||||||
int error = git_reset(repo, d.data(), type, &opts);
|
int error = git_reset(repo, d.data(), type, &opts);
|
||||||
emit repo.notifier()->referenceUpdated(repo.head());
|
if (triggerReferenceUpdated)
|
||||||
|
emit repo.notifier()->referenceUpdated(repo.head(),
|
||||||
|
type == git_reset_t::GIT_RESET_HARD);
|
||||||
if (repo.state() != state) {
|
if (repo.state() != state) {
|
||||||
Patch::clearConflictResolutions(repo);
|
Patch::clearConflictResolutions(repo);
|
||||||
emit repo.notifier()->stateChanged();
|
emit repo.notifier()->stateChanged();
|
||||||
|
@ -70,7 +70,8 @@ public:
|
|||||||
|
|
||||||
// Reset HEAD to this commit.
|
// Reset HEAD to this commit.
|
||||||
bool reset(git_reset_t type = GIT_RESET_MIXED,
|
bool reset(git_reset_t type = GIT_RESET_MIXED,
|
||||||
const QStringList &paths = QStringList()) const;
|
const QStringList &paths = QStringList(),
|
||||||
|
bool triggerReferenceUpdated = true) const;
|
||||||
|
|
||||||
// favorite commits
|
// favorite commits
|
||||||
bool isStarred() const;
|
bool isStarred() const;
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
#include "Diff.h"
|
#include "Diff.h"
|
||||||
#include "Patch.h"
|
#include "Patch.h"
|
||||||
|
#include "Debug.h"
|
||||||
#include "git2/patch.h"
|
#include "git2/patch.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
bool containsPath(QString &str, QString &occurence, Qt::CaseSensitivity cs) {
|
bool containsPath(QString &str, QString &occurence, Qt::CaseSensitivity cs) {
|
||||||
if (str.contains(occurence, cs)) {
|
if (str.contains(occurence, cs)) {
|
||||||
@ -108,13 +108,13 @@ QByteArray Diff::print() {
|
|||||||
QByteArray diff;
|
QByteArray diff;
|
||||||
for (auto file : data.files) {
|
for (auto file : data.files) {
|
||||||
for (auto hunk : file.hunks) {
|
for (auto hunk : file.hunks) {
|
||||||
diff.append(hunk.header);
|
diff.append(hunk.header.toUtf8());
|
||||||
|
|
||||||
for (auto line : hunk.lines)
|
for (auto line : hunk.lines)
|
||||||
diff.append(line);
|
diff.append(line.toUtf8());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << QString(diff);
|
Debug(QString(diff));
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +173,9 @@ void Diff::findSimilar(bool untracked) {
|
|||||||
if (untracked)
|
if (untracked)
|
||||||
opts.flags = GIT_DIFF_FIND_FOR_UNTRACKED;
|
opts.flags = GIT_DIFF_FIND_FOR_UNTRACKED;
|
||||||
|
|
||||||
|
if (!isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
git_diff_find_similar(d->diff, &opts);
|
git_diff_find_similar(d->diff, &opts);
|
||||||
d->resetMap();
|
d->resetMap();
|
||||||
}
|
}
|
||||||
@ -195,6 +198,8 @@ void Diff::sort(SortRole role, Qt::SortOrder order) {
|
|||||||
: (rhsStatus < lhsStatus);
|
: (rhsStatus < lhsStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(role)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,10 @@ Id Index::headId(const QString &path, uint32_t *mode) const {
|
|||||||
return Id();
|
return Id();
|
||||||
|
|
||||||
git_tree_entry *entry = nullptr;
|
git_tree_entry *entry = nullptr;
|
||||||
if (git_tree_entry_bypath(&entry, commit.tree(), path.toUtf8()))
|
const auto tree = commit.tree();
|
||||||
|
if (!tree.isValid())
|
||||||
|
return Id(); // broken repository?
|
||||||
|
if (git_tree_entry_bypath(&entry, tree, path.toUtf8()))
|
||||||
return Id();
|
return Id();
|
||||||
|
|
||||||
if (mode)
|
if (mode)
|
||||||
|
@ -195,7 +195,7 @@ QByteArray Patch::header(int hidx) const {
|
|||||||
|
|
||||||
const git_diff_hunk *hunk = nullptr;
|
const git_diff_hunk *hunk = nullptr;
|
||||||
int result = git_patch_get_hunk(&hunk, nullptr, d.data(), hidx);
|
int result = git_patch_get_hunk(&hunk, nullptr, d.data(), hidx);
|
||||||
return !result ? hunk->header : QByteArray();
|
return (GIT_OK == result) ? hunk->header : QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
const git_diff_hunk *Patch::header_struct(int hidx) const {
|
const git_diff_hunk *Patch::header_struct(int hidx) const {
|
||||||
@ -204,7 +204,7 @@ const git_diff_hunk *Patch::header_struct(int hidx) const {
|
|||||||
|
|
||||||
const git_diff_hunk *hunk = nullptr;
|
const git_diff_hunk *hunk = nullptr;
|
||||||
int result = git_patch_get_hunk(&hunk, nullptr, d.data(), hidx);
|
int result = git_patch_get_hunk(&hunk, nullptr, d.data(), hidx);
|
||||||
return hunk;
|
return (GIT_OK == result) ? hunk : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Patch::lineCount(int hidx) const {
|
int Patch::lineCount(int hidx) const {
|
||||||
@ -235,7 +235,7 @@ char Patch::lineOrigin(int hidx, int ln) const {
|
|||||||
|
|
||||||
const git_diff_line *line = nullptr;
|
const git_diff_line *line = nullptr;
|
||||||
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx, ln);
|
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx, ln);
|
||||||
return !result ? line->origin : GIT_DIFF_LINE_CONTEXT;
|
return (GIT_OK == result) ? line->origin : GIT_DIFF_LINE_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Patch::lineNumber(int hidx, int ln, Diff::File file) const {
|
int Patch::lineNumber(int hidx, int ln, Diff::File file) const {
|
||||||
@ -256,7 +256,7 @@ git_off_t Patch::contentOffset(int hidx) const {
|
|||||||
const git_diff_line *line = nullptr;
|
const git_diff_line *line = nullptr;
|
||||||
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx,
|
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx,
|
||||||
0); // TODO: line index 0?
|
0); // TODO: line index 0?
|
||||||
return result == 0 ? line->content_offset : 0;
|
return (GIT_OK == result) ? line->content_offset : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Patch::lineContent(int hidx, int ln) const {
|
QByteArray Patch::lineContent(int hidx, int ln) const {
|
||||||
@ -265,7 +265,8 @@ QByteArray Patch::lineContent(int hidx, int ln) const {
|
|||||||
|
|
||||||
const git_diff_line *line = nullptr;
|
const git_diff_line *line = nullptr;
|
||||||
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx, ln);
|
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx, ln);
|
||||||
return !result ? QByteArray(line->content, line->content_len) : QByteArray();
|
return (GIT_OK == result) ? QByteArray(line->content, line->content_len)
|
||||||
|
: QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
Patch::ConflictResolution Patch::conflictResolution(int hidx) {
|
Patch::ConflictResolution Patch::conflictResolution(int hidx) {
|
||||||
@ -435,6 +436,7 @@ void Patch::apply(QList<QList<QByteArray>> &image, int hidx, int start_line,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// no-op
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ const git_rebase_operation *Rebase::operation(size_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Rebase::hasNext() const {
|
bool Rebase::hasNext() const {
|
||||||
int index = currentIndex();
|
size_t index = currentIndex();
|
||||||
int count = git_rebase_operation_entrycount(d.data());
|
size_t count = git_rebase_operation_entrycount(d.data());
|
||||||
return (count > 0 && (index == GIT_REBASE_NO_OPERATION || index < count - 1));
|
return (count > 0 && (index == GIT_REBASE_NO_OPERATION || index < count - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "Branch.h"
|
#include "Branch.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Id.h"
|
#include "Id.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
#include "TagRef.h"
|
#include "TagRef.h"
|
||||||
#include "git2/buffer.h"
|
#include "git2/buffer.h"
|
||||||
#include "git2/clone.h"
|
#include "git2/clone.h"
|
||||||
@ -423,7 +424,7 @@ int Remote::Callbacks::certificate(git_cert *cert, int valid, const char *host,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Repository repo = reinterpret_cast<Remote::Callbacks *>(payload)->repo();
|
Repository repo = reinterpret_cast<Remote::Callbacks *>(payload)->repo();
|
||||||
Config config = repo.isValid() ? repo.config() : Config::global();
|
Config config = repo.isValid() ? repo.gitConfig() : Config::global();
|
||||||
if (!config.value<bool>("http.sslVerify", true))
|
if (!config.value<bool>("http.sslVerify", true))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -444,9 +445,10 @@ int Remote::Callbacks::transfer(const git_indexer_progress *stats,
|
|||||||
case Resolve:
|
case Resolve:
|
||||||
return cbs->resolve(stats->total_deltas, stats->indexed_deltas) ? 0 : -1;
|
return cbs->resolve(stats->total_deltas, stats->indexed_deltas) ? 0 : -1;
|
||||||
|
|
||||||
default:
|
case Update:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Remote::Callbacks::update(const char *name, const git_oid *a,
|
int Remote::Callbacks::update(const char *name, const git_oid *a,
|
||||||
@ -596,7 +598,7 @@ Result Remote::push(Callbacks *callbacks, const Reference &src,
|
|||||||
refspec += ":" + dst;
|
refspec += ":" + dst;
|
||||||
} else {
|
} else {
|
||||||
QString key = QString("branch.%1.merge").arg(src.name());
|
QString key = QString("branch.%1.merge").arg(src.name());
|
||||||
QString upstream = repo.config().value<QString>(key);
|
QString upstream = repo.gitConfig().value<QString>(key);
|
||||||
if (!upstream.isEmpty())
|
if (!upstream.isEmpty())
|
||||||
refspec += ":" + upstream;
|
refspec += ":" + upstream;
|
||||||
}
|
}
|
||||||
@ -674,7 +676,7 @@ void Remote::log(const QString &text) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
||||||
QTextStream(&file) << time << " - " << text << endl;
|
QTextStream(&file) << time << " - " << text << Qt::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace git
|
} // namespace git
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "FilterList.h"
|
#include "FilterList.h"
|
||||||
#include "Index.h"
|
#include "Index.h"
|
||||||
#include "Patch.h"
|
#include "Patch.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
#include "Rebase.h"
|
#include "Rebase.h"
|
||||||
#include "Reference.h"
|
#include "Reference.h"
|
||||||
#include "Remote.h"
|
#include "Remote.h"
|
||||||
@ -151,7 +152,14 @@ Repository::Repository(git_repository *repo) : d(registerRepository(repo)) {}
|
|||||||
|
|
||||||
Repository::operator git_repository *() const { return d->repo; }
|
Repository::operator git_repository *() const { return d->repo; }
|
||||||
|
|
||||||
QDir Repository::dir() const { return QDir(git_repository_path(d->repo)); }
|
QDir Repository::dir(bool includeGitFolder) const {
|
||||||
|
QDir dir(git_repository_path(d->repo));
|
||||||
|
if (!includeGitFolder) {
|
||||||
|
assert(dir.dirName() == ".git");
|
||||||
|
assert(dir.cdUp());
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
QDir Repository::workdir() const {
|
QDir Repository::workdir() const {
|
||||||
return isBare() ? dir() : QDir(git_repository_workdir(d->repo));
|
return isBare() ? dir() : QDir(git_repository_workdir(d->repo));
|
||||||
@ -173,12 +181,16 @@ QString Repository::message() const {
|
|||||||
return QString::fromUtf8(buf.ptr, buf.size);
|
return QString::fromUtf8(buf.ptr, buf.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Config Repository::config() const {
|
// Config file used for git specific configs
|
||||||
|
// config file in <Repository>/.git/config
|
||||||
|
Config Repository::gitConfig() const {
|
||||||
git_config *config = nullptr;
|
git_config *config = nullptr;
|
||||||
git_repository_config(&config, d->repo);
|
git_repository_config(&config, d->repo);
|
||||||
return Config(config);
|
return Config(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config file used for app specific configs
|
||||||
|
// config file in <Repository>/.git/gittyup/config
|
||||||
Config Repository::appConfig() const {
|
Config Repository::appConfig() const {
|
||||||
Config config = Config::appGlobal();
|
Config config = Config::appGlobal();
|
||||||
QString path = appDir().filePath(kConfigFile);
|
QString path = appDir().filePath(kConfigFile);
|
||||||
@ -305,8 +317,11 @@ Diff Repository::status(const Index &index, Diff::Callbacks *callbacks,
|
|||||||
Diff Repository::diffTreeToIndex(const Tree &tree, const Index &index,
|
Diff Repository::diffTreeToIndex(const Tree &tree, const Index &index,
|
||||||
bool ignoreWhitespace) const {
|
bool ignoreWhitespace) const {
|
||||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS |
|
opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE;
|
||||||
GIT_DIFF_INCLUDE_TYPECHANGE;
|
|
||||||
|
if (!appConfig().value<bool>("untracked.hide", false))
|
||||||
|
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS;
|
||||||
|
|
||||||
if (ignoreWhitespace)
|
if (ignoreWhitespace)
|
||||||
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
|
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
|
||||||
|
|
||||||
@ -319,8 +334,11 @@ Diff Repository::diffIndexToWorkdir(const Index &index,
|
|||||||
Diff::Callbacks *callbacks,
|
Diff::Callbacks *callbacks,
|
||||||
bool ignoreWhitespace) const {
|
bool ignoreWhitespace) const {
|
||||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
opts.flags |= (GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS |
|
opts.flags |= (GIT_DIFF_DISABLE_MMAP | GIT_DIFF_INCLUDE_TYPECHANGE);
|
||||||
GIT_DIFF_DISABLE_MMAP | GIT_DIFF_INCLUDE_TYPECHANGE);
|
|
||||||
|
if (!appConfig().value<bool>("untracked.hide", false))
|
||||||
|
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS;
|
||||||
|
|
||||||
if (ignoreWhitespace)
|
if (ignoreWhitespace)
|
||||||
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
|
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
|
||||||
|
|
||||||
@ -477,7 +495,7 @@ QStringList Repository::existingTags() const {
|
|||||||
|
|
||||||
QStringList list;
|
QStringList list;
|
||||||
|
|
||||||
for (int i = 0; i < array.count; i++) {
|
for (size_t i = 0; i < array.count; i++) {
|
||||||
list.append(array.strings[i]);
|
list.append(array.strings[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,6 +636,7 @@ Commit Repository::commit(const Signature &author, const Signature &committer,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// no-op
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,7 +753,7 @@ QList<Remote> Repository::remotes() const {
|
|||||||
return QList<Remote>();
|
return QList<Remote>();
|
||||||
|
|
||||||
QList<Remote> remotes;
|
QList<Remote> remotes;
|
||||||
for (int i = 0; i < names.count; ++i) {
|
for (size_t i = 0; i < names.count; ++i) {
|
||||||
if (Remote remote = lookupRemote(names.strings[i]))
|
if (Remote remote = lookupRemote(names.strings[i]))
|
||||||
remotes.append(remote);
|
remotes.append(remote);
|
||||||
}
|
}
|
||||||
@ -889,8 +908,10 @@ void Repository::rebase(const AnnotatedCommit &mergeHead,
|
|||||||
git_rebase_init(&r, d->repo, nullptr, mergeHead, nullptr, &opts);
|
git_rebase_init(&r, d->repo, nullptr, mergeHead, nullptr, &opts);
|
||||||
auto rebase = git::Rebase(d->repo, r, overrideUser, overrideEmail);
|
auto rebase = git::Rebase(d->repo, r, overrideUser, overrideEmail);
|
||||||
|
|
||||||
if (!rebase.isValid())
|
if (!rebase.isValid()) {
|
||||||
emit d->notifier->rebaseInitError();
|
emit d->notifier->rebaseInitError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// start rebasing
|
// start rebasing
|
||||||
rebaseContinue(QStringLiteral(""));
|
rebaseContinue(QStringLiteral(""));
|
||||||
@ -920,7 +941,6 @@ void Repository::rebaseContinue(const QString &commitMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Loop over rebase operations.
|
// Loop over rebase operations.
|
||||||
int count = r.count();
|
|
||||||
while (r.hasNext()) {
|
while (r.hasNext()) {
|
||||||
git::Commit before = r.next();
|
git::Commit before = r.next();
|
||||||
if (!before.isValid()) {
|
if (!before.isValid()) {
|
||||||
@ -1010,7 +1030,7 @@ void Repository::cleanupState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QTextCodec *Repository::codec() const {
|
QTextCodec *Repository::codec() const {
|
||||||
QString encoding = config().value<QString>("gui.encoding");
|
QString encoding = gitConfig().value<QString>("gui.encoding");
|
||||||
QTextCodec *codec = QTextCodec::codecForName(encoding.toUtf8());
|
QTextCodec *codec = QTextCodec::codecForName(encoding.toUtf8());
|
||||||
return codec ? codec : QTextCodec::codecForLocale();
|
return codec ? codec : QTextCodec::codecForLocale();
|
||||||
}
|
}
|
||||||
@ -1040,7 +1060,7 @@ QStringList Repository::lfsEnvironment() {
|
|||||||
|
|
||||||
Repository::LfsTracking Repository::lfsTracked() {
|
Repository::LfsTracking Repository::lfsTracked() {
|
||||||
QString output = lfsExecute({"track"});
|
QString output = lfsExecute({"track"});
|
||||||
QStringList lines = output.split('\n', QString::SkipEmptyParts);
|
QStringList lines = output.split('\n', Qt::SkipEmptyParts);
|
||||||
if (!lines.isEmpty())
|
if (!lines.isEmpty())
|
||||||
lines.removeFirst();
|
lines.removeFirst();
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public:
|
|||||||
|
|
||||||
RepositoryNotifier *notifier() const { return d->notifier; }
|
RepositoryNotifier *notifier() const { return d->notifier; }
|
||||||
|
|
||||||
QDir dir() const;
|
QDir dir(bool includeGitFolder = true) const;
|
||||||
QDir workdir() const;
|
QDir workdir() const;
|
||||||
QDir appDir() const;
|
QDir appDir() const;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ public:
|
|||||||
QString message() const;
|
QString message() const;
|
||||||
|
|
||||||
// config
|
// config
|
||||||
Config config() const;
|
Config gitConfig() const;
|
||||||
Config appConfig() const;
|
Config appConfig() const;
|
||||||
|
|
||||||
// bare
|
// bare
|
||||||
@ -316,7 +316,7 @@ signals:
|
|||||||
void referenceAdded(const Reference &ref);
|
void referenceAdded(const Reference &ref);
|
||||||
void referenceAboutToBeRemoved(const Reference &ref);
|
void referenceAboutToBeRemoved(const Reference &ref);
|
||||||
void referenceRemoved(const QString &name);
|
void referenceRemoved(const QString &name);
|
||||||
void referenceUpdated(const Reference &ref);
|
void referenceUpdated(const Reference &ref, bool restoreSelection = false);
|
||||||
|
|
||||||
void remoteAboutToBeAdded(const QString &name);
|
void remoteAboutToBeAdded(const QString &name);
|
||||||
void remoteAdded(const Remote &remote);
|
void remoteAdded(const Remote &remote);
|
||||||
|
@ -26,7 +26,7 @@ Submodule::operator git_submodule *() const { return d.data(); }
|
|||||||
bool Submodule::isInitialized() const {
|
bool Submodule::isInitialized() const {
|
||||||
Repository repo(git_submodule_owner(d.data()));
|
Repository repo(git_submodule_owner(d.data()));
|
||||||
QString key = QString("submodule.%1.url").arg(name());
|
QString key = QString("submodule.%1.url").arg(name());
|
||||||
return !repo.config().value<QString>(key).isEmpty();
|
return !repo.gitConfig().value<QString>(key).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submodule::initialize() const { git_submodule_init(d.data(), false); }
|
void Submodule::initialize() const { git_submodule_init(d.data(), false); }
|
||||||
@ -34,7 +34,7 @@ void Submodule::initialize() const { git_submodule_init(d.data(), false); }
|
|||||||
void Submodule::deinitialize() const {
|
void Submodule::deinitialize() const {
|
||||||
// Remove git config entry.
|
// Remove git config entry.
|
||||||
Repository repo(git_submodule_owner(d.data()));
|
Repository repo(git_submodule_owner(d.data()));
|
||||||
Config config = repo.config();
|
Config config = repo.gitConfig();
|
||||||
QString regex = QString("submodule\\.%1\\..*").arg(name());
|
QString regex = QString("submodule\\.%1\\..*").arg(name());
|
||||||
Config::Iterator it = config.glob(regex);
|
Config::Iterator it = config.glob(regex);
|
||||||
while (Config::Entry entry = it.next())
|
while (Config::Entry entry = it.next())
|
||||||
|
@ -30,8 +30,8 @@ const QString kThemeIconFmt = ":/%1_%2.png";
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Account::Account(const QString &username)
|
Account::Account(const QString &username)
|
||||||
: mMgr(new QNetworkAccessManager()), mUsername(username),
|
: mUsername(username), mError(new AccountError(this)),
|
||||||
mError(new AccountError(this)), mProgress(new AccountProgress(this)) {
|
mProgress(new AccountProgress(this)), mMgr(new QNetworkAccessManager()) {
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
mMgr, &QNetworkAccessManager::sslErrors,
|
mMgr, &QNetworkAccessManager::sslErrors,
|
||||||
[this](QNetworkReply *reply, const QList<QSslError> &errors) {
|
[this](QNetworkReply *reply, const QList<QSslError> &errors) {
|
||||||
@ -204,6 +204,8 @@ QString Account::helpText(Kind kind) {
|
|||||||
case Beanstalk:
|
case Beanstalk:
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(kind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Account::defaultUrl(Kind kind) {
|
QString Account::defaultUrl(Kind kind) {
|
||||||
@ -219,6 +221,8 @@ QString Account::defaultUrl(Kind kind) {
|
|||||||
case GitLab:
|
case GitLab:
|
||||||
return GitLab::defaultUrl();
|
return GitLab::defaultUrl();
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(kind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Account::Kind Account::kindFromString(const QString &kind, bool *ok) {
|
Account::Kind Account::kindFromString(const QString &kind, bool *ok) {
|
||||||
@ -258,6 +262,8 @@ QString Account::kindToString(Kind kind) {
|
|||||||
case GitLab:
|
case GitLab:
|
||||||
return "gitlab";
|
return "gitlab";
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(kind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::startProgress() {
|
void Account::startProgress() {
|
||||||
|
@ -35,16 +35,8 @@ else()
|
|||||||
set_target_properties(indexer PROPERTIES INSTALL_RPATH "$ORIGIN")
|
set_target_properties(indexer PROPERTIES INSTALL_RPATH "$ORIGIN")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FLATPAK)
|
install(
|
||||||
# Install application.
|
TARGETS indexer
|
||||||
install(
|
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
TARGETS indexer
|
COMPONENT ${GITTYUP_NAME})
|
||||||
DESTINATION ./bin # otherwise the executable will not be found by flatpak
|
|
||||||
COMPONENT ${GITTYUP_NAME})
|
|
||||||
else()
|
|
||||||
install(
|
|
||||||
TARGETS indexer
|
|
||||||
DESTINATION .
|
|
||||||
COMPONENT ${GITTYUP_NAME})
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -93,7 +93,19 @@ Lexer::Lexeme GenericLexer::next() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case Comment: // fall through
|
||||||
|
case Keyword: // fall through
|
||||||
|
case Operator: // fall through
|
||||||
|
case Error: // fall through
|
||||||
|
case Preprocessor: // fall through
|
||||||
|
case Constant: // fall through
|
||||||
|
case Variable: // fall through
|
||||||
|
case Function: // fall through
|
||||||
|
case Class: // fall through
|
||||||
|
case Type: // fall through
|
||||||
|
case Label: // fall through
|
||||||
|
case Regex: // fall through
|
||||||
|
case Embedded: // fall through
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ bool Index::write(PostingMap map) {
|
|||||||
quint32 postCount = readVInt(postIn);
|
quint32 postCount = readVInt(postIn);
|
||||||
bool end = (newIt == newEnd || newIt.key() != it->key);
|
bool end = (newIt == newEnd || newIt.key() != it->key);
|
||||||
postings.reserve(postCount + (!end ? newIt.value().size() : 0));
|
postings.reserve(postCount + (!end ? newIt.value().size() : 0));
|
||||||
for (int i = 0; i < postCount; ++i) {
|
for (quint32 i = 0; i < postCount; ++i) {
|
||||||
quint32 proxPos;
|
quint32 proxPos;
|
||||||
Posting posting;
|
Posting posting;
|
||||||
posting.id = readVInt(postIn);
|
posting.id = readVInt(postIn);
|
||||||
@ -243,7 +243,7 @@ QList<git::Commit> Index::commits(const QString &filter) const {
|
|||||||
// Sort by commit date.
|
// Sort by commit date.
|
||||||
QList<git::Commit> commits = query->commits(this);
|
QList<git::Commit> commits = query->commits(this);
|
||||||
std::sort(commits.begin(), commits.end(),
|
std::sort(commits.begin(), commits.end(),
|
||||||
[this](const git::Commit &lhs, const git::Commit &rhs) {
|
[](const git::Commit &lhs, const git::Commit &rhs) {
|
||||||
return (lhs.committer().date() > rhs.committer().date());
|
return (lhs.committer().date() > rhs.committer().date());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -288,7 +288,7 @@ QList<Index::Posting> Index::postings(const Term &term, bool positional) const {
|
|||||||
// Read list.
|
// Read list.
|
||||||
QList<Posting> postings;
|
QList<Posting> postings;
|
||||||
quint32 postCount = readVInt(in);
|
quint32 postCount = readVInt(in);
|
||||||
for (int i = 0; i < postCount; ++i) {
|
for (quint32 i = 0; i < postCount; ++i) {
|
||||||
quint32 proxPos;
|
quint32 proxPos;
|
||||||
Posting posting;
|
Posting posting;
|
||||||
posting.id = readVInt(in);
|
posting.id = readVInt(in);
|
||||||
@ -331,7 +331,7 @@ QList<Index::Posting> Index::postings(const Predicate &pred,
|
|||||||
|
|
||||||
// Read list.
|
// Read list.
|
||||||
quint32 postCount = readVInt(in);
|
quint32 postCount = readVInt(in);
|
||||||
for (int i = 0; i < postCount; ++i) {
|
for (quint32 i = 0; i < postCount; ++i) {
|
||||||
quint32 proxPos;
|
quint32 proxPos;
|
||||||
Posting posting;
|
Posting posting;
|
||||||
posting.id = readVInt(in);
|
posting.id = readVInt(in);
|
||||||
@ -373,7 +373,7 @@ QMap<Index::Field, QStringList> Index::fieldMap(const QString &prefix) const {
|
|||||||
// Read list.
|
// Read list.
|
||||||
QString name = it->key;
|
QString name = it->key;
|
||||||
quint32 postCount = readVInt(in);
|
quint32 postCount = readVInt(in);
|
||||||
for (int i = 0; i < postCount; ++i) {
|
for (quint32 i = 0; i < postCount; ++i) {
|
||||||
quint8 field;
|
quint8 field;
|
||||||
quint32 proxPos;
|
quint32 proxPos;
|
||||||
readVInt(in); // Discard id.
|
readVInt(in); // Discard id.
|
||||||
@ -443,6 +443,8 @@ QByteArray Index::fieldName(Index::Field field) {
|
|||||||
case Index::Pathspec:
|
case Index::Pathspec:
|
||||||
return "pathspec";
|
return "pathspec";
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(field)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Index::indexDir(const git::Repository &repo) {
|
QDir Index::indexDir(const git::Repository &repo) {
|
||||||
@ -506,7 +508,7 @@ void Index::readPositions(QDataStream &in, QVector<quint32> &positions) {
|
|||||||
quint32 prev = 0;
|
quint32 prev = 0;
|
||||||
quint32 count = readVInt(in);
|
quint32 count = readVInt(in);
|
||||||
positions.reserve(count);
|
positions.reserve(count);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (quint32 i = 0; i < count; ++i) {
|
||||||
// Convert to absolute from delta.
|
// Convert to absolute from delta.
|
||||||
quint32 position = prev + readVInt(in);
|
quint32 position = prev + readVInt(in);
|
||||||
positions.append(position);
|
positions.append(position);
|
||||||
|
@ -182,16 +182,24 @@ public:
|
|||||||
QList<git::Commit> rhs = mRhs->commits(index);
|
QList<git::Commit> rhs = mRhs->commits(index);
|
||||||
QList<git::Commit> commits = mLhs->commits(index);
|
QList<git::Commit> commits = mLhs->commits(index);
|
||||||
if (mKind == And) {
|
if (mKind == And) {
|
||||||
// Remove commits that don't match the right hand side.
|
// Remove commits that don't match the right hand side.
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
QSet<git::Commit> set(rhs.begin(), rhs.end());
|
||||||
|
#else
|
||||||
QSet<git::Commit> set = QSet<git::Commit>::fromList(rhs);
|
QSet<git::Commit> set = QSet<git::Commit>::fromList(rhs);
|
||||||
|
#endif
|
||||||
QMutableListIterator<git::Commit> it(commits);
|
QMutableListIterator<git::Commit> it(commits);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
if (!set.contains(it.next()))
|
if (!set.contains(it.next()))
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add commits that aren't already in the result set.
|
// Add commits that aren't already in the result set.
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
QSet<git::Commit> set(commits.begin(), commits.end());
|
||||||
|
#else
|
||||||
QSet<git::Commit> set = QSet<git::Commit>::fromList(commits);
|
QSet<git::Commit> set = QSet<git::Commit>::fromList(commits);
|
||||||
|
#endif
|
||||||
foreach (const git::Commit &commit, rhs) {
|
foreach (const git::Commit &commit, rhs) {
|
||||||
if (!set.contains(commit))
|
if (!set.contains(commit))
|
||||||
commits.append(commit);
|
commits.append(commit);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "Index.h"
|
#include "Index.h"
|
||||||
#include "GenericLexer.h"
|
#include "GenericLexer.h"
|
||||||
#include "LPegLexer.h"
|
#include "LPegLexer.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
#include "conf/Settings.h"
|
#include "conf/Settings.h"
|
||||||
#include "git/Config.h"
|
#include "git/Config.h"
|
||||||
#include "git/Index.h"
|
#include "git/Index.h"
|
||||||
@ -105,7 +106,7 @@ void log(QFile *out, const QString &text) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
||||||
QTextStream(out) << time << " - " << text << endl;
|
QTextStream(out) << time << " - " << text << Qt::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(QFile *out, const QString &fmt, const git::Id &id) {
|
void log(QFile *out, const QString &fmt, const git::Id &id) {
|
||||||
@ -148,7 +149,22 @@ void index(const Lexer::Lexeme &lexeme, Intermediate::FieldMap &fields,
|
|||||||
case Lexer::Comment:
|
case Lexer::Comment:
|
||||||
field |= Index::Comment;
|
field |= Index::Comment;
|
||||||
break;
|
break;
|
||||||
default:
|
case Lexer::Nothing: // fall through
|
||||||
|
case Lexer::Whitespace: // fall through
|
||||||
|
case Lexer::Number: // fall through
|
||||||
|
case Lexer::Keyword: // fall through
|
||||||
|
case Lexer::Identifier: // fall through
|
||||||
|
case Lexer::Operator: // fall through
|
||||||
|
case Lexer::Error: // fall through
|
||||||
|
case Lexer::Preprocessor: // fall through
|
||||||
|
case Lexer::Constant: // fall through
|
||||||
|
case Lexer::Variable: // fall through
|
||||||
|
case Lexer::Function: // fall through
|
||||||
|
case Lexer::Class: // fall through
|
||||||
|
case Lexer::Type: // fall through
|
||||||
|
case Lexer::Label: // fall through
|
||||||
|
case Lexer::Regex: // fall through
|
||||||
|
case Lexer::Embedded: // fall through
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +188,13 @@ void index(const Lexer::Lexeme &lexeme, Intermediate::FieldMap &fields,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// Ignore everything else.
|
// Ignore everything else.
|
||||||
default:
|
case Lexer::Nothing: // fall through
|
||||||
|
case Lexer::Whitespace: // fall through
|
||||||
|
case Lexer::Number: // fall through
|
||||||
|
case Lexer::Operator: // fall through
|
||||||
|
case Lexer::Error: // fall through
|
||||||
|
case Lexer::Regex: // fall through
|
||||||
|
case Lexer::Embedded: // fall through
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,7 +353,7 @@ private:
|
|||||||
QFile *mOut;
|
QFile *mOut;
|
||||||
|
|
||||||
int mContextLines = 3;
|
int mContextLines = 3;
|
||||||
int mTermLimit = 1000000;
|
quint32 mTermLimit = 1000000;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Reduce {
|
class Reduce {
|
||||||
@ -405,7 +427,12 @@ public:
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
QList<git::Commit> commits;
|
QList<git::Commit> commits;
|
||||||
git::Commit commit = mWalker.next();
|
git::Commit commit = mWalker.next();
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
QSet<git::Id> ids(mIndex.ids().begin(), mIndex.ids().end());
|
||||||
|
#else
|
||||||
QSet<git::Id> ids = QSet<git::Id>::fromList(mIndex.ids());
|
QSet<git::Id> ids = QSet<git::Id>::fromList(mIndex.ids());
|
||||||
|
#endif
|
||||||
while (commit.isValid() && count < 8192) {
|
while (commit.isValid() && count < 8192) {
|
||||||
// Don't index merge commits.
|
// Don't index merge commits.
|
||||||
if (!commit.isMerge() && !ids.contains(commit.id())) {
|
if (!commit.isMerge() && !ids.contains(commit.id())) {
|
||||||
@ -440,7 +467,7 @@ public:
|
|||||||
// Write to disk.
|
// Write to disk.
|
||||||
log(mOut, "start write");
|
log(mOut, "start write");
|
||||||
if (mIndex.write(mWatcher.result()) && mNotify)
|
if (mIndex.write(mWatcher.result()) && mNotify)
|
||||||
QTextStream(stdout) << "write" << endl;
|
QTextStream(stdout) << "write" << Qt::endl;
|
||||||
log(mOut, "end write");
|
log(mOut, "end write");
|
||||||
|
|
||||||
// Restart.
|
// Restart.
|
||||||
@ -450,10 +477,14 @@ public:
|
|||||||
|
|
||||||
bool nativeEventFilter(const QByteArray &type, void *message,
|
bool nativeEventFilter(const QByteArray &type, void *message,
|
||||||
long *result) override {
|
long *result) override {
|
||||||
|
Q_UNUSED(result);
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
MSG *msg = static_cast<MSG *>(message);
|
MSG *msg = static_cast<MSG *>(message);
|
||||||
if (msg->message == WM_CLOSE)
|
if (msg->message == WM_CLOSE)
|
||||||
cancel();
|
cancel();
|
||||||
|
#else
|
||||||
|
Q_UNUSED(type);
|
||||||
|
Q_UNUSED(message);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "GenericLexer.h"
|
#include "GenericLexer.h"
|
||||||
#include "LPegLexer.h"
|
#include "LPegLexer.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
#include "conf/Settings.h"
|
#include "conf/Settings.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
@ -29,7 +30,7 @@ void print(QTextStream &out, const Lexer::Lexeme &lexeme, int indent = 0) {
|
|||||||
out << lexeme.text << " - " << lexeme.token;
|
out << lexeme.text << " - " << lexeme.token;
|
||||||
if (lexeme.token < kStyleNames.length())
|
if (lexeme.token < kStyleNames.length())
|
||||||
out << " (" << kStyleNames.at(lexeme.token) << ")";
|
out << " (" << kStyleNames.at(lexeme.token) << ")";
|
||||||
out << endl;
|
out << Qt::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(QTextStream &out, Lexer *lexer, int indent = 0) {
|
void print(QTextStream &out, Lexer *lexer, int indent = 0) {
|
||||||
@ -65,7 +66,13 @@ void print(QTextStream &out, Lexer *lexer, int indent = 0) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// Ignore everything else.
|
// Ignore everything else.
|
||||||
default:
|
case Lexer::Whitespace: // fall through
|
||||||
|
case Lexer::Nothing: // fall through
|
||||||
|
case Lexer::Number: // fall through
|
||||||
|
case Lexer::Operator: // fall through
|
||||||
|
case Lexer::Error: // fall through
|
||||||
|
case Lexer::Regex: // fall through
|
||||||
|
case Lexer::Embedded:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +109,7 @@ int main(int argc, char *argv[]) {
|
|||||||
// Lex buffer.
|
// Lex buffer.
|
||||||
Lexer *lexer = lexers.value(name);
|
Lexer *lexer = lexers.value(name);
|
||||||
if (lexer->lex(buffer)) {
|
if (lexer->lex(buffer)) {
|
||||||
out << name << " - " << arg << ":" << endl;
|
out << name << " - " << arg << ":" << Qt::endl;
|
||||||
print(out, lexer);
|
print(out, lexer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,9 @@ void LogDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
|||||||
|
|
||||||
QRect rect = decorationRect(option, index);
|
QRect rect = decorationRect(option, index);
|
||||||
if (static_cast<QMetaType::Type>(variant.type()) == QMetaType::QChar) {
|
if (static_cast<QMetaType::Type>(variant.type()) == QMetaType::QChar) {
|
||||||
Badge::paint(painter, {Badge::Label(variant.toChar())}, rect, &opt);
|
Badge::paint(painter,
|
||||||
|
{Badge::Label(Badge::Label::Type::Log, variant.toChar())},
|
||||||
|
rect, &opt);
|
||||||
} else if (variant.canConvert<int>()) {
|
} else if (variant.canConvert<int>()) {
|
||||||
int progress = variant.toInt();
|
int progress = variant.toInt();
|
||||||
ProgressIndicator::paint(painter, rect, "#808080", progress, opt.widget);
|
ProgressIndicator::paint(painter, rect, "#808080", progress, opt.widget);
|
||||||
@ -126,7 +128,9 @@ void LogDelegate::initStyleOption(QStyleOptionViewItem *option,
|
|||||||
QStyledItemDelegate::initStyleOption(option, index);
|
QStyledItemDelegate::initStyleOption(option, index);
|
||||||
QVariant variant = index.data(Qt::DecorationRole);
|
QVariant variant = index.data(Qt::DecorationRole);
|
||||||
if (static_cast<QMetaType::Type>(variant.type()) == QMetaType::QChar) {
|
if (static_cast<QMetaType::Type>(variant.type()) == QMetaType::QChar) {
|
||||||
option->decorationSize = Badge::size(option->font) - ADJUSTMENT_SIZE;
|
option->decorationSize =
|
||||||
|
Badge::size(option->font, Badge::Label(Badge::Label::Type::Log)) -
|
||||||
|
ADJUSTMENT_SIZE;
|
||||||
} else if (variant.canConvert<int>()) {
|
} else if (variant.canConvert<int>()) {
|
||||||
option->decorationSize = ProgressIndicator::size();
|
option->decorationSize = ProgressIndicator::size();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "LogModel.h"
|
#include "LogModel.h"
|
||||||
#include "LogEntry.h"
|
#include "LogEntry.h"
|
||||||
|
#include <QLocale>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -74,8 +75,8 @@ QVariant LogModel::data(const QModelIndex &index, int role) const {
|
|||||||
QDateTime date = entry->timestamp();
|
QDateTime date = entry->timestamp();
|
||||||
QString timestamp =
|
QString timestamp =
|
||||||
(date.date() == QDate::currentDate())
|
(date.date() == QDate::currentDate())
|
||||||
? date.time().toString(Qt::DefaultLocaleShortDate)
|
? QLocale().toString(date.time(), QLocale::ShortFormat)
|
||||||
: date.toString(Qt::DefaultLocaleShortDate);
|
: QLocale().toString(date, QLocale::ShortFormat);
|
||||||
text = kTimeFmt.arg(timestamp, text);
|
text = kTimeFmt.arg(timestamp, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Plugin.h"
|
#include "Plugin.h"
|
||||||
|
#include "qtsupport.h"
|
||||||
#include "conf/Settings.h"
|
#include "conf/Settings.h"
|
||||||
#include "editor/TextEditor.h"
|
#include "editor/TextEditor.h"
|
||||||
#include "git/Config.h"
|
#include "git/Config.h"
|
||||||
@ -491,7 +492,7 @@ Plugin::Plugin(const QString &file, const git::Repository &repo,
|
|||||||
|
|
||||||
// Print error messages to the console.
|
// Print error messages to the console.
|
||||||
connect(this, &Plugin::error, [](const QString &msg) {
|
connect(this, &Plugin::error, [](const QString &msg) {
|
||||||
QTextStream(stderr) << "plugin error: " << msg << endl;
|
QTextStream(stderr) << "plugin error: " << msg << Qt::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load libraries.
|
// Load libraries.
|
||||||
@ -613,6 +614,8 @@ QVariant Plugin::optionValue(const QString &key) const {
|
|||||||
case String:
|
case String:
|
||||||
return config().value<QString>(kKeyFmt.arg(mName, key), value.toString());
|
return config().value<QString>(kKeyFmt.arg(mName, key), value.toString());
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("unreachable; value=" +
|
||||||
|
std::to_string(static_cast<int>(optionKind(key))));
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin::OptionKind Plugin::optionKind(const QString &key) const {
|
Plugin::OptionKind Plugin::optionKind(const QString &key) const {
|
||||||
|
17
src/qtsupport.h
Normal file
17
src/qtsupport.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/// Backwards compatibility for older versions of QT
|
||||||
|
/// Several symbols have been deprecated in QT5.14 and moved to new
|
||||||
|
/// namespaces. This file provides support for older versions of QT.
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
namespace Qt {
|
||||||
|
static auto endl = ::endl;
|
||||||
|
static auto KeepEmptyParts = QString::KeepEmptyParts;
|
||||||
|
static auto SkipEmptyParts = QString::SkipEmptyParts;
|
||||||
|
} // namespace Qt
|
||||||
|
|
||||||
|
// QButtonGroup::buttonClicked is deprecated in favor of QButtonGroup::idClicked
|
||||||
|
#define idClicked buttonClicked
|
||||||
|
#endif
|
@ -1,6 +1,6 @@
|
|||||||
add_library(tools DiffTool.cpp EditTool.cpp ExternalTool.cpp MergeTool.cpp
|
add_library(tools DiffTool.cpp EditTool.cpp ExternalTool.cpp MergeTool.cpp
|
||||||
ShowTool.cpp)
|
ShowTool.cpp)
|
||||||
|
|
||||||
target_link_libraries(tools conf git Qt5::Gui)
|
target_link_libraries(tools conf git Qt5::Gui util)
|
||||||
|
|
||||||
set_target_properties(tools PROPERTIES AUTOMOC ON)
|
set_target_properties(tools PROPERTIES AUTOMOC ON)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "git/Repository.h"
|
#include "git/Repository.h"
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
DiffTool::DiffTool(const QString &file, const git::Blob &localBlob,
|
DiffTool::DiffTool(const QString &file, const git::Blob &localBlob,
|
||||||
const git::Blob &remoteBlob, QObject *parent)
|
const git::Blob &remoteBlob, QObject *parent)
|
||||||
@ -59,8 +60,25 @@ bool DiffTool::start() {
|
|||||||
|
|
||||||
// Destroy this after process finishes.
|
// Destroy this after process finishes.
|
||||||
QProcess *process = new QProcess(this);
|
QProcess *process = new QProcess(this);
|
||||||
|
process->setProcessChannelMode(
|
||||||
|
QProcess::ProcessChannelMode::ForwardedChannels);
|
||||||
auto signal = QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished);
|
auto signal = QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished);
|
||||||
QObject::connect(process, signal, this, &ExternalTool::deleteLater);
|
QObject::connect(process, signal, [this, process] {
|
||||||
|
qDebug() << "Merge Process Exited!";
|
||||||
|
qDebug() << "Stdout: " << process->readAllStandardOutput();
|
||||||
|
qDebug() << "Stderr: " << process->readAllStandardError();
|
||||||
|
deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
|
#if defined(FLATPAK) || defined(DEBUG_FLATPAK)
|
||||||
|
QStringList arguments = {"--host", "--env=LOCAL=" + local->fileName(),
|
||||||
|
"--env=REMOTE=" + remotePath,
|
||||||
|
"--env=MERGED=" + mFile, "--env=BASE=" + mFile};
|
||||||
|
arguments.append("sh");
|
||||||
|
arguments.append("-c");
|
||||||
|
arguments.append(command);
|
||||||
|
process->start("flatpak-spawn", arguments);
|
||||||
|
#else
|
||||||
|
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
env.insert("LOCAL", local->fileName());
|
env.insert("LOCAL", local->fileName());
|
||||||
@ -78,9 +96,12 @@ bool DiffTool::start() {
|
|||||||
emit error(BashNotFound);
|
emit error(BashNotFound);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!process->waitForStarted())
|
if (!process->waitForStarted()) {
|
||||||
|
qDebug() << "DiffTool starting failed";
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Detach from parent.
|
// Detach from parent.
|
||||||
setParent(nullptr);
|
setParent(nullptr);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user