[en-GB] Added 13 words to autocorrect
[LibreOffice.git] / .git-hooks / pre-commit
blob1f2e9307de01ec72d723d7da284ca0fca1718754
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 (/<property name="margin[-_]left"/ )
106 bad_line("use margin-start instead of margin-left", $_, "ui");
108 if (/<property name="margin[-_]right"/ )
110 bad_line("use margin-end instead of margin-right", $_, "ui");
112 if (/<object class="GtkAlignment"/)
114 bad_line("use margin-start (etc) on child instead of a GtkAlignment", $_, "ui");
116 if (/<property name="use[-_]stock"/ )
118 bad_line("use translation context 'stock' and the English string as button label instead", $_, "ui");
120 if (/<property name="stock[-_]id"/ )
122 bad_line("use an icon-name listed at https://developer.gnome.org/gtk3/stable/gtk3-Stock-Items.html", $_, "ui");
124 if (/<property name="stock"/ )
126 bad_line("use an icon-name listed at https://developer.gnome.org/gtk3/stable/gtk3-Stock-Items.html", $_, "ui");
128 if ((/translatable="yes"/) and not(/context=/))
130 bad_line("translatable .ui file line without context", $_, "ui");
132 if ((/requires/) and (/lib="gtk+/) and not (/version="3.20/))
134 bad_line("min supported version of gtk3 is 3.20", $_, "ui");
136 if ((/<interface/) and not(/domain=/))
138 bad_line(".ui file without translation domain", $_, "ui");
142 if ( $found_bad)
144 exit($found_bad);
148 sub check_author()
150 my $author = `git var GIT_AUTHOR_IDENT`;
151 chomp $author;
152 if ($author =~ /^Your Name <you\@example.com>/)
154 print("ERROR: You have a suspicious author identity: '$author'\n");
155 exit(1);
159 sub check_style($)
161 if (! -e "solenv/clang-format/ClangFormat.pm")
163 # Commit happens in a submodule.
164 return;
167 require ClangFormat;
168 ClangFormat->import();
170 my ($h) = @_;
171 my $src = ClangFormat::get_extension_regex();
172 my @bad_names = ();
173 my $clang_format = ClangFormat::find();
175 ## Check if ClangFormat has get_excludelist or the old
176 ## get_blacklist
177 my $excluded_list_names;
178 eval { ClangFormat::get_excludelist() };
179 if ($@) { $excluded_list_names = ClangFormat::get_blacklist(); }
180 else { $excluded_list_names = ClangFormat::get_excludelist(); }
182 # Get a list of non-deleted changed files.
183 open (FILES, "git diff-index --cached --diff-filter=AM --name-only $h |") || die "Cannot run git diff.";
184 while (my $filename = <FILES>)
186 chomp $filename;
187 if ($filename =~ /\.($src)$/ and !exists($excluded_list_names->{$filename}))
189 if (!defined($clang_format))
191 my $version = ClangFormat::get_wanted_version();
192 my $opt_lo = ClangFormat::get_own_directory();
194 print("\nWARNING: Commit touches new (non-excluded) files, but no clang-format"
195 . " ${version}\n");
196 print(" found (via CLANG_FORMAT or PATH env vars, or in ${opt_lo}).\n\n");
198 my $platform = "linux64";
199 my $download = "wget";
200 if ($^O eq "cygwin")
202 $platform = "win.exe";
204 elsif ($^O eq "darwin")
206 $platform = "mac";
207 $download = "curl -O";
210 print("To get a suitable binary, please do:\n\n");
211 print("mkdir -p $opt_lo\n");
212 print("cd $opt_lo\n");
213 print("$download https://dev-www.libreoffice.org/bin/clang-format-$version-$platform\n");
214 print("cp clang-format-$version-$platform clang-format\n");
215 print("chmod +x clang-format\n\n");
217 print("(Or read solenv/clang-format/README on how to build it yourself.\n");
218 return;
220 if (!ClangFormat::check_style($clang_format, $filename))
222 push @bad_names, $filename;
227 # Enforce style.
228 if (scalar @bad_names)
230 my $autostyle = `git config libreoffice.autostyle`;
231 chomp $autostyle;
232 if ($autostyle ne "true")
234 print("\nThe above differences were found between the code to commit \n");
235 print("and the clang-format rules. You can apply these changes with:\n");
236 print("\n$clang_format -i " . join(" ", @bad_names) . "\n\n");
237 print("Aborting commit. Apply changes and commit again or skip checking\n");
238 print("with --no-verify (not recommended).\n");
239 exit(1);
241 else
243 # 'git config libreoffice.autostyle true' was invoked to run
244 # clang-format automatically.
245 print("\nThe above differences were found between the code to commit \n");
246 print("and the clang-format rules. Fixing these now automatically.\n");
247 print("Running '$clang_format -i " . join(" ", @bad_names) . "' for you...\n");
248 system("$clang_format -i " . join(" ", @bad_names));
249 # TODO this stages all local modifications, staging originally
250 # unstaged hunks.
251 system("git add " . join(" ", @bad_names));
252 print("Done.\n");
257 sub check_submodules($)
259 my ($h) = @_;
261 my $toplevel = `git rev-parse --show-toplevel`;
262 chomp $toplevel;
264 # trick to get a list of submodules - directly read from the .gitmodules
265 open(SUBMODULES, "git config --file '$toplevel'/.gitmodules --get-regexp path | awk '{ print \$2 }' |" ) || die "Cannot run git config on the .gitmodules.";
266 while (<SUBMODULES>)
268 chomp;
270 my $ignore = `git config submodule.$_.ignore`;
271 chomp $ignore;
272 if ($ignore eq 'all')
274 print <<EOM;
275 Error: Your git configuration has submodule.$_.ignore set to 'all'.
277 This is dangerous and can lead to accidentally pushing unwanted changes to
278 submodules.
280 To fix it, please do:
282 git config --unset submodule.$_.ignore
285 exit(1);
288 my $diff = `git diff --cached --name-only -z $h -- $_`;
289 chomp $diff;
290 if ($diff ne '')
292 print <<EOM;
293 Error: You are trying to commit changes to submodule $_ from the main repo.
295 Please do not do that, commit only to the submodule, the git hook on the
296 server will make sure the appropriate change is mirrored in the main repo.
298 To remove the change, you can do:
300 git submodule update $_
302 If it fails with 'error: Server does not allow request for unadvertised object',
303 run the following:
305 git submodule sync
306 git submodule update $_
309 exit(1);
314 # Do the work :-)
316 # Initial commit: diff against an empty tree object
317 my $against="4b825dc642cb6eb9a060e54bf8d69288fbee4904";
318 if ( system( "git rev-parse --verify HEAD >/dev/null 2>&1" ) == 0 )
320 $against="HEAD"
323 # If you want to allow non-ascii filenames set this variable to true.
324 my $allownonascii=`git config hooks.allownonascii`;
325 chomp $allownonascii;
327 # Cross platform projects tend to avoid non-ascii filenames; prevent
328 # them from being added to the repository. We exploit the fact that the
329 # printable range starts at the space character and ends with tilde.
330 if ( $allownonascii ne "true" &&
331 # Note that the use of brackets around a tr range is ok here, (it's
332 # even required, for portability to Solaris 10's /usr/bin/tr), since
333 # the square bracket bytes happen to fall in the designated range.
334 `git diff --cached --name-only --diff-filter=A -z $against | \
335 LC_ALL=C tr -d '[ -~]\\0'` ne "" )
337 print <<EOM;
338 Error: Attempt to add a non-ascii file name.
340 This can cause problems if you want to work
341 with people on other platforms.
343 To be portable it is advisable to rename the file ...
345 If you know what you are doing you can disable this
346 check using:
348 git config hooks.allownonascii true
351 exit( 1 );
354 # Block large files.
355 open( FILES, "git diff --cached --name-only --diff-filter=A -z $against |" ) || die "Cannot run git diff-index.";
356 while (<FILES>)
358 if (/\.ui$/) # .ui files can get large
360 continue;
362 if (/\.xsl$/) # XSLT
364 continue;
366 my $size = `git cat-file -s :$_`;
367 # For now let's say large is 500KB
368 my $limit = 500;
369 if ($size > $limit * 1024)
371 print "Error: Attempt to add a large file: $_, pleasy try to fit into $limit KB.\n";
372 exit( 1 );
376 # fix whitespace in code
377 check_whitespaces( $against);
379 # fix style in code
380 check_style($against);
382 # catch missing author info
383 check_author();
385 # catch commits to the submodules
386 check_submodules($against);
388 # all OK
389 exit( 0 );
390 # vi:set shiftwidth=4 expandtab: