diff --git a/bibcop.pl b/bibcop.pl index 05af914..574f090 100755 --- a/bibcop.pl +++ b/bibcop.pl @@ -969,9 +969,15 @@ sub fail { my @entries = entries($bib); if (exists $args{'--fix'}) { my $fixed = ''; + my %seen; for my $i (0..(@entries+0 - 1)) { my %entry = %{ $entries[$i] }; + my $name = $entry{':name'}; + if (exists $seen{$name}) { + next; + } $fixed = $fixed . entry_fix(%entry); + $seen{$name} = 1; } if (exists $args{'-i'} or exists $args{'--in-place'}) { open(my $out, '>', $file) or error('Cannot open file for writing: ' . $file); diff --git a/perl-tests/cli_fixing.pl b/perl-tests/cli_fixing.pl new file mode 100644 index 0000000..8c28ba6 --- /dev/null +++ b/perl-tests/cli_fixing.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl +# (The MIT License) +# +# Copyright (c) 2022-2024 Yegor Bugayenko +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +package bibcop; + +use strict; +use warnings; +use File::Temp qw/ tempfile /; + +assert_fix_compare('duplicates'); +assert_fix_compare('no-fixes'); + +sub read_file { + my ($path) = @_; + open(my $h, '<', $path) or error('Cannot open file: ' . $path); + my $content; { local $/; $content = <$h>; } + $content =~ s/^\s+|\s+$//g; + return $content; +} + +sub assert_fix_compare { + my ($dir) = @_; + my $before = "test-files/fixes/$dir/before.bib"; + my $expected = "test-files/fixes/$dir/expected.bib"; + my ($a, $after) = tempfile(); + my $cmd = "perl ./bibcop.pl --fix $before > $after"; + my $stdout = `$cmd`; + my $exit = $? >> 8; + if ($exit != 0) { + print "---\n$stdout\n"; + print "Exit code is $exit (not zero) for '$cmd'\n"; + exit 1; + } + my $expected_bib = read_file($expected); + my $after_bib = read_file($after); + if (not $expected_bib eq $after_bib) { + print "$after_bib\n"; + print "Doesn't match:\n"; + print "$expected_bib\n"; + exit 1; + } +} + + +1; diff --git a/test-files/fixes/duplicates/before.bib b/test-files/fixes/duplicates/before.bib new file mode 100644 index 0000000..8f15d67 --- /dev/null +++ b/test-files/fixes/duplicates/before.bib @@ -0,0 +1,14 @@ +@book{knuth1974, + author = {Knuth, Donald E. and Duane, Bibby}, + doi = {10.5555/1102013}, + publisher = {Addison-Wesley Professional}, + title = {{The TeX Book}}, + year = {1984}, +} + +@book{knuth1974, + author = {Donald E. Knuth}, + publisher = {Addison-Wesley}, + title = {The TeX Book}, + year = {1984}, +} \ No newline at end of file diff --git a/test-files/fixes/duplicates/expected.bib b/test-files/fixes/duplicates/expected.bib new file mode 100644 index 0000000..68ef31f --- /dev/null +++ b/test-files/fixes/duplicates/expected.bib @@ -0,0 +1,7 @@ +@book{knuth1974, + author = {Knuth, Donald E. and Duane, Bibby}, + doi = {10.5555/1102013}, + publisher = {Addison-Wesley Professional}, + title = {{The TeX Book}}, + year = {1984}, +} \ No newline at end of file diff --git a/test-files/fixes/no-fixes/before.bib b/test-files/fixes/no-fixes/before.bib new file mode 100644 index 0000000..68ef31f --- /dev/null +++ b/test-files/fixes/no-fixes/before.bib @@ -0,0 +1,7 @@ +@book{knuth1974, + author = {Knuth, Donald E. and Duane, Bibby}, + doi = {10.5555/1102013}, + publisher = {Addison-Wesley Professional}, + title = {{The TeX Book}}, + year = {1984}, +} \ No newline at end of file diff --git a/test-files/fixes/no-fixes/expected.bib b/test-files/fixes/no-fixes/expected.bib new file mode 100644 index 0000000..68ef31f --- /dev/null +++ b/test-files/fixes/no-fixes/expected.bib @@ -0,0 +1,7 @@ +@book{knuth1974, + author = {Knuth, Donald E. and Duane, Bibby}, + doi = {10.5555/1102013}, + publisher = {Addison-Wesley Professional}, + title = {{The TeX Book}}, + year = {1984}, +} \ No newline at end of file diff --git a/test-files/test.bib b/test-files/test.bib index ee67bcd..1d45299 100644 --- a/test-files/test.bib +++ b/test-files/test.bib @@ -1,5 +1,5 @@ -% This is a test file, which is perfectly formatted. -% Bibcop must not complain about it. +% This is a test file, which is NOT perfectly formatted. +% Bibcop must complain about certain parts of it (see perl-tests/cli.pl). @book{knuth1974, author = {Knuth, Donald E. and Duane, Bibby}, diff --git a/tests.pl b/tests.pl index add7d6c..c0e6900 100755 --- a/tests.pl +++ b/tests.pl @@ -63,6 +63,7 @@ sub show { require './perl-tests/functions.pl'; require './perl-tests/checks.pl'; require './perl-tests/cli.pl'; +require './perl-tests/cli_fixing.pl'; print "\033[0;32mGREAT!\033[0m All tests are green.\n";