http://qs1969.pair.com?node_id=1148041

LanX has asked for the wisdom of the Perl Monks concerning the following question:

Brethren! =)

I'm confronted with the task to merge two versions of the same Module which spread apart a year ago.

Unfortunately winmerge is highlighting 90% differences ...

My plan is now to extract all comments and POD , to normalize the code ( Perl::Tidy ) and to rearrange the methods (with hints to the original position, probably using B::Xref ).

Finally I want to analyse the differences of the resulting code to track conflicts.

Before I reinvent the wheel, are there recommended tools specialized on Perl to help me do what I plan?

TIA!

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

Replies are listed 'Best First'.
Re: Tool for diff'ing/anaylyzing two branches of same Perl code?
by stevieb (Canon) on Nov 18, 2015 at 17:57 UTC

    Hey LanX,

    Recently I updated one of my modules to use PPI, so this was fresh in my memory. This won't get you all the way, but it's a sane way to remove all POD and comment elements, as well as providing you an array of the sub names in the order they are currently listed in the file you're working on.

    use warnings; use strict; use PPI; my $file = 'Test.pm'; my $outfile = 'Nopod.pm'; my $ppi_doc = PPI::Document->new($file); $ppi_doc->prune('PPI::Token::Pod'); $ppi_doc->prune('PPI::Token::Comment'); my @subs; for (@{ $ppi_doc->find('PPI::Statement::Sub') }){ push @subs, $_->name; } $ppi_doc->save($outfile); print "$_\n" for @subs;

    Hope this helps!

    Update: added code to catch the original order of subs in the file.

    Update2: I monkeyed around with one of my own modules Devel::Examine::Subs (v1.56+) that does subroutine maintenance, and with some trickery (as a PoC), wrote a script that strips POD and comments, gets the order of the sub names, removes all subs from each file, and inserts them back in (starting at the first line where the first sub used to start in each file) in the order taken from the first argument. Just pass the script the two files, starting with the one who's sub order you want to keep.

    use warnings; use strict; use Devel::Examine::Subs; use PPI; # unneeded, technically due to above use if (@ARGV != 2){ print "Usage: ./script.pl Good.pm Old.pm\n"; exit; } my @files = @ARGV; my @order; for my $file (@files){ my $outfile = "$file.new"; my $ppi_doc = PPI::Document->new($file); $ppi_doc->prune('PPI::Token::Pod'); $ppi_doc->prune('PPI::Token::Comment'); my @subs; for (@{ $ppi_doc->find('PPI::Statement::Sub') }){ push @subs, $_->name; } # set the order in the global var @order = @subs if ! @order; $ppi_doc->save($outfile); my ($des, $sub_obj_hash); { $des = Devel::Examine::Subs->new(file => $outfile); $sub_obj_hash = $des->objects(objects_in_hash => 1); } $ppi_doc = PPI::Document->new($outfile); $ppi_doc->prune('PPI::Statement::Sub'); $ppi_doc->save($outfile); $des = Devel::Examine::Subs->new(file => $outfile); my $first_line = $sub_obj_hash->{$subs[0]}->start; my @code; for (@order){ push @code, @{ $sub_obj_hash->{$_}->code }; } $des->inject(line_num => $first_line, code => \@code); }

    I know others have provided solutions already, but I'm curious to see how far this actually gets you. It assumes both files have the same subroutines, and the data is written to the same files passed in, with a ".new" extension.

    Update: if you've read this far, you see what I'm trying to do. I'm going to take the CPAN namespace Devel::Examine::File so I can extend what I've already done, and make it officially file-based. The want that OP desired is something I've wanted to expand into anyways, and it will alleviate some of the hacks I have in the current module that it just shouldn't be doing.

      Thanks!

      Sorry for the delay but since it's work related I restrict answering to office time, and this problem slid out of scope.

      The idea of using ppi to have a semantic diff is quite nice, I'll follow this track next time I'm confronted with that problem.

      Thanks again! :)

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Re: Tool for diff'ing/anaylyzing two branches of same Perl code?
by choroba (Cardinal) on Nov 18, 2015 at 17:46 UTC
    I sympathise with you. Maybe Code::CutNPaste could help you?
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Tool for diff'ing/anaylyzing two branches of same Perl code? (pieces)
by tye (Sage) on Nov 18, 2015 at 17:58 UTC

    You look at the huge pile of merge conflicts and pick a common pattern of changes. Then you apply those changes to the branch where they weren't already applied. Then you look at the new, smaller pile of merge conflicts and pick another set of changes. Repeat until resolving the merge conflict is reasonable.

    - tye        

        Why not just use VCSVimDiff via vcscommand?

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: Tool for diff'ing/anaylyzing two branches of same Perl code?
by fishmonger (Chaplain) on Nov 18, 2015 at 19:30 UTC

    Have you considered using git for handling the merge as well as for tracking/managing any further changes going forward?

      Of course!

      Did I give the impression that its my project? :)

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!