From 0f6ea8d910a93ed3d4395ab023df197195d9770d Mon Sep 17 00:00:00 2001 From: Aleksandr Mezin Date: Fri, 1 Dec 2023 19:34:15 +0200 Subject: [PATCH] [WIP] Meson build system https://github.com/ddterm/gnome-shell-extension-ddterm/issues/648 --- .github/faketty.sh | 5 + .github/problem-matchers/generic.json | 4 +- .github/problem-matchers/gettext-stats.json | 2 +- .github/workflows/build.yml | 44 +- .github/workflows/check-po.yml | 20 +- .github/workflows/pot.yml | 77 ++- .github/workflows/pr.yml | 11 +- .github/workflows/push.yml | 11 +- .gitignore | 13 +- Makefile | 500 ------------------ PKGBUILD | 9 +- ...zin.ddterm => com.github.amezin.ddterm.in} | 2 +- bin/meson.build | 16 + bump-version.sh | 9 +- ddterm/app/icons/meson.build | 13 + ddterm/app/meson.build | 49 ++ ddterm/meson.build | 62 +++ ddterm/pref/meson.build | 31 ++ ddterm/pref/test/meson.build | 18 + ddterm/pref/ui/gtk3/meson.build | 22 + ddterm/pref/{glade => ui/gtk4}/3to4-fixup.xsl | 0 ddterm/pref/ui/gtk4/meson.build | 31 ++ ddterm/pref/ui/meson.build | 25 + ddterm/pref/{glade => ui}/prefs-animation.ui | 0 ddterm/pref/{glade => ui}/prefs-behavior.ui | 0 ddterm/pref/{glade => ui}/prefs-colors.ui | 0 ddterm/pref/{glade => ui}/prefs-command.ui | 0 .../pref/{glade => ui}/prefs-compatibility.ui | 0 ddterm/pref/{glade => ui}/prefs-panel-icon.ui | 0 .../pref/{glade => ui}/prefs-position-size.ui | 0 ddterm/pref/{glade => ui}/prefs-scrolling.ui | 0 ddterm/pref/{glade => ui}/prefs-shortcuts.ui | 0 ddterm/pref/{glade => ui}/prefs-tabs.ui | 0 ddterm/pref/{glade => ui}/prefs-text.ui | 0 ddterm/shell/meson.build | 24 + ddterm/util/meson.build | 11 + docs/BUILD.md | 107 ++-- docs/Test.md | 17 +- docs/Translations.md | 5 +- docs/Vagrant.md | 22 +- locale | 1 + meson.build | 186 +++++++ metadata.json.in | 8 +- package-lock.json | 1 + package.json | 3 +- po/POTFILES.in | 35 ++ po/gen-potfiles.py | 66 +++ po/meson.build | 40 ++ po/remove-potcdate.sin | 19 - po/update-pot.sh | 26 - renovate.json | 2 +- schemas/meson.build | 31 ++ test/conftest.py | 28 +- test/ddterm_fixtures.py | 4 +- test/tox.ini | 1 + tools/makezip.py | 29 + vagrant-provision/deploy.yml | 11 +- 57 files changed, 925 insertions(+), 726 deletions(-) create mode 100755 .github/faketty.sh delete mode 100755 Makefile rename bin/{com.github.amezin.ddterm => com.github.amezin.ddterm.in} (78%) create mode 100644 bin/meson.build create mode 100644 ddterm/app/icons/meson.build create mode 100644 ddterm/app/meson.build create mode 100644 ddterm/meson.build create mode 100644 ddterm/pref/meson.build create mode 100644 ddterm/pref/test/meson.build create mode 100644 ddterm/pref/ui/gtk3/meson.build rename ddterm/pref/{glade => ui/gtk4}/3to4-fixup.xsl (100%) create mode 100644 ddterm/pref/ui/gtk4/meson.build create mode 100644 ddterm/pref/ui/meson.build rename ddterm/pref/{glade => ui}/prefs-animation.ui (100%) rename ddterm/pref/{glade => ui}/prefs-behavior.ui (100%) rename ddterm/pref/{glade => ui}/prefs-colors.ui (100%) rename ddterm/pref/{glade => ui}/prefs-command.ui (100%) rename ddterm/pref/{glade => ui}/prefs-compatibility.ui (100%) rename ddterm/pref/{glade => ui}/prefs-panel-icon.ui (100%) rename ddterm/pref/{glade => ui}/prefs-position-size.ui (100%) rename ddterm/pref/{glade => ui}/prefs-scrolling.ui (100%) rename ddterm/pref/{glade => ui}/prefs-shortcuts.ui (100%) rename ddterm/pref/{glade => ui}/prefs-tabs.ui (100%) rename ddterm/pref/{glade => ui}/prefs-text.ui (100%) create mode 100644 ddterm/shell/meson.build create mode 100644 ddterm/util/meson.build create mode 120000 locale create mode 100644 meson.build create mode 100644 po/POTFILES.in create mode 100755 po/gen-potfiles.py create mode 100644 po/meson.build delete mode 100644 po/remove-potcdate.sin delete mode 100755 po/update-pot.sh create mode 100644 schemas/meson.build create mode 100644 tools/makezip.py diff --git a/.github/faketty.sh b/.github/faketty.sh new file mode 100755 index 000000000..d523f1503 --- /dev/null +++ b/.github/faketty.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +export COLUMNS=80 + +exec script -q -e -c "$(printf "%q " "$@")" diff --git a/.github/problem-matchers/generic.json b/.github/problem-matchers/generic.json index 83bf46ea4..d26773421 100644 --- a/.github/problem-matchers/generic.json +++ b/.github/problem-matchers/generic.json @@ -4,7 +4,7 @@ "owner": "generic", "pattern": [ { - "regexp": "^([^\\s:]+):(\\d+)(?::(\\d+))?:?\\s+(?:((?i)warning|error):?)?\\s*(.+)$", + "regexp": "^(?:\\.\\./)?([^\\s:]+):(\\d+)(?::(\\d+))?:?\\s+(?:((?i)warning|error):?)?\\s*(.+)$", "file": 1, "line": 2, "column": 3, @@ -17,7 +17,7 @@ "owner": "generic-nolocation", "pattern": [ { - "regexp": "^(?:([^\\s:]+):?\\s+)?((?i)warning|error):?\\s*(.+)$", + "regexp": "^(?:\\.\\./)?(?:([^\\s:]+):?\\s+)?((?i)warning|error):?\\s*(.+)$", "file": 1, "severity": 2, "message": 3 diff --git a/.github/problem-matchers/gettext-stats.json b/.github/problem-matchers/gettext-stats.json index ed6034a50..ec2c73ff7 100644 --- a/.github/problem-matchers/gettext-stats.json +++ b/.github/problem-matchers/gettext-stats.json @@ -5,7 +5,7 @@ "severity": "warning", "pattern": [ { - "regexp": "msgfmt .* --statistics .* (po/.*\\.po)", + "regexp": "(?:^|\\s)(?:\\.\\./)?(locale/.*\\.po)$", "file": 1 }, { diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e380769e3..9681e6f5a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,6 +17,7 @@ on: env: FORCE_COLOR: 1 PIP_DISABLE_PIP_VERSION_CHECK: 1 + TERM: xterm-color jobs: lint: @@ -44,11 +45,11 @@ jobs: - name: Install JS dependencies id: npm - run: npm ci + run: npm install if: ${{ always() && steps.checkout.conclusion == 'success' }} - name: Lint JS code - run: make "ESLINT_OPTS=--format .github/eslint-formatter.js" lint + run: npm run-script lint -- --format .github/eslint-formatter.js if: ${{ always() && steps.npm.conclusion == 'success' }} - name: Pre-create pip cache directory @@ -75,16 +76,33 @@ jobs: run: echo "::add-matcher::.github/problem-matchers/generic.json" if: ${{ always() && steps.checkout.conclusion == 'success' }} - - name: Compile GSettings schemas - run: make schemas 2>&1 | tee schemas.log - shell: bash + - name: Upgrade Meson + run: | + # renovate: datasource=pypi depName=meson + MESON_VERSION=1.3.1 + pip3 install "meson==${MESON_VERSION}" if: ${{ always() && steps.checkout.conclusion == 'success' }} - - name: Validate Gtk .ui files - run: xvfb-run make gtk-builder-validate 2>&1 | tee gtk-builder.log - shell: bash + - id: meson-setup + name: Prepare build directory + run: .github/faketty.sh meson setup build if: ${{ always() && steps.checkout.conclusion == 'success' }} + - name: Run glib-compile-schemas checks + run: ../.github/faketty.sh meson test -v -j1 --no-rebuild --suite glib-compile-schemas --logbase glib-compile-schemas + working-directory: build + if: ${{ always() && steps.meson-setup.conclusion == 'success' }} + + - name: Run desktop-file-validate checks + run: ../.github/faketty.sh meson test -v -j1 --suite desktop-file-validate --logbase desktop-file-validate + working-directory: build + if: ${{ always() && steps.meson-setup.conclusion == 'success' }} + + - name: Run gtk-builder-validate checks + run: ../.github/faketty.sh xvfb-run meson test -v -j1 --suite gtk-builder-validate --logbase gtk-builder-validate + working-directory: build + if: ${{ always() && steps.meson-setup.conclusion == 'success' }} + - name: Ensure Python requirements .txt files are in sync with .in files run: | tox --sitepackages -e pip-compile @@ -102,7 +120,7 @@ jobs: if: ${{ always() && steps.checkout.conclusion == 'success' }} - name: Upload reports to Testspace - run: testspace --verbose eslint.xml "*.log{lint}" + run: testspace --verbose eslint.xml "*.log{lint}" "build/meson-logs/*.txt{lint}" if: ${{ always() && steps.setup_testspace.outcome == 'success' }} pack: @@ -119,13 +137,17 @@ jobs: - name: Enable generic error matcher run: echo "::add-matcher::.github/problem-matchers/generic.json" + - name: Prepare build directory + run: .github/faketty.sh meson setup build + - name: Build extension package - run: xvfb-run make ONLY_RELEASE_LOCALES=true pack + run: xvfb-run ninja -j1 pack + working-directory: build - name: Upload extension package as artifact id: upload uses: actions/upload-artifact@v4 with: name: pack - path: "*.shell-extension.zip" + path: "build/*.shell-extension.zip" if-no-files-found: error diff --git a/.github/workflows/check-po.yml b/.github/workflows/check-po.yml index 66f656871..84ec72844 100644 --- a/.github/workflows/check-po.yml +++ b/.github/workflows/check-po.yml @@ -4,7 +4,6 @@ on: env: FORCE_COLOR: 1 - PIP_DISABLE_PIP_VERSION_CHECK: 1 jobs: configure: @@ -23,7 +22,7 @@ jobs: echo -n linguas= >>$GITHUB_OUTPUT grep -Ev '^\s*#.*' LINGUAS | jq -Rcn '[inputs | scan("\\S+")]' >>$GITHUB_OUTPUT shell: bash - working-directory: po + working-directory: locale check: needs: configure @@ -39,27 +38,26 @@ jobs: steps: - name: Checkout - id: checkout uses: actions/checkout@v4 - run: git config --global --replace-all safe.directory "$GITHUB_WORKSPACE" - - name: Enable gettext stats problem matcher - run: echo "::add-matcher::.github/problem-matchers/gettext-stats.json" - - name: Enable generic problem matcher run: echo "::add-matcher::.github/problem-matchers/generic.json" + - name: Enable gettext stats problem matcher + run: echo "::add-matcher::.github/problem-matchers/gettext-stats.json" + - name: Compile translation - run: make msgfmt/${{ matrix.lang }} 2>&1 | tee $GITHUB_STEP_SUMMARY + run: | + echo locale/${{ matrix.lang }}.po + msgfmt --check -v -o /dev/null locale/${{ matrix.lang }}.po 2>&1 | tee $GITHUB_STEP_SUMMARY shell: bash - name: Disable gettext stats problem matcher run: echo "::remove-matcher owner=gettext-stats::" - name: Ensure .po file is in sync with .pot - run: | - touch po/*.pot # Make sure .pot won't be re-generated - make msgcmp/${{ matrix.lang }} 2>&1 + run: msgcmp --use-untranslated --use-fuzzy locale/${{ matrix.lang }}.po locale/*.pot shell: bash - if: ${{ always() && steps.checkout.conclusion == 'success' }} + if: ${{ always() && steps.meson-setup.conclusion == 'success' }} diff --git a/.github/workflows/pot.yml b/.github/workflows/pot.yml index 880782287..87ce38597 100644 --- a/.github/workflows/pot.yml +++ b/.github/workflows/pot.yml @@ -1,20 +1,30 @@ -concurrency: - group: ${{ github.workflow }}/${{ github.ref }} - -name: pot - on: workflow_dispatch: + inputs: + commit: + description: Commit changes + required: false + default: false + type: boolean + workflow_call: - push: - branches: - - master - paths-ignore: - - docs/** - - po/*.po - - README.md - - Vagrantfile - - vagrant-provision/** + inputs: + commit: + description: Commit changes + required: false + default: false + type: boolean + secrets: + APP_ID: + description: 'ID of the committer application' + required: false + APP_KEY: + description: 'Private key of the committer application' + required: false + +env: + FORCE_COLOR: 1 + TERM: xterm-color jobs: pot: @@ -23,28 +33,31 @@ jobs: image: ghcr.io/ddterm/ci-docker-image:meson steps: - - name: Get app token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_KEY }} - - name: Checkout uses: actions/checkout@v4 - with: - token: ${{ steps.app-token.outputs.token }} - run: git config --global --replace-all safe.directory "$GITHUB_WORKSPACE" - name: Enable generic error matcher run: echo "::add-matcher::.github/problem-matchers/generic.json" - - name: Update .pot files - run: po/update-pot.sh + - name: Prepare build directory + run: .github/faketty.sh meson setup build + + - name: Update POTFILES.in + run: ninja -j1 potfiles + working-directory: build + + - name: Update .pot file + run: ninja -j1 msgmerge + working-directory: build + + - name: Update .po files + run: for pofile in *.po; do msgmerge --update --previous "$pofile" *.pot; done + working-directory: po - name: Stage changes - run: git add po/*.po po/*.pot + run: git add po/*.po po/*.pot po/POTFILES.in - name: Check if there are any changes id: diff @@ -52,12 +65,20 @@ jobs: with: result-encoding: string script: | - const { stdout } = await exec.getExecOutput('git', ['diff', '--cached']); + const { stdout } = await exec.getExecOutput('git', ['diff', '--cached', '--ignore-matching-lines=^"POT-Creation-Date: ']); return stdout.trim(); + - name: Get commit token + id: app-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_KEY }} + if: inputs.commit + - name: Commit uses: ddterm/github-api-commit-action@ccf9b520c5698380ad3b9619c5add427369b7ef1 - if: steps.diff.outputs.result != '' with: token: ${{ steps.app-token.outputs.token }} commit-message: 'Update translation files' + if: inputs.commit && steps.diff.outputs.result diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 28bf243af..c14b109fe 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,7 +6,10 @@ on: pull_request: paths-ignore: - docs/** - - po/** + - po/*.po + - po/*.pot + - po/POTFILES + - po/POTFILES.in - README.md - Vagrantfile - vagrant-provision/** @@ -24,3 +27,9 @@ jobs: test: needs: build uses: ./.github/workflows/test.yml + + translations: + uses: ./.github/workflows/pot.yml + with: + commit: false + secrets: inherit diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 429149d72..c8e45f76d 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -12,7 +12,10 @@ on: - v* paths-ignore: - docs/** - - po/** + - po/*.po + - po/*.pot + - po/POTFILES + - po/POTFILES.in - README.md - Vagrantfile - vagrant-provision/** @@ -26,3 +29,9 @@ jobs: test: needs: build uses: ./.github/workflows/test.yml + + translations: + uses: ./.github/workflows/pot.yml + with: + commit: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }} + secrets: inherit diff --git a/.gitignore b/.gitignore index ef8801700..951e52c31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,6 @@ *~ -/node_modules/ -# Makefile output -/*.shell-extension.zip -/ddterm/pref/ui/ -/ddterm/com.github.amezin.ddterm.desktop -/ddterm/com.github.amezin.ddterm.desktop.in -/ddterm/com.github.amezin.ddterm.service -/metadata.json -/schemas/gschemas.compiled -/locale/ -/tmp/ -/revision.txt +/node_modules/ # do-in-docker.sh/do-in-podman.sh /.container-home/ diff --git a/Makefile b/Makefile deleted file mode 100755 index dae82623c..000000000 --- a/Makefile +++ /dev/null @@ -1,500 +0,0 @@ -#!/usr/bin/env -S make -f - -# See docs/BUILD.md - -SHELL := /bin/bash - -EXTENSION_UUID := ddterm@amezin.github.com - -TRUE_VALUES := yes YES true TRUE on ON 1 -is-true = $(filter 1,$(words $(filter $(TRUE_VALUES),$(1)))) - -all: -.PHONY: all - -find-tool = $(or $(shell command -v $(1)),tool-not-found/$(1)) - -define tool-not-found-message -$* not found and is required. -You could use do-in-docker.sh or do-in-podman.sh to avoid installing build dependencies. -Please check docs/BUILD.md -endef - -tool-not-found/%: - $(error $(tool-not-found-message)) - -CLEAN := -TRANSLATABLE_SOURCES := -PACK_CONTENT := - -# Git revision file - -ifeq ($(file $@ - -else - -revision.txt: revision.txt.in - cat $< >$@ - -endif - -CLEAN += revision.txt -PACK_CONTENT += revision.txt - -# GSettings schemas - -SCHEMAS := $(wildcard schemas/*.gschema.xml) -SCHEMAS_COMPILED := schemas/gschemas.compiled -SCHEMAS_ALL := $(SCHEMAS) $(SCHEMAS_COMPILED) - -GLIB_COMPILE_SCHEMAS := $(call find-tool,glib-compile-schemas) - -$(SCHEMAS_COMPILED): $(SCHEMAS) $(GLIB_COMPILE_SCHEMAS) - $(GLIB_COMPILE_SCHEMAS) --strict $(dir $@) - -CLEAN += $(SCHEMAS_COMPILED) -PACK_CONTENT += $(SCHEMAS) - -schemas: $(SCHEMAS_COMPILED) -.PHONY: schemas -all: schemas - -# Locales - -LINGUAS_FILE := po/LINGUAS -LOCALES_RELEASE := cs de el fr it nb_NO pl pt ru zh_CN -LOCALE_SOURCE_PATTERN := po/%.po -LOCALES_ALL := $(shell grep -Ev '^\s*#.*' $(LINGUAS_FILE)) - -ONLY_RELEASE_LOCALES := no - -ifeq ($(call is-true,$(ONLY_RELEASE_LOCALES)),1) -LOCALES := $(LOCALES_RELEASE) -else -LOCALES := $(LOCALES_ALL) -endif - -LOCALE_COMPILED_PATTERN := locale/%/LC_MESSAGES/$(EXTENSION_UUID).mo -LOCALES_COMPILED := $(patsubst %,$(LOCALE_COMPILED_PATTERN),$(LOCALES)) - -MSGFMT := $(call find-tool,msgfmt) - -$(LOCALES_COMPILED): $(LOCALE_COMPILED_PATTERN): $(LOCALE_SOURCE_PATTERN) $(MSGFMT) - mkdir -p $(dir $@) - $(MSGFMT) --check --strict --statistics -o $@ $< - -$(addprefix msgfmt/,$(LOCALES)): msgfmt/%: $(LOCALE_COMPILED_PATTERN) - -CLEAN += $(LOCALES_COMPILED) -PACK_CONTENT += $(LOCALES_COMPILED) - -locales msgfmt: $(LOCALES_COMPILED) -.PHONY: locales msgfmt - -# Glade UI - -PREFS_GLADE_UI := $(wildcard ddterm/pref/glade/*.ui) -PREFS_GLADE_UI_PATTERN := ddterm/pref/glade/%.ui -TRANSLATABLE_SOURCES += $(APP_GLADE_UI) $(PREFS_GLADE_UI) - -ddterm/pref/ui: - mkdir -p $@ - -# Gtk 3 .ui - -GTK_BUILDER_TOOL := $(call find-tool,gtk-builder-tool) - -ddterm/pref/ui/gtk3: | ddterm/pref/ui - mkdir -p $@ - -PREFS_UI_GTK3_PATTERN := ddterm/pref/ui/gtk3/%.ui -PREFS_UI_GTK3 := $(patsubst $(PREFS_GLADE_UI_PATTERN),$(PREFS_UI_GTK3_PATTERN),$(PREFS_GLADE_UI)) - -$(PREFS_UI_GTK3): $(PREFS_UI_GTK3_PATTERN): $(PREFS_GLADE_UI_PATTERN) $(GTK_BUILDER_TOOL) | ddterm/pref/ui/gtk3 - $(GTK_BUILDER_TOOL) simplify $< >$@ - -GTK3_GENERATED_UI := $(APP_UI) $(PREFS_UI_GTK3) -GTK3_HANDCRAFTED_UI := ddterm/app/menus.ui -GTK3_UI := $(GTK3_GENERATED_UI) $(GTK3_HANDCRAFTED_UI) - -CLEAN += $(GTK3_GENERATED_UI) -PACK_CONTENT += $(GTK3_UI) -TRANSLATABLE_SOURCES += $(GTK3_HANDCRAFTED_UI) - -# Gtk 4 .ui - -GTK4_BUILDER_TOOL := $(call find-tool,gtk4-builder-tool) -XSLTPROC := $(call find-tool,xsltproc) - -ddterm/pref/ui/gtk4 ddterm/pref/ui/gtk4/3to4-fixup ddterm/pref/ui/gtk4/3to4: - mkdir -p $@ - -ddterm/pref/ui/gtk4/3to4-fixup ddterm/pref/ui/gtk4/3to4: | ddterm/pref/ui/gtk4 - -PREFS_UI_3TO4_FIXUP_PATTERN := ddterm/pref/ui/gtk4/3to4-fixup/%.ui -PREFS_UI_3TO4_FIXUP := $(patsubst $(PREFS_GLADE_UI_PATTERN),$(PREFS_UI_3TO4_FIXUP_PATTERN),$(PREFS_GLADE_UI)) - -$(PREFS_UI_3TO4_FIXUP): $(PREFS_UI_3TO4_FIXUP_PATTERN): $(PREFS_GLADE_UI_PATTERN) ddterm/pref/glade/3to4-fixup.xsl $(XSLTPROC) | ddterm/pref/ui/gtk4/3to4-fixup - $(XSLTPROC) ddterm/pref/glade/3to4-fixup.xsl $< >$@ - -PREFS_UI_3TO4_PATTERN := ddterm/pref/ui/gtk4/3to4/%.ui -PREFS_UI_3TO4 := $(patsubst $(PREFS_UI_3TO4_FIXUP_PATTERN),$(PREFS_UI_3TO4_PATTERN),$(PREFS_UI_3TO4_FIXUP)) - -$(PREFS_UI_3TO4): $(PREFS_UI_3TO4_PATTERN): $(PREFS_UI_3TO4_FIXUP_PATTERN) $(GTK4_BUILDER_TOOL) | ddterm/pref/ui/gtk4/3to4 - $(GTK4_BUILDER_TOOL) simplify --3to4 $< >$@ - -PREFS_UI_GTK4_PATTERN := ddterm/pref/ui/gtk4/%.ui -PREFS_UI_GTK4 := $(patsubst $(PREFS_UI_3TO4_PATTERN),$(PREFS_UI_GTK4_PATTERN),$(PREFS_UI_3TO4)) - -$(PREFS_UI_GTK4): $(PREFS_UI_GTK4_PATTERN): $(PREFS_UI_3TO4_PATTERN) $(GTK4_BUILDER_TOOL) | ddterm/pref/ui/gtk4 - $(GTK4_BUILDER_TOOL) simplify $< >$@ - -CLEAN += $(PREFS_UI_3TO4_FIXUP) $(PREFS_UI_3TO4) $(PREFS_UI_GTK4) - -GTK4_UI := $(PREFS_UI_GTK4) - -PACK_CONTENT += $(GTK4_UI) - -# metadata.json - -# Prevent people from trying to feed source archives to 'gnome-extensions install'. -# https://github.com/ddterm/gnome-shell-extension-ddterm/issues/61 - -metadata.json: metadata.json.in - cp $< $@ - -PACK_CONTENT += metadata.json -CLEAN += metadata.json - -# JS sources - -JS_SOURCE_WILDCARDS := \ - *.js \ - ddterm/*.js \ - ddterm/app/*.js \ - ddterm/backport/*.js \ - ddterm/pref/*.js \ - ddterm/shell/*.js \ - ddterm/util/*.js \ - misc/*.js \ - -JS_SOURCES := $(wildcard $(JS_SOURCE_WILDCARDS)) -LAUNCHER := bin/com.github.amezin.ddterm -EXECUTABLES := $(LAUNCHER) - -TRANSLATABLE_SOURCES += $(JS_SOURCES) -PACK_CONTENT += $(EXECUTABLES) $(filter-out $(EXECUTABLES),$(JS_SOURCES)) - -# .desktop entry - -UNTRANSLATED_DESKTOP_ENTRY := ddterm/com.github.amezin.ddterm.desktop.in.in -TRANSLATABLE_SOURCES += $(UNTRANSLATED_DESKTOP_ENTRY) - -UNCONFIGURED_DESKTOP_ENTRY := $(basename $(UNTRANSLATED_DESKTOP_ENTRY)) - -$(UNCONFIGURED_DESKTOP_ENTRY): $(UNTRANSLATED_DESKTOP_ENTRY) $(MSGFMT) - $(MSGFMT) --desktop -o $@ --template=$< -d po - -$(UNCONFIGURED_DESKTOP_ENTRY): $(patsubst %,$(LOCALE_SOURCE_PATTERN),$(LOCALES)) -$(UNCONFIGURED_DESKTOP_ENTRY): $(LINGUAS_FILE) - -$(UNCONFIGURED_DESKTOP_ENTRY): export LINGUAS := $(LOCALES) - -CLEAN += $(UNCONFIGURED_DESKTOP_ENTRY) - -UNCONFIGURED_DBUS_SERVICE := ddterm/com.github.amezin.ddterm.service.in - -# package - -PACK_CONTENT += \ - ddterm/app/style.css \ - ddterm/app/dependencies.json \ - $(wildcard ddterm/app/icons/*) \ - ddterm/com.github.amezin.ddterm.Extension.xml \ - ddterm/com.github.amezin.ddterm.HeapDump.xml \ - $(UNCONFIGURED_DESKTOP_ENTRY) \ - $(UNCONFIGURED_DBUS_SERVICE) \ - LICENSE \ - -PACK_CONTENT := $(sort $(PACK_CONTENT)) - -build: $(PACK_CONTENT) -.PHONY: build - -ZIP := $(call find-tool,zip) - -EXTENSION_PACK := $(EXTENSION_UUID).shell-extension.zip -$(EXTENSION_PACK): $(PACK_CONTENT) $(ZIP) $(LINGUAS_FILE) - $(RM) $@ - $(ZIP) -y -nw $@ -- $(PACK_CONTENT) - -pack: $(EXTENSION_PACK) -.PHONY: pack - -all: pack -CLEAN += $(EXTENSION_PACK) - -# install/uninstall package - user - -user-install: $(EXTENSION_PACK) develop-uninstall - gnome-extensions install -f $< - -user-uninstall: develop-uninstall - gnome-extensions uninstall $(EXTENSION_UUID) - -.PHONY: user-install user-uninstall - -# install/uninstall package - system-wide - -# https://www.gnu.org/software/make/manual/html_node/Command-Variables.html -INSTALL := install -INSTALL_PROGRAM := $(INSTALL) -INSTALL_DATA := $(INSTALL) -m 644 - -# https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html -prefix := /usr -exec_prefix := $(prefix) -datarootdir := $(prefix)/share -datadir := $(datarootdir) -bindir := $(exec_prefix)/bin - -extensiondir := $(datadir)/gnome-shell/extensions - -CONFIGURED_DESKTOP_ENTRY := $(basename $(UNCONFIGURED_DESKTOP_ENTRY)) -CONFIGURED_DBUS_SERVICE := $(basename $(UNCONFIGURED_DBUS_SERVICE)) - -SYS_INSTALLED_EXTENSION_DIR := $(extensiondir)/$(EXTENSION_UUID) -SYS_INSTALLED_CONTENT := $(addprefix $(SYS_INSTALLED_EXTENSION_DIR)/,$(filter-out $(SCHEMAS_ALL),$(PACK_CONTENT))) -SYS_INSTALLED_SCHEMAS := $(addprefix $(datadir)/glib-2.0/,$(SCHEMAS)) -SYS_INSTALLED_DESKTOP_ENTRY := $(datadir)/applications/$(notdir $(CONFIGURED_DESKTOP_ENTRY)) -SYS_INSTALLED_DBUS_SERVICE := $(datadir)/dbus-1/services/$(notdir $(CONFIGURED_DBUS_SERVICE)) -SYS_INSTALLED_EXECUTABLES := $(addprefix $(SYS_INSTALLED_EXTENSION_DIR)/,$(EXECUTABLES)) -SYS_INSTALLED_LAUNCHER := $(filter %$(LAUNCHER),$(SYS_INSTALLED_EXECUTABLES)) -SYS_INSTALLED_LAUNCHER_SYMLINK := $(bindir)/$(notdir $(LAUNCHER)) -SYS_INSTALLED_ALL := \ - $(SYS_INSTALLED_CONTENT) \ - $(SYS_INSTALLED_SCHEMAS) \ - $(SYS_INSTALLED_DESKTOP_ENTRY) \ - $(SYS_INSTALLED_DBUS_SERVICE) \ - $(SYS_INSTALLED_LAUNCHER_SYMLINK) \ - -SYS_INSTALLED_DIRS := $(sort $(dir $(SYS_INSTALLED_ALL))) - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_DIRS)): - mkdir -p $@ - -installdirs: $(addprefix $(DESTDIR),$(SYS_INSTALLED_DIRS)) - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_CONTENT)): $(DESTDIR)$(SYS_INSTALLED_EXTENSION_DIR)/%: % | installdirs - $(INSTALL) $< $@ - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_SCHEMAS)): $(DESTDIR)$(datadir)/glib-2.0/%: % | installdirs - $(INSTALL) $< $@ - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_CONTENT) $(SYS_INSTALLED_SCHEMAS)): INSTALL := $(INSTALL_DATA) -$(addprefix $(DESTDIR),$(SYS_INSTALLED_EXECUTABLES)): INSTALL := $(INSTALL_PROGRAM) - -$(CONFIGURED_DESKTOP_ENTRY) $(CONFIGURED_DBUS_SERVICE): - sed -e 's:@LAUNCHER@:$(SYS_INSTALLED_LAUNCHER):g' $< >$@ - -$(CONFIGURED_DESKTOP_ENTRY): $(UNCONFIGURED_DESKTOP_ENTRY) -$(CONFIGURED_DBUS_SERVICE): $(UNCONFIGURED_DBUS_SERVICE) - -CLEAN += $(CONFIGURED_DESKTOP_ENTRY) $(CONFIGURED_DBUS_SERVICE) - -DESKTOP_FILE_VALIDATE_TOOL := $(call find-tool,desktop-file-validate) - -desktop-file-validate: $(DESKTOP_FILE_VALIDATE_TOOL) $(CONFIGURED_DESKTOP_ENTRY) - $^ - -.PHONY: desktop-file-validate - -ifneq (tool-not-found/desktop-file-validate,$(DESKTOP_FILE_VALIDATE_TOOL)) -all: desktop-file-validate -endif - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_DESKTOP_ENTRY) $(SYS_INSTALLED_DBUS_SERVICE)): | installdirs - $(INSTALL_DATA) $< $@ - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_DESKTOP_ENTRY)): $(CONFIGURED_DESKTOP_ENTRY) -$(addprefix $(DESTDIR),$(SYS_INSTALLED_DBUS_SERVICE)): $(CONFIGURED_DBUS_SERVICE) - -$(addprefix $(DESTDIR),$(SYS_INSTALLED_LAUNCHER_SYMLINK)): | installdirs - ln -s $(SYS_INSTALLED_LAUNCHER) $@ - -system-schemas-compile system-schemas-compile-nodeps: $(GLIB_COMPILE_SCHEMAS) - $(GLIB_COMPILE_SCHEMAS) $(DESTDIR)$(datadir)/glib-2.0/schemas - -system-schemas-compile: $(addprefix $(DESTDIR),$(SYS_INSTALLED_SCHEMAS)) - -.PHONY: system-schemas-compile system-schemas-compile-nodeps - -system-install: $(addprefix $(DESTDIR),$(SYS_INSTALLED_ALL)) - -system-uninstall: - $(RM) $(addprefix $(DESTDIR),$(SYS_INSTALLED_ALL)) - $(RM) -r $(DESTDIR)$(SYS_INSTALLED_EXTENSION_DIR) - -.PHONY: system-install system-uninstall installdirs - -ifeq ($(DESTDIR),) -system-install: system-schemas-compile -system-uninstall: system-schemas-compile-nodeps -endif - -# System/user install autodetect - -ifneq ($(DESTDIR),) -INSTALL_FLAVOR := system -else ifeq ($(shell id -u),0) -INSTALL_FLAVOR := system -else -INSTALL_FLAVOR := user -endif - -install: $(INSTALL_FLAVOR)-install -uninstall: $(INSTALL_FLAVOR)-uninstall - -.PHONY: install uninstall - -# develop/symlink install - -DEVELOP_SYMLINK := $(HOME)/.local/share/gnome-shell/extensions/$(EXTENSION_UUID) - -develop: build - mkdir -p "$(dir $(DEVELOP_SYMLINK))" - @if [[ -e "$(DEVELOP_SYMLINK)" && ! -L "$(DEVELOP_SYMLINK)" ]]; then \ - echo "$(DEVELOP_SYMLINK) exists and is not a symlink, not overwriting"; exit 1; \ - fi - if [[ "$(abspath .)" != "$(abspath $(DEVELOP_SYMLINK))" ]]; then \ - ln -snf "$(abspath .)" "$(DEVELOP_SYMLINK)"; \ - fi - -develop-uninstall: - if [[ -L "$(DEVELOP_SYMLINK)" ]]; then \ - unlink "$(DEVELOP_SYMLINK)"; \ - fi - -.PHONY: develop develop-uninstall - -# clean - -clean: - $(RM) $(CLEAN) - -.PHONY: clean - -# .ui validation - -GTK3_VALIDATE_UI := $(addprefix gtk-builder-validate/,$(GTK3_UI)) - -$(GTK3_VALIDATE_UI): gtk-builder-validate/%: % $(GTK_BUILDER_TOOL) - $(GTK_BUILDER_TOOL) validate $< - -.PHONY: $(GTK3_VALIDATE_UI) - -GTK4_VALIDATE_UI := $(addprefix gtk-builder-validate/,$(GTK4_UI)) - -$(GTK4_VALIDATE_UI): gtk-builder-validate/%: % $(GTK4_BUILDER_TOOL) - $(GTK4_BUILDER_TOOL) validate $< - -.PHONY: $(GTK4_VALIDATE_UI) - -gtk-builder-validate: $(GTK3_VALIDATE_UI) $(GTK4_VALIDATE_UI) - -all: gtk-builder-validate -.PHONY: gtk-builder-validate - -# Translation helpers - -POT_FILE := po/$(EXTENSION_UUID).pot -XGETTEXT := $(call find-tool,xgettext) - -$(POT_FILE): $(TRANSLATABLE_SOURCES) $(XGETTEXT) - $(XGETTEXT) \ - --from-code=UTF-8 \ - --default-domain=$(EXTENSION_UUID) \ - --package-name=ddterm \ - --add-comments \ - --output=$@ \ - $(sort $(TRANSLATABLE_SOURCES)) - -pot: $(POT_FILE) -.PHONY: pot - -MSGCMP_GOALS := $(addprefix msgcmp/, $(LOCALES)) -MSGCMP_FLAGS := --use-untranslated --use-fuzzy -MSGCMP := $(call find-tool,msgcmp) - -$(MSGCMP_GOALS): msgcmp/%: $(LOCALE_SOURCE_PATTERN) $(POT_FILE) $(MSGCMP) - $(MSGCMP) $(MSGCMP_FLAGS) $< $(POT_FILE) - -msgcmp: $(MSGCMP_GOALS) - -msgcmp-strict: override MSGCMP_FLAGS := -msgcmp-strict: $(MSGCMP_GOALS) - -.PHONY: msgcmp msgcmp-strict $(MSGCMP_GOALS) - -MSGMERGE_GOALS := $(addprefix msgmerge/, $(LOCALES)) -MSGMERGE_FLAGS := --no-fuzzy-matching --update -MSGMERGE := $(call find-tool,msgmerge) - -$(MSGMERGE_GOALS): msgmerge/%: $(LOCALE_SOURCE_PATTERN) $(POT_FILE) $(MSGMERGE) - $(MSGMERGE) $(MSGMERGE_FLAGS) $< $(POT_FILE) - -msgmerge: $(MSGMERGE_GOALS) - -msgmerge-fuzzy: override MSGMERGE_FLAGS := --update --previous -msgmerge-fuzzy: $(MSGMERGE_GOALS) - -.PHONY: msgmerge $(MSGMERGE_GOALS) - -# ESLint - -ESLINT_CMD := node_modules/.bin/eslint -ESLINT_OPTS := -NPM_INSTALLED += $(ESLINT_CMD) - -lint/eslintrc-gjs.yml: - curl -o $@ 'https://gitlab.gnome.org/GNOME/gnome-shell/-/raw/39ed7f83fd97a5a3f688d77adb73e00fd24b7bfe/lint/eslintrc-gjs.yml' - -lint: $(ESLINT_CMD) lint/eslintrc-gjs.yml - $< $(ESLINT_OPTS) . - -.PHONY: lint -all: lint - -# Automagic 'npm install' - -NPM_INSTALL := yes - -ifeq ($(call is-true,$(NPM_INSTALL)),1) - -$(NPM_INSTALLED): node_modules/.package-lock.json -NPM := $(call find-tool,npm) - -node_modules/.package-lock.json: package.json package-lock.json $(NPM) - $(NPM) install - -npm: node_modules/.package-lock.json -.PHONY: npm - -endif - -# Various helpers - -prefs enable disable reset info show: - gnome-extensions $@ $(EXTENSION_UUID) - -.PHONY: prefs enable disable reset info show - -toggle quit begin-subscription-leak-check end-subscription-leak-check: - gapplication action com.github.amezin.ddterm $@ - -.PHONY: toggle quit begin-subscription-leak-check end-subscription-leak-check diff --git a/PKGBUILD b/PKGBUILD index 662821fb4..abb43ed55 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -8,7 +8,7 @@ license=('GPL3') conflicts=('gnome-shell-extension-ddterm') provides=('gnome-shell-extension-ddterm') depends=('gjs' 'gtk3' 'vte3') -makedepends=('git' 'gtk4' 'libxslt' 'xorg-server-xvfb') +makedepends=('meson' 'git' 'gtk4' 'libxslt' 'xorg-server-xvfb') source=("$pkgname::git+file://$(git rev-parse --show-toplevel)") md5sums=('SKIP') @@ -18,13 +18,12 @@ pkgver() { } build() { - cd "$pkgname" + arch-meson $pkgname build # gtk-builder-tool needs X or Wayland - LIBGL_ALWAYS_SOFTWARE=1 xvfb-run -- make build + LIBGL_ALWAYS_SOFTWARE=1 xvfb-run -- meson compile -C build } package() { - cd "$pkgname" - make DESTDIR="$pkgdir/" install + meson install -C build --destdir "$pkgdir" } diff --git a/bin/com.github.amezin.ddterm b/bin/com.github.amezin.ddterm.in similarity index 78% rename from bin/com.github.amezin.ddterm rename to bin/com.github.amezin.ddterm.in index 1d078776d..bdbda2f3e 100755 --- a/bin/com.github.amezin.ddterm +++ b/bin/com.github.amezin.ddterm.in @@ -10,4 +10,4 @@ then PATH="$bindir${PATH:+:${PATH}}" fi -exec gjs -m "${bindir%/*}/ddterm/app/main.js" "$@" +exec "@GJS@" -m "${bindir%/*}/ddterm/app/main.js" "$@" diff --git a/bin/meson.build b/bin/meson.build new file mode 100644 index 000000000..de0360602 --- /dev/null +++ b/bin/meson.build @@ -0,0 +1,16 @@ +pack += configure_file( + input: 'com.github.amezin.ddterm.in', + output: '@BASENAME@', + configuration: gjs_config, + install: true, + install_dir: extension_dir / 'bin', + install_mode: 'rwxr-xr-x' +) + +launcher_installed = extension_dir / 'bin' / 'com.github.amezin.ddterm' + +install_symlink( + 'com.github.amezin.ddterm', + pointing_to: launcher_installed, + install_dir: bindir, +) diff --git a/bump-version.sh b/bump-version.sh index 2804ce5d9..d8a922192 100755 --- a/bump-version.sh +++ b/bump-version.sh @@ -4,14 +4,11 @@ set -ex command -V jq -CURRENT_VERSION=$(jq .version metadata.json.in) +CURRENT_VERSION=$(meson rewrite kwargs info project / 2>&1 | jq -r '.kwargs."project#/".version') NEXT_VERSION=$(( ${CURRENT_VERSION} + 1 )) -git tag v${CURRENT_VERSION} - -jq ".version=${NEXT_VERSION}" metadata.json.in > metadata.json.next -mv -f metadata.json.next metadata.json.in - +meson rewrite kwargs set project / version "${NEXT_VERSION}" sed -i "/^pkgver=/c\pkgver=${NEXT_VERSION}" PKGBUILD +git tag "v${CURRENT_VERSION}" git commit -m "[ci skip] Post-release version bump" metadata.json.in PKGBUILD diff --git a/ddterm/app/icons/meson.build b/ddterm/app/icons/meson.build new file mode 100644 index 000000000..f1163f76b --- /dev/null +++ b/ddterm/app/icons/meson.build @@ -0,0 +1,13 @@ +icon_files = files( + 'quotation-symbolic.svg', + 'regex-symbolic.svg', + 'uppercase-symbolic.svg', +) + +foreach icon_file : icon_files + pack += fs.copyfile( + icon_file, + install: true, + install_dir: extension_dir / 'ddterm' / 'app' / 'icons', + ) +endforeach diff --git a/ddterm/app/meson.build b/ddterm/app/meson.build new file mode 100644 index 000000000..96cabd877 --- /dev/null +++ b/ddterm/app/meson.build @@ -0,0 +1,49 @@ +app_js_files = files( + 'accellabel.js', + 'application.js', + 'appwindow.js', + 'dependencies.js', + 'extensiondbus.js', + 'gtktheme.js', + 'heapdump.js', + 'init.js', + 'main.js', + 'meta.js', + 'notebook.js', + 'pcre2.js', + 'prefsdialog.js', + 'resources.js', + 'search.js', + 'settings.js', + 'tablabel.js', + 'tcgetpgrp.js', + 'terminal.js', + 'terminalpage.js', + 'terminalsettings.js', + 'urldetect.js', + 'urldetect_patterns.js', + 'waitstatus.js' +) + +app_ui_files = files( + 'menus.ui', +) + +foreach app_file : app_js_files + app_ui_files + files('dependencies.json', 'style.css') + pack += fs.copyfile( + app_file, + install: true, + install_dir: extension_dir / 'ddterm' / 'app', + ) +endforeach + +subdir('icons') + +foreach app_ui_file : app_ui_files + test( + fs.parent(app_ui_file) / fs.name(app_ui_file), + gtk3_builder_tool, + args: ['validate', app_ui_file], + suite: ['gtk-builder-validate'], + ) +endforeach diff --git a/ddterm/meson.build b/ddterm/meson.build new file mode 100644 index 000000000..166919f70 --- /dev/null +++ b/ddterm/meson.build @@ -0,0 +1,62 @@ +ddterm_files = files( + 'com.github.amezin.ddterm.Extension.xml', + 'com.github.amezin.ddterm.HeapDump.xml', + 'com.github.amezin.ddterm.service.in', +) + +foreach ddterm_file : ddterm_files + pack += fs.copyfile( + ddterm_file, + install: true, + install_dir: extension_dir / 'ddterm', + ) +endforeach + +desktop_entry_untranslated = files('com.github.amezin.ddterm.desktop.in.in') + +pack += i18n.merge_file( + input: desktop_entry_untranslated, + output: '@BASENAME@', + po_dir: '../locale', + type: 'desktop', + install: true, + install_dir: extension_dir / 'ddterm', +) + +launcher_config = configuration_data() +launcher_config.set('LAUNCHER', launcher_installed) + +desktop_entry_final = i18n.merge_file( + input: configure_file( + input: desktop_entry_untranslated, + output: '@BASENAME@_configured', + configuration: launcher_config, + ), + output: '@BASENAME@', + po_dir: '../locale', + type: 'desktop', + install: true, + install_dir: applications_dir, +) + +configure_file( + input: 'com.github.amezin.ddterm.service.in', + output: '@BASENAME@', + configuration: launcher_config, + install: true, + install_dir: dbus_service_dir, +) + +subdir('app') +subdir('pref') +subdir('shell') +subdir('util') + +desktop_file_validate_tool = find_program('desktop-file-validate') + +test( + desktop_entry_final.full_path(), + desktop_file_validate_tool, + args: [desktop_entry_final], + suite: ['desktop-file-validate'], +) diff --git a/ddterm/pref/meson.build b/ddterm/pref/meson.build new file mode 100644 index 000000000..21175929d --- /dev/null +++ b/ddterm/pref/meson.build @@ -0,0 +1,31 @@ +pref_files = files( + 'adw.js', + 'animation.js', + 'behavior.js', + 'colors.js', + 'command.js', + 'compatibility.js', + 'panelicon.js', + 'positionsize.js', + 'scrolling.js', + 'shortcuts.js', + 'tabs.js', + 'text.js', + 'util.js', + 'widget.js', +) + +pref_copy_files = [] + +foreach pref_file : pref_files + pref_copy_files += fs.copyfile( + pref_file, + install: true, + install_dir: extension_dir / 'ddterm' / 'pref', + ) +endforeach + +pack += pref_copy_files + +subdir('ui') +subdir('test') diff --git a/ddterm/pref/test/meson.build b/ddterm/pref/test/meson.build new file mode 100644 index 000000000..c3b22d240 --- /dev/null +++ b/ddterm/pref/test/meson.build @@ -0,0 +1,18 @@ +pref_test_common_files = [ + fs.copyfile('common.js'), + pref_copy_files, + schema_copy, + schemas_compiled, +] + +run_target( + 'pref-gtk3-test', + command: [gjs, '-m', fs.copyfile('gtk3.js')], + depends: [pref_test_common_files, pref_ui_gtk3_files] +) + +run_target( + 'pref-gtk4-test', + command: [gjs, '-m', fs.copyfile('gtk4.js')], + depends: [pref_test_common_files, pref_ui_gtk4_files] +) diff --git a/ddterm/pref/ui/gtk3/meson.build b/ddterm/pref/ui/gtk3/meson.build new file mode 100644 index 000000000..558765427 --- /dev/null +++ b/ddterm/pref/ui/gtk3/meson.build @@ -0,0 +1,22 @@ +pref_ui_gtk3_files = [] + +foreach pref_ui_file: pref_ui_files + out_file = custom_target( + command: [output_capture, gtk3_builder_tool, 'simplify', '@INPUT@'], + input: pref_ui_file, + output: '@PLAINNAME@', + install: true, + install_dir: extension_dir / 'ddterm' / 'pref' / 'ui' / 'gtk3', + ) + + test( + out_file.full_path(), + gtk3_builder_tool, + args: ['validate', out_file], + suite: ['gtk-builder-validate'], + ) + + pref_ui_gtk3_files += out_file +endforeach + +pack += pref_ui_gtk3_files diff --git a/ddterm/pref/glade/3to4-fixup.xsl b/ddterm/pref/ui/gtk4/3to4-fixup.xsl similarity index 100% rename from ddterm/pref/glade/3to4-fixup.xsl rename to ddterm/pref/ui/gtk4/3to4-fixup.xsl diff --git a/ddterm/pref/ui/gtk4/meson.build b/ddterm/pref/ui/gtk4/meson.build new file mode 100644 index 000000000..6283f4739 --- /dev/null +++ b/ddterm/pref/ui/gtk4/meson.build @@ -0,0 +1,31 @@ +gtk4_builder_tool = find_program('gtk4-builder-tool') +xsltproc = find_program('xsltproc') + +pref_ui_gtk4_files = [] + +foreach pref_ui_file: pref_ui_files + fixup = custom_target( + command: [xsltproc, '-o', '@OUTPUT@', files('3to4-fixup.xsl'), '@INPUT@'], + input: pref_ui_file, + output: fs.stem(pref_ui_file) + '.fixup.ui', + ) + + out_file = custom_target( + command: [output_capture, gtk4_builder_tool, 'simplify', '--3to4', '@INPUT@'], + input: fixup, + output: fs.name(pref_ui_file), + install: true, + install_dir: extension_dir / 'ddterm' / 'pref' / 'ui' / 'gtk4', + ) + + pref_ui_gtk4_files += out_file + + test( + out_file.full_path(), + gtk4_builder_tool, + args: ['validate', out_file], + suite: ['gtk-builder-validate'], + ) +endforeach + +pack += pref_ui_gtk4_files diff --git a/ddterm/pref/ui/meson.build b/ddterm/pref/ui/meson.build new file mode 100644 index 000000000..2aefe6c7f --- /dev/null +++ b/ddterm/pref/ui/meson.build @@ -0,0 +1,25 @@ +pref_ui_files = files( + 'prefs-animation.ui', + 'prefs-behavior.ui', + 'prefs-colors.ui', + 'prefs-command.ui', + 'prefs-compatibility.ui', + 'prefs-panel-icon.ui', + 'prefs-position-size.ui', + 'prefs-scrolling.ui', + 'prefs-shortcuts.ui', + 'prefs-tabs.ui', + 'prefs-text.ui', +) + +foreach pref_ui_file: pref_ui_files + test( + fs.parent(pref_ui_file) / fs.name(pref_ui_file), + gtk3_builder_tool, + args: ['validate', pref_ui_file], + suite: ['gtk-builder-validate'], + ) +endforeach + +subdir('gtk3') +subdir('gtk4') diff --git a/ddterm/pref/glade/prefs-animation.ui b/ddterm/pref/ui/prefs-animation.ui similarity index 100% rename from ddterm/pref/glade/prefs-animation.ui rename to ddterm/pref/ui/prefs-animation.ui diff --git a/ddterm/pref/glade/prefs-behavior.ui b/ddterm/pref/ui/prefs-behavior.ui similarity index 100% rename from ddterm/pref/glade/prefs-behavior.ui rename to ddterm/pref/ui/prefs-behavior.ui diff --git a/ddterm/pref/glade/prefs-colors.ui b/ddterm/pref/ui/prefs-colors.ui similarity index 100% rename from ddterm/pref/glade/prefs-colors.ui rename to ddterm/pref/ui/prefs-colors.ui diff --git a/ddterm/pref/glade/prefs-command.ui b/ddterm/pref/ui/prefs-command.ui similarity index 100% rename from ddterm/pref/glade/prefs-command.ui rename to ddterm/pref/ui/prefs-command.ui diff --git a/ddterm/pref/glade/prefs-compatibility.ui b/ddterm/pref/ui/prefs-compatibility.ui similarity index 100% rename from ddterm/pref/glade/prefs-compatibility.ui rename to ddterm/pref/ui/prefs-compatibility.ui diff --git a/ddterm/pref/glade/prefs-panel-icon.ui b/ddterm/pref/ui/prefs-panel-icon.ui similarity index 100% rename from ddterm/pref/glade/prefs-panel-icon.ui rename to ddterm/pref/ui/prefs-panel-icon.ui diff --git a/ddterm/pref/glade/prefs-position-size.ui b/ddterm/pref/ui/prefs-position-size.ui similarity index 100% rename from ddterm/pref/glade/prefs-position-size.ui rename to ddterm/pref/ui/prefs-position-size.ui diff --git a/ddterm/pref/glade/prefs-scrolling.ui b/ddterm/pref/ui/prefs-scrolling.ui similarity index 100% rename from ddterm/pref/glade/prefs-scrolling.ui rename to ddterm/pref/ui/prefs-scrolling.ui diff --git a/ddterm/pref/glade/prefs-shortcuts.ui b/ddterm/pref/ui/prefs-shortcuts.ui similarity index 100% rename from ddterm/pref/glade/prefs-shortcuts.ui rename to ddterm/pref/ui/prefs-shortcuts.ui diff --git a/ddterm/pref/glade/prefs-tabs.ui b/ddterm/pref/ui/prefs-tabs.ui similarity index 100% rename from ddterm/pref/glade/prefs-tabs.ui rename to ddterm/pref/ui/prefs-tabs.ui diff --git a/ddterm/pref/glade/prefs-text.ui b/ddterm/pref/ui/prefs-text.ui similarity index 100% rename from ddterm/pref/glade/prefs-text.ui rename to ddterm/pref/ui/prefs-text.ui diff --git a/ddterm/shell/meson.build b/ddterm/shell/meson.build new file mode 100644 index 000000000..26b0863c3 --- /dev/null +++ b/ddterm/shell/meson.build @@ -0,0 +1,24 @@ +shell_files = files( + 'appcontrol.js', + 'dbusapi.js', + 'extension.js', + 'geometry.js', + 'install.js', + 'notifications.js', + 'packagekit.js', + 'panelicon.js', + 'sd_journal.js', + 'service.js', + 'subprocess.js', + 'windowmatch.js', + 'wlclipboard.js', + 'wm.js', +) + +foreach shell_file : shell_files + pack += fs.copyfile( + shell_file, + install: true, + install_dir: extension_dir / 'ddterm' / 'shell', + ) +endforeach diff --git a/ddterm/util/meson.build b/ddterm/util/meson.build new file mode 100644 index 000000000..a5d133d28 --- /dev/null +++ b/ddterm/util/meson.build @@ -0,0 +1,11 @@ +util_files = files( + 'displayconfig.js', +) + +foreach util_file : util_files + pack += fs.copyfile( + util_file, + install: true, + install_dir: extension_dir / 'ddterm' / 'util', + ) +endforeach diff --git a/docs/BUILD.md b/docs/BUILD.md index 6afb37a17..9680e9455 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -9,20 +9,15 @@ GitHub UI provides multiple options for downloading the source code as a `.zip` (or, sometimes, `.tar.gz`) archive - for releases, and arbitrary commits. -# 2. Working directory +# 2. Set up the build environment -`cd` into the source code directory. All the following commands should be run -there. - - $ cd gnome-shell-extension-ddterm - -# 3. Setup the build environment - -## 3.a) Install the necessary dependencies +## 2.a) Install the necessary dependencies To build the extension package, you should have the following tools installed: -- GNU `make` +- [Meson build system](https://mesonbuild.com/) - available as a package named +`meson` in multiple distributions. It automatically brings in a tool called +[`ninja`](https://ninja-build.org/) (package `ninja-build`) and Python 3. - `gtk-builder-tool` (`libgtk-3-bin` package on Ubuntu, `gtk3-devel` on Fedora, `gtk3` package on Arch) @@ -36,82 +31,92 @@ on Fedora, `gtk4` package on Arch) - `zip` -## 3.b) Build in a container +## 2.b) Build in a container Alternatively, you can use `docker` or `podman` to perform build steps in a container - the same image/environment that's used by the CI system. To do it, run build command with `./do-in-docker.sh` or `./do-in-podman.sh` wrapper: - $ ./do-in-docker.sh make pack + $ ./do-in-docker.sh meson setup build-dir + +# 3. Build the package + +To build the package, `cd` into the directory with the source code: -# 4. `make pack` + $ cd gnome-shell-extension-ddterm + +and run the following commands: -To build the package, run `make pack`: + $ meson setup build-dir + $ ninja -C build-dir pack - $ make pack +Meson puts all built/generated files into a separate directory, in this document +it will be `build-dir`. If you want to build in a docker/podman container, prepend `./do-in-docker.sh`/ `./do-in-podman.sh`: - $ ./do-in-docker.sh make pack + $ ./do-in-docker.sh meson setup build-dir + $ ./do-in-docker.sh ninja -C build-dir pack + +After these steps, you should have the package: +`build-dir/ddterm@amezin.github.com.shell-extension.zip`. -# 5. Install the package +If the process fails, please double-check that you have all the dependencies +(2.a) installed. + +# 4. Install the package The installation process is described in [INSTALL.md - continue from step 2](INSTALL.md#2-install-the-package). -Alternatively, you could use `make` to install the package too. +Alternatively, you could use `meson`/`ninja` to install the package too - +but only if you didn't use containers for the build. -## 5.1. `make install` +## 4.1.a) `meson install` -To install the package, run: +You should never run `meson install` with `./run-in-docker.sh` or +`./run-in-podman.sh`. If build has been performed in the container, +installation on the host system through `meson install` will fail. - $ make install +You may run `meson install` under `sudo` to install the package system-wide +(to `/usr/share/gnome-shell/extensions`): -You should never run `make install` with `./run-in-docker.sh` or -`./run-in-podman.sh`. You want the extension installed on your host system, not -in the container. + $ sudo meson install -C build-dir -You could run `make install` under `sudo` to install the package system-wide -(to `/usr/share/gnome-shell/extensions`): +Or, the same command with ninja: - $ sudo make install + $ ninja -C build-dir install + +Installed files can be removed with the following command: + + $ ninja -C build-dir uninstall However, `sudo` installation is not recommended. Instead, you should build and -use OS-specific packages (`.deb`, `.rpm`). `make DESTDIR=... install` should -work fine in DEB and RPM build scripts. +use OS-specific packages (`.deb`, `.rpm`). `meson install ... --destdir ...` +should work fine in DEB and RPM build scripts. See Arch Linux +[PKGBUILD](/PKGBUILD) for example. + +## 4.1.b) `user-install` -There are explicit targets for system-wide and user installation: +The following command builds the package, if necessary, and installs it +inside user's `$HOME` directory (i.e. typical install location for extensions): - $ make user-install - $ sudo make system-install + $ ninja -C build-dir user-install -`make install` just switches between them according to the current uid. +The extension can be uninstalled using the following command: -## 5.2. Restart GNOME Shell + $ ninja -C build-dir user-install + +## 4.2. Restart GNOME Shell Described in [INSTALL.md - step 3](INSTALL.md#3-restart-gnome-shell). -## 5.3. Enable the extension +## 4.3. Enable the extension You can enable the extension as described in [INSTALL.md - step 4](INSTALL.md#4-enable-the-extension), or by running: - $ make enable + $ ninja -C build-dir enable You'll have to perform this step only once. - -# `make develop` - -Instead of building and installing the package, you can simply symlink the -repository into GNOME Shell's extensions directory. `make develop` can do it -for you: - - $ git clone https://github.com/ddterm/gnome-shell-extension-ddterm.git - $ cd gnome-shell-extension-ddterm - $ make develop - -`make develop` replaces steps 5 and 6.1, but you still have to restart GNOME -Shell afterwards, and enable the extension if you didn't. - -`make develop` may be more convenient when you're developing/modifying the code. diff --git a/docs/Test.md b/docs/Test.md index 0d08842b4..4d14819ea 100644 --- a/docs/Test.md +++ b/docs/Test.md @@ -28,11 +28,20 @@ Or to do both at the same time: ### Run tests - $ tox [--sitepackages] -- + $ tox [--sitepackages] -- [--pack=path] -Without `--sitepackages` you'll have to install PyGObject's build dependencies. +Before running tests, you need to [build the extension package](/docs/BUILD.md). -Options: +You either have to specify: + + `--pack=path/to/built/ddterm@amezin.github.com.shell-extension.zip` + +or run tox from `meson devenv -C build-dir` shell. + +Without `--sitepackages` you'll have to install PyGObject's build dependencies, +and PyGObject will be automatically built from source by `tox`. + +#### Other options: `--image=IMAGE` - run tests using the specified container image `IMAGE`. Can be repeated multiple times to run tests with multiple images. @@ -43,8 +52,6 @@ with multiple images. `--screenshot-failing-only` - capture screenshots only for failing tests. -`--pack=PACK` - install ddterm from the specified `PACK` package file. - `-n numprocesses` - run `numprocesses` parallel test processes. If no options are specified, reasonable defaults are used. diff --git a/docs/Translations.md b/docs/Translations.md index b2d800d6d..af92b0d44 100644 --- a/docs/Translations.md +++ b/docs/Translations.md @@ -11,9 +11,8 @@ a pull request on GitHub. ## Other tools -CI system automatically upates `.pot` and `.po` files using -[`update-pot.sh`](/po/update-pot.sh) script, so there should be no need to run -it manually. +CI system automatically adds new strings to `.pot` and `.po` files, using +`msgmerge` build target. There should be no need to run it manually. You can add/edit a `.po` file with the tool of your choice and create a pull request. diff --git a/docs/Vagrant.md b/docs/Vagrant.md index 80d609322..b03afabe9 100644 --- a/docs/Vagrant.md +++ b/docs/Vagrant.md @@ -24,18 +24,24 @@ QEMU/libvirt VMs use SPICE for display. So you'll have to install ddterm will be installed into the VM from the extension package. So if you haven't built the package yet, you'll need to do so: - $ make pack + $ meson setup build-dir + $ ninja -C build-dir pack Then: - $ vagrant up ubuntu2204 + $ meson devenv -C build-dir -w . vagrant up fedora39 -will start Ubuntu 22.04 VirtualBox VM, install the necessary packages -(primarily GNOME Shell with dependencies), and will install ddterm into the VM. +will start Fedora 39 VM, install the necessary packages (primarily GNOME Shell +with dependencies), and will install ddterm into the VM. + +Instead of prefixing `vagrant` command with `meson devenv ...` every time, +it's possible to just run `meson devenv -C build-dir` once. It will start a new +shell with all necessary environment variables, and raw `vagrant` commands will +work in that shell without additional setup. If you prefer QEMU, pass `--provider=libvirt` to `vagrant up`: - $ vagrant up --provider=libvirt ubuntu2204 + $ meson devenv -C build-dir -w . vagrant up --provider=libvirt fedora39 Then connect to the VM using `virt-manager`. VMs are started in user session, so if you can't find the VM in `virt-manager`, click @@ -49,11 +55,11 @@ session by default. If you've made some changes to ddterm sources, and want to test them, rebuild the package: - $ make pack + $ ninja -C build-dir pack and reinstall it: - $ vagrant provision --provision-with deploy ubuntu2204 + $ meson devenv -C build-dir -w . vagrant provision --provision-with deploy fedora39 GNOME Shell session in the VM will automatically be terminated, you'll have to login again - because GNOME Shell can't reload extensions without a complete @@ -61,7 +67,7 @@ restart. You may omit `--provision-with deploy`: - $ vagrant provision --provision-with deploy ubuntu2204 + $ meson devenv -C build-dir -w . vagrant provision fedora39 but the process might take longer in this case, because Ansible will try to upgrade OS packages. diff --git a/locale b/locale new file mode 120000 index 000000000..1664e9e3b --- /dev/null +++ b/locale @@ -0,0 +1 @@ +po \ No newline at end of file diff --git a/meson.build b/meson.build new file mode 100644 index 000000000..72e11eecb --- /dev/null +++ b/meson.build @@ -0,0 +1,186 @@ +project( + 'ddterm', + version : '50', + meson_version : '>= 1.0.0', + license : 'GPL3+', + default_options : ['prefix=/usr'] +) + +gjs = find_program('gjs', version: '>=1.78.0') + +fs = import('fs') +i18n = import('i18n') + +uuid = 'ddterm@amezin.github.com' +gettext_domain = uuid +settings_schema = 'com.github.amezin.ddterm' + +prefix = get_option('prefix') +bindir = prefix / get_option('bindir') +datadir = prefix / get_option('datadir') + +extension_dir = datadir / 'gnome-shell' / 'extensions' / uuid +schema_dir = datadir / 'glib-2.0' / 'schemas' +applications_dir = datadir / 'applications' +dbus_service_dir = datadir / 'dbus-1' / 'services' + +pack = [] + +pack += fs.copyfile( + 'extension.js', + install: true, + install_dir: extension_dir +) + +pack += fs.copyfile( + 'prefs.js', + install: true, + install_dir: extension_dir +) + +pack += fs.copyfile('LICENSE') + +metadata = configuration_data() +metadata.set('version', meson.project_version()) +metadata.set_quoted('uuid', uuid) +metadata.set_quoted('gettext_domain', gettext_domain) +metadata.set_quoted('settings_schema', settings_schema) + +pack += configure_file( + input: 'metadata.json.in', + output: '@BASENAME@', + configuration: metadata, + install: true, + install_dir: extension_dir, +) + +output_capture = ['sh', '-c', 'exec >"$0" "$@"', '@OUTPUT@'] +need_git_version = fs.read('revision.txt.in').strip() == '$Format:%H$' + +git = find_program('git', disabler: true, required: need_git_version) + +if need_git_version + pack += custom_target( + command: [ + output_capture, + git, + '-C', + '@CURRENT_SOURCE_DIR@', + '--git-dir', + '.git', + 'rev-parse', + 'HEAD' + ], + output: 'revision.txt', + build_always_stale: true, + install: true, + install_dir: extension_dir, + ) +else + pack += fs.copyfile( + 'revision.txt.in', + 'revision.txt', + install: true, + install_dir: extension_dir, + ) +endif + +gjs_config = configuration_data() +gjs_config.set('GJS', gjs.full_path()) + +gtk3_builder_tool = find_program('gtk-builder-tool') + +subdir('bin') +subdir('schemas') +subdir('ddterm') +subdir('locale') + +pack_target = custom_target( + command: [ + 'tools' / 'makezip.py', '--output', '@OUTPUT@', '--relative-to', '@OUTDIR@', '--', '@INPUT@' + ], + input: pack, + output: f'@uuid@.shell-extension.zip', + build_by_default: true, +) + +alias_target('pack', pack_target) + +meson.add_devenv({'DDTERM_BUILT_PACK': pack_target.full_path()}) + +extensions_tool = find_program('gnome-extensions', required: false, disabler: true) + +run_target( + 'user-install', + command: [extensions_tool, 'install', '-f', pack_target], +) + +run_target('user-uninstall', command: [extensions_tool, 'uninstall', uuid]) + +foreach target: ['prefs', 'enable', 'disable', 'reset'] + run_target(target, command: [extensions_tool, target, uuid]) +endforeach + +gapplication_tool = find_program( + 'gapplication', + required: false, + disabler: true, +) + +foreach target: ['toggle', 'quit'] + run_target(target, command: [gapplication_tool, 'action', 'com.github.amezin.ddterm', target]) +endforeach + +npm_tool = find_program('npm', required: false, disabler: true) + +if meson.version().version_compare('>=1.3.0') + ignore_dir = fs.relative_to( + meson.current_build_dir(), + meson.current_source_dir(), + ) +else + ignore_dir = run_command( + 'python3', + '-c', + 'import os.path; import sys; print(os.path.relpath(*sys.argv[1:]))', + meson.current_build_dir(), + meson.current_source_dir(), + capture: true, + check: true, + ).stdout().strip() +endif + +npm_install_stamp = meson.current_build_dir() / 'npm-install' +npm_env = {'DDTERM_POST_INSTALL_STAMP': npm_install_stamp} +meson.add_devenv(npm_env) + +npm_install = custom_target( + command: [npm_tool, '-C', '@CURRENT_SOURCE_DIR@', 'install'], + output: fs.name(npm_install_stamp), + depend_files: files('package.json', 'package-lock.json'), + console: true, + env: npm_env, +) + +eslint_extra_args = ['--ignore-pattern', ignore_dir] + +run_target( + 'eslint', + command: [npm_tool, '-C', '@CURRENT_SOURCE_DIR@', 'run-script', '--', 'lint'] + eslint_extra_args, + depends: npm_install, +) + +run_target( + 'eslint-fix', + command: [npm_tool, '-C', '@CURRENT_SOURCE_DIR@', 'run-script', '--', 'lint:fix'] + eslint_extra_args, + depends: npm_install, +) + +test( + 'eslint', + npm_tool, + args: ['run-script', '--', 'lint'] + eslint_extra_args, + depends: npm_install, + workdir: meson.current_source_dir(), + suite: ['eslint'], +) diff --git a/metadata.json.in b/metadata.json.in index 9fed1eaa5..e5613f75c 100644 --- a/metadata.json.in +++ b/metadata.json.in @@ -1,12 +1,12 @@ { "name": "ddterm", "description": "Another drop down terminal extension for GNOME Shell. With tabs. Works on Wayland natively", - "uuid": "ddterm@amezin.github.com", - "gettext-domain": "ddterm@amezin.github.com", - "settings-schema": "com.github.amezin.ddterm", + "uuid": @uuid@, + "gettext-domain": @gettext_domain@, + "settings-schema": @settings_schema@, "shell-version": [ "45" ], - "version": 50, + "version": @version@, "url": "https://github.com/ddterm/gnome-shell-extension-ddterm" } diff --git a/package-lock.json b/package-lock.json index ca30551fa..37764d699 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "name": "gnome-shell-extension-ddterm", + "hasInstallScript": true, "devDependencies": { "eslint": "8.56.0", "eslint-formatter-checkstyle": "^8.40.0", diff --git a/package.json b/package.json index d9a7253f8..8dc5d8e2e 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "scripts": { "lint": "eslint .", - "lint:fix": "eslint --fix ." + "lint:fix": "eslint --fix .", + "postinstall": "if [ -n \"$DDTERM_POST_INSTALL_STAMP\" ]; then touch \"$DDTERM_POST_INSTALL_STAMP\"; fi" } } diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 000000000..0ef2349be --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,35 @@ +ddterm/app/application.js +ddterm/app/appwindow.js +ddterm/app/dependencies.js +ddterm/app/menus.ui +ddterm/app/notebook.js +ddterm/app/prefsdialog.js +ddterm/app/search.js +ddterm/app/tablabel.js +ddterm/app/terminalpage.js +ddterm/com.github.amezin.ddterm.desktop.in.in +ddterm/pref/adw.js +ddterm/pref/animation.js +ddterm/pref/behavior.js +ddterm/pref/colors.js +ddterm/pref/command.js +ddterm/pref/compatibility.js +ddterm/pref/ui/prefs-animation.ui +ddterm/pref/ui/prefs-behavior.ui +ddterm/pref/ui/prefs-colors.ui +ddterm/pref/ui/prefs-command.ui +ddterm/pref/ui/prefs-compatibility.ui +ddterm/pref/ui/prefs-panel-icon.ui +ddterm/pref/ui/prefs-position-size.ui +ddterm/pref/ui/prefs-scrolling.ui +ddterm/pref/ui/prefs-shortcuts.ui +ddterm/pref/ui/prefs-tabs.ui +ddterm/pref/ui/prefs-text.ui +ddterm/pref/panelicon.js +ddterm/pref/positionsize.js +ddterm/pref/scrolling.js +ddterm/pref/shortcuts.js +ddterm/pref/tabs.js +ddterm/pref/text.js +ddterm/shell/notifications.js +ddterm/shell/panelicon.js diff --git a/po/gen-potfiles.py b/po/gen-potfiles.py new file mode 100755 index 000000000..6e4ae5c52 --- /dev/null +++ b/po/gen-potfiles.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +import os.path +import subprocess + + +PATTERNS = [ + ':/**/*.js', + ':/**/*.ui', + ':/**/*.desktop.in', + ':/**/*.desktop.in.in', + # exclude, just in case + ':!/test/', + ':!/tools/', +] + + +def check_file_translatable(filename, xgettext='xgettext', xgettext_args=('--from-code=UTF-8',)): + argv = [xgettext, *xgettext_args, '-o-', filename] + return subprocess.check_output(argv).strip() != b'' + + +def all_git_files(git='git', chdir=os.curdir): + argv = [git, '-C', chdir, 'ls-files', '-z', '--deduplicate', '--full-name', '--'] + PATTERNS + + return [ + os.fsdecode(filename) + for filename in subprocess.check_output(argv).split(b'\0') + if filename + ] + + +def get_toplevel(git='git', chdir=os.curdir): + argv = [git, '-C', chdir, 'rev-parse', '--show-toplevel'] + return os.fsdecode(subprocess.check_output(argv).rstrip(b'\n')) + + +def gen(output, git='git', xgettext='xgettext', chdir=os.curdir, xgettext_args=('--from-code=UTF-8',)): + toplevel = get_toplevel(git=git, chdir=chdir) + + content = sorted( + filename + for filename in all_git_files(git=git, chdir=chdir) + if check_file_translatable(os.path.join(toplevel, filename), xgettext=xgettext, xgettext_args=xgettext_args) + ) + + print(f'# This file is generated by {os.path.basename(__file__)}, do not edit', file=output) + + for line in content: + print(line, file=output) + + +def cli(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('-o', '--output', type=argparse.FileType('w')) + parser.add_argument('--git', default='git') + parser.add_argument('--xgettext', default='xgettext') + parser.add_argument('-C', dest='chdir', default=os.curdir) + parser.add_argument('xgettext_args', nargs='*', default=('--from-code=UTF-8',)) + + gen(**vars(parser.parse_args())) + + +if __name__ == '__main__': + cli() diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 000000000..6c2321ae7 --- /dev/null +++ b/po/meson.build @@ -0,0 +1,40 @@ +gettext_args = [ + '--from-code=UTF-8', + '--add-comments', + '--check=ellipsis-unicode', + '--check=space-ellipsis', + '--check=bullet-unicode', + # TODO: '--check=quote-unicode', +] + +gettext_targets = i18n.gettext( + gettext_domain, + args: gettext_args, + install: true, + install_dir: extension_dir / 'locale' +) + +alias_target('locales', gettext_targets[0]) +alias_target('pot', gettext_targets[1]) +alias_target('msgmerge', gettext_targets[2]) + +pack += gettext_targets[0] + +xgettext = find_program('xgettext', disabler: true, required: false) + +run_target( + 'potfiles', + command: [ + 'gen-potfiles.py', + '-C', + '@CURRENT_SOURCE_DIR@', + '--git', + git, + '--xgettext', + xgettext, + '-o', + '@CURRENT_SOURCE_DIR@' / 'POTFILES.in', + '--', + gettext_args + ] +) diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin deleted file mode 100644 index 2436c49e7..000000000 --- a/po/remove-potcdate.sin +++ /dev/null @@ -1,19 +0,0 @@ -# Sed script that remove the POT-Creation-Date line in the header entry -# from a POT file. -# -# The distinction between the first and the following occurrences of the -# pattern is achieved by looking at the hold space. -/^"POT-Creation-Date: .*"$/{ -x -# Test if the hold space is empty. -s/P/P/ -ta -# Yes it was empty. First occurrence. Remove the line. -g -d -bb -:a -# The hold space was nonempty. Following occurrences. Do nothing. -x -:b -} diff --git a/po/update-pot.sh b/po/update-pot.sh deleted file mode 100755 index 8a4da3514..000000000 --- a/po/update-pot.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -SCRIPT_DIR=$(CDPATH="" cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) -MAKEFILE_DIR="$SCRIPT_DIR/.." - -remove_potcdate() { - sed -f "$SCRIPT_DIR/remove-potcdate.sin" "$@" -} - -set -ex - -# Update .pot file(s), but keep existing POT-Creation-Date if nothing else changed - -for POTFILE in "$SCRIPT_DIR"/*.pot -do - mv "$POTFILE" "$POTFILE~" # backup - make -C "$MAKEFILE_DIR" "$(realpath --relative-to="$MAKEFILE_DIR" "$POTFILE")" - # Compare ignoring POT-Creation-Date - if diff <(remove_potcdate "$POTFILE~") <(remove_potcdate "$POTFILE") - then - mv "$POTFILE~" "$POTFILE" # restore old file if no changes - exit 0 - fi -done - -make -C "$MAKEFILE_DIR" msgmerge-fuzzy diff --git a/renovate.json b/renovate.json index 18e7f4135..0a11b854b 100644 --- a/renovate.json +++ b/renovate.json @@ -12,7 +12,7 @@ }, "regexManagers": [ { - "fileMatch": [".+\\.sh$"], + "fileMatch": [".+\\.sh$", "^\\.github/workflows/.+\\.ya?ml"], "matchStrings": [ "#\\s*renovate:\\s+datasource=(?[^\\s]+)\\s+depName=(?[^\\s]+)(\\s+(lookupName|packageName)=(?[^\\s]+))?(\\s+versioning=(?[^\\s]+))?\\n\\s*\\w+=[\"']?(?[^\\s\"']+)[\"']?(\\s|$)" ] diff --git a/schemas/meson.build b/schemas/meson.build new file mode 100644 index 000000000..2f0dfe006 --- /dev/null +++ b/schemas/meson.build @@ -0,0 +1,31 @@ +schema = files(f'@settings_schema@.gschema.xml') + +glib_compile_schemas_tool = find_program('glib-compile-schemas') + +schemas_compiled = custom_target( + command: [ + glib_compile_schemas_tool, + '--strict', + '--targetdir=@OUTDIR@', + '@CURRENT_SOURCE_DIR@' + ], + input: schema, + output: 'gschemas.compiled', +) + +test( + fs.parent(schema) / fs.name(schema), + glib_compile_schemas_tool, + args: ['--strict', '--dry-run', meson.current_source_dir()], + suite: ['glib-compile-schemas'], +) + +schema_copy = fs.copyfile( + schema, + install: true, + install_dir: schema_dir +) + +pack += schema_copy + +meson.add_install_script(glib_compile_schemas_tool, schema_dir, skip_if_destdir: true) diff --git a/test/conftest.py b/test/conftest.py index d2b1d1877..4f8fb667d 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,4 +1,5 @@ import json +import os import pathlib import re import subprocess @@ -37,10 +38,7 @@ def container_image(request): @pytest.fixture(scope='session') def extension_pack(request): - pack = request.config.getoption('--pack') - - if pack: - return pack.resolve() + return request.config.getoption('--pack').resolve() def pytest_addoption(parser): @@ -67,11 +65,14 @@ def pytest_addoption(parser): help='podman command/executable path' ) + pack_from_env = os.getenv('DDTERM_BUILT_PACK') + parser.addoption( '--pack', - default=None, + default=pathlib.Path(pack_from_env) if pack_from_env else None, + required=not pack_from_env, type=pathlib.Path, - help='install ddterm from the specified package file' + help='built ddterm extension package (ddterm@amezin.github.com.shell-extension.zip)', ) @@ -133,13 +134,8 @@ def syslog_server(tmp_path_factory, log_sync): @pytest.fixture(scope='session') def ddterm_metadata(extension_pack): - if extension_pack: - with zipfile.ZipFile(extension_pack) as z: - with z.open('metadata.json') as f: - return json.load(f) - - else: - with open(SRC_DIR / 'metadata.json', 'r') as f: + with zipfile.ZipFile(extension_pack) as z: + with z.open('metadata.json') as f: return json.load(f) @@ -157,11 +153,7 @@ def container_create_lock(request): @pytest.fixture(scope='session') def container_volumes(ddterm_metadata, test_metadata, extension_pack, tmp_path_factory): sys_install_dir = gnome_container.GnomeContainer.extensions_system_install_path() - - if extension_pack: - install_mount = (extension_pack, extension_pack, 'ro') - else: - install_mount = (SRC_DIR, sys_install_dir / ddterm_metadata['uuid'], 'ro') + install_mount = (extension_pack, extension_pack, 'ro') basetemp = tmp_path_factory.getbasetemp() basetemp.chmod(0o777) diff --git a/test/ddterm_fixtures.py b/test/ddterm_fixtures.py index 06608d7d3..5363e9cfb 100644 --- a/test/ddterm_fixtures.py +++ b/test/ddterm_fixtures.py @@ -28,9 +28,7 @@ def configure_session(self, container, request): super().configure_session(container, request) extension_pack = request.getfixturevalue('extension_pack') - - if extension_pack: - container.install_extension(extension_pack, timeout=self.START_STOP_TIMEOUT_SEC) + container.install_extension(extension_pack, timeout=self.START_STOP_TIMEOUT_SEC) @pytest.fixture(scope='class') def enable_ddterm_extension(self, shell_dbus_api, ddterm_metadata): diff --git a/test/tox.ini b/test/tox.ini index 3ac3dc946..a818e26fc 100644 --- a/test/tox.ini +++ b/test/tox.ini @@ -8,6 +8,7 @@ passenv = FORCE_COLOR GITHUB_ACTIONS PIP_DISABLE_PIP_VERSION_CHECK + DDTERM_BUILT_PACK deps = -r requirements.txt diff --git a/tools/makezip.py b/tools/makezip.py new file mode 100644 index 000000000..c1605c967 --- /dev/null +++ b/tools/makezip.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import argparse +import os.path +import zipfile + + +def makezip(output, inputs, relative_to): + with zipfile.ZipFile( + output, + mode='w', + compression=zipfile.ZIP_DEFLATED, + compresslevel=9, + ) as out: + for infile in inputs: + out.write(infile, arcname=os.path.relpath(infile, relative_to)) + + +def cli(*args, **kwargs): + parser = argparse.ArgumentParser() + parser.add_argument('--relative-to', default=os.curdir) + parser.add_argument('--output', required=True) + parser.add_argument('inputs', nargs='+') + + makezip(**vars(parser.parse_args(*args, **kwargs))) + + +if __name__ == '__main__': + cli() diff --git a/vagrant-provision/deploy.yml b/vagrant-provision/deploy.yml index 209245f07..98c9ef81a 100644 --- a/vagrant-provision/deploy.yml +++ b/vagrant-provision/deploy.yml @@ -1,17 +1,12 @@ --- - hosts: all vars: - extension_pack: "{{ query('ansible.builtin.fileglob', '../*.shell-extension.zip') }}" + extension_pack: "{{ lookup('ansible.builtin.env', 'DDTERM_BUILT_PACK') }}" pre_tasks: - ansible.builtin.assert: that: extension_pack - fail_msg: Extension package not found. Please run 'make pack' - quiet: yes - - - ansible.builtin.assert: - that: extension_pack | length <= 1 - fail_msg: Multiple extension packages found {{ extension_pack | join(', ') }} + fail_msg: Extension package not found. Please run Vagrant from `meson devenv` shell. quiet: yes handlers: @@ -29,7 +24,7 @@ - name: Upload extension package ansible.builtin.copy: - src: "{{ extension_pack[0] }}" + src: "{{ extension_pack }}" dest: "{{ upload_dir.path }}/" register: upload_pack