[Midnightbsd-cvs] mports: mporter: Add mporter; a script I use to automate repetative
ctriv at midnightbsd.org
ctriv at midnightbsd.org
Wed Dec 10 11:39:31 EST 2008
Log Message:
-----------
Add mporter; a script I use to automate repetative maintaince tasks. At the
moment it is poorly documented, but I hope to improve the docs in the
future.
Added Files:
-----------
mports/Tools/scripts:
mporter (r1.1)
-------------- next part --------------
--- /dev/null
+++ Tools/scripts/mporter
@@ -0,0 +1,331 @@
+#!/usr/local/bin/perl
+
+use strict;
+use warnings;
+use File::Temp qw(tempfile);
+use File::Copy qw(move);
+use Cwd;
+
+my %operations = (
+ licenseit => \&add_license,
+ add => \&checkin_port,
+ freecp => \©_from_freebsd,
+ mportify => \&convert_from_freebsd_style,
+ syncdir => \&update_directory_makefile,
+);
+
+
+my $cmd = shift || usage();
+
+my $op = $operations{$cmd} || usage();
+
+$op->(@ARGV);
+
+
+sub add_license {
+ my ($cvs) = @_;
+
+ if ($cvs && $cvs eq '-c') {
+ $cvs = 1;
+ } else {
+ $cvs = 0;
+ }
+
+ my $linenum = 0;
+ open(my $mk, '<', 'Makefile') || die "Couldn't open Makefile ($!). Did you cd to the port?\n";
+ while (<$mk>) {
+ $linenum++;
+ if (m/COMMENT/) {
+ last;
+ }
+ }
+ close($mk) || die "Couldn't close Makefile: $!\n";
+
+ # bump once more to get to the next line
+ $linenum++;
+ my $wrksrc = makevar('WRKSRC');
+
+ runq("make BATCH=1 extract");
+ runq("cd $wrksrc && ls && $ENV{SHELL}");
+
+ runq("$ENV{EDITOR} +$linenum Makefile");
+
+ if ($cvs) {
+ run("make FATAL_LICENSE_CHECK=1 check-license"); # this dies if bad
+ cvs_ci("added license", "Makefile");
+ }
+}
+
+
+sub copy_from_freebsd {
+ my ($port) = @_;
+
+ unless ($port) {
+ ($port = getcwd()) =~ s:^/usr/mports::;
+ }
+
+ $port =~ m:\w+/\w+: || die "Invalid port name: $port\n";
+
+ unless (-d "/usr/mports/$port") {
+ mkdir("/usr/mports/$port") || die "Couldn't mkdir /usr/mports/$port: $!\n";
+ }
+
+ run("cd /usr/mports/$port && cvs -d anoncvs\@anoncvs1.freebsd.org:/home/ncvs export -DNOW ports/$port");
+ runq("mv /usr/mports/$port/ports/$port/* /usr/mports/$port/");
+ runq("rm -r /usr/mports/$port/ports");
+}
+
+
+sub convert_from_freebsd_style {
+ my ($tmp, $tmpname) = tempfile();
+
+ open(my $in, '<', 'Makefile') || die "Couldn't open makefile ($!), did you cd to the port?\n";
+ while (<$in>) {
+ next if m/^#.*for:/ || m/^#.*created:/ || m/^#.*Whom:/;
+
+ if (m/\$FreeBSD/) {
+ s/\$FreeBSD/\$MidnightBSD/;
+ }
+
+ if (m/MAINTAINER=(\s*)(\S+)/) {
+ $_ = "MAINTAINER=$1ports\@MidnightBSD.org\n";
+ }
+
+ print $tmp $_;
+ }
+
+ close($in) || die "Couldn't close makefile: $!\n";
+ close($tmp) || die "Couldn't close $tmpname: $!\n";
+
+ move($tmpname, 'Makefile') || die "Couldn't mv $tmpname Makefile: $!\n";
+}
+
+
+sub checkin_port {
+ my $name = makevar('PKGNAME');
+ my $orig = getcwd();
+ my $upDirMakefile = 0;
+
+ unless (-d 'CVS') {
+ chdir('..') || die "Couldn't chdir '..': $!\n";
+ (my $dir = $orig) =~ s:.*/::;
+
+ run("cvs add $dir");
+ $upDirMakefile = 1;
+ chdir($orig) || die "Couldn't chdir $orig: $!\n";
+ }
+
+ run("cvs add Makefile distinfo pkg-*");
+
+ if (-d 'files') {
+ run("cvs add files");
+ system("cd files && cvs add *"); # we don't care if this returns non-zero.
+
+ }
+
+ cvs_ci("Added $name");
+
+ if ($upDirMakefile) {
+ chdir('..') || die "Couldn't chidr to '..': $!\n";
+ update_directory_makefile();
+ }
+
+}
+
+
+sub update_directory_makefile {
+ # XXX check that we're really in a directory
+ my @ports = list_directories();
+ my $make = DirMakefile->new('Makefile');
+
+ $make->subdirs(\@ports);
+
+ $make->write;
+
+ cvs_ci($make->message, 'Makefile');
+}
+
+
+sub list_directories {
+ my $dh;
+
+ opendir($dh, '.') || die "Couldn't open .: $!\n";
+
+ my @dirs = grep { -d && $_ ne '.' && $_ ne '..' && $_ ne 'CVS' } readdir($dh);
+
+ closedir($dh) || die "Couldn't close .: $!\n";
+
+ return @dirs;
+}
+
+
+=head2 cvs_ci(@files)
+
+Check in files to cvs, but first display the diff and let the user review
+the changes
+
+=cut
+
+sub cvs_ci {
+ my ($msg, @files) = @_;
+
+ runq("cvs diff -u @files | $ENV{PAGER}");
+
+ print STDERR qq/Check in changes with message: "$msg" [yes]: /;
+ chomp(my $ans = <>);
+
+ if (!$ans || $ans =~ m/y(es)?/i) {
+ run("cvs ci -m '$msg' @files");
+ }
+}
+
+
+sub run {
+ my ($cmd) = @_;
+
+ print $cmd, "\n";
+ runq($cmd);
+}
+
+
+sub runq {
+ my ($cmd) = @_;
+ system($cmd) == 0 || die "$cmd returned non-zero: " . ($? >> 8) . "\n";
+}
+
+
+sub makevar {
+ my ($var) = @_;
+
+ my $val = `make -V $var`;
+ chomp($val);
+
+ return $val;
+}
+
+sub usage {
+ my $self = $0;
+ $self =~ s:.*/::;
+
+ die "Usage: $self <@{[ sort keys %operations ]}>\n";
+}
+
+
+=head1 DirMakefile
+
+This class represents a directory makefile. It can parse such a file, change the list of
+subdirs, and then update the file on disk.
+
+=cut
+
+{
+ package DirMakefile;
+
+ use strict;
+ use warnings;
+
+ sub new {
+ my ($class, $file) = @_;
+
+ my $self = bless { file => $file }, $class;
+
+ $self->_parse_file;
+
+ return $self;
+ }
+
+
+ sub _parse_file {
+ my ($self) = @_;
+
+ local $_;
+ $self->{header} = '';
+ $self->{footer} = '';
+ $self->{subdirs} = [];
+
+ open(my $fh, '<', $self->{file}) || die "Couldn't open $self->{file}: $!\n";
+
+ while (<$fh>) {
+ last if m/SUBDIR/;
+
+ $self->{header} .= $_;
+ }
+
+
+ if (m/SUBDIR\s*\+?=\s*([\.\w-]+)/) {
+ push(@{$self->{subdirs}}, $1);
+ } else {
+ die "Couldn't match first subdir.";
+ }
+
+ while (<$fh>) {
+ last unless m/SUBDIR\s*\+?=\s*([\.\w-]+)/;
+ push(@{$self->{subdirs}}, $1);
+ }
+
+ $self->{footer} .= $_;
+ $self->{footer} .= $_ for <$fh>;
+
+ close($fh) || die "Couldn't close $self->{file}: $!";
+ }
+
+
+ sub subdirs {
+ my $self = shift;
+
+ if (@_) {
+ my $new = shift;
+ $new = [ sort @$new ];
+
+ $self->{msg} = _build_diff_msg($self->{subdirs}, $new);
+ $self->{subdirs} = $new;
+ }
+
+ return $self->{subdirs};
+ }
+
+
+ sub _build_diff_msg {
+ my ($old, $new) = @_;
+
+ my %old = map { $_ => 1 } @$old;
+ my %new = map { $_ => 1 } @$new;
+
+ my @added = grep { !$old{$_} } @$new;
+ my @removed = grep { !$new{$_} } @$old;
+
+ my $msg = '';
+
+ if (@added) {
+ $msg .= "added: " . join(', ' => @added) . '. ';
+ }
+
+ if (@removed) {
+ $msg .= "removed: " . join(',' => @removed) . '. ';
+ }
+
+ return $msg;
+ }
+
+
+ sub write {
+ my ($self) = @_;
+
+ my ($tmp, $tmpname) = File::Temp::tempfile();
+
+ print $tmp $self->{header};
+
+ for (@{$self->{subdirs}}) {
+ print $tmp " SUBDIR += $_\n";
+ }
+
+ print $tmp $self->{footer};
+
+ close($tmp) || die "Couldn't close tmpfile: $!\n";
+
+ File::Copy::move($tmpname, $self->{file});
+ }
+
+ sub message { return $_[0]->{msg}; }
+}
+
\ No newline at end of file
More information about the Midnightbsd-cvs
mailing list