#!/usr/bin/perl use strict; use warnings; use version; use Carp; use Digest; use File::Spec; use File::Spec::Unix; use YAML::Tiny; my $version = qv('0.0.1'); sub say { print @_, "\n"; } my $basedir = '../..'; my $commands = { 'help' => \&help, 'add' => \&add, 'status' => \&status, }; my $help = {}; sub filetype { my ($path) = @_; if ($path =~ /\.(java|g)$/xms) { return 'text/plain'; } else { return 'application/octet-stream'; } } sub sha1sum { my ($filename) = @_; open my $in, '<', $filename or croak "Can't open $filename: $!"; if (filetype($filename) =~ /^text\//xms) { # keep standard line feed conversion } else { if (!binmode $in) { croak "Can't binmode $filename: $!"; } } my $sha1 = Digest->new('SHA-1'); $sha1->addfile($in); my $digest = $sha1->hexdigest; close $in or warn "Can't close $filename: $!"; return $digest; } my $inc_paths = [ $basedir, "$basedir/runtime/Java/src", ]; sub resolve_file { my ($filename) = @_; my $resolved_file; if (-e $filename) { $resolved_file = $filename; } else { my @canidates = grep { -e $_ } map { File::Spec->catfile($_, $filename) } @$inc_paths; $resolved_file = $canidates[0]; } if (defined $resolved_file) { $resolved_file = File::Spec::Unix->canonpath($resolved_file); } return $resolved_file; } $help->{help} = << 'EOH'; help: Describe the usage of this program or its subcommands. Usage: help [SUBCOMMAND...] EOH sub help { my ($cmd) = @_; if (defined $cmd) { print $help->{$cmd}; } else { say << 'EOH'; Usage: port <subcommand> [options] [args] EOH say "Available subcommands:"; foreach my $cmd (keys %$help) { say " $cmd"; } } } $help->{add} = << 'EOH'; add: Adds the file to the list of ported files. Usage: add PATH... EOH sub add { my ($filename) = @_; my $port = YAML::Tiny->read('port.yml'); my $status = $port->[0]->{status}; if (!defined $status) { $status = $port->[0]->{status} = {}; } my $path = resolve_file($filename); if (!defined $path) { croak "File not found: $filename"; } my $digest = sha1sum($path); $status->{$filename} = { 'sha1' => $digest, }; $port->write('port.yml'); } $help->{status} = << 'EOH'; status: Print the status of the ported files. usage: status [PATH...] EOH sub status { my $port = YAML::Tiny->read('port.yml'); my $status = $port->[0]->{status}; while (my ($filename, $fstatus) = each (%$status)) { my $path = resolve_file($filename); my $digest = sha1sum($path); if ($digest ne $fstatus->{sha1}) { say "M $filename"; } } } my ($cmd, @args) = @ARGV; if (defined $cmd) { my $cmd_f = $commands->{$cmd}; if (defined $cmd_f) { $cmd_f->(@args); } else { say "Unknown command: '$cmd'"; say "Type 'port help' for usage."; exit 1; } } else { say "Type 'port help' for usage."; exit 1; } __END__ =head1 NAME port - ANTLR Perl 5 port status =head1 VERSION This documentation refers to port version 0.0.1 =head1 USAGE port help port status =head1 DESCRIPTION The primary language target for ANTLR is Java. The Perl 5 port only follows this primary target language. This brings up the problem to follow the changes made to the primary target, by knowing I<what> has changed and I<how>. This tool keeps a database of file paths and content checksum. Once the port of a file (Java class, grammar, ...) is completed it is added to the database (C<port add>). This database can then be queried to check what primary files have changed (C<port status>). The revision control software should be helpful to determine the actual changes. =head1 AUTHOR Ronald Blaschke (ron@rblasch.org)