From 4e52e1e8be6040cf2085d408dded47b9bd56f6aa Mon Sep 17 00:00:00 2001 From: Frederik Tilmann Date: Sun, 14 Jul 2024 15:46:06 +0200 Subject: [PATCH] Generate missing .bbl files for --flatten option by running bibtex. Based on PR #127 --- latexdiff-vc | 88 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/latexdiff-vc b/latexdiff-vc index b3f806f..27d094a 100755 --- a/latexdiff-vc +++ b/latexdiff-vc @@ -27,7 +27,8 @@ # # TODO/IDEAS: - option to call external pre-processing codes # -# version 1.3.4a: +# version 1.3.4a: +# - Enhancement: if --flatten option is used, and no bbl file is included in the version management, then latexdiff-vc will try to run bibtex to generate the bbl file. Implements the suggestion of PR #127 # - bug fix: minor fix for --only-changed that makes detection of changed pages more reliable [ PR #297 contributed by user nelijuc ] # # version 1.3.2: @@ -75,7 +76,7 @@ use Getopt::Long ; use Pod::Usage qw/pod2usage/ ; use File::Temp qw/tempdir/ ; -use File::Basename qw/dirname/; +use File::Basename qw/dirname fileparse/; use File::Copy; use File::Path; @@ -102,6 +103,8 @@ my ($configlatexdiff,@config,$config,$assign); #my $latexcmd="latex"; # latex compiler if not further identified my $vc=""; my $tempdir=tempdir(CLEANUP => 1); # generate a temp dir, which will automatically be deleted at program exit +#printf STDERR "DEBUG: tempdir $tempdir\n"; + # Variables my ($file1,$file2,$diff,$diffbase,$rootdir,$answer,$options,$infile,$append,$dirname,$cwd); my (@files,@ldoptions,@tmpfiles,@ptmpfiles,@difffiles,$extracomp); # , @@ -431,34 +434,43 @@ while ( $infile=$file2=shift @files ) { print STDERR "Working on $infile \n"; if ( scalar(@revs) == 1 ) { if ( defined($flatten) ) { - my $olddir=$tempdir . "/latexdiff-vc-$revs[0]"; - print STDERR "Checking out old dir into: $olddir (rev: $revs[0])\n"; - checkout_dir($revs[0],$olddir); + my $olddir=$tempdir . "/latexdiff-vc-$revs[0]"; + print STDERR "Checking out old dir into: $olddir (rev: $revs[0])\n"; + checkout_dir($revs[0],$olddir,$infile); ### print STDERR "DEBUG olddir $olddir"; ### unless (-e $olddir) { mkdir $olddir or die "Cannot mkdir $olddir ." ;} ### print STDERR "DEBUG svn checkout -r $revs[0] $rootdir $olddir"; ### system("svn checkout -r $revs[0] $rootdir $olddir")==0 or die "Something went wrong in executing: svn checkout -r $revs[0] $rootdir"; - $file1=$olddir ."/".$infile; - } else { - ($file1=$infile) =~ s/\.(tex|bbl|flt)/-oldtmp-$$.$1/ ; - push @tmpfiles,$file1; - # compare file with previous version ($revs[0]="") or specified version - ### system("$diffcmd$revs[0] $infile| $patchcmd -o$file1") ; - if (system("$diffcmd$revs[0] \"$infile\" | $patchcmd -o\"$file1\"")==0 and -z $file1 ) { - # no differences detected, i.e. file is equal to current version - copy($infile,$file1) || die "copy($infile,$file1) failed: $!"; - } - } + $file1=$olddir ."/".$infile; + + # generate bibliography for new file if + if ( greptex('^[^%]*\\\\bibliography\\{',$infile) == 0) { + my ($filebase,$filedir)=fileparse($infile,".tex"); + if ( ! -e "$filedir$filebase.bbl" ) { + system("$CFG{LATEX} --interaction=batchmode '$infile'; $CFG{BIBTEX} '$filedir$filebase'") + or die "Something went wrong in executing: $CFG{LATEX} --interaction=batchmode '$infile'; $CFG{BIBTEX} '$filedir$filebase'" ; + } + } + } else { + ($file1=$infile) =~ s/\.(tex|bbl|flt)/-oldtmp-$$.$1/ ; + push @tmpfiles,$file1; + # compare file with previous version ($revs[0]="") or specified version + ### system("$diffcmd$revs[0] $infile| $patchcmd -o$file1") ; + if (system("$diffcmd$revs[0] \"$infile\" | $patchcmd -o\"$file1\"")==0 and -z $file1 ) { + # no differences detected, i.e. file is equal to current version + copy($infile,$file1) || die "copy($infile,$file1) failed: $!"; + } + } } elsif ( scalar(@revs) == 2 ) { if ( defined($flatten) ) { my $olddir=$tempdir . "/latexdiff-vc-$revs[0]"; print STDERR "Checking out old dir into: $olddir (rev: $revs[0])\n"; - checkout_dir($revs[0],$olddir); + checkout_dir($revs[0],$olddir,$infile); $file1=$olddir ."/".$infile; my $newdir=$tempdir . "/latexdiff-vc-$revs[1]"; print STDERR "Checking out new dir into: $newdir\n"; - checkout_dir($revs[1],$newdir); + checkout_dir($revs[1],$newdir,$infile); $file2=$newdir ."/".$infile; } else { ($file1=$infile) =~ s/\.(tex|bbl|flt)/-oldtmp-$$.$1/ ; @@ -485,7 +497,7 @@ while ( $infile=$file2=shift @files ) { } else { ($diff=$infile) =~ s/\.(tex|bbl|flt)$/$append.$1/ ; } - + ### print STDERR "DEBUG: diff $diff"; # make directories if needed $dirname=dirname($diff) ; @@ -506,13 +518,14 @@ while ( $infile=$file2=shift @files ) { die "Abort ... " ; } } + print STDERR "Running: $CFG{LATEXDIFF} $options \"$file1\" \"$file2\" > \"$diff\"\n"; unless ( system("$CFG{LATEXDIFF} $options \"$file1\" \"$file2\" > \"$diff\"") == 0 ) { print STDERR "Something went wrong in $CFG{LATEXDIFF}. Deleting $diff and abort\n" ; unlink $diff ; exit(5) }; print "Generated difference file $diff\n"; - if ( $run and !( scalar(@revs) && greptex( qr/\\document(?:class|style)/ , $diff ) ) ) { + if ( $run and !( scalar(@revs) && greptex( qr/\\document(?:class|style)/ , $diff,25) ) ) { # save filename for later processing if postscript or pdf conversion is requested and either two-file mode was used (scalar(@revs)==0) or the diff file contains documentclass statement (ie. is a root document) push @difffiles, $diff ; } @@ -537,7 +550,8 @@ foreach $diff ( @difffiles ) { if ( $run ) { print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n" if $debug; - if ( system("grep -q \'^[^%]*\\\\bibliography{\' \"$diff\"") == 0 ) { +# if ( system("grep -q \'^[^%]*\\\\bibliography{\' \"$diff\"") == 0 ) { + if ( greptex('^[^%]*\\\\bibliography{',$diff ) == 0 ) { system("$CFG{LATEX} --interaction=batchmode \"$diff\"; $CFG{BIBTEX} \"$diffbase\";"); push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; } @@ -661,12 +675,14 @@ sub compresspages { return @res; } -# checkout_dir(rev,dirname) +# checkout_dir(rev,dirname, ) # checks out revision rev and stores it in dirname -# uses global variables: $vc, $rootdir +# If argument is provided, check if this file imports a bibliography and generate it if necessary +# uses global variables: $vc, $rootdir, $CFG sub checkout_dir { - my ($rev,$dirname)=@_; + my ($rev,$dirname,$file)=@_; + my ($filebase,$filedir); unless (-e $dirname) { mkpath([ $dirname ]) or die "Cannot mkdir $dirname ." ;} if ( $vc eq "SVN" ) { system("svn checkout -r $rev $rootdir $dirname")==0 or die "Something went wrong in executing: svn checkout -r $rev $rootdir $dirname"; @@ -678,13 +694,25 @@ sub checkout_dir { } else { die "checkout_dir: only works with SVN, HG and GIT VCS system (selected: $vc)"; } + # Check if the main file needs a bbl generated + if ( defined($file) and greptex('^[^%]*\\\\bibliography\\{',$file) == 0) { + ($filebase,$filedir)=fileparse($file,".tex"); + if ( ! -e "$filedir$filebase.bbl" ){ + printf STDERR "Running $CFG{BIBTEX} to generate $filedir$filebase.bbl.\n"; + system("cd '$dirname'; $CFG{LATEX} --interaction=batchmode '$file'; $CFG{BIBTEX} '$filedir$filebase'")==0 + or die "Something went wrong in executing: cd '$dirname'; $CFG{LATEX} --interaction=batchmode '$file'; $CFG{BIBTEX} '$filedir$filebase'" ; + } +# else { # DEBUG +# printf STDERR "DEBUG: Skipping bbl file generation as $filedir$filebase.bbl already exists.\n" +# } #DEBUG + } } -# greptex returns 1 if regex is not matched in filename -# only the 25 first non-comment lines are scanned +# greptex($regex,$filename, ) returns 1 if regex is not matched in filename +# only the first non-comment lines are scanned; by default everythin is scanned # 0 if there is a match sub greptex { - my ($regex,$filename)=@_; + my ($regex,$filename,$nlines)=@_; my ($i)=0; open (FH, $filename) or die("Couldn't open $filename: $!"); while () { @@ -693,9 +721,9 @@ sub greptex { close(FH); return(0); } - # only scan 25 lines + # only scan lines, if optional parameter proviede $i++; - last if $i>25 ; + last if defined($nlines) and $i>$nlines ; } close(FH); return(1); @@ -779,7 +807,7 @@ complete directory hierarchy. Optionally, a pathname F can be specified, =item B<--flatten,--flatten=keep-intermediate> If combined with C<--git>, C<--svn> or C<--hg> option or the corresponding modes, check out the revisions to compare in a separate temporary directory, and then pass on option C<--flatten> to latexdiff. The directory in which C is invoked defines the subtree which will be checked out. -Note that if additional files are needed which are not included in the flatten procedure (package files, included graphics), they need to be accessible in the current directory. If you use bibtex, it is recommended to include the C<.bbl> file in the version management. +Note that if additional files are needed which are not included in the flatten procedure (package files, included graphics), they need to be accessible in the current directory. If you use bibtex, it is recommended to include the C<.bbl> file in the version management. From latexdiff-vc >=1.3.4 there will be an attempt to create the C<.bbl> file by running bibtex in the retrieved subdirectories; note that the bibtex is run in the temporary subdirectories so any .bib or .bst files either need to be under version management, or in the global search paths for bibtex (shell environment variables C and C). The generic usage of this function is : C where master.tex is the project file containing the highest level of includes etc.