- Rename project name and package: novelWriter -> UmbraEdit, novelwriter -> umbraedit - Rename entry script novelWriter.py -> UmbraEdit.py - Rename package directory novelwriter/ -> umbraedit/ - Rename i18n translation sources nw_*.ts -> ue_*.ts - Rename packaging files (appdata, project xml template) - Update all imports, references, docs, workflows, tests and build config - Update pyproject.toml project name, GUI script and URLs - Preserve full upstream git history; origin repointed below
273 lines
11 KiB
Python
Executable File
273 lines
11 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
UmbraEdit - Packaging Utils Main
|
|
==================================
|
|
|
|
This file is a part of UmbraEdit.
|
|
|
|
Copyright (C) 2019 Veronica Berglyd Olsen and UmbraEdit contributors.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
""" # noqa
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import datetime
|
|
import shutil
|
|
import sys
|
|
|
|
import utils.assets
|
|
import utils.build_appimage
|
|
import utils.build_binary
|
|
import utils.build_debian
|
|
import utils.build_flatpak
|
|
import utils.build_pypi
|
|
import utils.build_windows
|
|
import utils.docs
|
|
import utils.icon_themes
|
|
|
|
from utils.common import (
|
|
ROOT_DIR,
|
|
SETUP_DIR,
|
|
extractReqs,
|
|
extractVersion,
|
|
isStableVersion,
|
|
log,
|
|
readFile,
|
|
stripVersion,
|
|
writeFile,
|
|
)
|
|
|
|
OS_LINUX = sys.platform.startswith("linux")
|
|
OS_DARWIN = sys.platform.startswith("darwin")
|
|
OS_WIN = sys.platform.startswith("win32")
|
|
|
|
|
|
def printVersion(args: argparse.Namespace) -> None:
|
|
"""Print the UmbraEdit version and exit."""
|
|
print(extractVersion(beQuiet=True)[0], end=None)
|
|
|
|
|
|
def printChannel(args: argparse.Namespace) -> None:
|
|
"""Print 'stable' or 'pre' depending on the release channel, and exit."""
|
|
print("stable" if isStableVersion() else "pre", end=None)
|
|
|
|
|
|
def cleanBuildDirs(args: argparse.Namespace) -> None:
|
|
"""Recursively delete the 'build' and 'dist' folders."""
|
|
log("")
|
|
log("[b]Cleaning up build environment ...[e]")
|
|
log("")
|
|
|
|
folders = [
|
|
ROOT_DIR / ".flatpak-builder",
|
|
ROOT_DIR / "build_bin",
|
|
ROOT_DIR / "build",
|
|
ROOT_DIR / "dist_appimage",
|
|
ROOT_DIR / "dist_bin",
|
|
ROOT_DIR / "dist_deb",
|
|
ROOT_DIR / "dist_doc",
|
|
ROOT_DIR / "dist_flathub",
|
|
ROOT_DIR / "dist_flatpak",
|
|
ROOT_DIR / "dist_pypi",
|
|
ROOT_DIR / "dist_upload",
|
|
ROOT_DIR / "dist",
|
|
ROOT_DIR / "UmbraEdit.egg-info",
|
|
]
|
|
|
|
for folder in folders:
|
|
if folder.is_dir():
|
|
try:
|
|
shutil.rmtree(folder)
|
|
log(f"[cg]Deleted:[e] {folder}")
|
|
except OSError:
|
|
log(f"[cr]Failed:[e] {folder}")
|
|
else:
|
|
log(f"[cy]Missing:[e] {folder}")
|
|
|
|
log("")
|
|
|
|
|
|
def genMacOSPlist(args: argparse.Namespace) -> None:
|
|
"""Set necessary values for .plist file for MacOS build."""
|
|
outDir = SETUP_DIR / "macos"
|
|
numVers = stripVersion(extractVersion()[0])
|
|
copyrightYear = datetime.datetime.now().year
|
|
|
|
# These keys are no longer used but are present for compatibility
|
|
pkgVersMaj, pkgVersMin = numVers.split(".")[:2]
|
|
|
|
plistXML = readFile(outDir / "Info.plist.template").format(
|
|
macosBundleSVers=numVers,
|
|
macosBundleVers=numVers,
|
|
macosBundleVersMajor=pkgVersMaj,
|
|
macosBundleVersMinor=pkgVersMin,
|
|
macosBundleCopyright=f"Copyright {copyrightYear}, Veronica Berglyd Olsen",
|
|
)
|
|
|
|
log(f"[b]Writing Info.plist to {outDir}/Info.plist[e]")
|
|
writeFile(outDir / "Info.plist", plistXML)
|
|
|
|
|
|
def genReqFiles(args: argparse.Namespace) -> None:
|
|
"""Generate requirements.txt file from pyproject.toml."""
|
|
select = [s.strip().lower() for s in args.groups] if args.groups else ["app"]
|
|
(ROOT_DIR / "requirements.txt").write_text("\n".join(extractReqs(select)), encoding="utf-8")
|
|
|
|
|
|
def main() -> None:
|
|
"""Parse command line options and run the commands."""
|
|
parser = argparse.ArgumentParser(
|
|
usage="pkgutils.py [command] [--flags]",
|
|
description=(
|
|
"This tool provides setup and build commands for installing or distributing "
|
|
"UmbraEdit as a package on Linux, Mac and Windows, as well as developer tools "
|
|
"for internationalisation."
|
|
),
|
|
)
|
|
parsers = parser.add_subparsers()
|
|
|
|
# Version
|
|
cmdVersion = parsers.add_parser("version", help="Print the UmbraEdit version.")
|
|
cmdVersion.set_defaults(func=printVersion)
|
|
|
|
# Release Channel
|
|
cmdChannel = parsers.add_parser("channel", help="Print 'stable' or 'pre' depending on the release channel.")
|
|
cmdChannel.set_defaults(func=printChannel)
|
|
|
|
# Additional Builds
|
|
# =================
|
|
|
|
# Build Icons
|
|
styles = ", ".join(["all", "default", "optional", "free", "non_free", *utils.icon_themes.ICON_SOURCES.keys()])
|
|
cmdIcons = parsers.add_parser("icons", help="Build icon theme files from upstream sources.")
|
|
cmdIcons.add_argument("style", help=f"What icon style to build: {styles}")
|
|
cmdIcons.add_argument("--work-dir", help="Working directory.")
|
|
cmdIcons.set_defaults(func=utils.icon_themes.main)
|
|
|
|
# Import Translations
|
|
cmdImportTS = parsers.add_parser("qtlimport", help="Import updated i18n files from a Crowdin zip file.")
|
|
cmdImportTS.add_argument("file", help="Path to zip file from Crowdin")
|
|
cmdImportTS.add_argument("--threshold", type=float, default=75.0, help="Minimum translation percentage.")
|
|
cmdImportTS.add_argument("--credits-since", metavar="DATE", help="Print translator credits since DATE.")
|
|
cmdImportTS.set_defaults(func=utils.assets.importI18nUpdates)
|
|
|
|
# Update i18n Sources
|
|
cmdUpdateTS = parsers.add_parser("qtlupdate", help="Update translation files for internationalisation.")
|
|
cmdUpdateTS.add_argument("files", nargs="+")
|
|
cmdUpdateTS.set_defaults(func=utils.assets.updateTranslationSources)
|
|
|
|
# Build i18n Files
|
|
cmdBuildQM = parsers.add_parser("qtlrelease", help="Build the language files for internationalisation.")
|
|
cmdBuildQM.set_defaults(func=utils.assets.buildTranslationAssets)
|
|
|
|
# Update Docs i18n Sources
|
|
cmdUpdateDocsPo = parsers.add_parser("docs-lupdate", help="Update translation files for the docs.")
|
|
cmdUpdateDocsPo.add_argument("lang", nargs="+")
|
|
cmdUpdateDocsPo.set_defaults(func=utils.docs.updateDocsTranslationSources)
|
|
|
|
# Build PDF Docs
|
|
cmdBuildPdfDocs = parsers.add_parser("docs-pdf", help="Build the PDF manual files.")
|
|
cmdBuildPdfDocs.add_argument("lang", nargs="+")
|
|
cmdBuildPdfDocs.set_defaults(func=utils.docs.buildPdfDocAssets)
|
|
|
|
# Build HTML Docs
|
|
cmdBuildHtmlDocs = parsers.add_parser("docs-html", help="Build the HTML docs.")
|
|
cmdBuildHtmlDocs.add_argument("lang", nargs="+", help="Language codes to generate docs for.")
|
|
cmdBuildHtmlDocs.set_defaults(func=utils.docs.buildHtmlDocs)
|
|
|
|
# Build Sample
|
|
cmdBuildSample = parsers.add_parser("sample", help="Build the sample project zip file and add it to assets.")
|
|
cmdBuildSample.set_defaults(func=utils.assets.buildSampleZip)
|
|
|
|
# Clean Assets
|
|
cmdCleanAssets = parsers.add_parser("clean-assets", help="Delete assets built by docs-pdf, sample and qtlrelease.")
|
|
cmdCleanAssets.set_defaults(func=utils.assets.cleanBuiltAssets)
|
|
|
|
# Build Assets
|
|
cmdBuildAssets = parsers.add_parser("build-assets", help="Build all assets (except icon themes).")
|
|
cmdBuildAssets.set_defaults(func=utils.assets.buildAllAssets)
|
|
|
|
# Python Packaging
|
|
# ================
|
|
|
|
# Build Debian Package
|
|
distros = ", ".join(utils.build_debian.DISTRO_TARGETS.keys())
|
|
cmdBuildDeb = parsers.add_parser("build-deb", help="Build .deb packages for publishing.")
|
|
cmdBuildDeb.add_argument("distro", help=f"Release to build for: {distros}.")
|
|
cmdBuildDeb.add_argument("--sign", action="store_true", help="Sign the package.")
|
|
cmdBuildDeb.add_argument("--build", type=int, help="Set build number, appended to the distro suffix.")
|
|
cmdBuildDeb.add_argument("--install-source", help="Override the install source in meta.toml.")
|
|
cmdBuildDeb.set_defaults(func=utils.build_debian.debian)
|
|
|
|
# Print Debian Build Dependencies
|
|
cmdDebDepends = parsers.add_parser("build-deb-depends", help="Print the apt package dependencies.")
|
|
cmdDebDepends.add_argument("distro", help=f"Release to build for: {distros}.")
|
|
cmdDebDepends.set_defaults(func=utils.build_debian.printDebDepends)
|
|
|
|
# Build AppImage
|
|
# See https://github.com/pypa/manylinux
|
|
# See https://python-appimage.readthedocs.io/en/latest/#available-python-appimages
|
|
cmdBuildAppImage = parsers.add_parser("build-appimage", help="Build an AppImage.")
|
|
cmdBuildAppImage.add_argument("linux", help="Manylinux version, e.g. manylinux_2_28")
|
|
cmdBuildAppImage.add_argument("arch", help="Architecture, e.g. x86_64")
|
|
cmdBuildAppImage.add_argument("python", help="Python version, e.g. 3.13")
|
|
cmdBuildAppImage.set_defaults(func=utils.build_appimage.appImage)
|
|
|
|
# Build Flatpak
|
|
cmdBuildFlatpak = parsers.add_parser("build-flatpak", help="Build a Flatpak image for direct download.")
|
|
cmdBuildFlatpak.set_defaults(func=utils.build_flatpak.flatpak)
|
|
|
|
# Build Flathub Submission Files
|
|
cmdBuildFlathub = parsers.add_parser("build-flathub", help="Generate manifest and support files for a Flathub.")
|
|
cmdBuildFlathub.add_argument("path", nargs="?", help="Path to copy the generated files into.")
|
|
cmdBuildFlathub.set_defaults(func=utils.build_flatpak.flathub)
|
|
|
|
# Build PyPI Packages
|
|
cmdBuildPypi = parsers.add_parser("build-pypi", help="Build sdist and wheel packages for PyPI.")
|
|
cmdBuildPypi.set_defaults(func=utils.build_pypi.pypi)
|
|
|
|
# Build Windows Inno Setup Installer
|
|
cmdBuildSetupExe = parsers.add_parser("build-win-exe", help="Build a setup.exe installer for Windows.")
|
|
cmdBuildSetupExe.set_defaults(func=utils.build_windows.main)
|
|
|
|
# Build Binary
|
|
cmdBuildBinary = parsers.add_parser("build-bin", help="Build a standalone binary package.")
|
|
cmdBuildBinary.set_defaults(func=utils.build_binary.main)
|
|
|
|
# Build Clean
|
|
cmdBuildClean = parsers.add_parser("build-clean", help="Recursively delete all build folders.")
|
|
cmdBuildClean.set_defaults(func=cleanBuildDirs)
|
|
|
|
# Generate MacOS PList File
|
|
cmdGenMacOSPlist = parsers.add_parser("gen-plist", help="Generate an Info.plist for use in a MacOS Bundle.")
|
|
cmdGenMacOSPlist.set_defaults(func=genMacOSPlist)
|
|
|
|
# Generate Requirement File
|
|
cmdGenReq = parsers.add_parser("gen-req", help="Generate a requirements.txt file for pip.")
|
|
cmdGenReq.add_argument(
|
|
"groups",
|
|
nargs="*",
|
|
help=(
|
|
"Groups to generate for, or 'all' to generate for all groups. "
|
|
"Use 'app' to generate for just the core application. "
|
|
"Defaults to 'app' if none are specified."
|
|
),
|
|
)
|
|
cmdGenReq.set_defaults(func=genReqFiles)
|
|
|
|
args = parser.parse_args()
|
|
args.func(args)
|