1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use version;
7use Carp;
8use Digest;
9use File::Spec;
10use File::Spec::Unix;
11use YAML::Tiny;
12
13my $version = qv('0.0.1');
14
15sub say {
16    print @_, "\n";
17}
18
19my $basedir = '../..';
20
21my $commands = {
22    'help'   => \&help,
23    'add'    => \&add,
24    'status' => \&status,
25};
26
27my $help = {};
28
29sub filetype {
30    my ($path) = @_;
31
32    if ($path =~ /\.(java|g)$/xms) {
33        return 'text/plain';
34    }
35    else {
36        return 'application/octet-stream';
37    }
38}
39
40sub sha1sum {
41    my ($filename) = @_;
42
43    open my $in, '<', $filename or croak "Can't open $filename: $!";
44    if (filetype($filename) =~ /^text\//xms) {
45        # keep standard line feed conversion
46    } else {
47        if (!binmode $in) {
48            croak "Can't binmode $filename: $!";
49        }
50    }
51    my $sha1 = Digest->new('SHA-1');
52    $sha1->addfile($in);
53    my $digest = $sha1->hexdigest;
54    close $in or warn "Can't close $filename: $!";
55    return $digest;
56}
57
58my $inc_paths = [
59    $basedir,
60    "$basedir/runtime/Java/src",
61];
62
63sub resolve_file {
64    my ($filename) = @_;
65
66    my $resolved_file;
67    if (-e $filename) {
68        $resolved_file = $filename;
69    }
70    else {
71        my @canidates
72            = grep { -e $_ }
73              map { File::Spec->catfile($_, $filename) }
74              @$inc_paths;
75        $resolved_file = $canidates[0];
76    }
77
78    if (defined $resolved_file) {
79        $resolved_file = File::Spec::Unix->canonpath($resolved_file);
80    }
81
82    return $resolved_file;
83}
84
85$help->{help} = << 'EOH';
86help: Describe the usage of this program or its subcommands.
87Usage: help [SUBCOMMAND...]
88EOH
89
90sub help {
91    my ($cmd) = @_;
92
93    if (defined $cmd) {
94        print $help->{$cmd};
95    }
96    else {
97        say << 'EOH';
98Usage: port <subcommand> [options] [args]
99EOH
100        say "Available subcommands:";
101        foreach my $cmd (keys %$help) {
102            say "   $cmd";
103        }
104    }
105
106}
107
108$help->{add} = << 'EOH';
109add: Adds the file to the list of ported files.
110Usage: add PATH...
111EOH
112
113sub add {
114    my ($filename) = @_;
115
116    my $port = YAML::Tiny->read('port.yml');
117    my $status = $port->[0]->{status};
118    if (!defined $status) {
119        $status = $port->[0]->{status} = {};
120    }
121
122    my $path = resolve_file($filename);
123    if (!defined $path) {
124        croak "File not found: $filename";
125    }
126    my $digest = sha1sum($path);
127    $status->{$filename} = {
128        'sha1' => $digest,
129    };
130    $port->write('port.yml');
131}
132
133$help->{status} = << 'EOH';
134status: Print the status of the ported files.
135usage: status [PATH...]
136EOH
137
138sub status {
139    my $port = YAML::Tiny->read('port.yml');
140
141    my $status = $port->[0]->{status};
142
143    while (my ($filename, $fstatus) = each (%$status)) {
144        my $path = resolve_file($filename);
145
146        my $digest = sha1sum($path);
147
148        if ($digest ne $fstatus->{sha1}) {
149            say "M $filename";
150        }
151    }
152}
153
154my ($cmd, @args) = @ARGV;
155
156if (defined $cmd) {
157    my $cmd_f = $commands->{$cmd};
158    if (defined $cmd_f) {
159        $cmd_f->(@args);
160    }
161    else {
162        say "Unknown command: '$cmd'";
163        say "Type 'port help' for usage.";
164        exit 1;
165    }
166}
167else {
168    say "Type 'port help' for usage.";
169    exit 1;
170}
171
172__END__
173
174=head1 NAME
175
176port - ANTLR Perl 5 port status
177
178=head1 VERSION
179
180This documentation refers to port version 0.0.1
181
182=head1 USAGE
183
184    port help
185
186    port status
187
188=head1 DESCRIPTION
189
190The primary language target for ANTLR is Java.  The Perl 5 port only follows
191this primary target language.  This brings up the problem to follow the
192changes made to the primary target, by knowing I<what> has changed and I<how>.
193
194This tool keeps a database of file paths and content checksum.  Once the port
195of a file (Java class, grammar, ...) is completed it is added to the
196database (C<port add>).  This database can then be queried to check what
197primary files have changed (C<port status>).  The revision control software
198should be helpful to determine the actual changes.
199
200=head1 AUTHOR
201
202Ronald Blaschke (ron@rblasch.org)
203
204