Revert "tdf#127471 Remove font width scaling hack"
[LibreOffice.git] / .git-hooks / pre-commit
blobfd0cfeea2e6234b160a65c5ed074b29c6838c20d
1 #!/usr/bin/env perl
3 # A hook script to verify what is about to be committed.
4 # Called by "git commit" with no arguments. The hook should
5 # exit with non-zero status after issuing an appropriate message
6 # if it wants to stop the commit.
8 use strict;
9 use lib "solenv/clang-format";
10 #use File::Copy;
11 #use Cwd;
13 $ENV{LC_ALL} = "C";
15 sub check_whitespaces($)
17 my ($h) = @_;
18 my $src_limited = "c|cpp|cxx|h|hrc|hxx|idl|inl|java|swift|map|MK|pmk|pl|pm|sdi|sh|src|tab|ui|xcu|xml|xsl|py";
19 my $src_full = "c|cpp|cxx|h|hrc|hxx|idl|inl|java|swift|map|mk|MK|pmk|pl|pm|sdi|sh|src|tab|ui|xcu|xml|xsl|py";
21 my $found_bad = 0;
22 my $filename;
23 my $reported_filename = "";
24 my $lineno;
25 sub bad_line
27 my ($why, $line, $file_filter) = @_;
28 if (!defined $file_filter || $filename =~ /\.($file_filter)$/)
30 if (!$found_bad)
32 print STDERR "*\n";
33 print STDERR "* You have some suspicious patch lines:\n";
34 print STDERR "*\n";
35 $found_bad = 1;
37 if ($reported_filename ne $filename)
39 print STDERR "* In $filename\n";
40 $reported_filename = $filename;
42 print STDERR "* $why (line $lineno)\n";
43 print STDERR "$filename:$lineno:$line\n";
46 open( FILES, "git-diff-index -p -M --cached $h |" ) || die "Cannot run git diff-index.";
47 while (<FILES>)
49 if (m|^diff --git a/(.*) b/\1$|)
51 $filename = $1;
52 next;
54 if (/^@@ -\S+ \+(\d+)/)
56 $lineno = $1 - 1;
57 next;
59 if (/^ /)
61 $lineno++;
62 next;
64 if (s/^\+//)
66 $lineno++;
67 chomp;
68 if (/\s$/)
70 bad_line("trailing whitespace", $_ , $src_limited);
72 if (/\r$/)
74 bad_line("DOS lineends", $_ , $src_limited);
76 if (/\s* /)
78 bad_line("indent with Tab", $_, $src_limited);
80 if (/^(?:[<>=]){7}$/)
82 bad_line("unresolved merge conflict", $src_full);
84 if (/SAL_DEBUG/)
86 bad_line("temporary debug in commit", $_, $src_limited);
88 if ((/OOXMLIMPORT/) and ($filename =~ /ooxmlexport/))
90 bad_line("OOXMLIMPORT definition used in a ooxmlexport file", $_, "cxx");
92 if ((/OOXMLEXPORT/) and ($filename =~ /ooxmlimport/))
94 bad_line("OOXMLEXPORT definition used in a ooxmlimport file", $_, "cxx");
96 if (/<property name="use_markup">True<\/property>/)
98 bad_line("use font attributes instead of use-markup", $_, "ui");
100 if (/<property name="tooltip_markup"/ )
102 bad_line("use tooltip_text instead of tooltip_markup", $_, "ui");
104 if ((/translatable="yes"/) and not(/context=/))
106 bad_line("translatable .ui file line without context", $_, "ui");
108 if ((/requires/) and (/lib="gtk+/) and not (/version="3.20/))
110 bad_line("min supported version of gtk3 is 3.20", $_, "ui");
112 if ((/<interface/) and not(/domain=/))
114 bad_line(".ui file without translation domain", $_, "ui");
118 if ( $found_bad)
120 exit($found_bad);
124 sub check_author()
126 my $author = `git var GIT_AUTHOR_IDENT`;
127 chomp $author;
128 if ($author =~ /^Your Name <you\@example.com>/)
130 print("ERROR: You have a suspicious author identity: '$author'\n");
131 exit(1);
135 sub check_style($)
137 if (! -e "solenv/clang-format/ClangFormat.pm")
139 # Commit happens in a submodule.
140 return;
143 require ClangFormat;
144 ClangFormat->import();
146 my ($h) = @_;
147 my $src = ClangFormat::get_extension_regex();
148 my @bad_names = ();
149 my $clang_format = ClangFormat::find();
151 ## Check if ClangFormat has get_excludelist or the old
152 ## get_blacklist
153 my $excluded_list_names;
154 eval { ClangFormat::get_excludelist() };
155 if ($@) { $excluded_list_names = ClangFormat::get_blacklist(); }
156 else { $excluded_list_names = ClangFormat::get_excludelist(); }
158 # Get a list of non-deleted changed files.
159 open (FILES, "git diff-index --cached --diff-filter=AM --name-only $h |") || die "Cannot run git diff.";
160 while (my $filename = <FILES>)
162 chomp $filename;
163 if ($filename =~ /\.($src)$/ and !exists($excluded_list_names->{$filename}))
165 if (!defined($clang_format))
167 my $version = ClangFormat::get_wanted_version();
168 my $opt_lo = ClangFormat::get_own_directory();
170 print("\nWARNING: Commit touches new (non-excluded) files, but no clang-format"
171 . " ${version}\n");
172 print(" found (via CLANG_FORMAT or PATH env vars, or in ${opt_lo}).\n\n");
174 my $platform = "linux64";
175 my $download = "wget";
176 if ($^O eq "cygwin")
178 $platform = "win.exe";
180 elsif ($^O eq "darwin")
182 $platform = "mac";
183 $download = "curl -O";
186 print("To get a suitable binary, please do:\n\n");
187 print("mkdir -p $opt_lo\n");
188 print("cd $opt_lo\n");
189 print("$download https://dev-www.libreoffice.org/bin/clang-format-$version-$platform\n");
190 print("cp clang-format-$version-$platform clang-format\n");
191 print("chmod +x clang-format\n\n");
193 print("(Or read solenv/clang-format/README on how to build it yourself.\n");
194 return;
196 if (!ClangFormat::check_style($clang_format, $filename))
198 push @bad_names, $filename;
203 # Enforce style.
204 if (scalar @bad_names)
206 my $autostyle = `git config libreoffice.autostyle`;
207 chomp $autostyle;
208 if ($autostyle ne "true")
210 print("\nThe above differences were found between the code to commit \n");
211 print("and the clang-format rules. You can apply these changes with:\n");
212 print("\n$clang_format -i " . join(" ", @bad_names) . "\n\n");
213 print("Aborting commit. Apply changes and commit again or skip checking\n");
214 print("with --no-verify (not recommended).\n");
215 exit(1);
217 else
219 # 'git config libreoffice.autostyle true' was invoked to run
220 # clang-format automatically.
221 print("\nThe above differences were found between the code to commit \n");
222 print("and the clang-format rules. Fixing these now automatically.\n");
223 print("Running '$clang_format -i " . join(" ", @bad_names) . "' for you...\n");
224 system("$clang_format -i " . join(" ", @bad_names));
225 # TODO this stages all local modifications, staging originally
226 # unstaged hunks.
227 system("git add " . join(" ", @bad_names));
228 print("Done.\n");
233 sub check_submodules($)
235 my ($h) = @_;
237 my $toplevel = `git rev-parse --show-toplevel`;
238 chomp $toplevel;
240 # trick to get a list of submodules - directly read from the .gitmodules
241 open(SUBMODULES, "git config --file '$toplevel'/.gitmodules --get-regexp path | awk '{ print \$2 }' |" ) || die "Cannot run git config on the .gitmodules.";
242 while (<SUBMODULES>)
244 chomp;
246 my $ignore = `git config submodule.$_.ignore`;
247 chomp $ignore;
248 if ($ignore eq 'all')
250 print <<EOM;
251 Error: Your git configuration has submodule.$_.ignore set to 'all'.
253 This is dangerous and can lead to accidentally pushing unwanted changes to
254 submodules.
256 To fix it, please do:
258 git config --unset submodule.$_.ignore
261 exit(1);
264 my $diff = `git diff --cached --name-only -z $h -- $_`;
265 chomp $diff;
266 if ($diff ne '')
268 print <<EOM;
269 Error: You are trying to commit changes to submodule $_ from the main repo.
271 Please do not do that, commit only to the submodule, the git hook on the
272 server will make sure the appropriate change is mirrored in the main repo.
274 To remove the change, you can do:
276 git submodule update $_
278 If it fails with 'error: Server does not allow request for unadvertised object',
279 run the following:
281 git submodule sync
282 git submodule update $_
285 exit(1);
290 # Do the work :-)
292 # Initial commit: diff against an empty tree object
293 my $against="4b825dc642cb6eb9a060e54bf8d69288fbee4904";
294 if ( system( "git rev-parse --verify HEAD >/dev/null 2>&1" ) == 0 )
296 $against="HEAD"
299 # If you want to allow non-ascii filenames set this variable to true.
300 my $allownonascii=`git config hooks.allownonascii`;
301 chomp $allownonascii;
303 # Cross platform projects tend to avoid non-ascii filenames; prevent
304 # them from being added to the repository. We exploit the fact that the
305 # printable range starts at the space character and ends with tilde.
306 if ( $allownonascii ne "true" &&
307 # Note that the use of brackets around a tr range is ok here, (it's
308 # even required, for portability to Solaris 10's /usr/bin/tr), since
309 # the square bracket bytes happen to fall in the designated range.
310 `git diff --cached --name-only --diff-filter=A -z $against | \
311 LC_ALL=C tr -d '[ -~]\\0'` ne "" )
313 print <<EOM;
314 Error: Attempt to add a non-ascii file name.
316 This can cause problems if you want to work
317 with people on other platforms.
319 To be portable it is advisable to rename the file ...
321 If you know what you are doing you can disable this
322 check using:
324 git config hooks.allownonascii true
327 exit( 1 );
330 # Block large files.
331 open( FILES, "git diff --cached --name-only --diff-filter=A -z $against |" ) || die "Cannot run git diff-index.";
332 while (<FILES>)
334 if (/\.ui$/) # .ui files can get large
336 continue;
338 if (/\.xsl$/) # XSLT
340 continue;
342 my $size = `git cat-file -s :$_`;
343 # For now let's say large is 500KB
344 my $limit = 500;
345 if ($size > $limit * 1024)
347 print "Error: Attempt to add a large file: $_, pleasy try to fit into $limit KB.\n";
348 exit( 1 );
352 # fix whitespace in code
353 check_whitespaces( $against);
355 # fix style in code
356 check_style($against);
358 # catch missing author info
359 check_author();
361 # catch commits to the submodules
362 check_submodules($against);
364 # all OK
365 exit( 0 );
366 # vi:set shiftwidth=4 expandtab: