mirror of
https://github.com/Murmele/Gittyup.git
synced 2024-08-15 13:40:32 +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
|
||||
container:
|
||||
# image: bilelmoussaoui/flatpak-github-actions:kde-5.15-21.08
|
||||
image: exactlyonekas/gittyup-flatpak-builder:latest
|
||||
image: archlinux:latest
|
||||
options: --privileged
|
||||
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
|
||||
run: >
|
||||
echo IS_RELEASE: ${{ env.IS_RELEASE }}
|
||||
@ -67,7 +76,7 @@ jobs:
|
||||
- name: Replace git tag by the commit id on which it runs
|
||||
if: github.ref_type != 'tag'
|
||||
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
|
||||
if: github.ref_type == 'tag'
|
||||
@ -88,6 +97,11 @@ jobs:
|
||||
run: >
|
||||
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
|
||||
run: cat com.github.Murmele.Gittyup/com.github.Murmele.Gittyup.yml
|
||||
|
||||
@ -123,8 +137,11 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
ninja_platform: linux
|
||||
qt_platform: linux
|
||||
qt_arch: gcc_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: {}
|
||||
|
||||
- name: macos
|
||||
@ -193,7 +210,7 @@ jobs:
|
||||
perl-version: '5.30'
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2.13.0
|
||||
uses: jurplel/install-qt-action@v3.3.0
|
||||
timeout-minutes: 10
|
||||
if: "!matrix.qt.check_only"
|
||||
with:
|
||||
@ -205,7 +222,7 @@ jobs:
|
||||
modules: qtwebengine
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2.13.0
|
||||
uses: jurplel/install-qt-action@v3.3.0
|
||||
timeout-minutes: 10
|
||||
if: matrix.qt.check_only
|
||||
with:
|
||||
@ -264,7 +281,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p 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
|
||||
run: |
|
||||
@ -301,15 +318,20 @@ jobs:
|
||||
if: matrix.env.pack && !matrix.qt.check_only
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: build/release/VERSION.txt
|
||||
path: build/release/Version.txt
|
||||
name: Gittyup-VERSION
|
||||
|
||||
- name: Check Version file
|
||||
run: |
|
||||
cd build/release
|
||||
cat ./Version.txt
|
||||
|
||||
- name: Test
|
||||
if: matrix.env.ninja_platform != 'win' && matrix.env.ninja_platform != 'mac'
|
||||
uses: GabrielBB/xvfb-action@v1
|
||||
with:
|
||||
working-directory: build/release
|
||||
run: ninja check
|
||||
run: ninja check --verbose
|
||||
|
||||
- name: Test (Windows)
|
||||
if: matrix.env.ninja_platform == 'win'
|
||||
@ -317,6 +339,44 @@ jobs:
|
||||
cd build/release
|
||||
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:
|
||||
# https://github.com/marvinpinto/actions/issues/177
|
||||
needs: [flatpak, build]
|
||||
@ -347,7 +407,7 @@ jobs:
|
||||
# version is exported from cmake to file
|
||||
- name: Retrieve version
|
||||
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
|
||||
|
||||
- name: Update GitHub release (latest tag)
|
||||
@ -363,6 +423,7 @@ jobs:
|
||||
**/artifacts/Gittyup macos/Gittyup*.dmg
|
||||
**/artifacts/Gittyup Flatpak/com.github.Murmele.Gittyup.yml
|
||||
**/Gittyup-x86_64/*.flatpak
|
||||
**/artifacts/GittyupAppImage/*
|
||||
|
||||
- name: Update GitHub release (version tag)
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
@ -378,6 +439,7 @@ jobs:
|
||||
**/artifacts/Gittyup macos/Gittyup*.dmg
|
||||
**/artifacts/Gittyup Flatpak/com.github.Murmele.Gittyup.yml
|
||||
**/Gittyup-x86_64/*.flatpak
|
||||
**/artifacts/GittyupAppImage/*
|
||||
|
||||
# needed otherwise the docs folder is not available
|
||||
- name: Checkout repository
|
||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,5 +1,13 @@
|
||||
build
|
||||
.cache
|
||||
.DS_Store
|
||||
.project
|
||||
.vscode/
|
||||
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)
|
||||
|
||||
# Set name and version.
|
||||
set(GITTYUP_NAME "Gittyup")
|
||||
set(GITTYUP_EXECUTABLE_NAME "gittyup")
|
||||
set(GITTYUP_IDENTIFIER "com.github.Murmele.Gittyup")
|
||||
set(GITTYUP_VERSION_MAJOR 1)
|
||||
set(GITTYUP_VERSION_MINOR 2)
|
||||
set(GITTYUP_VERSION_PATCH 1)
|
||||
set(GITTYUP_VERSION_MINOR 3)
|
||||
set(GITTYUP_VERSION_PATCH 0)
|
||||
set(GITTYUP_VERSION
|
||||
"${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
|
||||
# github manifest
|
||||
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(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_LIBGIT2
|
||||
@ -68,7 +76,10 @@ set(LUA_MODULES_PATH
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
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)
|
||||
endif()
|
||||
|
||||
@ -86,9 +97,20 @@ if(UNIX)
|
||||
set(QT_MODULES ${QT_MODULES} DBus)
|
||||
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)
|
||||
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()
|
||||
|
||||
find_package(
|
||||
@ -103,6 +125,10 @@ if(FLATPAK)
|
||||
add_compile_definitions(FLATPAK)
|
||||
endif()
|
||||
|
||||
if(ENABLE_UPDATE_OVER_GUI)
|
||||
add_compile_definitions(ENABLE_UPDATE_OVER_GUI)
|
||||
endif()
|
||||
|
||||
if(DEBUG_FLATPAK)
|
||||
add_compile_definitions(DEBUG_FLATPAK)
|
||||
endif()
|
||||
@ -125,6 +151,18 @@ if(APPLE)
|
||||
endforeach()
|
||||
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(src)
|
||||
add_subdirectory(l10n)
|
||||
|
@ -1,7 +1,7 @@
|
||||
MIT License
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
**Build**
|
||||
|
||||
```
|
||||
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
|
||||
-----------------
|
||||
@ -177,7 +180,6 @@ function run_disown_silence(){
|
||||
run_disown_silence flatpak run com.github.Murmele.Gittyup
|
||||
```
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
-------
|
||||
|
||||
|
35
cl-fmt.sh
35
cl-fmt.sh
@ -1,18 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Variable that will hold the name of the clang-format command
|
||||
FMT=""
|
||||
|
||||
FOLDERS=("./src" "./test")
|
||||
FOLDERS=("./src" "./test" "./l10n")
|
||||
|
||||
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
|
||||
# that the version number be part of the command. We prefer clang-format if
|
||||
# that's present, otherwise we work backwards from highest version to lowest
|
||||
# version but at least 13.
|
||||
for clangfmt in clang-format{,-{1,2,3}{9,8,7,6,5,4,3}}; do
|
||||
if which "$clangfmt" &>/dev/null; then
|
||||
# We specifically require clang-format v13. Some distros include the version
|
||||
# number in the name, others don't. Prefer the specifically-named version.
|
||||
for clangfmt in clang-format-13 clang-format
|
||||
do
|
||||
if command -v "$clangfmt" &>/dev/null; then
|
||||
FMT="$clangfmt"
|
||||
break
|
||||
fi
|
||||
@ -24,6 +24,14 @@ if [ -z "$FMT" ]; then
|
||||
exit 1
|
||||
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() {
|
||||
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}";
|
||||
@ -41,9 +49,18 @@ for dir in ${FOLDERS[@]}; do
|
||||
fi
|
||||
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"
|
||||
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 . \
|
||||
\( -type d -path './test/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
|
||||
file(READ "${CHANGELOG_HTML}" HTML_CHANGELOGS)
|
||||
# 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 "<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(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})
|
||||
configure_file(${APPDATA_CONF} ${APPDATA})
|
||||
|
@ -56,13 +56,13 @@ theme['button'] = {
|
||||
-- commit list colors
|
||||
-- { default, active, inactive, disabled }
|
||||
theme['commits'] = {
|
||||
text = '#E1E5F2',
|
||||
bright_text = '#AAB2BE',
|
||||
text = '#AAB2BE',
|
||||
bright_text = '#E1E5F2',
|
||||
background = '#2D2E34',
|
||||
alternate = '#2D2E34', -- an alternate background color for list rows
|
||||
highlight = { active = '#2A82DA', inactive = '#1B5B9B' },
|
||||
highlighted_text = { active = '#E1E5F2', inactive = '#E1E5F2' },
|
||||
highlighted_bright_text = { active = '#A6CBF0', inactive = '#9090A5' }
|
||||
highlighted_text = { active = '#A6CBF0', inactive = '#E1E5F2' },
|
||||
highlighted_bright_text = { active = '#E1E5F2', inactive = '#9090A5' }
|
||||
}
|
||||
|
||||
-- status badge colors
|
||||
@ -77,7 +77,12 @@ theme['badge'] = {
|
||||
selected = '#E1E5F2', -- the color when a list item is selected
|
||||
conflicted = '#DA2ADA', -- the color of conflicted items
|
||||
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 }
|
||||
theme['badge'] = {
|
||||
foreground = {
|
||||
normal = '#FFFFFF',
|
||||
normal = '#000000',
|
||||
selected = '#6C6C6C'
|
||||
},
|
||||
background = {
|
||||
@ -77,7 +77,12 @@ theme['badge'] = {
|
||||
selected = '#FFFFFF', -- the color when a list item is selected
|
||||
conflicted = '#D22222', -- the color of conflicted items
|
||||
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)
|
||||
set(TARGET git-credential-${NAME})
|
||||
add_executable(${TARGET} ${PATH}/${NAME}/${TARGET}.c)
|
||||
set_target_properties(${TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||
$<TARGET_FILE_DIR:gittyup>)
|
||||
set_target_properties(
|
||||
${TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||
$<TARGET_FILE_DIR:gittyup>/credential-helpers)
|
||||
|
||||
if(${ARGC} GREATER 1)
|
||||
target_link_libraries(${TARGET} ${ARGV1})
|
||||
@ -14,7 +15,7 @@ if(NOT USE_SYSTEM_GIT)
|
||||
if(NOT APPLE)
|
||||
install(
|
||||
TARGETS ${TARGET}
|
||||
DESTINATION .
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}/credential-helpers
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
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(SCINTILLUA_LEXERS_DIR
|
||||
${RESOURCES_DIR}/lexers
|
||||
CACHE INTERNAL "")
|
||||
set(SRC_SCINTILLUA_LEXERS_DIR
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scintillua/lexers
|
||||
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
|
||||
|
||||
#### 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 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
|
||||
|
@ -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.
|
||||
|
||||
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
|
||||
========
|
||||
@ -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)
|
||||
|
||||
### Staring commits
|
||||
### Starring commits
|
||||
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
|
||||
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)
|
||||
|
||||
### 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)
|
||||
|
||||
|
@ -14,10 +14,18 @@ set(LANGUAGES
|
||||
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
|
||||
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})
|
||||
set(TS_FILES ${TS_FILES} gittyup_${LANGUAGE}.ts)
|
||||
set(SUPPORTED_LANGUAGES
|
||||
"${SUPPORTED_LANGUAGES} {\"${LANGUAGE}\", \"${LANGUAGE}\"},")
|
||||
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)
|
||||
# FIXME: Clean removes the .ts files.
|
||||
qt5_create_translation(QM_FILES ${SOURCE_FILES} ${TS_FILES})
|
||||
@ -28,12 +36,11 @@ endif()
|
||||
add_custom_target(translations DEPENDS ${QM_FILES})
|
||||
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
|
||||
if(APPLE)
|
||||
set(CONTENTS_DIR ${GITTYUP_NAME}.app/Contents)
|
||||
elseif(UNIX)
|
||||
set(CONTENTS_DIR ${CMAKE_INSTALL_DATADIR}/gittyup)
|
||||
endif()
|
||||
|
||||
foreach(LANGUAGE ${LANGUAGES})
|
||||
set(QT_QM_FILES ${QT_QM_FILES} ${QT_TRANSLATIONS_DIR}/qtbase_${LANGUAGE}.qm)
|
||||
@ -44,19 +51,22 @@ foreach(LANGUAGE ${LANGUAGES})
|
||||
TARGET translations
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
${DIR}/${CONTENTS_DIR}/Resources/${LANGUAGE}.lproj)
|
||||
${DIR}/${RESOURCES_DIR}/${LANGUAGE}.lproj)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(APPLE OR UNIX)
|
||||
set(RESOURCES_PREFIX ${CONTENTS_DIR}/)
|
||||
endif()
|
||||
|
||||
foreach(QM_FILE ${QM_FILES} ${QT_QM_FILES})
|
||||
foreach(QM_FILE ${QT_QM_FILES})
|
||||
if(EXISTS ${QM_FILE})
|
||||
install(
|
||||
FILES ${QM_FILE}
|
||||
DESTINATION ${RESOURCES_PREFIX}Resources/l10n
|
||||
DESTINATION ${L10N_INSTALL_DIR}
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
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(MAC $<PLATFORM_ID:Darwin>)
|
||||
set(CONTENTS_DIR ${GITTYUP_NAME}.app/Contents)
|
||||
|
||||
# Install Qt plugins.
|
||||
set(QT_PLUGINS QJpegPlugin)
|
||||
@ -17,6 +16,14 @@ else()
|
||||
QComposePlatformInputContextPlugin)
|
||||
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)
|
||||
qt_import_plugins(gittyup INCLUDE ${QT_PLUGINS})
|
||||
elseif(NOT USE_SYSTEM_QT)
|
||||
@ -35,7 +42,7 @@ elseif(NOT USE_SYSTEM_QT)
|
||||
|
||||
install(
|
||||
FILES ${PLUGIN}
|
||||
DESTINATION $<${MAC}:${CONTENTS_DIR}/>Plugins/${DIR_NAME}
|
||||
DESTINATION ${INSTALL_LIBDIR}/Plugins/${DIR_NAME}
|
||||
PERMISSIONS
|
||||
OWNER_READ
|
||||
OWNER_WRITE
|
||||
@ -100,7 +107,7 @@ elseif(NOT USE_SYSTEM_QT)
|
||||
|
||||
install(
|
||||
FILES ${QT_LIBRARY}
|
||||
DESTINATION .
|
||||
DESTINATION ${INSTALL_LIBDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ
|
||||
OWNER_WRITE
|
||||
@ -131,7 +138,7 @@ if(UNIX AND NOT APPLE)
|
||||
|
||||
install(
|
||||
FILES "${LIB_PATH}/${LIB_NAME}${LIB_EXT}"
|
||||
DESTINATION .
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ
|
||||
OWNER_WRITE
|
||||
@ -166,7 +173,7 @@ if(NOT APPLE)
|
||||
|
||||
install(
|
||||
FILES ${SSL_LIB}
|
||||
DESTINATION .
|
||||
DESTINATION ${INSTALL_LIBDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ
|
||||
OWNER_WRITE
|
||||
@ -186,16 +193,25 @@ if(NOT APPLE)
|
||||
set(QT_CONF ${CONF_DIR}/qt.conf)
|
||||
install(
|
||||
FILES ${QT_CONF}
|
||||
DESTINATION $<${MAC}:${CONTENTS_DIR}/Resources/>.
|
||||
DESTINATION
|
||||
$<${MAC}:${RESOURCES_DIR}>$<$<PLATFORM_ID:Windows>:${INSTALL_LIBDIR}>
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
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(
|
||||
DIRECTORY ${RSRC_DIR}/Gittyup.iconset
|
||||
DESTINATION "Resources"
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
FILES ${RSRC_DIR}/Gittyup.iconset/gittyup_logo.svg
|
||||
DESTINATION share/icons/hicolor/scalable/apps
|
||||
COMPONENT ${GITTYUP_NAME}
|
||||
RENAME ${GITTYUP_EXECUTABLE_NAME}.svg)
|
||||
endif()
|
||||
|
||||
# Sign bundle on macOS.
|
||||
@ -204,7 +220,7 @@ if(APPLE AND CODESIGN_IDENTITY)
|
||||
CODE "execute_process(COMMAND
|
||||
codesign --deep --timestamp --options runtime
|
||||
-s \"${CODESIGN_IDENTITY}\"
|
||||
\${CMAKE_INSTALL_PREFIX}/${GITTYUP_NAME}.app
|
||||
\${CMAKE_INSTALL_PREFIX}/${GITTYUP_EXECUTABLE_NAME}.app
|
||||
)"
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
@ -220,9 +236,10 @@ elseif(WIN32)
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||
"CreateShortCut \
|
||||
\\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${GITTYUP_NAME}.lnk\\\" \
|
||||
\\\"$INSTDIR\\\\${GITTYUP_NAME}.exe\\\"")
|
||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
set(CPACK_NSIS_MUI_FINISHPAGE_RUN ${GITTYUP_NAME}.exe)
|
||||
\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_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)
|
||||
install(
|
||||
@ -262,11 +279,11 @@ if(WIN32)
|
||||
set(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' 'Icon' '\\\"$INSTDIR\\\\gittyup.exe\\\"'
|
||||
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\gittyup.exe\\\" \\\"%V\\\"'
|
||||
WriteRegStr HKCR 'Directory\\\\Background\\\\shell\\\\Gittyup' 'Icon' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\"'
|
||||
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' 'Icon' '\\\"$INSTDIR\\\\gittyup.exe\\\"'
|
||||
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\gittyup.exe\\\" \\\"%L\\\"'"
|
||||
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup' 'Icon' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\"'
|
||||
WriteRegStr HKCR 'Directory\\\\shell\\\\Gittyup\\\\command' '' '\\\"$INSTDIR\\\\${CMAKE_INSTALL_BINDIR}\\\\${GITTYUP_EXECUTABLE_NAME}.exe\\\" \\\"%L\\\"'"
|
||||
)
|
||||
set(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_DIRECTORY ${CMAKE_BINARY_DIR}/pack)
|
||||
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_MINOR ${GITTYUP_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${GITTYUP_VERSION_PATCH})
|
||||
|
||||
if(WIN32)
|
||||
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()
|
||||
|
||||
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
|
||||
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>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<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>
|
||||
|
||||
<provides>
|
||||
<binary>Gittyup</binary>
|
||||
<binary>gittyup</binary>
|
||||
<id>com.github.Murmele.Gittyup</id>
|
||||
</provides>
|
||||
|
||||
|
@ -2,11 +2,10 @@
|
||||
Encoding=UTF-8
|
||||
Name=Gittyup
|
||||
Comment=Graphical Git client for Windows, Linux and macOS
|
||||
Exec=Gittyup
|
||||
StartupWMClass=gittyup
|
||||
Exec=gittyup
|
||||
StartupWMClass=com.github.Murmele.Gittyup
|
||||
Icon=gittyup
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Development;
|
||||
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})
|
||||
|
||||
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(conf)
|
||||
add_subdirectory(cred)
|
||||
@ -13,7 +21,6 @@ add_subdirectory(plugins)
|
||||
add_subdirectory(tools)
|
||||
add_subdirectory(ui)
|
||||
add_subdirectory(update)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(watcher)
|
||||
|
||||
# Add executable last.
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "ui/RepoView.h"
|
||||
#include "ui/TabWidget.h"
|
||||
#include "update/Updater.h"
|
||||
#include "languages.h"
|
||||
#include "util/Debug.h"
|
||||
#include <QCloseEvent>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDesktopServices>
|
||||
@ -132,6 +134,18 @@ Application::Application(int &argc, char **argv, bool haltOnParseError)
|
||||
// Set debug menu option.
|
||||
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.
|
||||
mPathspec = parser.value("filter");
|
||||
|
||||
@ -159,6 +173,12 @@ Application::Application(int &argc, char **argv, bool haltOnParseError)
|
||||
.toBool()) &&
|
||||
(!parser.isSet("no-translation"))) {
|
||||
// Load translation files.
|
||||
|
||||
const auto &language =
|
||||
Settings::instance()->value(Setting::Id::Language).toString();
|
||||
if (language != Languages::system)
|
||||
QLocale::setDefault(QLocale(language));
|
||||
|
||||
QLocale locale;
|
||||
QDir l10n = Settings::l10nDir();
|
||||
QString name = QString(GITTYUP_NAME).toLower();
|
||||
@ -310,9 +330,9 @@ static MainWindow *openOrSwitch(QDir repo) {
|
||||
}
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
#define DBUS_SERVICE_NAME "com.github.Murmele.Gittyup"
|
||||
#define DBUS_INTERFACE_NAME "com.github.Murmele.Gittyup.Application"
|
||||
#define DBUS_OBJECT_PATH "/com/github/Murmele/Gittyup/Application"
|
||||
#define DBUS_SERVICE_NAME GITTYUP_IDENTIFIER
|
||||
#define DBUS_INTERFACE_NAME GITTYUP_DBUS_INTERFACE_NAME
|
||||
#define DBUS_OBJECT_PATH GITTYUP_DBUS_OBJECT_PATH
|
||||
|
||||
DBusGittyup::DBusGittyup(QObject *parent) : QObject(parent) {}
|
||||
|
||||
@ -488,4 +508,4 @@ void Application::handleSslErrors(QNetworkReply *reply,
|
||||
reply->ignoreSslErrors(errors);
|
||||
settings.setValue("ssl/ignore", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ file(GLOB CONFIG_FILES ${CONF_DIR}/*.lua)
|
||||
file(GLOB DICTIONARIES ${CONF_DIR}/dictionaries/*.aff
|
||||
${CONF_DIR}/dictionaries/*.dic ${CONF_DIR}/dictionaries/*.txt)
|
||||
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)
|
||||
|
||||
# Build resources.
|
||||
@ -59,11 +59,22 @@ endif()
|
||||
|
||||
target_compile_definitions(
|
||||
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}"
|
||||
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)
|
||||
|
||||
@ -103,8 +114,10 @@ endif()
|
||||
target_link_libraries(gittyup app)
|
||||
|
||||
set_target_properties(
|
||||
gittyup PROPERTIES OUTPUT_NAME ${GITTYUP_NAME} RUNTIME_OUTPUT_DIRECTORY
|
||||
${CMAKE_BINARY_DIR})
|
||||
gittyup
|
||||
PROPERTIES OUTPUT_NAME ${GITTYUP_EXECUTABLE_NAME}
|
||||
MACOSX_BUNDLE_BUNDLE_NAME ${GITTYUP_NAME}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(app Dbghelp.lib)
|
||||
@ -118,7 +131,7 @@ elseif(APPLE)
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${GITTYUP_VERSION}
|
||||
MACOSX_BUNDLE_LONG_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.
|
||||
set_source_files_properties(
|
||||
@ -152,19 +165,10 @@ endif()
|
||||
|
||||
add_dependencies(gittyup indexer relauncher)
|
||||
|
||||
if(FLATPAK)
|
||||
# Install application.
|
||||
install(
|
||||
TARGETS gittyup
|
||||
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()
|
||||
install(
|
||||
TARGETS gittyup
|
||||
DESTINATION $<IF:$<PLATFORM_ID:Darwin>,.,${CMAKE_INSTALL_BINDIR}>
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
if(APPLE)
|
||||
get_target_property(QT_LIBRARY Qt5::Core LOCATION)
|
||||
@ -172,7 +176,7 @@ if(APPLE)
|
||||
get_filename_component(RPATH ${QT_FRAMEWORK} DIRECTORY)
|
||||
|
||||
# Fixup relauncher RPATH.
|
||||
set(RELAUNCHER ${GITTYUP_NAME}.app/Contents/MacOS/relauncher)
|
||||
set(RELAUNCHER ${CONTENTS_DIR}/MacOS/relauncher)
|
||||
install(
|
||||
CODE "execute_process(COMMAND
|
||||
${CMAKE_INSTALL_NAME_TOOL} -delete_rpath \"${RPATH}\"
|
||||
@ -189,7 +193,7 @@ execute_process(COMMAND
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
# Fixup indexer RPATH.
|
||||
set(INDEXER ${GITTYUP_NAME}.app/Contents/MacOS/indexer)
|
||||
set(INDEXER ${CONTENTS_DIR}/MacOS/indexer)
|
||||
install(
|
||||
CODE "execute_process(COMMAND
|
||||
${CMAKE_INSTALL_NAME_TOOL} -delete_rpath \"${RPATH}\"
|
||||
@ -207,13 +211,16 @@ execute_process(COMMAND
|
||||
else()
|
||||
# Windows and UNIX must be ./ otherwise it is interpreted as absolute path
|
||||
if(UNIX)
|
||||
set(RESOURCES_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_DATADIR}/gittyup/Resources"
|
||||
CACHE STRING "The path for installing resource files")
|
||||
else()
|
||||
set(RESOURCES_INSTALL_DIR
|
||||
"Resources"
|
||||
CACHE STRING "The path for installing resource files")
|
||||
install(
|
||||
FILES ${CMAKE_SOURCE_DIR}/rsrc/linux/com.github.Murmele.Gittyup.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
||||
RENAME ${GITTYUP_EXECUTABLE_NAME}.desktop)
|
||||
if(${GENERATE_APPDATA})
|
||||
install(
|
||||
FILES ${APPDATA}
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo
|
||||
RENAME ${GITTYUP_EXECUTABLE_NAME}.appdata.xml)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Install config files.
|
||||
@ -224,13 +231,13 @@ else()
|
||||
install(
|
||||
FILES ${CHANGELOG_HTML} ${ACKNOWLEDGMENTS_HTML} ${PRIVACY_HTML}
|
||||
${PLUGIN_HTML}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}
|
||||
DESTINATION ${RESOURCES_DIR}
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
|
||||
install(
|
||||
FILES ${EMOJI} ${MERGETOOLS}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}
|
||||
DESTINATION ${RESOURCES_DIR}
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EMOJI}
|
||||
@ -241,7 +248,7 @@ else()
|
||||
foreach(CONFIG_FILE ${CONFIG_FILES})
|
||||
install(
|
||||
FILES ${CONFIG_FILE}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}
|
||||
DESTINATION ${RESOURCES_DIR}
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
file(RELATIVE_PATH CONFIG_FILE_DEST ${CONF_DIR} ${CONFIG_FILE})
|
||||
@ -252,7 +259,7 @@ else()
|
||||
|
||||
install(
|
||||
FILES ${DICTIONARIES}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}/dictionaries
|
||||
DESTINATION ${RESOURCES_DIR}/dictionaries
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
foreach(DICTIONARY ${DICTIONARIES})
|
||||
@ -263,7 +270,7 @@ else()
|
||||
|
||||
install(
|
||||
FILES ${THEMES}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}/themes
|
||||
DESTINATION ${RESOURCES_DIR}/themes
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
foreach(THEME ${THEMES})
|
||||
@ -274,7 +281,7 @@ else()
|
||||
|
||||
install(
|
||||
FILES ${LUA_PLUGINS}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}/plugins
|
||||
DESTINATION ${RESOURCES_DIR}/plugins
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
foreach(LUA_PLUGIN ${LUA_PLUGINS})
|
||||
@ -286,7 +293,7 @@ else()
|
||||
foreach(SCINTILLUA_LEXER ${SCINTILLUA_LEXERS})
|
||||
install(
|
||||
FILES ${SCINTILLUA_LEXER}
|
||||
DESTINATION ${RESOURCES_INSTALL_DIR}/lexers
|
||||
DESTINATION ${RESOURCES_DIR}/lexers
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
|
||||
get_filename_component(SCINTILLUA_LEXER_DEST ${SCINTILLUA_LEXER} NAME)
|
||||
|
@ -354,6 +354,21 @@ QColor CustomTheme::badge(BadgeRole role, BadgeState state) {
|
||||
case BadgeState::Notification:
|
||||
stateKey = "notification";
|
||||
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();
|
||||
@ -421,6 +436,8 @@ QColor CustomTheme::commitEditor(CommitEditor color) {
|
||||
case CommitEditor::LengthWarning:
|
||||
return commitEditor.value("lengthwarning").value<QColor>();
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor CustomTheme::diff(Diff color) {
|
||||
@ -450,6 +467,8 @@ QColor CustomTheme::diff(Diff color) {
|
||||
case Diff::Error:
|
||||
return diff.value("error").value<QColor>();
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor CustomTheme::heatMap(HeatMap color) {
|
||||
@ -461,6 +480,8 @@ QColor CustomTheme::heatMap(HeatMap color) {
|
||||
case HeatMap::Cold:
|
||||
return QColor(heatmap.value("cold").toString());
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor CustomTheme::remoteComment(Comment color) {
|
||||
@ -476,6 +497,8 @@ QColor CustomTheme::remoteComment(Comment color) {
|
||||
case Comment::Timestamp:
|
||||
return QColor(comment.value("timestamp").toString());
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor CustomTheme::star() {
|
||||
|
@ -101,7 +101,14 @@ QColor Theme::badge(BadgeRole role, BadgeState state) {
|
||||
case BadgeState::Head:
|
||||
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);
|
||||
}
|
||||
|
||||
@ -123,8 +130,20 @@ QColor Theme::badge(BadgeRole role, BadgeState state) {
|
||||
|
||||
case BadgeState::Notification:
|
||||
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() {
|
||||
@ -152,6 +171,8 @@ QColor Theme::commitEditor(CommitEditor color) {
|
||||
case CommitEditor::LengthWarning:
|
||||
return Qt::yellow;
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor Theme::diff(Diff color) {
|
||||
@ -180,6 +201,8 @@ QColor Theme::diff(Diff color) {
|
||||
case Diff::Error:
|
||||
return "#7E494B";
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
switch (color) {
|
||||
@ -206,6 +229,8 @@ QColor Theme::diff(Diff color) {
|
||||
case Diff::Error:
|
||||
return "#FF0000";
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor Theme::heatMap(HeatMap color) {
|
||||
@ -216,6 +241,8 @@ QColor Theme::heatMap(HeatMap color) {
|
||||
return mDark ? QPalette().color(QPalette::Inactive, QPalette::Highlight)
|
||||
: QPalette().color(QPalette::Mid);
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(color)));
|
||||
}
|
||||
|
||||
QColor Theme::remoteComment(Comment color) {
|
||||
@ -229,6 +256,8 @@ QColor Theme::remoteComment(Comment color) {
|
||||
case Comment::Timestamp:
|
||||
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); }
|
||||
|
@ -22,7 +22,18 @@ class Theme {
|
||||
public:
|
||||
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 };
|
||||
|
||||
|
@ -1,18 +1,15 @@
|
||||
add_library(conf ConfFile.cpp Settings.cpp Setting.cpp RecentRepositories.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(
|
||||
conf PRIVATE SCINTILLUA_LEXERS_DIR="${SCINTILLUA_LEXERS_DIR}")
|
||||
|
||||
if(UNIX)
|
||||
target_compile_definitions(
|
||||
conf
|
||||
PRIVATE CONF_DIR="${CMAKE_INSTALL_FULL_DATADIR}/gittyup/Resources"
|
||||
L10N_DIR="${CMAKE_INSTALL_FULL_DATADIR}/gittyup/Resources/l10n")
|
||||
else()
|
||||
|
||||
target_compile_definitions(conf PRIVATE CONF_DIR="" L10N_DIR="")
|
||||
endif()
|
||||
conf
|
||||
PRIVATE CONF_DIR="${RESOURCES_DIR}"
|
||||
SRC_CONF_DIR="${CMAKE_SOURCE_DIR}/conf"
|
||||
L10N_DIR="${L10N_INSTALL_DIR}"
|
||||
SRC_L10N_DIR="${CMAKE_BINARY_DIR}/l10n"
|
||||
SCINTILLUA_LEXERS_DIR="${SCINTILLUA_LEXERS_DIR}"
|
||||
SRC_SCINTILLUA_LEXERS_DIR="${SRC_SCINTILLUA_LEXERS_DIR}")
|
||||
set_target_properties(conf PROPERTIES AUTOMOC ON)
|
||||
|
@ -50,16 +50,20 @@ void RecentRepositories::remove(int index) {
|
||||
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();
|
||||
|
||||
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) {
|
||||
#ifdef Q_OS_WIN
|
||||
return repo->path().compare(rhs->path(), Qt::CaseInsensitive) == 0;
|
||||
return repo->gitpath().compare(rhs->gitpath(), Qt::CaseInsensitive) == 0;
|
||||
#else
|
||||
return (repo->path() == rhs->path());
|
||||
return (repo->gitpath() == rhs->gitpath());
|
||||
#endif
|
||||
});
|
||||
|
||||
@ -82,7 +86,7 @@ RecentRepositories *RecentRepositories::instance() {
|
||||
void RecentRepositories::store() {
|
||||
QStringList paths;
|
||||
foreach (RecentRepository *repo, mRepos)
|
||||
paths.append(repo->path());
|
||||
paths.append(repo->gitpath());
|
||||
|
||||
QSettings().setValue(kRecentKey, paths);
|
||||
|
||||
@ -125,6 +129,13 @@ void RecentRepositories::load() {
|
||||
qDeleteAll(mRepos);
|
||||
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) {
|
||||
RecentRepository *repo = new RecentRepository(path, this);
|
||||
auto functor = [repo](RecentRepository *rhs) {
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
#include "RecentRepository.h"
|
||||
|
||||
RecentRepository::RecentRepository(const QString &path, QObject *parent)
|
||||
: QObject(parent), mPath(path) {}
|
||||
RecentRepository::RecentRepository(const QString &gitpath, QObject *parent)
|
||||
: QObject(parent), mGitPath(gitpath) {}
|
||||
|
||||
QString RecentRepository::path() const { return mPath; }
|
||||
QString RecentRepository::gitpath() const { return mGitPath; }
|
||||
|
||||
QString RecentRepository::name() const {
|
||||
return mPath.section('/', -mSections);
|
||||
return mGitPath.section('/', -mSections, -1);
|
||||
}
|
||||
|
||||
void RecentRepository::increment() { ++mSections; }
|
||||
|
@ -16,15 +16,15 @@ class RecentRepository : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RecentRepository(const QString &path, QObject *parent = nullptr);
|
||||
RecentRepository(const QString &gitpath, QObject *parent = nullptr);
|
||||
|
||||
QString path() const;
|
||||
QString gitpath() const;
|
||||
QString name() const;
|
||||
|
||||
private:
|
||||
void increment();
|
||||
|
||||
QString mPath;
|
||||
QString mGitPath;
|
||||
int mSections = 1;
|
||||
|
||||
friend class RecentRepositories;
|
||||
|
@ -26,7 +26,7 @@ void Setting::initialize(QMap<Id, QString> &keys) {
|
||||
keys[Id::TerminalName] = "terminal/name";
|
||||
keys[Id::TerminalPath] = "terminal/path";
|
||||
keys[Id::DontTranslate] = "translation/disable";
|
||||
keys[Id::StoreCredentials] = "credential/store";
|
||||
keys[Id::Language] = "translation/language";
|
||||
keys[Id::AllowSingleInstanceOnly] = "singleInstance";
|
||||
keys[Id::CheckForUpdatesAutomatically] = "update/check";
|
||||
keys[Id::InstallUpdatesAutomatically] = "update/download";
|
||||
@ -35,8 +35,13 @@ void Setting::initialize(QMap<Id, QString> &keys) {
|
||||
keys[Id::SshKeyFilePath] = "ssh/keyFilePath";
|
||||
keys[Id::CommitMergeImmediately] = "merge/commit";
|
||||
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::ShowChangedFilesInSingleView] = "doubletreeview/single";
|
||||
keys[Id::ShowChangedFilesMultiColumn] = "doubletreeview/listviewmulticolumn";
|
||||
keys[Id::HideUntracked] = "untracked.hide";
|
||||
}
|
||||
|
||||
void Prompt::initialize(QMap<Kind, QString> &keys) {
|
||||
|
@ -50,7 +50,6 @@ public:
|
||||
TerminalName,
|
||||
TerminalPath,
|
||||
DontTranslate,
|
||||
StoreCredentials,
|
||||
AllowSingleInstanceOnly,
|
||||
CheckForUpdatesAutomatically,
|
||||
InstallUpdatesAutomatically,
|
||||
@ -59,8 +58,14 @@ public:
|
||||
SshKeyFilePath,
|
||||
CommitMergeImmediately,
|
||||
ShowCommitsInCompactMode,
|
||||
ShowCommitsAuthor,
|
||||
ShowCommitsDate,
|
||||
ShowCommitsId,
|
||||
ShowChangedFilesAsList,
|
||||
ShowChangedFilesMultiColumn, // For the list only
|
||||
ShowChangedFilesInSingleView,
|
||||
HideUntracked,
|
||||
Language,
|
||||
};
|
||||
Q_ENUM(Id)
|
||||
|
||||
|
@ -9,13 +9,14 @@
|
||||
|
||||
#include "Settings.h"
|
||||
#include "ConfFile.h"
|
||||
#include "Debug.h"
|
||||
#include "qtsupport.h"
|
||||
#include "languages.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define CS Qt::CaseInsensitive
|
||||
#else
|
||||
@ -24,18 +25,20 @@
|
||||
|
||||
namespace {
|
||||
|
||||
const QString kIgnoreWsKey = "diff/whitespace/ignore";
|
||||
const QString kLastPathKey = "lastpath";
|
||||
const QString kIgnoreWsKey("diff/whitespace/ignore");
|
||||
const QString kLastPathKey("lastpath");
|
||||
const QString kTranslation("translation");
|
||||
const QString kTranslationLanguage("language");
|
||||
|
||||
// Look up variant at key relative to root.
|
||||
QVariant lookup(const QVariantMap &root, const QString &key) {
|
||||
QStringList list = key.split("/", QString::SkipEmptyParts);
|
||||
QStringList list(key.split("/", Qt::SkipEmptyParts));
|
||||
if (list.isEmpty())
|
||||
return root;
|
||||
|
||||
QVariantMap map = root;
|
||||
QVariantMap map(root);
|
||||
while (map.contains(list.first())) {
|
||||
QVariant result = map.value(list.takeFirst());
|
||||
QVariant result(map.value(list.takeFirst()));
|
||||
if (list.isEmpty())
|
||||
return result;
|
||||
map = result.toMap();
|
||||
@ -45,24 +48,16 @@ QVariant lookup(const QVariantMap &root, const QString &key) {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Settings::Settings(QObject *parent) : QObject(parent) {
|
||||
foreach (const QFileInfo &file, confDir().entryInfoList(QStringList("*.lua")))
|
||||
mDefaults[file.baseName()] = ConfFile(file.absoluteFilePath()).parse();
|
||||
mDefaults[kLastPathKey] = QDir::homePath();
|
||||
QVariantMap map;
|
||||
map[kTranslationLanguage] = QVariant(Languages::system);
|
||||
mDefaults[kTranslation] = map;
|
||||
mDefaults[kTranslation].toMap()[kTranslationLanguage] = Languages::system;
|
||||
mCurrentMap = mDefaults;
|
||||
}
|
||||
|
||||
@ -76,7 +71,7 @@ QVariant Settings::value(const QString &key,
|
||||
const QVariant &defaultValue) const {
|
||||
QSettings settings;
|
||||
settings.beginGroup(group());
|
||||
QVariant result = settings.value(key, defaultValue);
|
||||
QVariant result(settings.value(key, defaultValue));
|
||||
settings.endGroup();
|
||||
return result;
|
||||
}
|
||||
@ -120,13 +115,13 @@ QString Settings::lexer(const QString &filename) {
|
||||
return "null";
|
||||
|
||||
QFileInfo info(filename);
|
||||
QString name = info.fileName();
|
||||
QString suffix = info.suffix().toLower();
|
||||
QString name(info.fileName());
|
||||
QString suffix(info.suffix().toLower());
|
||||
|
||||
// Try all patterns first.
|
||||
QVariantMap lexers = mDefaults.value("lexers").toMap();
|
||||
QVariantMap lexers(mDefaults.value("lexers").toMap());
|
||||
foreach (const QString &key, lexers.keys()) {
|
||||
QVariantMap map = lexers.value(key).toMap();
|
||||
QVariantMap map(lexers.value(key).toMap());
|
||||
if (map.contains("patterns")) {
|
||||
foreach (QString pattern, map.value("patterns").toString().split(",")) {
|
||||
QRegExp regExp(pattern, CS, QRegExp::Wildcard);
|
||||
@ -138,7 +133,7 @@ QString Settings::lexer(const QString &filename) {
|
||||
|
||||
// Try to match by extension.
|
||||
foreach (const QString &key, lexers.keys()) {
|
||||
QVariantMap map = lexers.value(key).toMap();
|
||||
QVariantMap map(lexers.value(key).toMap());
|
||||
if (map.contains("extensions")) {
|
||||
foreach (QString ext, map.value("extensions").toString().split(",")) {
|
||||
if (suffix == ext)
|
||||
@ -151,8 +146,8 @@ QString Settings::lexer(const QString &filename) {
|
||||
}
|
||||
|
||||
QString Settings::kind(const QString &filename) {
|
||||
QString key = lexer(filename);
|
||||
QVariantMap lexers = mDefaults.value("lexers").toMap();
|
||||
QString key(lexer(filename));
|
||||
QVariantMap lexers(mDefaults.value("lexers").toMap());
|
||||
return lexers.value(key).toMap().value("name").toString();
|
||||
}
|
||||
|
||||
@ -184,6 +179,8 @@ QString Settings::promptDescription(Prompt::Kind kind) const {
|
||||
case Prompt::Kind::LargeFiles:
|
||||
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) {
|
||||
@ -208,6 +205,13 @@ void Settings::setLastPath(const QString &lastPath) {
|
||||
setValue(kLastPathKey, lastPath);
|
||||
}
|
||||
|
||||
QDir Settings::rootDir() {
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
dir.cdUp();
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
QDir Settings::appDir() {
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
|
||||
@ -223,48 +227,62 @@ QDir Settings::appDir() {
|
||||
QDir Settings::docDir() { return confDir(); }
|
||||
|
||||
QDir Settings::confDir() {
|
||||
QDir dir = rootDir();
|
||||
if (!dir.cd("Resources"))
|
||||
dir = QDir(CONF_DIR);
|
||||
qDebug() << "Conf dir: " << dir;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
QDir dir(SRC_CONF_DIR);
|
||||
#else
|
||||
QDir dir(rootDir());
|
||||
if (!dir.cd("Resources")) {
|
||||
if (!dir.cd(CONF_DIR))
|
||||
dir.setPath(SRC_CONF_DIR);
|
||||
}
|
||||
#endif
|
||||
return dir;
|
||||
}
|
||||
|
||||
QDir Settings::l10nDir() {
|
||||
QDir dir = confDir();
|
||||
if (!dir.cd("l10n"))
|
||||
dir = QDir(L10N_DIR);
|
||||
|
||||
qDebug() << "l10n dir: " << dir;
|
||||
#if !defined(NDEBUG)
|
||||
QDir dir(QDir(SRC_L10N_DIR));
|
||||
#else
|
||||
QDir dir(confDir());
|
||||
if (!dir.cd("l10n")) {
|
||||
dir = rootDir();
|
||||
if (!dir.cd(L10N_DIR))
|
||||
dir.setPath(SRC_L10N_DIR);
|
||||
}
|
||||
#endif
|
||||
return dir;
|
||||
}
|
||||
|
||||
QDir Settings::dictionariesDir() {
|
||||
QDir dir = confDir();
|
||||
QDir dir(confDir());
|
||||
dir.cd("dictionaries");
|
||||
qDebug() << "Dictionaries dir: " << dir;
|
||||
return dir;
|
||||
}
|
||||
|
||||
QDir Settings::lexerDir() {
|
||||
QDir dir = confDir();
|
||||
if (!dir.cd("lexers"))
|
||||
dir = QDir(SCINTILLUA_LEXERS_DIR);
|
||||
qDebug() << "Lexers dir: " << dir;
|
||||
#if !defined(NDEBUG)
|
||||
QDir dir(SRC_SCINTILLUA_LEXERS_DIR);
|
||||
#else
|
||||
QDir dir(confDir());
|
||||
if (!dir.cd("lexers")) {
|
||||
dir = rootDir();
|
||||
if (!dir.cd(SCINTILLUA_LEXERS_DIR))
|
||||
dir.setPath(SRC_SCINTILLUA_LEXERS_DIR);
|
||||
}
|
||||
#endif
|
||||
return dir;
|
||||
}
|
||||
|
||||
QDir Settings::themesDir() {
|
||||
QDir dir = confDir();
|
||||
QDir dir(confDir());
|
||||
dir.cd("themes");
|
||||
qDebug() << "Theme dir: " << dir;
|
||||
return dir;
|
||||
}
|
||||
|
||||
QDir Settings::pluginsDir() {
|
||||
QDir dir = confDir();
|
||||
QDir dir(confDir());
|
||||
dir.cd("plugins");
|
||||
qDebug() << "Plugins dir: " << dir;
|
||||
return dir;
|
||||
}
|
||||
|
||||
@ -273,8 +291,8 @@ QDir Settings::userDir() {
|
||||
}
|
||||
|
||||
QDir Settings::tempDir() {
|
||||
QString name = QCoreApplication::applicationName();
|
||||
QDir dir = QDir::temp();
|
||||
QString name(QCoreApplication::applicationName());
|
||||
QDir dir(QDir::temp());
|
||||
dir.mkpath(name);
|
||||
dir.cd(name);
|
||||
return dir;
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
void setLastPath(const QString &lastPath);
|
||||
|
||||
// settings directories
|
||||
static QDir rootDir();
|
||||
static QDir appDir();
|
||||
static QDir docDir();
|
||||
static QDir confDir();
|
||||
|
@ -1,10 +1,5 @@
|
||||
if(WIN32)
|
||||
set(CREDENTIAL_IMPL_FILE WinCred.cpp)
|
||||
endif()
|
||||
add_library(cred Cache.cpp Store.cpp CredentialHelper.cpp GitCredential.cpp)
|
||||
|
||||
add_library(cred Cache.cpp CredentialHelper.cpp GitCredential.cpp
|
||||
${CREDENTIAL_IMPL_FILE})
|
||||
|
||||
target_link_libraries(cred conf Qt5::Core)
|
||||
target_link_libraries(cred conf git Qt5::Core)
|
||||
|
||||
set_target_properties(cred PROPERTIES AUTOMOC ON)
|
||||
|
@ -10,8 +10,10 @@
|
||||
#include "CredentialHelper.h"
|
||||
#include "Cache.h"
|
||||
#include "GitCredential.h"
|
||||
#include "WinCred.h"
|
||||
#include "qtsupport.h"
|
||||
#include "Store.h"
|
||||
#include "conf/Settings.h"
|
||||
#include "git/Config.h"
|
||||
#include <QLibrary>
|
||||
#include <QPointer>
|
||||
#include <QSettings>
|
||||
@ -22,27 +24,30 @@ namespace {
|
||||
|
||||
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
|
||||
|
||||
CredentialHelper *CredentialHelper::instance() {
|
||||
static QPointer<CredentialHelper> instance;
|
||||
if (!instance) {
|
||||
if (Settings::instance()->value(Setting::Id::StoreCredentials).toBool()) {
|
||||
#if defined(Q_OS_MAC)
|
||||
instance = new GitCredential("osxkeychain");
|
||||
#elif defined(Q_OS_WIN)
|
||||
// The git wincred helper fails for some users.
|
||||
instance = new WinCred;
|
||||
#else
|
||||
QLibrary lib("secret-1", 0);
|
||||
if (lib.load()) {
|
||||
instance = new GitCredential("libsecret");
|
||||
git::Config config = git::Config::global();
|
||||
auto helperName = config.value<QString>("credential.helper");
|
||||
if (isHelperValid(helperName)) {
|
||||
if (helperName == cacheStoreName) {
|
||||
instance = new Cache;
|
||||
} else if (helperName == storeStoreName) {
|
||||
auto path =
|
||||
QString::fromLocal8Bit(qgetenv("HOME") + "/.git-credentials");
|
||||
instance = new Store(path);
|
||||
} else {
|
||||
QLibrary lib("gnome-keyring", 0);
|
||||
if (lib.load())
|
||||
instance = new GitCredential("gnome-keyring");
|
||||
instance = new GitCredential(helperName);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!instance)
|
||||
@ -52,6 +57,31 @@ CredentialHelper *CredentialHelper::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() {
|
||||
return QSettings().value(kLogKey).toBool();
|
||||
}
|
||||
@ -69,5 +99,5 @@ void CredentialHelper::log(const QString &text) {
|
||||
return;
|
||||
|
||||
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 void setLoggingEnabled(bool enabled);
|
||||
|
||||
static QStringList getAvailableHelperNames();
|
||||
static bool isHelperValid(const QString &name);
|
||||
|
||||
protected:
|
||||
static void log(const QString &text);
|
||||
};
|
||||
|
@ -8,6 +8,8 @@
|
||||
//
|
||||
|
||||
#include "GitCredential.h"
|
||||
#include "qtsupport.h"
|
||||
#include <QStandardPaths>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
@ -44,11 +46,11 @@ bool GitCredential::get(const QString &url, QString &username,
|
||||
return false;
|
||||
|
||||
QTextStream out(&process);
|
||||
out << "protocol=" << protocol(url) << endl;
|
||||
out << "host=" << host(url) << endl;
|
||||
out << "protocol=" << protocol(url) << Qt::endl;
|
||||
out << "host=" << host(url) << Qt::endl;
|
||||
if (!username.isEmpty())
|
||||
out << "username=" << username << endl;
|
||||
out << endl;
|
||||
out << "username=" << username << Qt::endl;
|
||||
out << Qt::endl;
|
||||
|
||||
process.closeWriteChannel();
|
||||
process.waitForFinished();
|
||||
@ -79,11 +81,11 @@ bool GitCredential::store(const QString &url, const QString &username,
|
||||
return false;
|
||||
|
||||
QTextStream out(&process);
|
||||
out << "protocol=" << protocol(url) << endl;
|
||||
out << "host=" << host(url) << endl;
|
||||
out << "username=" << username << endl;
|
||||
out << "password=" << password << endl;
|
||||
out << endl;
|
||||
out << "protocol=" << protocol(url) << Qt::endl;
|
||||
out << "host=" << host(url) << Qt::endl;
|
||||
out << "username=" << username << Qt::endl;
|
||||
out << "password=" << password << Qt::endl;
|
||||
out << Qt::endl;
|
||||
|
||||
process.closeWriteChannel();
|
||||
process.waitForFinished();
|
||||
@ -92,6 +94,46 @@ bool GitCredential::store(const QString &url, const QString &username,
|
||||
}
|
||||
|
||||
QString GitCredential::command() const {
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
return dir.filePath(QString("git-credential-%1").arg(mName));
|
||||
QString name = 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 =
|
||||
"<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 "
|
||||
"contributors</p><p> If you have a question that might benefit the "
|
||||
"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);
|
||||
|
||||
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");
|
||||
l->addWidget(lMessage, Row::CommitMessageLabel, 0);
|
||||
l->addWidget(m_commitMessage, Row::CommitMessage, 0, 1, 2);
|
||||
|
@ -24,6 +24,7 @@ add_library(
|
||||
RebaseConflictDialog.cpp
|
||||
RemoteDialog.cpp
|
||||
RemoteTableModel.cpp
|
||||
RenameBranchDialog.cpp
|
||||
SettingsDialog.cpp
|
||||
StartDialog.cpp
|
||||
SubmoduleDelegate.cpp
|
||||
|
@ -100,17 +100,17 @@ public:
|
||||
|
||||
// Connect signals after initializing fields.
|
||||
connect(mName, &QLineEdit::textChanged, this, [this](const QString &text) {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.gitConfig();
|
||||
config.setValue("user.name", 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);
|
||||
});
|
||||
|
||||
connect(mFetch, &QCheckBox::toggled, view, [this, view](bool checked) {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.appConfig();
|
||||
config.setValue("autofetch.enable", checked);
|
||||
view->startFetchTimer();
|
||||
});
|
||||
@ -118,28 +118,28 @@ public:
|
||||
using Signal = void (QSpinBox::*)(int);
|
||||
auto signal = static_cast<Signal>(&QSpinBox::valueChanged);
|
||||
connect(mFetchMinutes, signal, this, [this](int value) {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.appConfig();
|
||||
config.setValue("autofetch.minutes", value);
|
||||
});
|
||||
|
||||
connect(mPushCommit, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.appConfig();
|
||||
config.setValue("autopush.enable", checked);
|
||||
});
|
||||
|
||||
connect(mPullUpdate, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.appConfig();
|
||||
config.setValue("autoupdate.enable", checked);
|
||||
});
|
||||
|
||||
connect(mAutoPrune, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.appConfig();
|
||||
config.setValue("autoprune.enable", checked);
|
||||
});
|
||||
}
|
||||
|
||||
void init() {
|
||||
git::Config config = mRepo.config();
|
||||
git::Config config = mRepo.gitConfig();
|
||||
mName->setText(config.value<QString>("user.name"));
|
||||
mEmail->setText(config.value<QString>("user.email"));
|
||||
|
||||
@ -158,6 +158,7 @@ public:
|
||||
git::Config app = mRepo.appConfig();
|
||||
mFetch->setChecked(app.value<bool>("autofetch.enable", fetch));
|
||||
mFetchMinutes->setValue(app.value<int>("autofetch.minutes", minutes));
|
||||
mFetchMinutes->setEnabled(mFetch->isChecked());
|
||||
mPushCommit->setChecked(app.value<bool>("autopush.enable", push));
|
||||
mPullUpdate->setChecked(app.value<bool>("autoupdate.enable", update));
|
||||
mAutoPrune->setChecked(app.value<bool>("autoprune.enable", prune));
|
||||
@ -605,7 +606,7 @@ public:
|
||||
QLineEdit *urlLineEdit =
|
||||
new QLineEdit(map.value("Endpoint").section(" ", 0, 0));
|
||||
connect(urlLineEdit, &QLineEdit::textChanged, [repo](const QString &text) {
|
||||
git::Config config = repo.config();
|
||||
git::Config config = repo.gitConfig();
|
||||
config.setValue("lfs.url", text);
|
||||
});
|
||||
|
||||
@ -614,7 +615,7 @@ public:
|
||||
pruneOffsetDays->setValue(map.value("PruneOffsetDays").toInt());
|
||||
auto signal = QOverload<int>::of(&QSpinBox::valueChanged);
|
||||
connect(pruneOffsetDays, signal, [repo](int value) {
|
||||
git::Config config = repo.config();
|
||||
git::Config config = repo.gitConfig();
|
||||
config.setValue("lfs.pruneoffsetdays", value);
|
||||
});
|
||||
QHBoxLayout *pruneOffsetLayout = new QHBoxLayout;
|
||||
@ -628,7 +629,7 @@ public:
|
||||
bool fetchRecentEnabled = map.value("FetchRecentAlways").contains("true");
|
||||
fetchRecentAlways->setChecked(fetchRecentEnabled);
|
||||
connect(fetchRecentAlways, &QCheckBox::toggled, [repo](bool checked) {
|
||||
git::Config config = repo.config();
|
||||
git::Config config = repo.gitConfig();
|
||||
config.setValue("lfs.fetchrecentalways", checked);
|
||||
});
|
||||
|
||||
@ -637,7 +638,7 @@ public:
|
||||
fetchRecentRefsDays->setValue(map.value("FetchRecentRefsDays").toInt());
|
||||
fetchRecentRefsDays->setEnabled(fetchRecentEnabled);
|
||||
connect(fetchRecentRefsDays, signal, [repo](int value) {
|
||||
git::Config config = repo.config();
|
||||
git::Config config = repo.gitConfig();
|
||||
config.setValue("lfs.fetchrecentrefsdays", value);
|
||||
});
|
||||
connect(fetchRecentAlways, &QCheckBox::toggled, this,
|
||||
@ -655,7 +656,7 @@ public:
|
||||
map.value("FetchRecentCommitsDays").toInt());
|
||||
fetchRecentCommitsDays->setEnabled(fetchRecentEnabled);
|
||||
connect(fetchRecentCommitsDays, signal, [repo](int value) {
|
||||
git::Config config = repo.config();
|
||||
git::Config config = repo.gitConfig();
|
||||
config.setValue("lfs.fetchrecentcommitsdays", value);
|
||||
});
|
||||
connect(fetchRecentAlways, &QCheckBox::toggled, this,
|
||||
|
@ -47,7 +47,7 @@ DeleteBranchDialog::DeleteBranchDialog(const git::Branch &branch,
|
||||
|
||||
QString name = upstream.name().section('/', 1);
|
||||
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();
|
||||
QString remoteName = remote.name();
|
||||
|
@ -24,7 +24,8 @@
|
||||
#include <QTextCodec>
|
||||
|
||||
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
|
||||
QSpinBox *context = new QSpinBox(this);
|
||||
QLabel *contextLabel = new QLabel(tr("lines"), this);
|
||||
|
@ -85,7 +85,7 @@ QVBoxLayout *ExternalToolsDialog::createUserDefinedLayout(const QString &type) {
|
||||
table->resizeColumnsToContents();
|
||||
});
|
||||
|
||||
connect(footer, &Footer::minusClicked, [this, table, model] {
|
||||
connect(footer, &Footer::minusClicked, [table, model] {
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows(0);
|
||||
foreach (const QModelIndex &index, indexes)
|
||||
model->remove(index.data(Qt::DisplayRole).toString());
|
||||
|
@ -90,7 +90,7 @@ RemoteDialog::RemoteDialog(Kind kind, RepoView *parent) : QDialog(parent) {
|
||||
if (ref.isValid()) {
|
||||
QString key = QString("branch.%1.merge").arg(ref.name());
|
||||
git::Config config =
|
||||
RepoView::parentView(this)->repo().config();
|
||||
RepoView::parentView(this)->repo().gitConfig();
|
||||
value = config.value<QString>(key);
|
||||
}
|
||||
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/MenuBar.h"
|
||||
#include "ui/RepoView.h"
|
||||
#include "languages.h"
|
||||
#include "update/Updater.h"
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
@ -105,17 +106,23 @@ public:
|
||||
new QCheckBox(tr("Update submodules after pull and clone"), this);
|
||||
mAutoPrune = new QCheckBox(tr("Prune when fetching"), 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 =
|
||||
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>"));
|
||||
connect(privacy, &QLabel::linkActivated,
|
||||
[] { AboutDialog::openSharedInstance(AboutDialog::Privacy); });
|
||||
|
||||
mSingleInstance =
|
||||
new QCheckBox(tr("Only allow a single running instance"), this);
|
||||
|
||||
QFormLayout *form = new QFormLayout;
|
||||
form->addRow(tr("User name:"), mName);
|
||||
form->addRow(tr("User email:"), mEmail);
|
||||
@ -124,11 +131,18 @@ public:
|
||||
form->addRow(QString(), mPullUpdate);
|
||||
form->addRow(QString(), mAutoPrune);
|
||||
form->addRow(tr("Language:"), mNoTranslation);
|
||||
form->addRow(tr("Language:"), mLanguages);
|
||||
form->addRow(tr("Credentials:"), mStoreCredentials);
|
||||
form->addRow(tr("Credential store type:"), mAvailableStores);
|
||||
form->addRow(QString(), privacy);
|
||||
|
||||
mSingleInstance =
|
||||
new QCheckBox(tr("Only allow a single running instance"), this);
|
||||
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
||||
form->addRow(tr("Single instance:"), mSingleInstance);
|
||||
#elif defined(Q_OS_MACX)
|
||||
mSingleInstance->setVisible(false);
|
||||
#endif
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
@ -179,11 +193,33 @@ public:
|
||||
Settings::instance()->setValue(Setting::Id::DontTranslate, checked);
|
||||
});
|
||||
|
||||
connect(mStoreCredentials, &QCheckBox::toggled, [](bool checked) {
|
||||
Settings::instance()->setValue(Setting::Id::StoreCredentials, checked);
|
||||
connect(mLanguages, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[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();
|
||||
});
|
||||
|
||||
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) {
|
||||
Settings::instance()->setValue(Setting::Id::AllowSingleInstanceOnly,
|
||||
checked);
|
||||
@ -196,6 +232,7 @@ public:
|
||||
mEmail->setText(config.value<QString>("user.email"));
|
||||
|
||||
Settings *settings = Settings::instance();
|
||||
|
||||
mFetch->setChecked(
|
||||
settings->value(Setting::Id::FetchAutomatically).toBool());
|
||||
mFetchMinutes->setValue(
|
||||
@ -211,8 +248,25 @@ public:
|
||||
|
||||
mNoTranslation->setChecked(
|
||||
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(
|
||||
settings->value(Setting::Id::AllowSingleInstanceOnly).toBool());
|
||||
@ -228,7 +282,9 @@ private:
|
||||
QCheckBox *mPullUpdate;
|
||||
QCheckBox *mAutoPrune;
|
||||
QCheckBox *mNoTranslation;
|
||||
QComboBox *mLanguages;
|
||||
QCheckBox *mStoreCredentials;
|
||||
QComboBox *mAvailableStores;
|
||||
QCheckBox *mSingleInstance;
|
||||
};
|
||||
|
||||
|
@ -117,10 +117,10 @@ public:
|
||||
RecentRepository *repo = repos->repository(index.row());
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return mShowFullPath ? repo->path() : repo->name();
|
||||
return mShowFullPath ? repo->gitpath() : repo->name();
|
||||
|
||||
case Qt::UserRole:
|
||||
return repo->path();
|
||||
return repo->gitpath();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@ -698,7 +698,7 @@ void StartDialog::updateButtons() {
|
||||
open->setEnabled(false);
|
||||
} else {
|
||||
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())
|
||||
clone = true;
|
||||
} else {
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
case Theme::Dark:
|
||||
Settings::instance()->setValue(Setting::Id::ColorTheme, "Dark");
|
||||
break;
|
||||
default:
|
||||
case Theme::Default:
|
||||
Settings::instance()->setValue(Setting::Id::ColorTheme, "Default");
|
||||
break;
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ public:
|
||||
virtual ~LexerLPeg() {}
|
||||
|
||||
/** Destroys the lexer object. */
|
||||
void SCI_METHOD Release() {
|
||||
void SCI_METHOD Release() override {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexers");
|
||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
|
||||
lua_pushnil(L), lua_settable(L, -3), lua_pop(L, 1); // sci_lexers
|
||||
@ -429,7 +429,7 @@ public:
|
||||
* @param buffer The document interface.
|
||||
*/
|
||||
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_setfield(L, LUA_REGISTRYINDEX, "sci_props");
|
||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
|
||||
@ -515,7 +515,7 @@ public:
|
||||
* @param buffer The document interface.
|
||||
*/
|
||||
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_setfield(L, LUA_REGISTRYINDEX, "sci_props");
|
||||
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
|
||||
@ -552,7 +552,8 @@ public:
|
||||
* @param key The string keyword.
|
||||
* @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 : " ";
|
||||
props.Set(key, val, strlen(key), strlen(val)); // ensure property is cleared
|
||||
return -1; // no need to re-lex
|
||||
@ -566,7 +567,7 @@ public:
|
||||
* @param arg The argument.
|
||||
* @return void *data
|
||||
*/
|
||||
void *SCI_METHOD PrivateCall(int code, void *arg) {
|
||||
void *SCI_METHOD PrivateCall(int code, void *arg) override {
|
||||
switch (code) {
|
||||
case SCI_GETDIRECTFUNCTION:
|
||||
fn = reinterpret_cast<SciFnDirect>(arg);
|
||||
@ -603,12 +604,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int SCI_METHOD Version() const { return 0; }
|
||||
const char *SCI_METHOD PropertyNames() { return ""; }
|
||||
int SCI_METHOD PropertyType(const char *) { return 0; }
|
||||
const char *SCI_METHOD DescribeProperty(const char *) { return ""; }
|
||||
const char *SCI_METHOD DescribeWordListSets() { return ""; }
|
||||
Sci_Position SCI_METHOD WordListSet(int, const char *) { return -1; }
|
||||
int SCI_METHOD Version() const override { return 0; }
|
||||
const char *SCI_METHOD PropertyNames() override { return ""; }
|
||||
int SCI_METHOD PropertyType(const char *) override { return 0; }
|
||||
const char *SCI_METHOD DescribeProperty(const char *) override { return ""; }
|
||||
const char *SCI_METHOD DescribeWordListSets() override { return ""; }
|
||||
Sci_Position SCI_METHOD WordListSet(int, const char *) override { return -1; }
|
||||
|
||||
int SCI_METHOD LineEndTypesSupported() noexcept override {
|
||||
return SC_LINE_END_TYPE_UNICODE;
|
||||
@ -636,7 +637,7 @@ public:
|
||||
|
||||
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. */
|
||||
static ILexer5 *LexerFactoryLPeg() { return new LexerLPeg(); }
|
||||
|
@ -128,7 +128,7 @@ void SurfaceImpl::Polygon(Point *pts, size_t npts, ColourDesired fore,
|
||||
PenColour(fore);
|
||||
|
||||
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);
|
||||
|
||||
QPainter *painter = GetPainter();
|
||||
@ -306,7 +306,7 @@ void SurfaceImpl::MeasureWidths(Font &font, std::string_view s,
|
||||
QTextLine tl = tlay.createLine();
|
||||
tlay.endLayout();
|
||||
|
||||
int i = 0;
|
||||
size_t i = 0;
|
||||
int ui = 0;
|
||||
int fit = su.size();
|
||||
const unsigned char *us = reinterpret_cast<const unsigned char *>(s.data());
|
||||
@ -468,9 +468,6 @@ void Window::SetCursor(Cursor curs) {
|
||||
case cursorText:
|
||||
shape = Qt::IBeamCursor;
|
||||
break;
|
||||
case cursorArrow:
|
||||
shape = Qt::ArrowCursor;
|
||||
break;
|
||||
case cursorUp:
|
||||
shape = Qt::UpArrowCursor;
|
||||
break;
|
||||
|
@ -185,7 +185,7 @@ void ScintillaQt::paintEvent(QPaintEvent *event) {
|
||||
}
|
||||
|
||||
void ScintillaQt::wheelEvent(QWheelEvent *event) {
|
||||
if (event->orientation() == Qt::Horizontal) {
|
||||
if (event->angleDelta().x() != 0) {
|
||||
if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
|
||||
event->ignore();
|
||||
else
|
||||
@ -194,7 +194,7 @@ void ScintillaQt::wheelEvent(QWheelEvent *event) {
|
||||
if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
|
||||
// Zoom! We play with the font sizes in the styles.
|
||||
// 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);
|
||||
} else {
|
||||
KeyCommand(SCI_ZOOMOUT);
|
||||
@ -327,8 +327,7 @@ void ScintillaQt::keyPressEvent(QKeyEvent *event) {
|
||||
|
||||
QString text = event->text();
|
||||
if (input && !text.isEmpty() && text[0].isPrint()) {
|
||||
QByteArray utext = text.toUtf8();
|
||||
AddCharUTF(utext.data(), utext.size());
|
||||
InsertCharacter(text.toStdString(), CharacterSource::directInput);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
@ -355,7 +354,7 @@ static int modifierTranslated(int sciModifier) {
|
||||
void ScintillaQt::mousePressEvent(QMouseEvent *event) {
|
||||
Point pos = PointFromQPoint(event->pos());
|
||||
|
||||
if (event->button() == Qt::MidButton &&
|
||||
if (event->button() == Qt::MiddleButton &&
|
||||
QApplication::clipboard()->supportsSelection()) {
|
||||
SelectionPosition selPos =
|
||||
SPositionFromLocation(pos, false, false, UserVirtualSpace());
|
||||
@ -440,6 +439,7 @@ void ScintillaQt::dragEnterEvent(QDragEnterEvent *event) {
|
||||
}
|
||||
|
||||
void ScintillaQt::dragLeaveEvent(QDragLeaveEvent *event) {
|
||||
Q_UNUSED(event);
|
||||
SetDragPosition(SelectionPosition(Sci::invalidPosition));
|
||||
}
|
||||
|
||||
@ -520,9 +520,8 @@ void ScintillaQt::inputMethodEvent(QInputMethodEvent *event) {
|
||||
const unsigned int ucWidth = commitStr.at(i).isHighSurrogate() ? 2 : 1;
|
||||
const QString oneCharUTF16 = commitStr.mid(i, ucWidth);
|
||||
const QByteArray oneChar = oneCharUTF16.toUtf8();
|
||||
const int oneCharLen = oneChar.length();
|
||||
|
||||
AddCharUTF(oneChar.data(), oneCharLen);
|
||||
InsertCharacter(oneChar.toStdString(), CharacterSource::directInput);
|
||||
i += ucWidth;
|
||||
}
|
||||
|
||||
@ -568,7 +567,7 @@ void ScintillaQt::inputMethodEvent(QInputMethodEvent *event) {
|
||||
indicator = SC_INDICATOR_CONVERTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
case QTextCharFormat::DashDotDotLine:
|
||||
indicator = SC_INDICATOR_UNKNOWN;
|
||||
}
|
||||
|
||||
@ -605,7 +604,7 @@ void ScintillaQt::inputMethodEvent(QInputMethodEvent *event) {
|
||||
numBytes += oneCharLen;
|
||||
imeCharPos[i + 1] = numBytes;
|
||||
|
||||
AddCharUTF(oneChar.data(), oneCharLen);
|
||||
InsertCharacter(oneChar.toStdString(), CharacterSource::directInput);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// 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);
|
||||
|
||||
switch (query) {
|
||||
case Qt::ImMicroFocus: {
|
||||
case Qt::ImCursorRectangle: {
|
||||
int startPos = (preeditPos >= 0) ? preeditPos : pos;
|
||||
Point pt =
|
||||
const_cast<ScintillaQt *>(this)->LocationFromPosition(startPos);
|
||||
@ -691,9 +690,23 @@ QVariant ScintillaQt::inputMethodQuery(Qt::InputMethodQuery query) const {
|
||||
return buffer.constData();
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
case Qt::ImEnabled: // fall through
|
||||
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) {
|
||||
|
@ -43,7 +43,9 @@ QPixmap stagedUnstagedIcon(const bool &checked, const QColor &background,
|
||||
QRect(QPoint(0, 0), QSize(fontHeight - 2, fontHeight - 2)));
|
||||
}
|
||||
|
||||
#if defined(FLATPAK)
|
||||
const float textHeightFactorCheckBoxSize = 2.0;
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
|
||||
QList<Diagnostic> diagnostics(int line);
|
||||
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.
|
||||
// FIXME: This should be an event filter?
|
||||
@ -154,7 +154,7 @@ private:
|
||||
int diagnosticMarker(int line);
|
||||
void loadMarkerIcon(Marker marker, const QIcon &icon);
|
||||
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);
|
||||
|
||||
QString mPath;
|
||||
|
@ -129,11 +129,11 @@ void Branch::remove(bool force) {
|
||||
}
|
||||
|
||||
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) {
|
||||
repo().config().setValue(kRebaseFmt.arg(name()), checked);
|
||||
repo().gitConfig().setValue(kRebaseFmt.arg(name()), checked);
|
||||
}
|
||||
|
||||
AnnotatedCommit Branch::annotatedCommitFromFetchHead() const {
|
||||
|
@ -251,7 +251,8 @@ bool Commit::amend(const Signature &author, const Signature &committer,
|
||||
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<QByteArray> storage;
|
||||
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();
|
||||
int state = repo.state();
|
||||
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) {
|
||||
Patch::clearConflictResolutions(repo);
|
||||
emit repo.notifier()->stateChanged();
|
||||
|
@ -70,7 +70,8 @@ public:
|
||||
|
||||
// Reset HEAD to this commit.
|
||||
bool reset(git_reset_t type = GIT_RESET_MIXED,
|
||||
const QStringList &paths = QStringList()) const;
|
||||
const QStringList &paths = QStringList(),
|
||||
bool triggerReferenceUpdated = true) const;
|
||||
|
||||
// favorite commits
|
||||
bool isStarred() const;
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
#include "Diff.h"
|
||||
#include "Patch.h"
|
||||
#include "Debug.h"
|
||||
#include "git2/patch.h"
|
||||
#include <algorithm>
|
||||
#include <QDebug>
|
||||
|
||||
bool containsPath(QString &str, QString &occurence, Qt::CaseSensitivity cs) {
|
||||
if (str.contains(occurence, cs)) {
|
||||
@ -108,13 +108,13 @@ QByteArray Diff::print() {
|
||||
QByteArray diff;
|
||||
for (auto file : data.files) {
|
||||
for (auto hunk : file.hunks) {
|
||||
diff.append(hunk.header);
|
||||
diff.append(hunk.header.toUtf8());
|
||||
|
||||
for (auto line : hunk.lines)
|
||||
diff.append(line);
|
||||
diff.append(line.toUtf8());
|
||||
}
|
||||
}
|
||||
qDebug() << QString(diff);
|
||||
Debug(QString(diff));
|
||||
return diff;
|
||||
}
|
||||
|
||||
@ -173,6 +173,9 @@ void Diff::findSimilar(bool untracked) {
|
||||
if (untracked)
|
||||
opts.flags = GIT_DIFF_FIND_FOR_UNTRACKED;
|
||||
|
||||
if (!isValid())
|
||||
return;
|
||||
|
||||
git_diff_find_similar(d->diff, &opts);
|
||||
d->resetMap();
|
||||
}
|
||||
@ -195,6 +198,8 @@ void Diff::sort(SortRole role, Qt::SortOrder order) {
|
||||
: (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();
|
||||
|
||||
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();
|
||||
|
||||
if (mode)
|
||||
|
@ -195,7 +195,7 @@ QByteArray Patch::header(int hidx) const {
|
||||
|
||||
const git_diff_hunk *hunk = nullptr;
|
||||
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 {
|
||||
@ -204,7 +204,7 @@ const git_diff_hunk *Patch::header_struct(int hidx) const {
|
||||
|
||||
const git_diff_hunk *hunk = nullptr;
|
||||
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 {
|
||||
@ -235,7 +235,7 @@ char Patch::lineOrigin(int hidx, int ln) const {
|
||||
|
||||
const git_diff_line *line = nullptr;
|
||||
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 {
|
||||
@ -256,7 +256,7 @@ git_off_t Patch::contentOffset(int hidx) const {
|
||||
const git_diff_line *line = nullptr;
|
||||
int result = git_patch_get_line_in_hunk(&line, d.data(), hidx,
|
||||
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 {
|
||||
@ -265,7 +265,8 @@ QByteArray Patch::lineContent(int hidx, int ln) const {
|
||||
|
||||
const git_diff_line *line = nullptr;
|
||||
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) {
|
||||
@ -435,6 +436,7 @@ void Patch::apply(QList<QList<QByteArray>> &image, int hidx, int start_line,
|
||||
break;
|
||||
|
||||
default:
|
||||
// no-op
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ const git_rebase_operation *Rebase::operation(size_t index) {
|
||||
}
|
||||
|
||||
bool Rebase::hasNext() const {
|
||||
int index = currentIndex();
|
||||
int count = git_rebase_operation_entrycount(d.data());
|
||||
size_t index = currentIndex();
|
||||
size_t count = git_rebase_operation_entrycount(d.data());
|
||||
return (count > 0 && (index == GIT_REBASE_NO_OPERATION || index < count - 1));
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Branch.h"
|
||||
#include "Config.h"
|
||||
#include "Id.h"
|
||||
#include "qtsupport.h"
|
||||
#include "TagRef.h"
|
||||
#include "git2/buffer.h"
|
||||
#include "git2/clone.h"
|
||||
@ -423,7 +424,7 @@ int Remote::Callbacks::certificate(git_cert *cert, int valid, const char *host,
|
||||
return 0;
|
||||
|
||||
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))
|
||||
return 0;
|
||||
|
||||
@ -444,9 +445,10 @@ int Remote::Callbacks::transfer(const git_indexer_progress *stats,
|
||||
case Resolve:
|
||||
return cbs->resolve(stats->total_deltas, stats->indexed_deltas) ? 0 : -1;
|
||||
|
||||
default:
|
||||
case Update:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
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())
|
||||
refspec += ":" + upstream;
|
||||
}
|
||||
@ -674,7 +676,7 @@ void Remote::log(const QString &text) {
|
||||
return;
|
||||
|
||||
QString time = QTime::currentTime().toString(Qt::ISODateWithMs);
|
||||
QTextStream(&file) << time << " - " << text << endl;
|
||||
QTextStream(&file) << time << " - " << text << Qt::endl;
|
||||
}
|
||||
|
||||
} // namespace git
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "FilterList.h"
|
||||
#include "Index.h"
|
||||
#include "Patch.h"
|
||||
#include "qtsupport.h"
|
||||
#include "Rebase.h"
|
||||
#include "Reference.h"
|
||||
#include "Remote.h"
|
||||
@ -151,7 +152,14 @@ Repository::Repository(git_repository *repo) : d(registerRepository(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 {
|
||||
return isBare() ? dir() : QDir(git_repository_workdir(d->repo));
|
||||
@ -173,12 +181,16 @@ QString Repository::message() const {
|
||||
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_repository_config(&config, d->repo);
|
||||
return Config(config);
|
||||
}
|
||||
|
||||
// Config file used for app specific configs
|
||||
// config file in <Repository>/.git/gittyup/config
|
||||
Config Repository::appConfig() const {
|
||||
Config config = Config::appGlobal();
|
||||
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,
|
||||
bool ignoreWhitespace) const {
|
||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS |
|
||||
GIT_DIFF_INCLUDE_TYPECHANGE;
|
||||
opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE;
|
||||
|
||||
if (!appConfig().value<bool>("untracked.hide", false))
|
||||
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS;
|
||||
|
||||
if (ignoreWhitespace)
|
||||
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
|
||||
|
||||
@ -319,8 +334,11 @@ Diff Repository::diffIndexToWorkdir(const Index &index,
|
||||
Diff::Callbacks *callbacks,
|
||||
bool ignoreWhitespace) const {
|
||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||
opts.flags |= (GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS |
|
||||
GIT_DIFF_DISABLE_MMAP | GIT_DIFF_INCLUDE_TYPECHANGE);
|
||||
opts.flags |= (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)
|
||||
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
|
||||
|
||||
@ -477,7 +495,7 @@ QStringList Repository::existingTags() const {
|
||||
|
||||
QStringList list;
|
||||
|
||||
for (int i = 0; i < array.count; i++) {
|
||||
for (size_t i = 0; i < array.count; i++) {
|
||||
list.append(array.strings[i]);
|
||||
}
|
||||
|
||||
@ -618,6 +636,7 @@ Commit Repository::commit(const Signature &author, const Signature &committer,
|
||||
break;
|
||||
|
||||
default:
|
||||
// no-op
|
||||
break;
|
||||
}
|
||||
|
||||
@ -734,7 +753,7 @@ QList<Remote> Repository::remotes() const {
|
||||
return QList<Remote>();
|
||||
|
||||
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]))
|
||||
remotes.append(remote);
|
||||
}
|
||||
@ -889,8 +908,10 @@ void Repository::rebase(const AnnotatedCommit &mergeHead,
|
||||
git_rebase_init(&r, d->repo, nullptr, mergeHead, nullptr, &opts);
|
||||
auto rebase = git::Rebase(d->repo, r, overrideUser, overrideEmail);
|
||||
|
||||
if (!rebase.isValid())
|
||||
if (!rebase.isValid()) {
|
||||
emit d->notifier->rebaseInitError();
|
||||
return;
|
||||
}
|
||||
|
||||
// start rebasing
|
||||
rebaseContinue(QStringLiteral(""));
|
||||
@ -920,7 +941,6 @@ void Repository::rebaseContinue(const QString &commitMessage) {
|
||||
}
|
||||
}
|
||||
// Loop over rebase operations.
|
||||
int count = r.count();
|
||||
while (r.hasNext()) {
|
||||
git::Commit before = r.next();
|
||||
if (!before.isValid()) {
|
||||
@ -1010,7 +1030,7 @@ void Repository::cleanupState() {
|
||||
}
|
||||
|
||||
QTextCodec *Repository::codec() const {
|
||||
QString encoding = config().value<QString>("gui.encoding");
|
||||
QString encoding = gitConfig().value<QString>("gui.encoding");
|
||||
QTextCodec *codec = QTextCodec::codecForName(encoding.toUtf8());
|
||||
return codec ? codec : QTextCodec::codecForLocale();
|
||||
}
|
||||
@ -1040,7 +1060,7 @@ QStringList Repository::lfsEnvironment() {
|
||||
|
||||
Repository::LfsTracking Repository::lfsTracked() {
|
||||
QString output = lfsExecute({"track"});
|
||||
QStringList lines = output.split('\n', QString::SkipEmptyParts);
|
||||
QStringList lines = output.split('\n', Qt::SkipEmptyParts);
|
||||
if (!lines.isEmpty())
|
||||
lines.removeFirst();
|
||||
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
|
||||
RepositoryNotifier *notifier() const { return d->notifier; }
|
||||
|
||||
QDir dir() const;
|
||||
QDir dir(bool includeGitFolder = true) const;
|
||||
QDir workdir() const;
|
||||
QDir appDir() const;
|
||||
|
||||
@ -81,7 +81,7 @@ public:
|
||||
QString message() const;
|
||||
|
||||
// config
|
||||
Config config() const;
|
||||
Config gitConfig() const;
|
||||
Config appConfig() const;
|
||||
|
||||
// bare
|
||||
@ -316,7 +316,7 @@ signals:
|
||||
void referenceAdded(const Reference &ref);
|
||||
void referenceAboutToBeRemoved(const Reference &ref);
|
||||
void referenceRemoved(const QString &name);
|
||||
void referenceUpdated(const Reference &ref);
|
||||
void referenceUpdated(const Reference &ref, bool restoreSelection = false);
|
||||
|
||||
void remoteAboutToBeAdded(const QString &name);
|
||||
void remoteAdded(const Remote &remote);
|
||||
|
@ -26,7 +26,7 @@ Submodule::operator git_submodule *() const { return d.data(); }
|
||||
bool Submodule::isInitialized() const {
|
||||
Repository repo(git_submodule_owner(d.data()));
|
||||
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); }
|
||||
@ -34,7 +34,7 @@ void Submodule::initialize() const { git_submodule_init(d.data(), false); }
|
||||
void Submodule::deinitialize() const {
|
||||
// Remove git config entry.
|
||||
Repository repo(git_submodule_owner(d.data()));
|
||||
Config config = repo.config();
|
||||
Config config = repo.gitConfig();
|
||||
QString regex = QString("submodule\\.%1\\..*").arg(name());
|
||||
Config::Iterator it = config.glob(regex);
|
||||
while (Config::Entry entry = it.next())
|
||||
|
@ -30,8 +30,8 @@ const QString kThemeIconFmt = ":/%1_%2.png";
|
||||
} // namespace
|
||||
|
||||
Account::Account(const QString &username)
|
||||
: mMgr(new QNetworkAccessManager()), mUsername(username),
|
||||
mError(new AccountError(this)), mProgress(new AccountProgress(this)) {
|
||||
: mUsername(username), mError(new AccountError(this)),
|
||||
mProgress(new AccountProgress(this)), mMgr(new QNetworkAccessManager()) {
|
||||
QObject::connect(
|
||||
mMgr, &QNetworkAccessManager::sslErrors,
|
||||
[this](QNetworkReply *reply, const QList<QSslError> &errors) {
|
||||
@ -204,6 +204,8 @@ QString Account::helpText(Kind kind) {
|
||||
case Beanstalk:
|
||||
return QString();
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(kind)));
|
||||
}
|
||||
|
||||
QString Account::defaultUrl(Kind kind) {
|
||||
@ -219,6 +221,8 @@ QString Account::defaultUrl(Kind kind) {
|
||||
case GitLab:
|
||||
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) {
|
||||
@ -258,6 +262,8 @@ QString Account::kindToString(Kind kind) {
|
||||
case GitLab:
|
||||
return "gitlab";
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(kind)));
|
||||
}
|
||||
|
||||
void Account::startProgress() {
|
||||
|
@ -35,16 +35,8 @@ else()
|
||||
set_target_properties(indexer PROPERTIES INSTALL_RPATH "$ORIGIN")
|
||||
endif()
|
||||
|
||||
if(FLATPAK)
|
||||
# Install application.
|
||||
install(
|
||||
TARGETS indexer
|
||||
DESTINATION ./bin # otherwise the executable will not be found by flatpak
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
else()
|
||||
install(
|
||||
TARGETS indexer
|
||||
DESTINATION .
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
install(
|
||||
TARGETS indexer
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT ${GITTYUP_NAME})
|
||||
endif()
|
||||
|
@ -93,7 +93,19 @@ Lexer::Lexeme GenericLexer::next() {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ bool Index::write(PostingMap map) {
|
||||
quint32 postCount = readVInt(postIn);
|
||||
bool end = (newIt == newEnd || newIt.key() != it->key);
|
||||
postings.reserve(postCount + (!end ? newIt.value().size() : 0));
|
||||
for (int i = 0; i < postCount; ++i) {
|
||||
for (quint32 i = 0; i < postCount; ++i) {
|
||||
quint32 proxPos;
|
||||
Posting posting;
|
||||
posting.id = readVInt(postIn);
|
||||
@ -243,7 +243,7 @@ QList<git::Commit> Index::commits(const QString &filter) const {
|
||||
// Sort by commit date.
|
||||
QList<git::Commit> commits = query->commits(this);
|
||||
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());
|
||||
});
|
||||
|
||||
@ -288,7 +288,7 @@ QList<Index::Posting> Index::postings(const Term &term, bool positional) const {
|
||||
// Read list.
|
||||
QList<Posting> postings;
|
||||
quint32 postCount = readVInt(in);
|
||||
for (int i = 0; i < postCount; ++i) {
|
||||
for (quint32 i = 0; i < postCount; ++i) {
|
||||
quint32 proxPos;
|
||||
Posting posting;
|
||||
posting.id = readVInt(in);
|
||||
@ -331,7 +331,7 @@ QList<Index::Posting> Index::postings(const Predicate &pred,
|
||||
|
||||
// Read list.
|
||||
quint32 postCount = readVInt(in);
|
||||
for (int i = 0; i < postCount; ++i) {
|
||||
for (quint32 i = 0; i < postCount; ++i) {
|
||||
quint32 proxPos;
|
||||
Posting posting;
|
||||
posting.id = readVInt(in);
|
||||
@ -373,7 +373,7 @@ QMap<Index::Field, QStringList> Index::fieldMap(const QString &prefix) const {
|
||||
// Read list.
|
||||
QString name = it->key;
|
||||
quint32 postCount = readVInt(in);
|
||||
for (int i = 0; i < postCount; ++i) {
|
||||
for (quint32 i = 0; i < postCount; ++i) {
|
||||
quint8 field;
|
||||
quint32 proxPos;
|
||||
readVInt(in); // Discard id.
|
||||
@ -443,6 +443,8 @@ QByteArray Index::fieldName(Index::Field field) {
|
||||
case Index::Pathspec:
|
||||
return "pathspec";
|
||||
}
|
||||
throw std::runtime_error("unreachable; value=" +
|
||||
std::to_string(static_cast<int>(field)));
|
||||
}
|
||||
|
||||
QDir Index::indexDir(const git::Repository &repo) {
|
||||
@ -506,7 +508,7 @@ void Index::readPositions(QDataStream &in, QVector<quint32> &positions) {
|
||||
quint32 prev = 0;
|
||||
quint32 count = readVInt(in);
|
||||
positions.reserve(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
for (quint32 i = 0; i < count; ++i) {
|
||||
// Convert to absolute from delta.
|
||||
quint32 position = prev + readVInt(in);
|
||||
positions.append(position);
|
||||
|
@ -182,16 +182,24 @@ public:
|
||||
QList<git::Commit> rhs = mRhs->commits(index);
|
||||
QList<git::Commit> commits = mLhs->commits(index);
|
||||
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);
|
||||
#endif
|
||||
QMutableListIterator<git::Commit> it(commits);
|
||||
while (it.hasNext()) {
|
||||
if (!set.contains(it.next()))
|
||||
it.remove();
|
||||
}
|
||||
} 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);
|
||||
#endif
|
||||
foreach (const git::Commit &commit, rhs) {
|
||||
if (!set.contains(commit))
|
||||
commits.append(commit);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Index.h"
|
||||
#include "GenericLexer.h"
|
||||
#include "LPegLexer.h"
|
||||
#include "qtsupport.h"
|
||||
#include "conf/Settings.h"
|
||||
#include "git/Config.h"
|
||||
#include "git/Index.h"
|
||||
@ -105,7 +106,7 @@ void log(QFile *out, const QString &text) {
|
||||
return;
|
||||
|
||||
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) {
|
||||
@ -148,7 +149,22 @@ void index(const Lexer::Lexeme &lexeme, Intermediate::FieldMap &fields,
|
||||
case Lexer::Comment:
|
||||
field |= Index::Comment;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -172,7 +188,13 @@ void index(const Lexer::Lexeme &lexeme, Intermediate::FieldMap &fields,
|
||||
break;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@ -331,7 +353,7 @@ private:
|
||||
QFile *mOut;
|
||||
|
||||
int mContextLines = 3;
|
||||
int mTermLimit = 1000000;
|
||||
quint32 mTermLimit = 1000000;
|
||||
};
|
||||
|
||||
class Reduce {
|
||||
@ -405,7 +427,12 @@ public:
|
||||
int count = 0;
|
||||
QList<git::Commit> commits;
|
||||
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());
|
||||
#endif
|
||||
while (commit.isValid() && count < 8192) {
|
||||
// Don't index merge commits.
|
||||
if (!commit.isMerge() && !ids.contains(commit.id())) {
|
||||
@ -440,7 +467,7 @@ public:
|
||||
// Write to disk.
|
||||
log(mOut, "start write");
|
||||
if (mIndex.write(mWatcher.result()) && mNotify)
|
||||
QTextStream(stdout) << "write" << endl;
|
||||
QTextStream(stdout) << "write" << Qt::endl;
|
||||
log(mOut, "end write");
|
||||
|
||||
// Restart.
|
||||
@ -450,10 +477,14 @@ public:
|
||||
|
||||
bool nativeEventFilter(const QByteArray &type, void *message,
|
||||
long *result) override {
|
||||
Q_UNUSED(result);
|
||||
#ifdef Q_OS_WIN
|
||||
MSG *msg = static_cast<MSG *>(message);
|
||||
if (msg->message == WM_CLOSE)
|
||||
cancel();
|
||||
#else
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(message);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "GenericLexer.h"
|
||||
#include "LPegLexer.h"
|
||||
#include "qtsupport.h"
|
||||
#include "conf/Settings.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
@ -29,7 +30,7 @@ void print(QTextStream &out, const Lexer::Lexeme &lexeme, int indent = 0) {
|
||||
out << lexeme.text << " - " << lexeme.token;
|
||||
if (lexeme.token < kStyleNames.length())
|
||||
out << " (" << kStyleNames.at(lexeme.token) << ")";
|
||||
out << endl;
|
||||
out << Qt::endl;
|
||||
}
|
||||
|
||||
void print(QTextStream &out, Lexer *lexer, int indent = 0) {
|
||||
@ -65,7 +66,13 @@ void print(QTextStream &out, Lexer *lexer, int indent = 0) {
|
||||
break;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@ -102,7 +109,7 @@ int main(int argc, char *argv[]) {
|
||||
// Lex buffer.
|
||||
Lexer *lexer = lexers.value(name);
|
||||
if (lexer->lex(buffer)) {
|
||||
out << name << " - " << arg << ":" << endl;
|
||||
out << name << " - " << arg << ":" << Qt::endl;
|
||||
print(out, lexer);
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,9 @@ void LogDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
|
||||
QRect rect = decorationRect(option, index);
|
||||
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>()) {
|
||||
int progress = variant.toInt();
|
||||
ProgressIndicator::paint(painter, rect, "#808080", progress, opt.widget);
|
||||
@ -126,7 +128,9 @@ void LogDelegate::initStyleOption(QStyleOptionViewItem *option,
|
||||
QStyledItemDelegate::initStyleOption(option, index);
|
||||
QVariant variant = index.data(Qt::DecorationRole);
|
||||
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>()) {
|
||||
option->decorationSize = ProgressIndicator::size();
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "LogModel.h"
|
||||
#include "LogEntry.h"
|
||||
#include <QLocale>
|
||||
#include <QStyle>
|
||||
|
||||
namespace {
|
||||
@ -74,8 +75,8 @@ QVariant LogModel::data(const QModelIndex &index, int role) const {
|
||||
QDateTime date = entry->timestamp();
|
||||
QString timestamp =
|
||||
(date.date() == QDate::currentDate())
|
||||
? date.time().toString(Qt::DefaultLocaleShortDate)
|
||||
: date.toString(Qt::DefaultLocaleShortDate);
|
||||
? QLocale().toString(date.time(), QLocale::ShortFormat)
|
||||
: QLocale().toString(date, QLocale::ShortFormat);
|
||||
text = kTimeFmt.arg(timestamp, text);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
//
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "qtsupport.h"
|
||||
#include "conf/Settings.h"
|
||||
#include "editor/TextEditor.h"
|
||||
#include "git/Config.h"
|
||||
@ -491,7 +492,7 @@ Plugin::Plugin(const QString &file, const git::Repository &repo,
|
||||
|
||||
// Print error messages to the console.
|
||||
connect(this, &Plugin::error, [](const QString &msg) {
|
||||
QTextStream(stderr) << "plugin error: " << msg << endl;
|
||||
QTextStream(stderr) << "plugin error: " << msg << Qt::endl;
|
||||
});
|
||||
|
||||
// Load libraries.
|
||||
@ -613,6 +614,8 @@ QVariant Plugin::optionValue(const QString &key) const {
|
||||
case String:
|
||||
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 {
|
||||
|
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
|
||||
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)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "git/Repository.h"
|
||||
#include <QProcess>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDebug>
|
||||
|
||||
DiffTool::DiffTool(const QString &file, const git::Blob &localBlob,
|
||||
const git::Blob &remoteBlob, QObject *parent)
|
||||
@ -59,8 +60,25 @@ bool DiffTool::start() {
|
||||
|
||||
// Destroy this after process finishes.
|
||||
QProcess *process = new QProcess(this);
|
||||
process->setProcessChannelMode(
|
||||
QProcess::ProcessChannelMode::ForwardedChannels);
|
||||
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();
|
||||
env.insert("LOCAL", local->fileName());
|
||||
@ -78,9 +96,12 @@ bool DiffTool::start() {
|
||||
emit error(BashNotFound);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!process->waitForStarted())
|
||||
if (!process->waitForStarted()) {
|
||||
qDebug() << "DiffTool starting failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detach from parent.
|
||||
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