[gnome-system-monitor] build, ci: Add script for checking formatting and wire it up to Meson and GitLab CI



commit 4ca29e6d32a01ad7cb274d199c4448f867fe78b6
Author: Ondřej Míchal <harrymichal seznam cz>
Date:   Sat Aug 6 23:16:33 2022 +0200

    build, ci: Add script for checking formatting and wire it up to Meson and GitLab CI

 .gitlab-ci.yml |  18 ++++++++
 check-style.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 meson.build    |  22 ++++++++++
 3 files changed, 173 insertions(+)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4c454e20..633c4519 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,6 +2,7 @@
 # Tests against the latest libtop master version.
 
 stages:
+  - check
   - build
 
 variables:
@@ -45,6 +46,23 @@ variables:
     libxml2-dev
     meson
 
+# Based on https://gitlab.gnome.org/GNOME/mutter/-/blob/main/.gitlab-ci.yml
+check-code-style:
+  image: fedora:latest
+  stage: check
+  allow_failure: true
+  before_script:
+    - dnf install -y python3 git patch uncrustify
+  script:
+    - if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]]; then
+        git remote add target $CI_MERGE_REQUEST_PROJECT_URL.git;
+        git fetch target $CI_MERGE_REQUEST_TARGET_BRANCH_NAME;
+        export common_parent_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list 
--first-parent "target/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME") <(git rev-list --first-parent HEAD) | head -1);
+        ./check-style.py --dry-run --sha $common_parent_sha;
+      else
+        echo "Not a merge request";
+      fi
+
 build-fedora:
   image: fedora:latest
   stage: build
diff --git a/check-style.py b/check-style.py
new file mode 100755
index 00000000..0fc50d01
--- /dev/null
+++ b/check-style.py
@@ -0,0 +1,133 @@
+#!/bin/env python3
+
+# Based on https://gitlab.gnome.org/GNOME/mutter/-/blob/main/check-style.py
+
+import argparse
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+
+# Path relative to this script
+uncrustify_cfg = 'tools/gtk.cfg'
+
+
+def check_progs():
+    git = shutil.which('git')
+    patch = shutil.which('patch')
+    uncrustify = shutil.which('uncrustify')
+
+    return git is not None and uncrustify is not None and patch is not None
+
+
+def find_files(sha, all):
+    if all:
+        files = []
+        for dirpath, dirnames, filenames in os.walk('src'):
+            for filename in filenames:
+                files.append(os.path.join(dirpath, filename))
+    else:
+        proc = subprocess.Popen(
+            ["git", "diff", "--name-only", sha, "HEAD"],
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT)
+        files = proc.stdout.read().strip().decode('utf-8')
+        files = files.split('\n')
+
+    files_filtered = []
+    for file in files:
+        if file.endswith('.cpp') or file.endswith('.c') or file.endswith('.h'):
+            files_filtered.append(file)
+
+    return files_filtered
+
+
+def reformat_files(files, rewrite):
+    changed = None
+
+    for file in files:
+        # uncrustify chunk
+        proc = subprocess.Popen(
+            ["uncrustify", "-c", uncrustify_cfg, "-f", file],
+            stdout=subprocess.PIPE)
+        reformatted_raw = proc.stdout.readlines()
+        proc.wait()
+        if proc.returncode != 0:
+            continue
+
+        reformatted_tmp = tempfile.NamedTemporaryFile()
+        for line in reformatted_raw:
+            reformatted_tmp.write(line)
+        reformatted_tmp.seek(0)
+
+        if dry_run is True:
+            # Show changes
+            proc = subprocess.Popen(
+                ["diff", "-up", "--color=always", file, reformatted_tmp.name],
+                stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT)
+            diff = proc.stdout.read().decode('utf-8')
+            if diff != '':
+                output = re.sub('\t', '↦\t', diff)
+                print(output)
+                changed = True
+        else:
+            # Apply changes
+            diff = subprocess.Popen(
+                ["diff", "-up", file, reformatted_tmp.name],
+                stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT)
+            patch = subprocess.Popen(["patch", file], stdin=diff.stdout)
+            diff.stdout.close()
+            patch.communicate()
+
+        reformatted_tmp.close()
+
+    return changed
+
+
+parser = argparse.ArgumentParser(description='Check code style.')
+parser.add_argument('--all', type=bool,
+                    action=argparse.BooleanOptionalAction,
+                    help='Format all source files')
+parser.add_argument('--sha', metavar='SHA', type=str,
+                    help='SHA for the commit to compare HEAD with')
+parser.add_argument('--dry-run', '-d', type=bool,
+                    action=argparse.BooleanOptionalAction,
+                    help='Only print changes to stdout, do not change code')
+parser.add_argument('--rewrite', '-r', type=bool,
+                    action=argparse.BooleanOptionalAction,
+                    help='Whether to amend the result to the last commit (e.g. \'git rebase --exec "%(prog)s 
-r"\')')
+
+# Change CWD to script location, necessary for always locating the configuration file
+os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
+
+args = parser.parse_args()
+all = args.all
+sha = args.sha or 'HEAD^'
+rewrite = args.rewrite
+dry_run = args.dry_run
+
+if all and args.sha is not None:
+    print("Flags --all and --sha are mutualy exclusive")
+    sys.exit(1)
+
+if check_progs() is False:
+    print("Make sure git, patch and uncrustify are installed")
+    sys.exit(1)
+
+files = find_files(sha, all)
+changed = reformat_files(files, rewrite)
+
+if dry_run is not True and rewrite is True:
+    proc = subprocess.Popen(
+        ["git", "commit", "--all", "--amend", "-C", "HEAD"],
+        stdout=subprocess.DEVNULL)
+    sys.exit(0)
+elif dry_run is True and changed is True:
+    print("\nIssue the following command in your local tree to apply the suggested changes:\n\n $ git rebase 
origin/main --exec \"./check-style.py -r\" \n")
+    sys.exit(2)
+
+sys.exit(0)
diff --git a/meson.build b/meson.build
index 8284ae75..d5321de4 100644
--- a/meson.build
+++ b/meson.build
@@ -180,6 +180,28 @@ if desktop_validate.found()
   )
 endif
 
+################################################################################
+# Tests
+
+python3 = find_program('python3', required: false)
+git = find_program('git', required: false)
+patch = find_program('patch', required: false)
+uncrustify = find_program('uncrustify', required: false)
+
+check_style_file = files('check-style.py')
+check_style_prog = find_program(check_style_file)
+
+if python3.found() and git.found() and patch.found() and uncrustify.found()
+  test('code formatting',
+    check_style_prog,
+    args: ['--all', '--dry-run'],
+    suite: 'formatting',
+  )
+else
+  message('Code formatting test requires: python3, git, patch, uncrustify')
+endif
+
+
 ################################################################################
 # Subdirectories
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]