summaryrefslogtreecommitdiff
path: root/.git-hooks
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2017-11-02 17:09:03 +0100
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-11-03 09:29:11 +0100
commit98f5f4d39c9c1cae7e8b56e2b33ee0be58e79f1d (patch)
treeffcaf204c4c934058abd3824ee6795cdf2e2f125 /.git-hooks
parentcd592cca271cdf5eabe2aba3479e4831ef3e14a6 (diff)
Enforce coding style with clang-format for new code
- The actual blacklist has to be generated with solenv/clang-format/generate-style-blacklist.sh in a separate commit. - .clang-format is from <https://lists.freedesktop.org/archives/libreoffice/2014-August/062802.html>, except: - the commented out lines are removed - Standard is Cpp11 instead of Cpp03 - explicitly avoid sorting includes (requested during ESC meeting 2017-10-11) - no indentation inside namespaces (lots of existing code in sc wants this) - The git hooks prints a diff when the style is violated, along with a command to fix up the violation automatically. It also enforces style only in new files and ignores all files listed in the blacklist. - To avoid introducing one more hard-to-setup build dependency for new developers, help them two ways: - if clang-format is not installed, provide pre-built binaries for Linux/Windows/macOS - download/install of these binaries are printed as cmdline instructions, similar to how we have our own 'make' on Windows - As per ESC call 2017-11-02, currently don't do any checks if clang-format is not installed (as a first step). Change-Id: Iaa139c396337e8734aa1853305d808438260c41a Reviewed-on: https://gerrit.libreoffice.org/43736 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to '.git-hooks')
-rwxr-xr-x.git-hooks/pre-commit113
1 files changed, 113 insertions, 0 deletions
diff --git a/.git-hooks/pre-commit b/.git-hooks/pre-commit
index b0779e5aaa1f..b40ad6f004d9 100755
--- a/.git-hooks/pre-commit
+++ b/.git-hooks/pre-commit
@@ -108,6 +108,116 @@ sub check_whitespaces($)
}
}
+sub check_style($)
+{
+ my ($h) = @_;
+ my $src = "c|cpp|cxx|h|hxx|inl";
+ my @bad_names = ();
+ my %blacklist_names = ();
+
+ # Use clang-format from PATH, unless it's available in our dedicated
+ # directory.
+ my $opt_lo = "/opt/lo/bin";
+ my $clang_format = "$opt_lo/clang-format";
+ if (! -x $clang_format)
+ {
+ foreach my $dir (split /:/, $ENV{PATH})
+ {
+ $clang_format = "$dir/clang-format";
+ if (-x $clang_format)
+ {
+ last;
+ }
+ }
+ }
+
+ # Read the blacklist.
+ if (open(LINES, "solenv/clang-format/blacklist"))
+ {
+ while (my $line = <LINES>)
+ {
+ chomp $line;
+ $blacklist_names{$line} = 1;
+ }
+ }
+
+ # Check if clang-format is installed.
+ if (! -x $clang_format)
+ {
+ # As a first step, don't do any checks in this case.
+ return;
+
+ my $version = "r302580";
+ my $platform = "linux64";
+ my $download = "wget";
+ if ($^O eq "cygwin")
+ {
+ $platform = "win.exe";
+ }
+ elsif ($^O eq "darwin")
+ {
+ $platform = "mac";
+ $download = "curl -O";
+ }
+
+ print("Error: clang-format is not found in $opt_lo or in your PATH.\n");
+ print("To get a clang-format binary for your platform, please do:\n\n");
+ print("mkdir -p $opt_lo\n");
+ print("cd $opt_lo\n");
+ print("$download https://dev-www.libreoffice.org/bin/clang-format-$version-$platform\n");
+ print("cp clang-format-$version-$platform clang-format\n");
+ print("chmod +x clang-format\n");
+ exit(1);
+ }
+
+ if ($^O eq "cygwin")
+ {
+ $clang_format = `cygpath -m $clang_format`;
+ chomp $clang_format;
+ }
+
+ # Get a list of non-deleted changed files.
+ open (FILES, "git diff-index --cached --diff-filter=AM --name-only $h |") || die "Cannot run git diff.";
+ while (my $filename = <FILES>)
+ {
+ chomp $filename;
+ if ($filename =~ /\.($src)$/ and !exists($blacklist_names{$filename}))
+ {
+ if (system("$clang_format $filename | git --no-pager diff --no-index --exit-code $filename -") != 0)
+ {
+ push @bad_names, $filename;
+ }
+ }
+ }
+
+ # Enforce style.
+ if (scalar @bad_names)
+ {
+ my $autostyle = `git config libreoffice.autostyle`;
+ chomp $autostyle;
+ if ($autostyle ne "true")
+ {
+ print("\nThe above differences were found between the code to commit \n");
+ print("and the clang-format rules. You can apply these changes with:\n");
+ print("\n$clang_format -i " . join(" ", @bad_names) . "\n\n");
+ print("Aborting commit. Apply changes and commit again or skip checking\n");
+ print("with --no-verify (not recommended).\n");
+ exit(1);
+ }
+ else
+ {
+ # 'git config libreoffice.autostyle true' was invoked to run
+ # clang-format automatically.
+ print("\nThe above differences were found between the code to commit \n");
+ print("and the clang-format rules. Fixing these now automatically.\n");
+ print("Running '$clang_format -i " . join(" ", @bad_names) . "' for you...\n");
+ system("$clang_format -i " . join(" ", @bad_names));
+ system("git add " . join(" ", @bad_names));
+ print("Done.\n");
+ }
+ }
+}
+
# Do the work :-)
# Initial commit: diff against an empty tree object
@@ -172,6 +282,9 @@ while (<FILES>)
# fix whitespace in code
check_whitespaces( $against);
+# fix style in code
+check_style($against);
+
# all OK
exit( 0 );
# vi:set shiftwidth=4 expandtab: