From 7d849ffdf43b630c47d887d0dfd0104b99aa232b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Tue, 19 Aug 2025 12:28:44 +0200 Subject: [PATCH] Add checks for Blueprint files To the pre-commit checks, we add the checks about translatable strings, as well as the check about sorting in blp-resources.in. We also run `blueprint-compiler format` in CI to make sure that we have consistent formatting. --- .gitlab-ci.yml | 2 +- .gitlab-ci/{run_checks.yml => check.yml} | 11 +- hooks/checks.sh | 82 ++++++++++++- meson.build | 26 ++-- src/meson.build | 149 +++++++++++------------ 5 files changed, 173 insertions(+), 97 deletions(-) rename .gitlab-ci/{run_checks.yml => check.yml} (68%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3109016c..340b1a8b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ workflow: - if: $CI_COMMIT_BRANCH include: - - local: .gitlab-ci/run_checks.yml + - local: .gitlab-ci/check.yml - local: .gitlab-ci/build.yml - local: .gitlab-ci/test.yml - component: "gitlab.gnome.org/GNOME/citemplates/basic-deploy-docs@master" diff --git a/.gitlab-ci/run_checks.yml b/.gitlab-ci/check.yml similarity index 68% rename from .gitlab-ci/run_checks.yml rename to .gitlab-ci/check.yml index bfa6c408..fab145a1 100644 --- a/.gitlab-ci/run_checks.yml +++ b/.gitlab-ci/check.yml @@ -2,16 +2,16 @@ include: '.gitlab-ci/utils.yml' -# Custom checks and lints -checks: +# Checks from the pre-commit hook +pre-commit-checks: stage: check image: "rustlang/rust:nightly-slim" interruptible: true script: - hooks/checks.sh --verbose --force-install -# Lint the code -cargo-clippy: +# Checks needing dependencies in the Flatpak runtime +flatpak-checks: extends: - .remove_build_only_modules stage: check @@ -21,4 +21,7 @@ cargo-clippy: interruptible: true script: - flatpak-builder --keep-build-dirs --user --disable-rofiles-fuse --stop-at=${FLATPAK_MODULE} flatpak_app --repo=repo ${BRANCH:+--default-branch=$BRANCH} ${MANIFEST_PATH} + # Lint the Rust code - echo "cargo clippy -- -D warnings" | flatpak-builder --disable-rofiles-fuse --build-shell=${FLATPAK_MODULE} flatpak_app ${MANIFEST_PATH} + # Lint the Blueprint files + - echo "blueprint-compiler format ../src" | flatpak-builder --disable-rofiles-fuse --build-shell=${FLATPAK_MODULE} flatpak_app ${MANIFEST_PATH} diff --git a/hooks/checks.sh b/hooks/checks.sh index d406d6c3..1d51f62a 100755 --- a/hooks/checks.sh +++ b/hooks/checks.sh @@ -437,6 +437,8 @@ check_potfiles() { fi if [[ ${line:(-3):3} == '.ui' ]]; then ui_potfiles+=($line) + elif [[ ${line:(-4):4} == '.blp' ]]; then + blp_potfiles+=($line) elif [[ ${line:(-3):3} == '.rs' ]]; then rs_potfiles+=($line) fi @@ -458,6 +460,8 @@ check_potfiles() { fi if [[ ${line:(-3):3} == '.ui' ]]; then ui_skip+=($line) + elif [[ ${line:(-4):4} == '.blp' ]]; then + blp_skip+=($line) elif [[ ${line:(-3):3} == '.rs' ]]; then rs_skip+=($line) fi @@ -471,13 +475,16 @@ check_potfiles() { fi # Get UI files with 'translatable="yes"'. - ui_files=(`grep -lIr 'translatable="yes"' src/*`) + ui_files=(`grep -lIr --include=*.ui 'translatable="yes"' src`) + + # Get blueprint files with '_('. + blp_files=(`grep -lIr --include=*.blp '_(' src`) # Get Rust files with regex 'gettext(_f)?\('. - rs_files=(`grep -lIrE 'gettext(_f)?\(' src/*`) + rs_files=(`grep -lIrE --include=*.rs 'gettext(_f)?\(' src`) # Get Rust files with macros, regex 'gettext!\('. - rs_macro_files=(`grep -lIrE 'gettext!\(' src/*`) + rs_macro_files=(`grep -lIrE --include=*.rs 'gettext!\(' src`) # Remove common files to_diff1=("${ui_skip[@]}") @@ -492,6 +499,18 @@ check_potfiles() { ui_potfiles=("${to_diff1[@]}") ui_files=("${to_diff2[@]}") + to_diff1=("${blp_skip[@]}") + to_diff2=("${blp_files[@]}") + diff + blp_skip=("${to_diff1[@]}") + blp_files=("${to_diff2[@]}") + + to_diff1=("${blp_potfiles[@]}") + to_diff2=("${blp_files[@]}") + diff + blp_potfiles=("${to_diff1[@]}") + blp_files=("${to_diff2[@]}") + to_diff1=("${rs_skip[@]}") to_diff2=("${rs_files[@]}") diff @@ -504,7 +523,7 @@ check_potfiles() { rs_potfiles=("${to_diff1[@]}") rs_files=("${to_diff2[@]}") - potfiles_count=$((${#ui_potfiles[@]} + ${#rs_potfiles[@]})) + potfiles_count=$((${#ui_potfiles[@]} + ${#blp_potfiles[@]} + ${#rs_potfiles[@]})) if [[ $potfiles_count -eq 1 ]]; then echo "" echo -e "$error Found 1 file in POTFILES.in without translatable strings:" @@ -517,11 +536,14 @@ check_potfiles() { for file in ${ui_potfiles[@]}; do echo $file done + for file in ${blp_potfiles[@]}; do + echo $file + done for file in ${rs_potfiles[@]}; do echo $file done - let files_count=$((${#ui_files[@]} + ${#rs_files[@]})) + let files_count=$((${#ui_files[@]} + ${#blp_files[@]} + ${#rs_files[@]})) if [[ $files_count -eq 1 ]]; then echo "" echo -e "$error Found 1 file with translatable strings not present in POTFILES.in:" @@ -534,6 +556,9 @@ check_potfiles() { for file in ${ui_files[@]}; do echo $file done + for file in ${blp_files[@]}; do + echo $file + done for file in ${rs_files[@]}; do echo $file done @@ -616,6 +641,45 @@ check_resources() { fi } +# Check if files in blp-resources.in are sorted alphabetically. +check_blp_resources() { + echo -e "$Checking blp-resources.in…" + + local ret=0 + local files=() + + # Get files. + while read -r line; do + if [[ -n $line && ${line::1} != '#' ]]; then + if [[ ! -f "src/${line}" ]]; then + echo -e "$error File '$line' in blp-resources.in does not exist" + ret=1 + fi + files+=($line) + fi + done < src/blp-resources.in + + # Check sorted alphabetically + local to_sort=("${files[@]}") + sort + for i in ${!files[@]}; do + if [[ "${files[$i]}" != "${to_sort[$i]}" ]]; then + echo -e "$error Found file '${files[$i]#src/}' before '${to_sort[$i]#src/}' in blp-resources.in" + ret=1 + break + fi + done + + if [[ ret -eq 1 ]]; then + echo "" + echo -e " Checking blp-resources.in result: $fail" + echo "Please fix the above issues" + exit 1 + else + echo -e " Checking blp-resources.in result: $ok" + fi +} + # Install cargo-sort with cargo. install_cargo_sort() { echo -e "$Installing cargo-sort…" @@ -728,6 +792,14 @@ else check_resources "data/resources/resources.gresource.xml" fi echo "" +if [[ -n $staged_files ]]; then + if [[ $staged_files = *src/blp-resources.in* ]]; then + check_blp_resources + fi +else + check_blp_resources +fi +echo "" if [[ $git_staged -eq 1 ]]; then staged_files=`git diff --name-only --cached | xargs ls -d 2>/dev/null | grep src/ui-resources.gresource.xml` if [[ -z $staged_files ]]; then diff --git a/meson.build b/meson.build index 1d5a516e..331a63d9 100644 --- a/meson.build +++ b/meson.build @@ -47,10 +47,10 @@ if build_machine.system() == 'linux' dependency('libseccomp', version: '>= 2.5.0') endif -glib_compile_resources = find_program('glib-compile-resources', required: true) -glib_compile_schemas = find_program('glib-compile-schemas', required: true) -desktop_file_validate = find_program('desktop-file-validate', required: false) -appstreamcli = find_program('appstreamcli', required: false) +# When the `build-env` profile is used, we only want to set up the build +# environment for the sandbox, we will not try to compile the app, so we can +# remove some build steps. +build_env_only = get_option('profile') == 'build-env' cargo = find_program('cargo', required: true) cargo_version = run_command(cargo, '--version', check: true).stdout().strip() @@ -58,9 +58,16 @@ message(cargo_version) rustc_version = run_command('rustc', '--version', check: true).stdout().strip() message(rustc_version) -blueprint_compiler = find_program('blueprint-compiler', required: true) -blueprint_compiler_version = run_command('blueprint-compiler', '--version', check: true).stdout().strip() -message('blueprint-compiler ' + blueprint_compiler_version) +if not build_env_only + glib_compile_resources = find_program('glib-compile-resources', required: true) + glib_compile_schemas = find_program('glib-compile-schemas', required: true) + desktop_file_validate = find_program('desktop-file-validate', required: false) + appstreamcli = find_program('appstreamcli', required: false) + + blueprint_compiler = find_program('blueprint-compiler', required: true) + blueprint_compiler_version = run_command('blueprint-compiler', '--version', check: true).stdout().strip() + message('blueprint-compiler ' + blueprint_compiler_version) +endif prefix = get_option('prefix') bindir = prefix / get_option('bindir') @@ -72,11 +79,6 @@ iconsdir = datadir / 'icons' podir = meson.project_source_root() / 'po' gettext_package = meson.project_name() -# When the `build-env` profile is used, we only want to set up the build -# environment for the sandbox, we will not try to compile the app, so we can -# remove some build steps. -build_env_only = get_option('profile') == 'build-env' - if get_option('profile') == 'development' or build_env_only profile = 'Devel' application_id += '.Devel' diff --git a/src/meson.build b/src/meson.build index d01c4596..ac692dcc 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,47 +1,49 @@ -# Compile Blueprint resources -blp_files = [] -foreach line : fs.read('blp-resources.in').splitlines() - if not line.startswith('#') and line.strip() != '' - blp_files += line - endif -endforeach +if not build_env_only + # Compile Blueprint resources + blp_files = [] + foreach line : fs.read('blp-resources.in').splitlines() + if not line.startswith('#') and line.strip() != '' + blp_files += line + endif + endforeach -blueprints = custom_target( - 'blueprints', - input: blp_files, - output: '.', - command: [blueprint_compiler, 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'], -) + blueprints = custom_target( + 'blueprints', + input: blp_files, + output: '.', + command: [blueprint_compiler, 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'], + ) -# Populate the GResource file for the compiled Blueprint files dynamically, -# using the same file list -compiled_ui_files = '' -foreach file : blp_files - compiled_ui_files += '\n ' + file.replace('.blp', '.ui') + '' -endforeach -blp_resources_xml = configure_file( - input: 'blp-resources.gresource.xml.in', - output: 'blp-resources.gresource.xml', - configuration: { 'UI_FILES': compiled_ui_files } -) + # Populate the GResource file for the compiled Blueprint files dynamically, + # using the same file list + compiled_ui_files = '' + foreach file : blp_files + compiled_ui_files += '\n ' + file.replace('.blp', '.ui') + '' + endforeach + blp_resources_xml = configure_file( + input: 'blp-resources.gresource.xml.in', + output: 'blp-resources.gresource.xml', + configuration: { 'UI_FILES': compiled_ui_files } + ) -blp_resources = gnome.compile_resources( - 'blp-resources', - blp_resources_xml, - gresource_bundle: true, - install: true, - install_dir: pkgdatadir, - dependencies: [blueprints, blp_resources_xml], -) + blp_resources = gnome.compile_resources( + 'blp-resources', + blp_resources_xml, + gresource_bundle: true, + install: true, + install_dir: pkgdatadir, + dependencies: [blueprints, blp_resources_xml], + ) -# Compile UI resources -ui_resources = gnome.compile_resources( - 'ui-resources', - 'ui-resources.gresource.xml', - gresource_bundle: true, - install: true, - install_dir: pkgdatadir, -) + # Compile UI resources + ui_resources = gnome.compile_resources( + 'ui-resources', + 'ui-resources.gresource.xml', + gresource_bundle: true, + install: true, + install_dir: pkgdatadir, + ) +endif # Generate config.rs global_conf = configuration_data() @@ -64,7 +66,7 @@ run_command( check: true ) -# Build binary with cargo +# Cargo settings cargo_options = [ '--manifest-path', meson.project_source_root() / 'Cargo.toml' ] cargo_options += [ '--target-dir', meson.project_build_root() / 'src' ] @@ -79,31 +81,28 @@ endif cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home' ] -if build_env_only - depends = [] -else - depends = [resources, blp_resources, ui_resources] +if not build_env_only + # Build binary with cargo + custom_target( + 'cargo-build', + build_by_default: true, + build_always_stale: true, + output: meson.project_name(), + console: true, + install: true, + install_dir: bindir, + depends: [resources, blp_resources, ui_resources], + command: [ + 'env', + cargo_env, + cargo, 'build', + cargo_options, + '&&', + 'cp', 'src' / rust_target / meson.project_name(), '@OUTPUT@', + ] + ) endif -custom_target( - 'cargo-build', - build_by_default: true, - build_always_stale: true, - output: meson.project_name(), - console: true, - install: true, - install_dir: bindir, - depends: depends, - command: [ - 'env', - cargo_env, - cargo, 'build', - cargo_options, - '&&', - 'cp', 'src' / rust_target / meson.project_name(), '@OUTPUT@', - ] -) - # Build docs with rustdoc rustdoc_flags = ' '.join([ '-Zunstable-options', @@ -136,14 +135,14 @@ doc_deps = [ ] custom_target( - 'cargo-doc', - build_by_default: false, - build_always_stale: true, - output: 'doc', - console: true, - command: [ - 'env', cargo_env + doc_env, - cargo, 'doc', - cargo_options + doc_deps + ['--no-deps', '-Zrustdoc-map'] , - ], - ) + 'cargo-doc', + build_by_default: false, + build_always_stale: true, + output: 'doc', + console: true, + command: [ + 'env', cargo_env + doc_env, + cargo, 'doc', + cargo_options + doc_deps + ['--no-deps', '-Zrustdoc-map'] , + ], +)