mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 20:59:44 +00:00
hooks: use pre-commit to run all hooks
Migrate all the pre-commit and commit-msg hooks to use pre-commit (https://pre-commit.com/) Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5192>
This commit is contained in:
parent
4ad6d4f99d
commit
3213e641ec
12 changed files with 99 additions and 548 deletions
|
@ -15,6 +15,7 @@ include:
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- 'preparation'
|
- 'preparation'
|
||||||
|
- 'check'
|
||||||
- 'build'
|
- 'build'
|
||||||
- 'test'
|
- 'test'
|
||||||
# Use the resulting binaries
|
# Use the resulting binaries
|
||||||
|
@ -34,8 +35,7 @@ variables:
|
||||||
|
|
||||||
FEDORA_AMD64_SUFFIX: 'amd64/fedora'
|
FEDORA_AMD64_SUFFIX: 'amd64/fedora'
|
||||||
DEBIAN_AMD64_SUFFIX: 'amd64/debian'
|
DEBIAN_AMD64_SUFFIX: 'amd64/debian'
|
||||||
INDENT_AMD64_SUFFIX: 'amd64/gst-indent'
|
CHECKS_AMD64_SUFFIX: 'amd64/checks'
|
||||||
COMMITLINT_AMD64_SUFFIX: 'amd64/commitlint'
|
|
||||||
WINDOWS_AMD64_SUFFIX: 'amd64/windows'
|
WINDOWS_AMD64_SUFFIX: 'amd64/windows'
|
||||||
ABI_CHECK_AMD64_SUFFIX: 'amd64/abi-check'
|
ABI_CHECK_AMD64_SUFFIX: 'amd64/abi-check'
|
||||||
|
|
||||||
|
@ -200,41 +200,23 @@ debian amd64 docker:
|
||||||
# (which has faster network connectivity to the registry).
|
# (which has faster network connectivity to the registry).
|
||||||
tags: [ 'placeholder-job' ]
|
tags: [ 'placeholder-job' ]
|
||||||
|
|
||||||
.gst-indent image:
|
.checks image:
|
||||||
tags: [ 'placeholder-job' ]
|
tags: [ 'placeholder-job' ]
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: 'bookworm'
|
FDO_DISTRIBUTION_VERSION: 'bookworm'
|
||||||
FDO_REPO_SUFFIX: "$INDENT_AMD64_SUFFIX"
|
FDO_REPO_SUFFIX: "$CHECKS_AMD64_SUFFIX"
|
||||||
FDO_DISTRIBUTION_TAG: "$INDENT_TAG-$GST_UPSTREAM_BRANCH"
|
FDO_DISTRIBUTION_TAG: "$CHECKS_TAG-$GST_UPSTREAM_BRANCH"
|
||||||
FDO_DISTRIBUTION_PACKAGES: 'curl indent git findutils ca-certificates'
|
FDO_DISTRIBUTION_PACKAGES: 'curl git findutils ca-certificates python3-pip'
|
||||||
FDO_DISTRIBUTION_EXEC: 'ci/docker/indent/prepare.sh'
|
FDO_DISTRIBUTION_EXEC: 'bash ci/docker/checks/prepare.sh'
|
||||||
|
|
||||||
gst-indent amd64 docker:
|
checks amd64 docker:
|
||||||
extends:
|
extends:
|
||||||
- '.gst-indent image'
|
- '.checks image'
|
||||||
- '.fdo.container-build@debian'
|
- '.fdo.container-build@debian'
|
||||||
stage: 'preparation'
|
stage: 'preparation'
|
||||||
# Do not depend on the trigger, as we want to run indent always
|
# Do not depend on the trigger, as we want to run indent always
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
.commitlint image:
|
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
variables:
|
|
||||||
FDO_DISTRIBUTION_VERSION: '37'
|
|
||||||
FDO_REPO_SUFFIX: "$COMMITLINT_AMD64_SUFFIX"
|
|
||||||
FDO_DISTRIBUTION_TAG: "$LINT_TAG-$GST_UPSTREAM_BRANCH"
|
|
||||||
FDO_DISTRIBUTION_PACKAGES: 'python3-pip git'
|
|
||||||
FDO_DISTRIBUTION_EXEC: 'ci/docker/lint/prepare.sh'
|
|
||||||
FDO_USER: "ciuser"
|
|
||||||
|
|
||||||
commitlint docker:
|
|
||||||
extends:
|
|
||||||
- '.commitlint image'
|
|
||||||
- '.fdo.container-build@fedora'
|
|
||||||
stage: 'preparation'
|
|
||||||
# Do not depend on the trigger, as we want to run indent always
|
|
||||||
needs: []
|
|
||||||
|
|
||||||
windows amd64 docker:
|
windows amd64 docker:
|
||||||
stage: "preparation"
|
stage: "preparation"
|
||||||
timeout: '3h'
|
timeout: '3h'
|
||||||
|
@ -287,66 +269,26 @@ abi-check docker:
|
||||||
- 'fedora amd64 docker'
|
- 'fedora amd64 docker'
|
||||||
|
|
||||||
# ---- Preparation ----- #
|
# ---- Preparation ----- #
|
||||||
#
|
pre-commit checks:
|
||||||
# gst-indent!!
|
|
||||||
#
|
|
||||||
gst indent:
|
|
||||||
extends:
|
extends:
|
||||||
- '.gst-indent image'
|
- '.checks image'
|
||||||
- '.fdo.suffixed-image@debian'
|
- '.fdo.suffixed-image@fedora'
|
||||||
stage: 'preparation'
|
stage: 'check'
|
||||||
needs:
|
needs:
|
||||||
- job: 'gst-indent amd64 docker'
|
- job: 'checks amd64 docker'
|
||||||
artifacts: false
|
artifacts: false
|
||||||
script:
|
|
||||||
- ./scripts/check-format-c
|
|
||||||
- ./scripts/format-csharp --check
|
|
||||||
# We want both wraps to use the same version, overkill to create a separate job for this
|
|
||||||
- cmp subprojects/gtk-sharp.wrap subprojects/gstreamer-sharp/subprojects/gtk-sharp.wrap
|
|
||||||
rules:
|
|
||||||
- !reference [.upstream-branch-rules, rules]
|
|
||||||
- if: '$CI_PROJECT_NAMESPACE != "gstreamer" || $CI_COMMIT_BRANCH != $GST_UPSTREAM_BRANCH'
|
|
||||||
when: 'always'
|
|
||||||
|
|
||||||
rustfmt:
|
|
||||||
extends:
|
|
||||||
- '.fedora image'
|
|
||||||
- '.fdo.suffixed-image@fedora'
|
|
||||||
stage: 'preparation'
|
|
||||||
needs:
|
|
||||||
- "fedora amd64 docker"
|
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
script:
|
|
||||||
- export RUSTUP_HOME="/usr/local/rustup"
|
|
||||||
- export PATH="/usr/local/cargo/bin:$PATH"
|
|
||||||
- ./scripts/format-rust --check
|
|
||||||
rules:
|
|
||||||
- changes:
|
|
||||||
compare_to: "$GST_UPSTREAM_BRANCH"
|
|
||||||
paths:
|
|
||||||
- .gitlab-ci.yml
|
|
||||||
- .gitlab-image-tags.yml
|
|
||||||
- subprojects/gstreamer/**/*.rs
|
|
||||||
- subprojects/gst-examples/**/*.rs
|
|
||||||
- ci/**/*
|
|
||||||
- ./scripts/format-rust
|
|
||||||
|
|
||||||
commitlint:
|
|
||||||
extends:
|
|
||||||
- '.commitlint image'
|
|
||||||
- '.fdo.suffixed-image@fedora'
|
|
||||||
stage: 'preparation'
|
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: fetch
|
GIT_STRATEGY: fetch
|
||||||
GIT_DEPTH: 100
|
GIT_DEPTH: 100
|
||||||
needs:
|
PRE_COMMIT_HOME: '/cache/${CI_PROJECT_NAMESPACE}/pre-commit'
|
||||||
- job: 'commitlint docker'
|
RUSTUP_HOME: '/usr/local/rustup'
|
||||||
artifacts: false
|
before_script:
|
||||||
before_script:
|
git config --global --add safe.directory $CI_PROJECT_DIR
|
||||||
- git config --global --add safe.directory $CI_PROJECT_DIR
|
|
||||||
script:
|
script:
|
||||||
|
- export PATH="/usr/local/cargo/bin:$PATH"
|
||||||
- echo $CI_MERGE_REQUEST_DIFF_BASE_SHA
|
- echo $CI_MERGE_REQUEST_DIFF_BASE_SHA
|
||||||
- gitlint --commits $CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD
|
- gitlint --commits $CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD
|
||||||
|
- pre-commit run --show-diff-on-failure --from-ref $CI_MERGE_REQUEST_DIFF_BASE_SHA --to-ref HEAD
|
||||||
rules:
|
rules:
|
||||||
# Only run on MR as we need CI_MERGE_REQUEST_DIFF_BASE_SHA to know
|
# Only run on MR as we need CI_MERGE_REQUEST_DIFF_BASE_SHA to know
|
||||||
# what commits to check
|
# what commits to check
|
||||||
|
|
|
@ -9,9 +9,7 @@ variables:
|
||||||
|
|
||||||
DEBIAN_TAG: '2025-01-11.0'
|
DEBIAN_TAG: '2025-01-11.0'
|
||||||
|
|
||||||
INDENT_TAG: '2024-05-28.0'
|
CHECKS_TAG: '2025-01-22.0'
|
||||||
|
|
||||||
LINT_TAG: '2024-02-20.0'
|
|
||||||
|
|
||||||
ABI_CHECK_TAG: '2025-01-29.0'
|
ABI_CHECK_TAG: '2025-01-29.0'
|
||||||
|
|
||||||
|
|
27
.pre-commit-config.yaml
Normal file
27
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
fail_fast: false
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/jorisroovers/gitlint
|
||||||
|
rev: v0.19.1
|
||||||
|
hooks:
|
||||||
|
- id: gitlint-ci
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
# Use dotnet format installed on your machine
|
||||||
|
- id: dotnet-format
|
||||||
|
name: dotnet-format
|
||||||
|
language: system
|
||||||
|
files: ^subprojects/gstreamer-sharp/.*
|
||||||
|
entry: dotnet format subprojects/gstreamer-sharp/gstreamer-sharp.sln -v normal --include
|
||||||
|
types_or: ["c#", "vb"]
|
||||||
|
- id: gst-indent
|
||||||
|
name: gst-indent
|
||||||
|
language: python
|
||||||
|
entry: ./scripts/gst-indent.py
|
||||||
|
types_or: ["c"]
|
||||||
|
# The rust hook uses cargo fmt, which requires a Cargo.toml
|
||||||
|
# We use a local hook to run rustfmt directly
|
||||||
|
- id: rustfmt
|
||||||
|
name: rustfmt
|
||||||
|
language: system
|
||||||
|
entry: rustfmt --verbose --edition 2021
|
||||||
|
types_or: ["rust"]
|
|
@ -1,2 +1,4 @@
|
||||||
GStreamer Docker images
|
GStreamer Docker images
|
||||||
|
|
||||||
|
* `fedora`: main image used to build GStreamer
|
||||||
|
* `checks`: image with pre-commit and gitlint used in the check stage
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
# Install dotnet-format
|
# Install dotnet-format
|
||||||
apt update -yqq
|
apt update -yqq
|
||||||
apt install -y gnupg apt-transport-https
|
apt install -y gnupg apt-transport-https
|
||||||
|
@ -20,7 +21,9 @@ ln -s ~/.dotnet/tools/dotnet-format /usr/local/bin/dotnet-format
|
||||||
# Build and install gst-indent-1.0
|
# Build and install gst-indent-1.0
|
||||||
echo "deb-src http://deb.debian.org/debian/ bookworm main" >> /etc/apt/sources.list
|
echo "deb-src http://deb.debian.org/debian/ bookworm main" >> /etc/apt/sources.list
|
||||||
apt update
|
apt update
|
||||||
apt-get install --assume-yes devscripts build-essential dpkg-dev wget meson ninja-build
|
|
||||||
|
apt-get install --assume-yes devscripts build-essential dpkg-dev wget meson ninja-build pkg-config libssl-dev
|
||||||
|
|
||||||
apt-get build-dep --assume-yes indent
|
apt-get build-dep --assume-yes indent
|
||||||
|
|
||||||
git clone https://gitlab.freedesktop.org/gstreamer/gst-indent.git
|
git clone https://gitlab.freedesktop.org/gstreamer/gst-indent.git
|
||||||
|
@ -50,10 +53,42 @@ gst-indent-1.0 \
|
||||||
gstbayer2rgb.c
|
gstbayer2rgb.c
|
||||||
done;
|
done;
|
||||||
|
|
||||||
# clean up
|
# Clean up gst-indent
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf gst-indent
|
rm -rf gst-indent
|
||||||
|
|
||||||
apt-get remove --assume-yes devscripts build-essential dpkg-dev wget meson ninja-build
|
export PIP_BREAK_SYSTEM_PACKAGES=1
|
||||||
|
# Install pre-commit
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install pre-commit==3.6.0
|
||||||
|
|
||||||
|
# Install gitlint
|
||||||
|
python3 -m pip install gitlint
|
||||||
|
|
||||||
|
# Install Rust
|
||||||
|
RUSTUP_VERSION=1.27.1
|
||||||
|
RUST_VERSION=1.81.0
|
||||||
|
RUST_ARCH="x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
RUSTUP_URL=https://static.rust-lang.org/rustup/archive/$RUSTUP_VERSION/$RUST_ARCH/rustup-init
|
||||||
|
curl -o rustup-init $RUSTUP_URL
|
||||||
|
|
||||||
|
export RUSTUP_HOME="/usr/local/rustup"
|
||||||
|
export CARGO_HOME="/usr/local/cargo"
|
||||||
|
export PATH="/usr/local/cargo/bin:$PATH"
|
||||||
|
|
||||||
|
chmod +x rustup-init;
|
||||||
|
./rustup-init -y --no-modify-path --default-toolchain $RUST_VERSION;
|
||||||
|
rm rustup-init;
|
||||||
|
chmod -R a+w $RUSTUP_HOME $CARGO_HOME
|
||||||
|
|
||||||
|
cargo install cargo-c --version 0.10.4+cargo-0.82.0 --locked
|
||||||
|
|
||||||
|
rustup --version
|
||||||
|
cargo --version
|
||||||
|
rustc --version
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
apt-get remove --assume-yes devscripts build-essential dpkg-dev wget meson ninja-build pkg-config libssl-dev
|
||||||
apt-get remove --assume-yes libtext-unidecode-perl libxml-namespacesupport-perl libxml-sax-base-perl libxml-sax-perl libxml-libxml-perl texinfo
|
apt-get remove --assume-yes libtext-unidecode-perl libxml-namespacesupport-perl libxml-sax-base-perl libxml-sax-perl libxml-libxml-perl texinfo
|
||||||
apt-get autoremove --assume-yes
|
apt-get autoremove --assume-yes
|
|
@ -1,6 +0,0 @@
|
||||||
#! /bin/bash
|
|
||||||
|
|
||||||
set -eux
|
|
||||||
|
|
||||||
python3 -m pip install gitlint
|
|
||||||
|
|
12
meson.build
12
meson.build
|
@ -31,9 +31,7 @@ if cmdres.returncode() != 0
|
||||||
error('Do not run `ninja reconfigure` or `meson` for gst-build inside the development environment, you will run into problems')
|
error('Do not run `ninja reconfigure` or `meson` for gst-build inside the development environment, you will run into problems')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Install gst-indent pre-commit hook
|
# pre-commit hooks are not interactive so we use gitlint's hook to check commit messages
|
||||||
run_command(python3, '-c', 'import shutil; shutil.copy("scripts/git-hooks/multi-pre-commit.hook", ".git/hooks/pre-commit")', check: false)
|
|
||||||
|
|
||||||
gitlint_req = '>= 0.18'
|
gitlint_req = '>= 0.18'
|
||||||
gitlint = find_program('gitlint', version: gitlint_req, required: false)
|
gitlint = find_program('gitlint', version: gitlint_req, required: false)
|
||||||
if gitlint.found()
|
if gitlint.found()
|
||||||
|
@ -42,6 +40,14 @@ else
|
||||||
message('gitlint not found or too old, please install it with your package manager or `python3 -m pip install gitlint` to enable the commit message hook')
|
message('gitlint not found or too old, please install it with your package manager or `python3 -m pip install gitlint` to enable the commit message hook')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
pre_commit_req = '>= 3.6.0'
|
||||||
|
pre_commit = find_program('pre-commit', version: pre_commit_req, required: false)
|
||||||
|
if pre_commit.found()
|
||||||
|
run_command(pre_commit, 'install', '-f', check: true)
|
||||||
|
else
|
||||||
|
warning('pre-commit not found or too old, please install it with your package manager or `python3 -m pip install pre-commit`')
|
||||||
|
endif
|
||||||
|
|
||||||
# On macOS, you have to run "Install Certificates.command" otherwise Python
|
# On macOS, you have to run "Install Certificates.command" otherwise Python
|
||||||
# doesn't have access to the latest SSL CA Certificates, and Meson will fail to
|
# doesn't have access to the latest SSL CA Certificates, and Meson will fail to
|
||||||
# download wrap files from websites that use, for example, Let's Encrypt.
|
# download wrap files from websites that use, for example, Let's Encrypt.
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# Git pre-commit hook that runs multiple hooks specified in $HOOKS.
|
|
||||||
# Make sure this script is executable. Bypass hooks with git commit --no-verify.
|
|
||||||
|
|
||||||
# This file is inspired by a set of unofficial pre-commit hooks available
|
|
||||||
# at github.
|
|
||||||
# Link: https://github.com/githubbrowser/Pre-commit-hooks
|
|
||||||
# Contact: David Martin, david.martin.mailbox@googlemail.com
|
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
|
||||||
# SETTINGS:
|
|
||||||
# pre-commit hooks to be executed. They should be in the same .git/hooks/ folder
|
|
||||||
# as this script. Hooks should return 0 if successful and nonzero to cancel the
|
|
||||||
# commit. They are executed in the order in which they are listed.
|
|
||||||
###########################################################
|
|
||||||
|
|
||||||
HOOKS="scripts/git-hooks/pre-commit.hook scripts/git-hooks/pre-commit-invoke-python.hook"
|
|
||||||
|
|
||||||
# exit on error
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ "$GST_DISABLE_PRE_COMMIT_HOOKS" = "1" ]
|
|
||||||
then
|
|
||||||
echo "Pre-commits hooks disabled by env GST_DISABLE_PRE_COMMIT_HOOKS."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $PWD
|
|
||||||
|
|
||||||
for hook in $HOOKS
|
|
||||||
do
|
|
||||||
echo "Running hook: $hook"
|
|
||||||
# run hook if it exists
|
|
||||||
# if it returns with nonzero exit with 1 and thus abort the commit
|
|
||||||
if [ -f "$PWD/$hook" ]; then
|
|
||||||
"$PWD/$hook"
|
|
||||||
if [ $? != 0 ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Error: file $hook not found."
|
|
||||||
echo "Aborting commit. Make sure the hook is at $PWD/$hook and executable."
|
|
||||||
echo "You can disable it by removing it from the list"
|
|
||||||
echo "You can skip all pre-commit hooks with --no-verify (not recommended)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
PYTHON="python3"
|
echo "This hook is deprecated, please run 'meson setup' to update your configuration"
|
||||||
if [[ $OS =~ Windows ]]; then
|
|
||||||
if type -p py &>/dev/null; then
|
|
||||||
PYTHON="py -3"
|
|
||||||
elif type -p python &>/dev/null; then
|
|
||||||
PYTHON="python"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
$PYTHON "`dirname $0`/pre-commit-python.hook"
|
|
||||||
|
|
|
@ -1,233 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import json
|
|
||||||
import glob
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, Optional, Set, Tuple
|
|
||||||
|
|
||||||
NOT_PYCODESTYLE_COMPLIANT_MESSAGE_PRE = \
|
|
||||||
"Your code is not fully pycodestyle compliant and contains"\
|
|
||||||
" the following coding style issues:\n\n"
|
|
||||||
|
|
||||||
NOT_PYCODESTYLE_COMPLIANT_MESSAGE_POST = \
|
|
||||||
"Please fix these errors and commit again, you can do so "\
|
|
||||||
"from the root directory automatically like this, assuming the whole "\
|
|
||||||
"file is to be committed:"
|
|
||||||
|
|
||||||
NO_PYCODESTYLE_MESSAGE = \
|
|
||||||
"You should install the pycodestyle style checker to be able"\
|
|
||||||
" to commit in this repo.\nIt allows us to guarantee that "\
|
|
||||||
"anything that is committed respects the pycodestyle coding style "\
|
|
||||||
"standard.\nYou can install it:\n"\
|
|
||||||
" * on ubuntu, debian: $sudo apt-get install pycodestyle \n"\
|
|
||||||
" * on fedora: #yum install python3-pycodestyle \n"\
|
|
||||||
" * on arch: #pacman -S python-pycodestyle \n"\
|
|
||||||
" * or `pip install --user pycodestyle`"
|
|
||||||
|
|
||||||
|
|
||||||
def system(*args, **kwargs):
|
|
||||||
kwargs.setdefault('stdout', subprocess.PIPE)
|
|
||||||
proc = subprocess.Popen(args, **kwargs)
|
|
||||||
out, err = proc.communicate()
|
|
||||||
if isinstance(out, bytes):
|
|
||||||
out = out.decode()
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
def copy_files_to_tmp_dir(files):
|
|
||||||
tempdir = tempfile.mkdtemp()
|
|
||||||
for name in files:
|
|
||||||
filename = os.path.join(tempdir, name)
|
|
||||||
filepath = os.path.dirname(filename)
|
|
||||||
if not os.path.exists(filepath):
|
|
||||||
os.makedirs(filepath)
|
|
||||||
with open(filename, 'w', encoding="utf-8") as f:
|
|
||||||
system('git', 'show', ':' + name, stdout=f)
|
|
||||||
|
|
||||||
return tempdir
|
|
||||||
|
|
||||||
def find_builddir() -> Optional[Path]:
|
|
||||||
# Explicitly-defined builddir takes precedence
|
|
||||||
if 'GST_DOC_BUILDDIR' in os.environ:
|
|
||||||
return Path(os.environ['GST_DOC_BUILDDIR'])
|
|
||||||
|
|
||||||
# Now try the usual suspects
|
|
||||||
for name in ('build', '_build', 'builddir', 'b'):
|
|
||||||
if Path(name, 'build.ninja').exists():
|
|
||||||
return Path(name)
|
|
||||||
|
|
||||||
# Out of luck, look for the most recent folder with a `build.ninja` file
|
|
||||||
for d in sorted([p for p in Path('.').iterdir() if p.is_dir()], key=lambda p: p.stat().st_mtime):
|
|
||||||
if Path(d, 'build.ninja').exists():
|
|
||||||
print ('Found', d)
|
|
||||||
return d
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def hotdoc_conf_needs_rebuild(conf_path: Path, conf_data: Dict, modified_fpaths):
|
|
||||||
if not isinstance(conf_data, dict):
|
|
||||||
return False
|
|
||||||
|
|
||||||
for (key, value) in conf_data.items():
|
|
||||||
if key.endswith('c_sources'):
|
|
||||||
if any(['*' in f for f in value]):
|
|
||||||
continue
|
|
||||||
conf_dir = conf_path.parent
|
|
||||||
for f in value:
|
|
||||||
fpath = Path(f)
|
|
||||||
if not fpath.is_absolute():
|
|
||||||
fpath = Path(conf_dir, fpath)
|
|
||||||
|
|
||||||
fpath = fpath.resolve()
|
|
||||||
if fpath in modified_fpaths:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_hotdoc_confs_to_rebuild(builddir, modified_files) -> Tuple[Set, Set]:
|
|
||||||
srcdir = Path(os.getcwd())
|
|
||||||
modified_fpaths = set()
|
|
||||||
for f in modified_files:
|
|
||||||
modified_fpaths.add(Path(srcdir, f))
|
|
||||||
|
|
||||||
confs_need_rebuild = set()
|
|
||||||
caches_need_rebuild = set()
|
|
||||||
for path in glob.glob('**/docs/*.json', root_dir=builddir, recursive=True):
|
|
||||||
conf_path = Path(srcdir, builddir, path)
|
|
||||||
with open(conf_path) as f:
|
|
||||||
conf_data = json.load(f)
|
|
||||||
|
|
||||||
if hotdoc_conf_needs_rebuild(conf_path, conf_data, modified_fpaths):
|
|
||||||
confs_need_rebuild.add(conf_path)
|
|
||||||
caches_need_rebuild.add(conf_data.get('gst_plugin_library'))
|
|
||||||
|
|
||||||
return (confs_need_rebuild, caches_need_rebuild)
|
|
||||||
|
|
||||||
def build(builddir):
|
|
||||||
subprocess.run(['ninja', '-C', builddir], check=True)
|
|
||||||
for subproject in ('gstreamer', 'gst-plugins-base', 'gst-plugins-good', 'gst-plugins-bad', 'gst-plugins-ugly', 'gst-rtsp-server', 'gst-libav', 'gst-editing-services'):
|
|
||||||
subprocess.run(['ninja', '-C', builddir, f'subprojects/{subproject}/docs/hotdoc-configs.json'], check=True)
|
|
||||||
|
|
||||||
def build_cache(builddir, subproject, targets, subdir):
|
|
||||||
if not targets:
|
|
||||||
return
|
|
||||||
|
|
||||||
print (f'Rebuilding {subproject} cache with changes from {targets}')
|
|
||||||
|
|
||||||
cmd = [
|
|
||||||
os.path.join(builddir, f'subprojects/gstreamer/docs/gst-plugins-doc-cache-generator'),
|
|
||||||
os.path.join(os.getcwd(), f'subprojects/{subproject}/docs/{subdir}gst_plugins_cache.json'),
|
|
||||||
os.path.join(builddir, f'subprojects/{subproject}/docs/gst_plugins_cache.json'),
|
|
||||||
] + targets
|
|
||||||
|
|
||||||
subprocess.run(cmd)
|
|
||||||
|
|
||||||
class StashManager:
|
|
||||||
def __enter__(self):
|
|
||||||
print ('Stashing changes')
|
|
||||||
# First, save the difference with the current index to a patch file
|
|
||||||
tree = subprocess.run(['git', 'write-tree'], capture_output=True, check=True).stdout.strip()
|
|
||||||
result = subprocess.run(['git', 'diff-index', '--ignore-submodules', '--binary', '--no-color', '--no-ext-diff', tree], check=True, capture_output=True)
|
|
||||||
# Don't delete the temporary file, we want to make sure to prevent data loss
|
|
||||||
with tempfile.NamedTemporaryFile(delete_on_close=False, delete=False) as f:
|
|
||||||
f.write(result.stdout)
|
|
||||||
self.patch_file_name = f.name
|
|
||||||
|
|
||||||
# Print the path to the diff file, useful is something goes wrong
|
|
||||||
print ("unstaged diff saved to ", self.patch_file_name)
|
|
||||||
|
|
||||||
# Now stash the changes, we do not use git stash --keep-index because it causes spurious rebuilds
|
|
||||||
subprocess.run(['git', '-c', 'submodule.recurse=0', 'checkout', '--', '.'], check=True)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
# Now re-apply the non-staged changes
|
|
||||||
subprocess.run(['git', 'apply', '--allow-empty', self.patch_file_name], check=True)
|
|
||||||
print ('Unstashed changes')
|
|
||||||
|
|
||||||
def run_doc_checks(modified_files):
|
|
||||||
builddir = find_builddir()
|
|
||||||
|
|
||||||
if builddir is None:
|
|
||||||
raise Exception('cannot run doc pre-commit hook without a build directory')
|
|
||||||
|
|
||||||
builddir = builddir.absolute()
|
|
||||||
|
|
||||||
build(builddir)
|
|
||||||
|
|
||||||
# Each subproject holds its own cache file. For each we keep track of the
|
|
||||||
# dynamic library associated with the hotdoc configuration files that need
|
|
||||||
# rebuilding, and only update the caches using those libraries.
|
|
||||||
# This is done in order to minimize spurious diffs as much as possible.
|
|
||||||
caches = {}
|
|
||||||
|
|
||||||
(confs_need_rebuild, caches_need_rebuild) = get_hotdoc_confs_to_rebuild(builddir, modified_files)
|
|
||||||
|
|
||||||
for libpath in caches_need_rebuild:
|
|
||||||
cache_project = Path(libpath).relative_to(builddir).parts[1]
|
|
||||||
if cache_project not in caches:
|
|
||||||
caches[cache_project] = [libpath]
|
|
||||||
else:
|
|
||||||
caches[cache_project].append(libpath)
|
|
||||||
|
|
||||||
for (subproject, libpaths) in caches.items():
|
|
||||||
cache_subdir = 'plugins/' if subproject in ['gst-plugins-bad', 'gst-plugins-base', 'gst-rtsp-server', 'gstreamer', 'gst-plugins-rs'] else ''
|
|
||||||
build_cache(builddir, subproject, libpaths, cache_subdir)
|
|
||||||
|
|
||||||
try:
|
|
||||||
subprocess.run(['git', 'diff', '--ignore-submodules', '--exit-code'], check=True)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print ('You have a diff in the plugin cache, please commit it')
|
|
||||||
raise e
|
|
||||||
|
|
||||||
print ('No pending diff in plugin caches, checking since tags')
|
|
||||||
|
|
||||||
for conf_path in confs_need_rebuild:
|
|
||||||
subprocess.run(['hotdoc', 'run', '--fatal-warnings', '--disable-warnings', '--enabled-warnings', 'missing-since-marker', '--conf-file', conf_path, '--previous-symbol-index', 'subprojects/gst-docs/symbols/symbol_index.json'], check=True)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
modified_files = system('git', 'diff-index', '--cached',
|
|
||||||
'--name-only', 'HEAD', '--diff-filter=ACMR').split("\n")[:-1]
|
|
||||||
|
|
||||||
if os.environ.get('GST_ENABLE_DOC_PRE_COMMIT_HOOK', '0') != '0':
|
|
||||||
with StashManager():
|
|
||||||
try:
|
|
||||||
run_doc_checks(modified_files)
|
|
||||||
except Exception as e:
|
|
||||||
print (e)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
non_compliant_files = []
|
|
||||||
output_message = None
|
|
||||||
|
|
||||||
for modified_file in modified_files:
|
|
||||||
try:
|
|
||||||
if not modified_file.endswith(".py"):
|
|
||||||
continue
|
|
||||||
pycodestyle_errors = system('pycodestyle', '--repeat', '--ignore', 'E402,E501,E128,W605,W503', modified_file)
|
|
||||||
if pycodestyle_errors:
|
|
||||||
if output_message is None:
|
|
||||||
output_message = NOT_PYCODESTYLE_COMPLIANT_MESSAGE_PRE
|
|
||||||
output_message += pycodestyle_errors
|
|
||||||
non_compliant_files.append(modified_file)
|
|
||||||
except OSError as e:
|
|
||||||
output_message = NO_PYCODESTYLE_MESSAGE
|
|
||||||
break
|
|
||||||
|
|
||||||
if output_message:
|
|
||||||
print(output_message)
|
|
||||||
if non_compliant_files:
|
|
||||||
print(NOT_PYCODESTYLE_COMPLIANT_MESSAGE_POST)
|
|
||||||
for non_compliant_file in non_compliant_files:
|
|
||||||
print("autopep8 -i --max-line-length 120", non_compliant_file, "; git add ",
|
|
||||||
non_compliant_file)
|
|
||||||
print("git commit")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -3,121 +3,4 @@
|
||||||
# Check that the code follows a consistant code style
|
# Check that the code follows a consistant code style
|
||||||
#
|
#
|
||||||
|
|
||||||
# Check for existence of indent, and error out if not present.
|
echo "This hook is deprecated, please run 'meson setup' to update your configuration"
|
||||||
# On some *bsd systems the binary seems to be called gnunindent,
|
|
||||||
# so check for that first.
|
|
||||||
|
|
||||||
|
|
||||||
version=$(gst-indent-1.0 --version 2>/dev/null)
|
|
||||||
if test -z "$version"; then
|
|
||||||
version=$(gnuindent --version 2>/dev/null)
|
|
||||||
if test -z "$version"; then
|
|
||||||
version=$(gindent --version 2>/dev/null)
|
|
||||||
if test -z "$version"; then
|
|
||||||
version=$(indent --version 2>/dev/null)
|
|
||||||
if test -z "$version"; then
|
|
||||||
echo "GStreamer git pre-commit hook:"
|
|
||||||
echo "Did not find GNU indent, please install it before continuing."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
INDENT=indent
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
INDENT=gindent
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
INDENT=gnuindent
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
INDENT=gst-indent-1.0
|
|
||||||
fi
|
|
||||||
|
|
||||||
case $($INDENT --version) in
|
|
||||||
GNU*)
|
|
||||||
;;
|
|
||||||
default)
|
|
||||||
echo "GStreamer git pre-commit hook:"
|
|
||||||
echo "Did not find GNU indent, please install it before continuing."
|
|
||||||
echo "(Found $INDENT, but it doesn't seem to be GNU indent)"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
INDENT_PARAMETERS="--braces-on-if-line \
|
|
||||||
--case-brace-indentation0 \
|
|
||||||
--case-indentation2 \
|
|
||||||
--braces-after-struct-decl-line \
|
|
||||||
--line-length80 \
|
|
||||||
--no-tabs \
|
|
||||||
--cuddle-else \
|
|
||||||
--dont-line-up-parentheses \
|
|
||||||
--continuation-indentation4 \
|
|
||||||
--honour-newlines \
|
|
||||||
--tab-size8 \
|
|
||||||
--indent-level2 \
|
|
||||||
--leave-preprocessor-space"
|
|
||||||
|
|
||||||
echo "--Checking style--"
|
|
||||||
for file in $(git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "\.c$") ; do
|
|
||||||
# nf is the temporary checkout. This makes sure we check against the
|
|
||||||
# revision in the index (and not the checked out version).
|
|
||||||
nf=$(git checkout-index --temp ${file} | cut -f 1)
|
|
||||||
newfile=$(mktemp /tmp/${nf}.XXXXXX) || exit 1
|
|
||||||
$INDENT ${INDENT_PARAMETERS} \
|
|
||||||
$nf -o $newfile 2>> /dev/null
|
|
||||||
# FIXME: Call indent twice as it tends to do line-breaks
|
|
||||||
# different for every second call.
|
|
||||||
$INDENT ${INDENT_PARAMETERS} \
|
|
||||||
$newfile 2>> /dev/null
|
|
||||||
diff -u -p "${nf}" "${newfile}"
|
|
||||||
r=$?
|
|
||||||
rm "${newfile}"
|
|
||||||
rm "${nf}"
|
|
||||||
if [ $r != 0 ] ; then
|
|
||||||
ERROR_FILES="$ERROR_FILES $file"
|
|
||||||
echo "================================================================================================="
|
|
||||||
echo " Code style error in: $file "
|
|
||||||
echo "================================================================================================="
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$ERROR_FILES" ];then
|
|
||||||
echo "================================================================================================="
|
|
||||||
echo " Code style error in: "
|
|
||||||
for file in $ERROR_FILES ; do
|
|
||||||
echo " $file"
|
|
||||||
done
|
|
||||||
echo " "
|
|
||||||
echo " Please fix before committing. Don't forget to run git add before trying to commit again. "
|
|
||||||
echo " If the whole file is to be committed, this should work (run from the top-level directory): "
|
|
||||||
echo " scripts/gst-indent$ERROR_FILES ; git add$ERROR_FILES ; git commit"
|
|
||||||
echo " "
|
|
||||||
echo "================================================================================================="
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
csharp_files=$( git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "^subprojects/gstreamer-sharp/.*cs$" )
|
|
||||||
if test -n "$csharp_files"; then
|
|
||||||
version=$(dotnet-format --version 2>/dev/null)
|
|
||||||
if test -z "$version"; then
|
|
||||||
echo "GStreamer git pre-commit hook:"
|
|
||||||
echo "Did not find dotnet-format required to format C# files, please install it before continuing."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
scripts/format-csharp --check
|
|
||||||
r=$?
|
|
||||||
if [ $r != 0 ] ; then
|
|
||||||
echo "================================================================================================="
|
|
||||||
echo " Code style error: "
|
|
||||||
echo " "
|
|
||||||
echo " Please fix before committing, running from the top-level directory: "
|
|
||||||
echo " scripts/format-chsarp "
|
|
||||||
echo " "
|
|
||||||
echo " Don't forget to run git add before trying to commit again. "
|
|
||||||
echo "================================================================================================="
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "--Checking style pass--"
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
for execname in gst-indent-1.0 gnuindent gindent indent; do
|
|
||||||
version=`$execname --version 2>/dev/null`
|
|
||||||
if test "x$version" != "x"; then
|
|
||||||
INDENT=$execname
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if test -z $INDENT; then
|
|
||||||
echo "GStreamer git pre-commit hook:"
|
|
||||||
echo "Did not find GNU indent, please install it before continuing."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case `$INDENT --version` in
|
|
||||||
GNU*)
|
|
||||||
;;
|
|
||||||
default)
|
|
||||||
echo "Did not find GNU indent, please install it before continuing."
|
|
||||||
echo "(Found $INDENT, but it doesn't seem to be GNU indent)"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Run twice. GNU indent isn't idempotent
|
|
||||||
# when run once
|
|
||||||
for i in 1 2; do
|
|
||||||
$INDENT \
|
|
||||||
--braces-on-if-line \
|
|
||||||
--case-brace-indentation0 \
|
|
||||||
--case-indentation2 \
|
|
||||||
--braces-after-struct-decl-line \
|
|
||||||
--line-length80 \
|
|
||||||
--no-tabs \
|
|
||||||
--cuddle-else \
|
|
||||||
--dont-line-up-parentheses \
|
|
||||||
--continuation-indentation4 \
|
|
||||||
--honour-newlines \
|
|
||||||
--tab-size8 \
|
|
||||||
--indent-level2 \
|
|
||||||
--leave-preprocessor-space \
|
|
||||||
$* || exit $?
|
|
||||||
done
|
|
Loading…
Reference in a new issue