diff options
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/after-install | 11 | ||||
| -rwxr-xr-x | bin/before-remove | 9 | ||||
| -rwxr-xr-x | bin/build-distribution-archives | 159 | ||||
| -rwxr-xr-x | bin/build-electron | 16 | ||||
| -rwxr-xr-x | bin/build-python | 52 | ||||
| -rw-r--r-- | bin/build-windows-installer | 21 | ||||
| -rw-r--r-- | bin/generate-translation-files | 27 | ||||
| -rwxr-xr-x | bin/git-pre-commit-hook | 17 | ||||
| -rw-r--r-- | bin/import-macos-keys | 12 | ||||
| -rw-r--r-- | bin/linux-sh-installer | 117 | ||||
| -rw-r--r-- | bin/notarize-app | 46 | ||||
| -rwxr-xr-x | bin/style-check | 8 |
12 files changed, 467 insertions, 28 deletions
diff --git a/bin/after-install b/bin/after-install new file mode 100755 index 00000000..10857314 --- /dev/null +++ b/bin/after-install @@ -0,0 +1,11 @@ +#!/bin/sh + +inkscape_dir="$(inkscape --system-data-directory)" + +if [ "$?" != 0 ]; then + echo "ERROR: Cannot find inkscape system data directory. Is inkscape installed and in root's PATH?" + exit 1 +fi + +rm -f "${inkscape_dir}/extensions/inkstitch" +ln -s /opt/inkstitch "${inkscape_dir}/extensions/inkstitch" diff --git a/bin/before-remove b/bin/before-remove new file mode 100755 index 00000000..ad500703 --- /dev/null +++ b/bin/before-remove @@ -0,0 +1,9 @@ +#!/bin/sh + +inkscape_dir="$(inkscape --system-data-directory)" + +if [ -n "$inkscape_dir" ]; then + if [ -L "${inkscape_dir}/extensions/inkstitch" ]; then + rm -f "${inkscape_dir}/extensions/inkstitch" + fi +fi diff --git a/bin/build-distribution-archives b/bin/build-distribution-archives index 6402122b..c7973022 100755 --- a/bin/build-distribution-archives +++ b/bin/build-distribution-archives @@ -1,34 +1,155 @@ -#!/bin/bash - VERSION="$(echo ${GITHUB_REF} | sed -e 's|refs/heads/||' -e 's|refs/tags/||' -e 's|/|-|g')" OS="${BUILD:-$(uname)}" ARCH="$(uname -m)" +mkdir artifacts if [ "$BUILD" = "osx" ]; then - cp -a images/examples palettes symbols fonts LICENSE VERSION dist/inkstitch.app/Contents - cp -a icons locales print dist/inkstitch.app/Contents/MacOS - cp -a electron/build/mac dist/inkstitch.app/Contents/electron + cp -a icons locales print LICENSE VERSION images/examples palettes symbols fonts inx dist/inkstitch.app/Contents/Resources + # adding version to Info.plist + sed -i '' 's/0.0.0/'${VERSION}'/' dist/inkstitch.app/Contents/Info.plist rm -rf dist/inkstitch/ + # Install location for pkgbuild + PKG_INSTALL_PATH="/tmp/inkstitch/" + # Checking arch of macos and setting path of electron for arm64 or intel + echo "Checking for macOS arch." + if [ "${ARCH}" = "arm64" ]; then + ELECTRON_BUILD_PATH="electron/build/mac-arm64" + echo "found arm64" + else + ELECTRON_BUILD_PATH="electron/build/mac" + echo "found intel" + fi + # inside the scripts folder are: + # - preinstaller (checks for previously installed inkstitch and deletes it, Inkscape check with error message) and + # - postinstaller (moves inkstitch folder from /tmp to user Inkscape extensions folder in $HOME) + # The postinstaller is a workaround for a proper way to install in user $HOME space + + # Build on GitHub will be handled differently from local builds. + # Local builds will not be signed nor notarized. They are run to produce releases for legacy versions of macOS. + # Notarization for development branches can be forced with this variable set to true + NOTARIZE_DEVELOPMENT_BUILDS=false + + if [[ ! -z "${GITHUB_REF}" ]]; then + # This code signs and notarize the inkstitch.app + DEV_IDENT="Developer ID Application: Lex Neva (929A568N58)" + echo "Signing of inkstitch.app" + # Coyping inkstitch-gui.app into inkstitch + ditto "${ELECTRON_BUILD_PATH}" dist/inkstitch.app/Contents/MacOS/electron + # signing the binary may fix notary issue + /usr/bin/codesign -s "${DEV_IDENT}" \ + --deep \ + --force \ + --entitlements installer_scripts/entitlements.plist \ + -o runtime \ + --timestamp \ + dist/inkstitch.app/Contents/MacOS/inkstitch -v + # last signing before packaging + /usr/bin/codesign -s "${DEV_IDENT}" \ + --deep \ + --force \ + --entitlements installer_scripts/entitlements.plist \ + -o runtime \ + --timestamp \ + dist/inkstitch.app -v + echo "Running pkgbuild" + INSTALLER_IDENT="Developer ID Installer: Lex Neva (929A568N58)" + /usr/bin/pkgbuild --root dist/inkstitch.app \ + -s "${INSTALLER_IDENT}" \ + --component-plist installer_scripts/inkstitch.plist \ + --ownership recommended \ + --identifier org.inkstitch.installer \ + --version ${VERSION} \ + --scripts installer_scripts/scripts \ + --install-location ${PKG_INSTALL_PATH}inkstitch.app \ + artifacts/inkstitch-${VERSION}-${OS}.pkg + if [[ "${GITHUB_REF}" =~ ^refs/tags/v[0-9.]+$ || $NOTARIZE_DEVELOPMENT_BUILDS == true ]]; then + echo "Notary starting" + bash bin/notarize-app "929A568N58" \ + "${NOTARY_ACCOUNT}" \ + "${NOTARY_PASSWORD}" \ + "org.inkstitch.app" \ + artifacts/inkstitch-${VERSION}-${OS}.pkg + fi + else + # local builds will not be signed or notarized + cp -a "${ELECTRON_BUILD_PATH}" dist/inkstitch.app/Contents/MacOS/electron + pkgbuild --root dist/inkstitch.app \ + --component-plist installer_scripts/inkstitch.plist \ + --ownership recommended \ + --identifier org.inkstitch.installer \ + --version ${VERSION} \ + --scripts installer_scripts/scripts \ + --install-location ${PKG_INSTALL_PATH}inkstitch.app \ + artifacts/inkstitch-${VERSION}-${OS}.pkg + fi + # Creating the zip for Drag n' Drop install + cd dist + python -m zipfile -c ../artifacts/inkstitch-${VERSION}-${OS}.zip * + cd .. else - cp -a images/examples palettes symbols fonts LICENSE VERSION dist/inkstitch + cp -a images/examples palettes symbols fonts inx LICENSE VERSION dist/inkstitch cp -a icons locales print dist/inkstitch/bin cp -a electron/build/*-unpacked dist/inkstitch/electron + fi -mkdir artifacts +if [ "$BUILD" = "windows" ]; then + # build the installer locally + # remotely it will be called through build.yml after signing + if [[ -z "${GITHUB_REF}" ]]; then + bash bin/build-windows-installer + fi +fi -for d in inx/*; do - lang=${d%.*} - lang=${lang#*/} - cp $d/*.inx dist +if [ "$BUILD" = "linux" ]; then + gem install fpm - cd dist - if [ "$BUILD" = "windows" ]; then - # The python zipfile command line utility can't handle directories - # containing files with UTF-8 names on Windows, so we use 7-zip instead. - 7z a ../artifacts/inkstitch-${VERSION}-${OS}-${lang}.zip * + if [[ "$VERSION" =~ ^v[0-9][.0-9]+$ ]]; then + VERSION=${VERSION#v} else - python -m zipfile -c ../artifacts/inkstitch-${VERSION}-${OS}-${lang}.zip * + # dpkg requires versions to start with a number, so we have to add + # 0.0.1 for development builds + VERSION="0.0.1-${VERSION}" fi - cd .. -done + + echo -n "$INKSTITCH_GPG_KEY" | base64 -d | gpg --import + cat <<EOF > $HOME/.rpmmacros +%_gpg_name EA93BCE2CCD0FB2E77B2CC29E8120E50709E5C44 +%_signature gpg +EOF + + deb_version="$(sed -E 's/[^a-zA-Z0-9.+]/./g' <<< "$VERSION")" + fpm -s dir \ + -t deb \ + -n inkstitch \ + -v "$deb_version" \ + -d "inkscape >= 1.0.0" \ + --license "GPL-3.0" \ + --description "An open-source machine embroidery design platform based on Inkscape" \ + --url "https://inkstitch.org" \ + --maintainer "maintainer@inkstitch.org" \ + --after-install bin/after-install \ + --before-remove bin/before-remove \ + --verbose \ + dist/inkstitch=/opt + + fpm -s dir \ + -t rpm \ + -n inkstitch \ + -v "$VERSION" \ + -d "inkscape >= 1.0.0" \ + --license "GPL-3.0" \ + --description "An open-source machine embroidery design platform based on Inkscape" \ + --url "https://inkstitch.org" \ + --maintainer "maintainer@inkstitch.org" \ + --after-install bin/after-install \ + --before-remove bin/before-remove \ + --verbose \ + dist/inkstitch=/opt + + rpmsign --addsign inkstitch*.rpm + mv inkstitch*.deb inkstitch*.rpm artifacts/ + + tar -C dist -Jcf artifacts/inkstitch-${VERSION}-${OS}.tar.xz inkstitch + cat "$(dirname "$0")/linux-sh-installer" artifacts/inkstitch-${VERSION}-${OS}.tar.xz > artifacts/inkstitch-${VERSION}-${OS}.sh +fi diff --git a/bin/build-electron b/bin/build-electron index 11616cb4..b0e93572 100755 --- a/bin/build-electron +++ b/bin/build-electron @@ -2,15 +2,29 @@ set -e set -x +ARCH="$(uname -m)" +# Check for cpu arch to build mac and linux electron arch +if [[ "$ARCH" = "arm64" ]] || [[ "$ARCH" = "aarch64" ]]; then + echo "Found ARM" + sed -i'' -e 's/CPU_ARCH/'arm64'/' electron/package.json +else + echo "Found x64" + sed -i'' -e 's/CPU_ARCH/'x64'/' electron/package.json +fi if [ "$BUILD" = "windows" ]; then args="-w --ia32" elif [ "$BUILD" = "linux" ]; then - args="-l --x64" + args="-l" elif [ "$BUILD" = "osx" ]; then + cp installer_scripts/electron-entitlements.plist electron/build/ args="-m" fi +# electron version setting on release +if [[ "$VERSION" =~ ^v[0-9][.0-9]+$ ]]; then + sed -i'' -e 's/11.99.11/'"${VERSION#v}"'/' electron/package.json +fi cd electron which yarn > /dev/null 2>&1 || npm install -g yarn yarn --link-duplicates --pure-lockfile diff --git a/bin/build-python b/bin/build-python index 88e166ae..14f77dae 100755 --- a/bin/build-python +++ b/bin/build-python @@ -1,15 +1,14 @@ #!/bin/bash set -e - +info_year=$( date "+%Y" ) site_packages="$(python -c "import os; print(os.path.dirname(os.__file__) + '/site-packages')")" - +arch=$(uname -m) if [ "$BUILD" = "linux" ]; then - # pyinstaller misses these - pyinstaller_args+="--add-binary /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so:. " - pyinstaller_args+="--add-binary /usr/lib/x86_64-linux-gnu/libproxy.so.1:. " - pyinstaller_args+="--add-binary /lib/x86_64-linux-gnu/libnsl.so.1:. " - pyinstaller_args+="--add-binary /usr/lib/x86_64-linux-gnu/libxcb.so.1:. " + pyinstaller_args+="--add-binary /usr/lib/"$arch"-linux-gnu/gio/modules/libgiolibproxy.so:. " + pyinstaller_args+="--add-binary /usr/lib/"$arch"-linux-gnu/libproxy.so.1:. " + pyinstaller_args+="--add-binary /lib/"$arch"-linux-gnu/libnsl.so.1:. " + pyinstaller_args+="--add-binary /usr/lib/"$arch"-linux-gnu/libxcb.so.1:. " fi # This one's tricky. ink/stitch doesn't actually _use_ gi.repository.Gtk, @@ -36,11 +35,48 @@ pyinstaller_args+="-p inkscape/share/extensions " # output useful debugging info that helps us trace library dependency issues pyinstaller_args+="--log-level DEBUG " +# This adds bundle identifier in reverse DSN format for macos +if [ "$BUILD" = "osx" ]; then + pyinstaller_args+="--osx-bundle-identifier org.inkstitch.app " + pyinstaller_args+="-i electron/build/icons/mac/inkstitch.icns" + if [[ -z ${GITHUB_REF} ]]; then + echo "Dev or Local Build" + else + bash bin/import-macos-keys + fi +fi + if [ "$BUILD" = "windows" ]; then + if [[ "$VERSION" =~ ^v[0-9][.0-9]+$ ]]; then + # setting the file and product version for release + # Code to remove the periods in the version number + ENT=. + SAL=${VERSION#v}$ENT + INFO_VERSION=() + while [[ $SAL ]]; do + INFO_VERSION+=( "${SAL%%"$ENT"*}" ); + SAL=${SAL#*"$ENT"}; + done; + sed -i'' 's/3, 2, 1,/'"${INFO_VERSION[0]}, ${INFO_VERSION[1]}, ${INFO_VERSION[2]},"'/' installer_scripts/file_version_info.txt + fi + # set year and version in version_info + sed -i'' 's/1.1.1/'"${VERSION#v}"'/' installer_scripts/file_version_info.txt + sed -i'' 's/1234/'"${info_year}"'/' installer_scripts/file_version_info.txt + # sets icon to inkstitch.exe + pyinstaller_args+="--i electron/build/icons/win/inkstitch.ico " + pyinstaller_args+="--version-file installer_scripts/file_version_info.txt " python -m PyInstaller $pyinstaller_args inkstitch.py -else +elif [ "$BUILD" = "linux" ]; then # without the LD_LIBRARY_PATH, it seems that pyinstaller can't find all of # wxpython's shared libraries + LD_LIBRARY_PATH="${site_packages}/wx" python -m PyInstaller $pyinstaller_args inkstitch.py; + + # We've found that stripping the _fblas library in scipy/linalg causes a bizarre + # error: + # + # ELF load command address/offset not properly aligned + find dist/inkstitch -type f | grep -E '.so($|\.)' | grep -v _fblas | xargs strip +else LD_LIBRARY_PATH="${site_packages}/wx" python -m PyInstaller $pyinstaller_args --strip inkstitch.py; fi diff --git a/bin/build-windows-installer b/bin/build-windows-installer new file mode 100644 index 00000000..a2d421ce --- /dev/null +++ b/bin/build-windows-installer @@ -0,0 +1,21 @@ +#!/bin/bash +VERSION="$(echo ${GITHUB_REF} | sed -e 's|refs/heads/||' -e 's|refs/tags/||' -e 's|/|-|g')" +OS="${BUILD:-$(uname)}" +# Create windows installer +mkdir win +cp installer_scripts/template.iss win/win_build.iss +# adds the year and version to the inno installer +info_year=$( date "+%Y" ) +copyright_year="#define COPYRIGHT \""${info_year}"\"" +version_block="#define VERSION \""${VERSION}"\"" +sed -i'' -e '/;inkstitch-year/ a\'$'\n'"${copyright_year}"'' win/win_build.iss +sed -i'' -e '/;inkstitch-version/ a\'$'\n'"${version_block}"'' win/win_build.iss + +iscc win/win_build.iss +mv win/inkstitch.exe artifacts/inkstitch-${VERSION}-${OS}.exe +cd dist +echo "Creating zip" +# The python zipfile command line utility can't handle directories +# containing files with UTF-8 names on Windows, so we use 7-zip instead. +7z a ../artifacts/inkstitch-${VERSION}-${OS}.zip * +cd .. diff --git a/bin/generate-translation-files b/bin/generate-translation-files new file mode 100644 index 00000000..c1f77a30 --- /dev/null +++ b/bin/generate-translation-files @@ -0,0 +1,27 @@ +#!/bin/bash + +# message files will look like this: +# translations/messages_en_US.po +if ls translations/*.po > /dev/null 2>&1; then + for po in translations/*.po; do + lang=${po%.*}; + lang=${lang#*_}; + mkdir -p locales/$lang/LC_MESSAGES/; + msgfmt $po -o locales/$lang/LC_MESSAGES/inkstitch.mo; + done; +else + mkdir -p locales; +fi; + +# copy locales also into the inx folder, inkscape needs +# them to be in exactly that place +mkdir -p inx; +cp -r locales/ inx/locale/; +# for some reason inkscape requires the language folder names +# as a two letter code ("en" instead of "en_US") +cd inx/locale; +for language in */; do + if [ ! -d ${language:0:2} ]; then + mv -- $language ${language:0:2}; + fi; +done; diff --git a/bin/git-pre-commit-hook b/bin/git-pre-commit-hook new file mode 100755 index 00000000..81ace2cd --- /dev/null +++ b/bin/git-pre-commit-hook @@ -0,0 +1,17 @@ +#!/bin/bash + +# copy (DO NOT SYMLINK) this file to .git/hooks/pre-commit +# to check style on all modified files before allowing the commit to complete +# +# DO NOT SYMLINK +# DO NOT SYMLINK +# DO NOT SYMLINK (why? security risk) + +cd $(dirname "$0")/../.. + +errors=$(git diff --cached | bin/style-check --diff 2>&1) + +if [ "$?" != "0" ]; then + echo "$errors" + exit 1 +fi diff --git a/bin/import-macos-keys b/bin/import-macos-keys new file mode 100644 index 00000000..2fa55f89 --- /dev/null +++ b/bin/import-macos-keys @@ -0,0 +1,12 @@ +#!/bin/bash +# first part of codesiging which is importing to build keychain +echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12 +security create-keychain -p "$KEYCHAIN_PWD" build.keychain +security default-keychain -s build.keychain +security unlock-keychain -p "$KEYCHAIN_PWD" build.keychain +security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign +security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PWD" build.keychain +# importing notary certificate +echo $INSTALLER_CERTIFICATE | base64 --decode > installer-certificate.p12 +security import installer-certificate.p12 -k build.keychain -P "$INSTALLER_PWD" -T /usr/bin/pkgbuild +security set-key-partition-list -S apple-tool:,apple:,pkgbuild: -s -k "$KEYCHAIN_PWD" build.keychain diff --git a/bin/linux-sh-installer b/bin/linux-sh-installer new file mode 100644 index 00000000..59bdf8d0 --- /dev/null +++ b/bin/linux-sh-installer @@ -0,0 +1,117 @@ +#!/bin/bash + +# This is a self-extracting archive that installs Ink/Stitch on your Linux +# system. This first part is an installer, and after that is a .tar.zx file +# containing Ink/Stitch itself. +# +# To install, simply run this script: +# +# sh inkstitch-<version>.sh +# +# +# EXPERT STUFF BELOW: +# +# If you'd rather install it yourself, run this script with --extract to +# produce the original inkstitch-<version>.tar.xz file in the current +# directory. +# +# This script will attempt to determine where to install Inkscape user +# extensions automatically. If it gets it wrong, you can set one of these +# environment variables: +# +# INKSCAPE_PATH (ex: /usr/bin/inkscape) +# The path to the inkscape executable program. This script will ask that program +# where to install extensions by passing it the --user-data-directory argument. +# +# INKSCAPE_EXTENSIONS_PATH (ex: $HOME/.config/inkscape/extensions) +# The path to the inkscape extensions directory. Use this to bypass the +# --user-data-directory method and specify a directory yourself. + +die() { + echo "$*" + exit 1 +} + +extract() { + ( grep -m1 '^__ARCHIVE__$' > /dev/null; cat ) < "$0" +} + +find_inkscape() { + # allow expert user override + if [ -n "$INKSCAPE_PATH" ]; then + echo "$INKSCAPE_PATH" + return + fi + + inkscape="$(which inkscape)" + + if [ -z "$inkscape" ]; then + read -p "Please enter the path to the inkscape program executable (example: /usr/bin/inkscape): " inkscape + fi + + if [ ! -x "$inkscape" ]; then + die "Inkscape not found or not executable ($inkscape)" + fi + + echo "$inkscape" +} + +find_extensions_dir() { + # allow expert user override + if [ -n "$INKSCAPE_EXTENSIONS_PATH" ]; then + echo "$INKSCAPE_EXTENSIONS_PATH" + return + fi + + inkscape="$(find_inkscape)" + + if [ -x "$inkscape" ]; then + extensions_dir="$(inkscape --user-data-directory)/extensions" + fi + + if [ -z "$extensions_dir" ]; then + read -p "Please enter the inkscape user extensions directory (example: $HOME/.config/inkscape/extensions): " extensions_dir + fi + + if [ -z "$extensions_dir" ]; then + die "Aborting." + fi + + mkdir -p "$extensions_dir" || die "unable to create $extensions_dir" + + echo "$extensions_dir" +} + +remove_existing() { + if [ -e "${1}/inkstitch" ]; then + read -p "${1}/inkstitch exists already. It must be removed in order to install $(basename ${0%.sh}). Delete? [y/N] " yesno + if [ "$yesno" != "y" -a "$yesno" != "Y" -a "$yesno" != "yes" ]; then + die "Aborting." + fi + + rm -rf "${1}/inkstitch" + fi +} + +install_inkstitch() { + extensions_dir="$(find_extensions_dir)" + echo "Installing Ink/Stitch to ${extensions_dir}/inkstitch" + + remove_existing "$extensions_dir" + + extract | tar -C "$extensions_dir" -Jxf - || die "error while extracting Ink/Stitch" + + echo "Ink/Stitch has been successfully installed. Please restart Inkscape if it is already running." +} + +if [ "$1" = "--extract" ]; then + dest="${0%.sh}.tar.xz" + extract > "$dest" + echo "Ink/Stitch extracted to $dest" +else + install_inkstitch +fi + +exit 0 + +__ARCHIVE__ diff --git a/bin/notarize-app b/bin/notarize-app new file mode 100644 index 00000000..4a2bbc41 --- /dev/null +++ b/bin/notarize-app @@ -0,0 +1,46 @@ +#!/bin/sh -u +# source of this code: https://github.com/rednoah/notarize-app +ASC_PROVIDER="$1" +ASC_USERNAME="$2" +ASC_PASSWORD="$3" + +BUNDLE_ID="$4" +BUNDLE_PKG="$5" + + +# create temporary files +NOTARIZE_APP_LOG=$(mktemp -t notarize-app) +NOTARIZE_INFO_LOG=$(mktemp -t notarize-info) + +# delete temporary files on exit +function finish { + rm "$NOTARIZE_APP_LOG" "$NOTARIZE_INFO_LOG" +} +trap finish EXIT + + +# submit app for notarization +if xcrun altool --notarize-app --primary-bundle-id "$BUNDLE_ID" --asc-provider "$ASC_PROVIDER" --username "$ASC_USERNAME" --password "$ASC_PASSWORD" -f "$BUNDLE_PKG" > "$NOTARIZE_APP_LOG" 2>&1; then + cat "$NOTARIZE_APP_LOG" + RequestUUID=$(awk -F ' = ' '/RequestUUID/ {print $2}' "$NOTARIZE_APP_LOG") + + # check status periodically + while sleep 60 && date; do + # check notarization status + if xcrun altool --notarization-info "$RequestUUID" --asc-provider "$ASC_PROVIDER" --username "$ASC_USERNAME" --password "$ASC_PASSWORD" > "$NOTARIZE_INFO_LOG" 2>&1; then + cat "$NOTARIZE_INFO_LOG" + + # once notarization is complete, run stapler and exit + if ! grep -q "Status: in progress" "$NOTARIZE_INFO_LOG"; then + xcrun stapler staple "$BUNDLE_PKG" + exit $? + fi + else + cat "$NOTARIZE_INFO_LOG" 1>&2 + exit 1 + fi + done +else + cat "$NOTARIZE_APP_LOG" 1>&2 + exit 1 +fi diff --git a/bin/style-check b/bin/style-check new file mode 100755 index 00000000..bafd6e74 --- /dev/null +++ b/bin/style-check @@ -0,0 +1,8 @@ +#!/bin/bash + +# Checks Python coding style based on our project's preferences. Checks the +# files passed on the command-line or everything if no files are passed. +# Instead of files, "--diff" may be passed to check only the lines changed +# by a diff piped to standard input. + +flake8 --count --max-complexity=10 --max-line-length=150 --statistics --exclude=pyembroidery,__init__.py,electron,build,src,dist "${@:-.}" |
