michael@428: ## michael@428: ## openpkg dev -- OpenPKG Package Development Tool michael@428: ## Copyright (c) 2008-2012 OpenPKG GmbH michael@428: ## michael@428: ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208. michael@428: ## All rights reserved. Licenses which grant limited permission to use, michael@428: ## copy, modify and distribute this software are available from the michael@428: ## OpenPKG GmbH. michael@428: ## michael@428: ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED michael@428: ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF michael@428: ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@428: ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR michael@428: ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@428: ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@428: ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF michael@428: ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND michael@428: ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, michael@428: ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT michael@428: ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF michael@428: ## SUCH DAMAGE. michael@428: ## michael@428: michael@428: require 5; michael@428: michael@428: # OpenPKG instance prefix and RPM michael@428: my $openpkg_prefix = $ENV{'OPENPKG_PREFIX'}; michael@428: delete $ENV{'OPENPKG_PREFIX'}; michael@428: michael@428: # program identification michael@428: my $prog_name = "dev"; michael@428: my $prog_vers = "20100111"; michael@428: michael@428: # home-brewn getopt(3) style option parser michael@428: sub getopts ($$@) { michael@428: my ($opt_spec, $opts, @argv_orig) = @_; michael@428: my (%optf) = map { m/(\w)/; $1 => $_ } $opt_spec =~ m/(\w:|\w)/g; michael@428: my (@argv, $optarg); michael@428: michael@428: foreach (@argv_orig) { michael@428: if (@argv) { michael@428: push @argv, $_; michael@428: } elsif (defined $optarg) { michael@428: if (exists $opts->{$optarg}) { michael@428: $opts->{$optarg} .= " $_"; michael@428: } else { michael@428: $opts->{$optarg} = $_; michael@428: } michael@428: $optarg = undef; michael@428: } elsif (!/^[-]/) { michael@428: push @argv, $_; michael@428: } else { michael@428: while (/^\-(\w)(.*)/) { michael@428: if (exists $optf{$1}) { michael@428: if (length($optf{$1}) > 1) { michael@428: if ($2 ne '') { michael@428: if (exists $opts->{$1}) { michael@428: $opts->{$1} .= " $2"; michael@428: } else { michael@428: $opts->{$1} = $2; michael@428: } michael@428: } else { michael@428: $optarg = $1; michael@428: } michael@428: last; michael@428: } else { michael@428: $opts->{$1} = 1; michael@428: } michael@428: } else { michael@428: warn "openpkg:$prog_name:WARNING: unknown option $_\n"; michael@428: } michael@428: $_ = "-$2"; michael@428: } michael@428: } michael@428: } michael@428: if (defined $optarg) { michael@428: warn "openpkg:$prog_name:WARNING: option $optarg requires an argument\n"; michael@428: } michael@428: foreach my $opt (keys %optf) { michael@428: if (not exists $opts->{$opt}) { michael@428: $opts->{$opt} = (length($optf{$opt}) > 1 ? "" : 0); michael@428: } michael@428: } michael@428: return @argv; michael@428: } michael@428: michael@428: # determine reasonable temporary directory michael@428: my $tmpdir = ($ENV{"TMPDIR"} || "/tmp"); michael@428: $tmpdir .= "/openpkg-$prog_name-$$"; michael@428: my $rc = system("umask 022; $openpkg_prefix/lib/openpkg/shtool mkdir -f -p -m 755 $tmpdir || exit $?"); michael@428: if ($rc != 0) { michael@428: die "failed to create temporary directory: $tmpdir"; michael@428: } michael@428: michael@428: # parse command line options michael@428: my $opts = {}; michael@428: @ARGV = getopts("h", $opts, @ARGV); michael@428: michael@428: # usage sanity check and usage help michael@428: sub usage { michael@428: my ($rc) = @_; michael@428: my $usage = michael@428: "openpkg:$prog_name:USAGE: openpkg dev []\n"; michael@428: if ($rc == 0) { michael@428: print STDOUT $usage; michael@428: } michael@428: else { michael@428: print STDERR $usage; michael@428: } michael@428: exit($rc); michael@428: } michael@428: if ($opts->{"h"}) { michael@428: usage(0); michael@428: } michael@428: if (@ARGV == 0) { michael@428: usage(1); michael@428: } michael@428: michael@428: # command map michael@428: my $map = { michael@428: "unpack " => { -alias => qr/^(up|ex)$/, -key => "x" }, michael@428: "edit\n" => { -alias => qr/^(ed|vi)$/, -key => "v" }, michael@428: "build -s track\n" => { -alias => qr/^(bt|tr)$/, -key => "t" }, michael@428: "build -s fetch\n" => { -alias => qr/^(bf|fe)$/, -key => "f" }, michael@428: "build\n" => { -alias => qr/^(ba|bu)$/, -key => "b" }, michael@428: "build -s prep\n" => { -alias => qr/^bp$/, -key => "1" }, michael@428: "build -s compile\n" => { -alias => qr/^bc$/, -key => "2" }, michael@428: "build -s install\n" => { -alias => qr/^bi$/, -key => "3" }, michael@428: "build -s binary\n" => { -alias => qr/^bb$/, -key => "4" }, michael@428: "build -s source\n" => { -alias => qr/^bs$/, -key => "s" }, michael@428: "peek\n" => { -alias => qr/^pe$/, -key => "p" }, michael@428: "diff\n" => { -alias => qr/^di$/, -key => "d" }, michael@428: "install\n" => { -alias => qr/^in(?:st)?$/, -key => "i" }, michael@428: "erase\n" => { -alias => qr/^er$/, -key => "e" }, michael@428: "lint\n" => { -alias => qr/^li$/, -key => "l" }, michael@428: "release " => { -alias => qr/^rel?$/, -key => "r" }, michael@428: }; michael@428: michael@428: # dispatch command michael@428: my $cmd = shift(@ARGV); michael@428: foreach my $c (keys %{$map}) { michael@428: my $a = $map->{$c}->{-alias}; michael@428: if ($cmd =~ $a) { michael@428: $c =~ s/\n$//; michael@428: my @args = split(/\s+/, $c); michael@428: $cmd = shift(@args); michael@428: unshift(@ARGV, @args); michael@428: print STDOUT "\033[34m\$ opd $cmd " . join(" ", map { michael@428: my $x = $_; michael@428: $x =~ s/"/\\"/g; michael@428: $x =~ s/^(.*[ \t].*)$/"$1"/; michael@428: $x michael@428: } @ARGV) . "\033[0m\n"; michael@428: } michael@428: } michael@428: my $func = "cmd_$cmd"; michael@428: if (not defined(&$func)) { michael@428: print STDERR "openpkg:$prog_name:ERROR: invalid command \"$cmd\"\n"; michael@428: usage(1); michael@428: } michael@428: my $rc = &$func($opts, @ARGV); michael@428: exit($rc); michael@428: michael@428: # execute a shell command michael@428: sub run { michael@428: my ($cmd) = @_; michael@428: print STDOUT "\033[34m\$ $cmd\033[0m\n"; michael@428: my $rc = system($cmd); michael@428: return $rc; michael@428: } michael@428: michael@428: # determine path to package specification michael@428: sub specfile { michael@428: my $specfile = (glob("*.spec"))[0]; michael@428: if (not defined $specfile) { michael@428: $specfile = (glob("src/*.spec"))[0]; michael@428: if (not defined $specfile) { michael@428: $specfile = (glob("*/*.spec"))[0]; michael@428: if (not defined $specfile) { michael@428: print STDERR "openpkg:$prog_name:ERROR: unable to determine package specification file\n"; michael@428: exit(1); michael@428: } michael@428: } michael@428: } michael@428: return $specfile; michael@428: } michael@428: michael@428: # command: interactive shell michael@428: sub cmd_shell ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("s", $lopts, @argv); michael@428: michael@428: # determine release michael@428: my $release = `$openpkg_prefix/bin/openpkg release -F '%t'`; michael@428: $release =~ s/\n$//s; michael@428: michael@428: # create dot files michael@428: my $screenrc = "$tmpdir/dot.screenrc"; michael@428: my $bashsh = "$tmpdir/bash.sh"; michael@428: my $bashrc = "$tmpdir/dot.bashrc"; michael@428: my $inputrc = "$tmpdir/dot.inputrc"; michael@428: unlink("$screenrc"); michael@428: unlink("$bashsh"); michael@428: unlink("$bashrc"); michael@428: unlink("$inputrc"); michael@428: my $title = "openpkg dev"; michael@428: $title .= '%? %{= rW} %n %{-}%?'; michael@428: $title .= ' %=%-w%{= rW}%50>%n %t%{-}%+w'; michael@428: my $screenrc_data = ""; michael@428: $screenrc_data .= "source \"$ENV{HOME}/.screenrc\"\n" if (-f "$ENV{HOME}/.screenrc"); michael@428: $screenrc_data .= michael@428: "escape ^Aa\n" . michael@428: "startup_message off\n" . michael@428: "vbell off\n" . michael@428: "defscrollback 10000\n" . michael@428: "defmonitor off\n" . michael@428: "msgminwait 1\n" . michael@428: "msgwait 1\n" . michael@428: "hardstatus alwayslastline \" $title \"\n" . michael@428: "shell $bashsh\n"; michael@428: my $bashsh_data = michael@428: "##\n" . michael@428: "##\ bash.sh -- \"openpkg dev shell\" GNU bash wrapper script\n" . michael@428: "##\n" . michael@428: "\n" . michael@428: "OPENPKG_PREFIX=\"$openpkg_prefix\"\n" . michael@428: "export OPENPKG_PREFIX\n" . michael@428: "INPUTRC=\"$inputrc\"\n" . michael@428: "export INPUTRC\n" . michael@428: "SHELL=\"$openpkg_prefix/lib/openpkg/bash\"\n" . michael@428: "export SHELL\n" . michael@428: "eval `$openpkg_prefix/bin/openpkg rpm --eval 'T=\"\%{_tmppath}\"; S=\"\%{_specdir}\"; D=\"\%{_sourcedir}\"'`\n" . michael@428: "export T S D\n" . michael@428: "\$SHELL --rcfile $bashrc"; michael@428: my $bashrc_data = michael@428: "##\n" . michael@428: "## dot.bashrc -- \"openpkg dev shell\" GNU bash configuration\n" . michael@428: "##\n" . michael@428: "\n" . michael@428: "# load user's standard bash run-command script\n" . michael@428: "if [ -f ~/.bashrc ]; then\n" . michael@428: " . ~/.bashrc\n" . michael@428: "fi\n" . michael@428: "\n" . michael@428: "# configure a special command-line prompt\n" . michael@428: "if [ \".\$TERM\" = .screen ]; then\n" . michael@428: " PS1=\"\\\\u@\\\\h:\\\\w [P=\\\\e[1m\\\${OPENPKG_PREFIX}\\\\e[0m]\\n\\\\\\\$ \\\\ek\\\\W\\\\e\\\\\\\\\"\n" . michael@428: "else\n" . michael@428: " PS1=\"\\\\u@\\\\h:\\\\w [P=\\\\e[1m\\\${OPENPKG_PREFIX}\\\\e[0m]\\n\\\\\\\$ \"\n" . michael@428: "fi\n" . michael@428: "alias openpkg=\"\\\${OPENPKG_PREFIX}/bin/openpkg\"\n" . michael@428: "alias opd=\"\\\${OPENPKG_PREFIX}/bin/openpkg dev\"\n" . michael@428: "\n"; michael@428: my $inputrc_data = michael@428: "##\n" . michael@428: "## dot.inputrc -- \"openpkg dev shell\" GNU readline configuration\n" . michael@428: "##\n" . michael@428: "\n"; michael@428: foreach my $c (keys %{$map}) { michael@428: my $k = $map->{$c}->{-key}; michael@428: $c =~ s/\n/\\n/sg; michael@428: $inputrc_data .= "\"\\e$k\": \"opd $c\"\n"; michael@428: } michael@428: $inputrc_data .= "\n"; michael@428: open(SCREENRC, ">$screenrc"); michael@428: print(SCREENRC $screenrc_data); michael@428: close(SCREENRC); michael@428: open(BASHSH, ">$bashsh"); michael@428: print(BASHSH $bashsh_data); michael@428: close(BASHSH); michael@428: system("chmod a+x $bashsh"); michael@428: open(BASHRC, ">$bashrc"); michael@428: print(BASHRC $bashrc_data); michael@428: close(BASHRC); michael@428: open(INPUTRC, ">$inputrc"); michael@428: print(INPUTRC $inputrc_data); michael@428: close(INPUTRC); michael@428: michael@428: # run interactive shell michael@428: print STDOUT "\033[34m++ entering OpenPKG $release development shell\033[0m\n"; michael@428: my $rc; michael@428: if ($lopts->{"s"}) { michael@428: $rc = system("screen -c $screenrc -S 'openpkg-dev-shell' -d -R"); michael@428: } michael@428: else { michael@428: $rc = system("$bashsh"); michael@428: } michael@428: michael@428: # cleanup michael@428: unlink("$tmpdir/dot.screenrc"); michael@428: unlink("$tmpdir/bash.sh"); michael@428: unlink("$tmpdir/dot.bashrc"); michael@428: unlink("$tmpdir/dot.inputrc"); michael@428: unlink("$tmpdir"); michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: unpack source RPM michael@428: sub cmd_unpack ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("l:b:sd", $lopts, @argv); michael@428: if ($lopts->{"l"} eq "") { michael@428: $lopts->{"l"} = "structured"; michael@428: } michael@428: if ($lopts->{"l"} !~ m/^(global|local|simple|structured|distributed)$/) { michael@428: die sprintf("invalid layout type \"%s\"", $lopts->{"l"}); michael@428: } michael@428: if (@argv != 1) { michael@428: die sprintf("exactly one SRPM has to be given"); michael@428: } michael@428: my $srpm = $argv[0]; michael@428: if (not -f $srpm) { michael@428: die sprintf("SRPM \"%s\" has to be a regular file", $srpm); michael@428: } michael@428: my $name = `$openpkg_prefix/bin/openpkg rpm -qp --qf '\%{NAME}' $srpm 2>/dev/null || true`; michael@428: $name =~ s/\r?\n$//s; michael@428: if ($name eq '') { michael@428: die sprintf("unable to determine package name from SRPM \"%s\"", $srpm); michael@428: } michael@428: if ($lopts->{"b"} eq "") { michael@428: $lopts->{"b"} = $srpm; michael@428: if ($lopts->{"b"} =~ m/\.src\.rpm$/) { michael@428: $lopts->{"b"} =~ s/\.src\.rpm$//; michael@428: } michael@428: else { michael@428: my $subdir = `$openpkg_prefix/bin/openpkg rpm -qp --qf '\%{NAME}-\%{VERSION}-\%{RELEASE}' $srpm 2>/dev/null || true`; michael@428: $lopts->{"b"} = $subdir; michael@428: } michael@428: } michael@428: michael@428: # determine result directory michael@428: my $basedir = $lopts->{"b"}; michael@428: my ($macrosfile, $specdir, $sourcedir); michael@428: if ($lopts->{"l"} eq "global") { michael@428: $macrosdir = "$openpkg_prefix/etc/openpkg"; michael@428: $macrosfile = "$openpkg_prefix/etc/openpkg/rpmmacros"; michael@428: $specdir = "$openpkg_prefix/RPM/SRC/$name"; michael@428: $sourcedir = "$openpkg_prefix/RPM/SRC/$name"; michael@428: $builddir = "$openpkg_prefix/RPM/TMP"; michael@428: $tmpdir = "$openpkg_prefix/RPM/TMP"; michael@428: $binrpmdir = "$openpkg_prefix/RPM/PKG"; michael@428: $srcrpmdir = "$openpkg_prefix/RPM/PKG"; michael@428: } michael@428: elsif ($lopts->{"l"} eq "local") { michael@428: $macrosdir = "$basedir/.openpkg"; michael@428: $macrosfile = "$basedir/.openpkg/rpmmacros"; michael@428: $specdir = "$basedir"; michael@428: $sourcedir = "$basedir"; michael@428: $builddir = "$basedir"; michael@428: $tmpdir = "$basedir"; michael@428: $binrpmdir = "$basedir"; michael@428: $srcrpmdir = "$basedir"; michael@428: } michael@428: elsif ($lopts->{"l"} eq "simple") { michael@428: $macrosdir = "$basedir/.openpkg"; michael@428: $macrosfile = "$basedir/.openpkg/rpmmacros"; michael@428: $specdir = "$basedir"; michael@428: $sourcedir = "$basedir"; michael@428: $builddir = "$tmpdir"; michael@428: $tmpdir = "$tmpdir"; michael@428: $binrpmdir = "$basedir/.."; michael@428: $srcrpmdir = "$basedir/.."; michael@428: } michael@428: elsif ($lopts->{"l"} eq "structured") { michael@428: $macrosdir = "$basedir/.openpkg"; michael@428: $macrosfile = "$basedir/.openpkg/rpmmacros"; michael@428: $specdir = "$basedir/src"; michael@428: $sourcedir = "$basedir/dst"; michael@428: $builddir = "$basedir/tmp"; michael@428: $tmpdir = "$basedir/tmp"; michael@428: $binrpmdir = "$basedir/pkg/bin"; michael@428: $srcrpmdir = "$basedir/pkg/src"; michael@428: } michael@428: elsif ($lopts->{"l"} eq "distributed") { michael@428: $macrosdir = "$basedir/.openpkg"; michael@428: $macrosfile = "$basedir/.openpkg/rpmmacros"; michael@428: $specdir = "$basedir/src/$name"; michael@428: $sourcedir = "$basedir/dst/$name"; michael@428: $builddir = "$basedir/tmp"; michael@428: $tmpdir = "$basedir/tmp"; michael@428: $binrpmdir = "$basedir/pkg/bin"; michael@428: $srcrpmdir = "$basedir/pkg/src"; michael@428: } michael@428: michael@428: # create still missing directories michael@428: foreach my $dir ($macrosdir, $specdir, $sourcedir, $builddir, $tmpdir, $binrpmdir, $srcrpmdir) { michael@428: if (not -d $dir) { michael@428: print STDOUT "openpkg:$prog_name: creating directory \"$dir\"\n"; michael@428: system("$openpkg_prefix/lib/openpkg/shtool mkdir -f -p -m 755 $dir"); michael@428: } michael@428: } michael@428: michael@428: # unpack SRPM michael@428: print STDOUT "openpkg:$prog_name: unpacking source: \"$srpm\"\n"; michael@428: print STDOUT "openpkg:$prog_name: unpacking target: \"$specdir\"\n"; michael@428: print STDOUT "openpkg:$prog_name: unpacking target: \"$sourcedir\"\n"; michael@428: my $abs_specdir = $specdir; michael@428: my $abs_sourcedir = $sourcedir; michael@428: my $pwd = `pwd`; $pwd =~ s/\r?\n$//s; michael@428: $abs_specdir = "$pwd/$abs_specdir" if ($abs_specdir !~ m/^\//); michael@428: $abs_sourcedir = "$pwd/$abs_sourcedir" if ($abs_sourcedir !~ m/^\//); michael@428: my $rc = system( michael@428: "$openpkg_prefix/bin/openpkg" . michael@428: " --keep-privileges" . michael@428: " rpm" . michael@428: " -i" . michael@428: " --define '_specdir $abs_specdir'" . michael@428: " --define '_sourcedir $abs_sourcedir'" . michael@428: " $srpm" michael@428: ); michael@428: michael@428: # fix location of files michael@428: if (not -f "$specdir/$name.spec") { michael@428: die sprintf("failed to install package \"%s\": file \"%s\" not found\n", $srpm, "$specdir/$name.spec"); michael@428: } michael@428: open(SPEC, "<$specdir/$name.spec"); michael@428: my $spec = ""; { local $/; $spec = ; } michael@428: close(SPEC); michael@428: my $src = {}; michael@428: $spec =~ s/^(?:Source|Patch)\d+:\s+(\S+)/$src->{$1} = 1, ''/mgei; michael@428: foreach my $file (keys %{$src}) { michael@428: if ($file !~ m/^(https?|ftp):\/\//) { michael@428: if (not -f "$specdir/$file" and -f "$sourcedir/$file") { michael@428: system("mv $sourcedir/$file $specdir/$file"); michael@428: } michael@428: } michael@428: } michael@428: michael@428: # create .openpkg/rpmmacros file michael@428: if (not -f $macrosfile) { michael@428: print STDOUT "openpkg:$prog_name: creating file: \"$macrosfile\"\n"; michael@428: my $rpmmacros = michael@428: "##\n" . michael@428: "## .openpkg/rpmmacros -- local OpenPKG RPM macro definitions\n" . michael@428: "##\n" . michael@428: "\n" . michael@428: "\%openpkg_layout" . michael@428: " macrosfile=\%{macrosfile}" . michael@428: " layout=" . $lopts->{"l"} . michael@428: " shared=" . ($lopts->{"s"} ? "yes" : "no") . michael@428: " debug=" . ($lopts->{"d"} ? "yes" : "no") . michael@428: "\n" . michael@428: "\n"; michael@428: open(MACROS, ">$macrosfile"); michael@428: print(MACROS $rpmmacros); michael@428: close(MACROS); michael@428: } michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: edit package specification michael@428: sub cmd_edit ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # run editor michael@428: my $editor = ($ENV{"EDITOR"} || "vi"); michael@428: my $specfile = ($argv[0] || specfile()); michael@428: run("$editor $specfile"); michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: build package michael@428: sub cmd_build ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("s:D:w:", $lopts, @argv); michael@428: if ($lopts->{"s"} eq '') { michael@428: $lopts->{"s"} = "all"; michael@428: } michael@428: if ($lopts->{"s"} !~ m/^(track|fetch|prep|compile|install|binary|source|all)$/) { michael@428: die "invalid step"; michael@428: } michael@428: michael@428: # assembly defines michael@428: my $defs = ""; michael@428: if ($lopts->{"D"}) { michael@428: foreach my $def (split(/\s+/, $lopts->{"D"})) { michael@428: if ($def =~ m/^([^=]+)=(.+)$/) { michael@428: $defs .= "--define '$1 $2' "; michael@428: } michael@428: else { michael@428: $defs .= "--define '$def yes' "; michael@428: } michael@428: } michael@428: } michael@428: if ($lopts->{"w"}) { michael@428: foreach my $def (split(/\s+/, $lopts->{"w"})) { michael@428: $defs .= "--with $def "; michael@428: } michael@428: } michael@428: michael@428: # run build command michael@428: my $specfile = ($argv[0] || specfile()); michael@428: if ($lopts->{"s"} eq 'track') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bt $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'fetch') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bf $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'prep') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bp $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'compile') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bc --short-circuit $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'install') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bi --short-circuit $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'binary') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bb --short-circuit $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'source') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -bs $defs$specfile"); michael@428: } michael@428: elsif ($lopts->{"s"} eq 'all') { michael@428: run("$openpkg_prefix/bin/openpkg rpm -ba $defs$specfile"); michael@428: } michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: peek into package michael@428: sub cmd_peek ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # run query command michael@428: my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{_rpmfilename}'`; michael@428: $template =~ s/\n$//s; michael@428: my $specfile = specfile(); michael@428: my $rpm = `$openpkg_prefix/bin/openpkg rpm -q --specfile '$specfile' --qf 'XXX$template'`; michael@428: $rpm =~ s/^XXX//s; michael@428: $rpm =~ s/\n$//s; michael@428: michael@428: # determine files michael@428: print STDOUT "\033[34m++ determining configuration files\033[0m\n"; michael@428: my @cfgfiles = split(/\n/, `$openpkg_prefix/bin/openpkg rpm -qplc $rpm`); michael@428: print STDOUT "\033[34m++ determining documentation files\033[0m\n"; michael@428: my @docfiles = split(/\n/, `$openpkg_prefix/bin/openpkg rpm -qpld $rpm`); michael@428: print STDOUT "\033[34m++ determining all file information\033[0m\n"; michael@428: my @allfiles = split(/\n/, `$openpkg_prefix/bin/openpkg rpm -qplv $rpm`); michael@428: michael@428: # create package file listing michael@428: foreach my $line (@allfiles) { michael@428: $prefix = ""; michael@428: foreach my $docfile (@docfiles) { michael@428: if ($line =~ m/\s+$docfile\b/s) { michael@428: $prefix .= "D"; michael@428: last; michael@428: } michael@428: } michael@428: foreach my $cfgfile (@cfgfiles) { michael@428: if ($line =~ m/\s+$cfgfile\b/s) { michael@428: $prefix .= "C"; michael@428: last; michael@428: } michael@428: } michael@428: $prefix .= "--"; michael@428: $prefix = substr($prefix, 0, 2); michael@428: if ($line =~ m/^d/) { michael@428: $line =~ s/(\s+\/\S+)/\033[34m$1\033[0m/s; michael@428: } michael@428: print "$prefix $line\n"; michael@428: } michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: show modifications via VCS michael@428: sub cmd_diff ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: my $vcs = ""; michael@428: my $cmd = ""; michael@428: if (-d "CVS") { michael@428: $vcs = "CVS"; michael@428: $cmd = "cvs diff -u3"; michael@428: } michael@428: elsif (-d ".svn") { michael@428: $vcs = "Subversion"; michael@428: $cmd = "svn diff"; michael@428: } michael@428: elsif (-d "_MTN" or -d ".mtn" or michael@428: -d "../_MTN" or -d "../.mtn" or michael@428: -d "../../_MTN" or -d "../../.mtn" or michael@428: -d "../../../_MTN" or -d "../../../.mtn") { michael@428: $vcs = "Monotone"; michael@428: $cmd = "mtn diff ."; michael@428: } michael@428: elsif (-d ".git" or michael@428: -d "../.git" or michael@428: -d "../../.git" or michael@428: -d "../../../.git") { michael@428: $vcs = "Git"; michael@428: $cmd = "git diff . "; michael@428: } michael@428: elsif (-d ".hg" or michael@428: -d "../.hg" or michael@428: -d "../../.hg" or michael@428: -d "../../../.hg") { michael@428: $vcs = "Mercurial"; michael@428: $cmd = "hg diff ." michael@428: } michael@428: else { michael@428: $vcs = "OSSP svs"; michael@428: $cmd = "svs diff"; michael@428: } michael@428: print STDOUT "\033[34m++ modifications as known to underlying $vcs VCS\033[0m\n"; michael@428: run($cmd); michael@428: } michael@428: michael@428: # command: install package michael@428: sub cmd_install ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("fnos", $lopts, @argv); michael@428: michael@428: # run install command michael@428: my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{_rpmfilename}'`; michael@428: $template =~ s/\n$//s; michael@428: my $specfile = specfile(); michael@428: my $rpm = `$openpkg_prefix/bin/openpkg rpm -q --specfile '$specfile' --qf 'XXX$template'`; michael@428: $rpm =~ s/^XXX//s; michael@428: $rpm =~ s/\n$//s; michael@428: chdir("/"); michael@428: run(($lopts->{"s"} ? "sudo " : "") . michael@428: "$openpkg_prefix/bin/openpkg rpm -Uvh" michael@428: . ($lopts->{"f"} ? " --force" : "") michael@428: . ($lopts->{"n"} ? " --nodeps" : "") michael@428: . ($lopts->{"o"} ? " --oldpackage" : "") michael@428: . " $rpm"); michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: erase package michael@428: sub cmd_erase ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("fnas", $lopts, @argv); michael@428: michael@428: # run erase command michael@428: my $specfile = specfile(); michael@428: my $name = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '%{NAME}'`; michael@428: $name =~ s/\n$//s; michael@428: chdir("/"); michael@428: run(($lopts->{"s"} ? "sudo " : "") . michael@428: "$openpkg_prefix/bin/openpkg rpm -e" michael@428: . ($lopts->{"f"} ? " --force" : "") michael@428: . ($lopts->{"n"} ? " --nodeps" : "") michael@428: . ($lopts->{"a"} ? " --allmatches" : "") michael@428: . " $name"); michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: lint package michael@428: sub cmd_lint ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("vb", $lopts, @argv); michael@428: michael@428: # run source linting commands michael@428: my $specfile = specfile(); michael@428: my $fslfile = $specfile; michael@428: $fslfile =~ s/([^\/]+)\.spec$/fsl.$1/s; michael@428: my $rcfile = $specfile; michael@428: $rcfile =~ s/([^\/]+)\.spec$/rc.$1/s; michael@428: my $name = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '%{NAME}'`; michael@428: $name =~ s/\n$//s; michael@428: my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{_rpmfilename}'`; michael@428: $template =~ s/\n$//s; michael@428: my $rpm = `$openpkg_prefix/bin/openpkg rpm -q --specfile '$specfile' --qf 'XXX$template'`; michael@428: $rpm =~ s/^XXX//s; michael@428: $rpm =~ s/\n$//s; michael@428: my $rc = 0; michael@428: $rc += run("$openpkg_prefix/bin/openpkg lint-spec" . ($lopts->{"v"} ? " --verbose" : "") . " $specfile"); michael@428: $rc += run("$openpkg_prefix/bin/openpkg lint-fsl" . ($lopts->{"v"} ? " --verbose" : "") . " $fslfile") if (-f $fslfile); michael@428: $rc += run("$openpkg_prefix/bin/openpkg lint-rc" . ($lopts->{"v"} ? " --verbose" : "") . " $rcfile") if (-f $rcfile); michael@428: michael@428: # optionally run binary linting command michael@428: run("$openpkg_prefix/bin/openpkg lint-rpm" . ($lopts->{"v"} ? " --verbose" : "") . " $rpm") if (-f $rpm and not $lopts->{"b"}); michael@428: michael@428: return $rc; michael@428: } michael@428: michael@428: # command: release package michael@428: sub cmd_release ($@) { michael@428: my ($gopts, @argv) = @_; michael@428: my $rc = 0; michael@428: michael@428: # command line argument processing michael@428: my $lopts = {}; michael@428: @argv = getopts("nm:f", $lopts, @argv); michael@428: michael@428: # implicit linting michael@428: if (not $lopts->{"f"}) { michael@428: my $rc = cmd_lint($gopts); michael@428: if ($rc != 0 and !$lopts->{"f"}) { michael@428: return $rc; michael@428: } michael@428: } michael@428: michael@428: # sanity check environment michael@428: my $cmd = $ENV{"OPENPKG_DEV_RELEASE"} michael@428: || `$openpkg_prefix/bin/openpkg rpm --eval '%{openpkg_dev_release}' 2>/dev/null || true` || ""; michael@428: $cmd =~ s/\n$//s; michael@428: if ($cmd eq "") { michael@428: print STDERR "openpkg:$prog_name:ERROR: no \$OPENPKG_DEV_RELEASE command defined\n"; michael@428: exit(1); michael@428: } michael@428: michael@428: # michael@428: # determine package information michael@428: # michael@428: michael@428: print STDOUT "\033[34m++ determining package information\033[0m\n"; michael@428: my $info = {}; michael@428: $info->{"openpkg-prefix"} = $openpkg_prefix; michael@428: $info->{"option-force"} = $lopts->{"f"} ? "yes" : "no"; michael@428: michael@428: print STDOUT "-- determining package name/version/release\n"; michael@428: my $specfile = specfile(); michael@428: my $result = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '::%{NAME}::%{VERSION}::%{RELEASE}'`; michael@428: $result =~ s/\n$//s; michael@428: $result =~ s/^:://s; michael@428: my @result = split(/::/, $result); michael@428: $info->{"package-name"} = $result[0]; michael@428: $info->{"package-version"} = $result[1]; michael@428: $info->{"package-release"} = $result[2]; michael@428: michael@428: print STDOUT "-- determining package source and distribution location\n"; michael@428: my $defines = "--define '\%name " . $info->{"package-name"} . "'"; michael@428: $defines .= " --define '\%version " . $info->{"package-version"} . "'"; michael@428: $defines .= " --define '\%release " . $info->{"package-release"} . "'"; michael@428: my $result = `$openpkg_prefix/bin/openpkg rpm $defines --eval '%{_specdir}::%{_sourcedir}'`; michael@428: $result =~ s/\n$//s; michael@428: @result = split(/::/, $result); michael@428: $info->{"spec-dir"} = $result[0]; michael@428: $info->{"source-dir"} = $result[1]; michael@428: michael@428: print STDOUT "-- determining package source and binary RPM files\n"; michael@428: my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{l_binrpmfilename}::%{_srcrpmdir}/%{l_srcrpmfilename}'`; michael@428: $template =~ s/\n$//s; michael@428: $result = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '::$template'`; michael@428: $result =~ s/\n$//s; michael@428: $result =~ s/^:://s; michael@428: @result = split(/::/, $result); michael@428: $info->{"binary-rpm-file"} = $result[0]; michael@428: $info->{"source-rpm-file"} = $result[1]; michael@428: $info->{"package-version-old"} = ""; michael@428: $info->{"package-release-old"} = ""; michael@428: $info->{"vcs"} = "none"; michael@428: michael@428: print STDOUT "-- determining previous package version/release\n"; michael@428: my $vcs = ""; michael@428: my $diff = ""; michael@428: my $content_old = ""; michael@428: my $specdir = $info->{"spec-dir"}; michael@428: my $specfile = $info->{"package-name"} . ".spec"; michael@428: if (-f "$specdir/$specfile") { michael@428: open(FP, "<$specdir/$specfile"); michael@428: $content_new .= $_ while (); michael@428: close(FP); michael@428: if ($content_new =~ m/\n\%No(?:Source|Patch)\s+/s) { michael@428: $info->{"source-rpm-file"} =~ s/\.src\.rpm$/.nosrc.rpm/s; michael@428: } michael@428: if (-d "$specdir/CVS") { michael@428: # package is version controlled via CVS michael@428: $vcs = "cvs"; michael@428: $diff = `(cd $specdir && cvs diff -u3 $specfile) 2>/dev/null || true`; michael@428: } michael@428: elsif (-d "$specdir/.svn") { michael@428: # package is version controlled via Subverson (SVN) michael@428: $vcs = "svn"; michael@428: $diff = `(cd $specdir && svn diff $specfile) 2>/dev/null || true`; michael@428: } michael@428: elsif (-d "$specdir/_MTN" or -d "$specdir/.mtn" or michael@428: -d "$specdir/../_MTN" or -d "$specdir/../.mtn" or michael@428: -d "$specdir/../../_MTN" or -d "$specdir/../../.mtn" or michael@428: -d "$specdir/../../../_MTN" or -d "$specdir/../../../.mtn") { michael@428: # package is version controlled via Monotone (MTN) michael@428: $vcs = "mtn"; michael@428: $diff = `(cd $specdir && mtn diff $specfile) 2>/dev/null || true`; michael@428: $content_old = `(cd $specdir && mtn automate get_file_of -r h: $specfile) 2>/dev/null || true`; michael@428: } michael@428: elsif (-d "$specdir/.git" or michael@428: -d "$specdir/../.git" or michael@428: -d "$specdir/../../.git" or michael@428: -d "$specdir/../../../.git") { michael@428: # package is version controlled via Git michael@428: $vcs = "git"; michael@428: $diff = `(cd $specdir && git diff $specfile) 2>/dev/null || true`; michael@428: } michael@428: elsif (-d "$specdir/.hg" or michael@428: -d "$specdir/../.hg" or michael@428: -d "$specdir/../../.hg" or michael@428: -d "$specdir/../../../.hg") { michael@428: # package is version controlled via Mercurial (Hg) michael@428: $vcs = "hg"; michael@428: $diff = `(cd $specdir && hg diff $specfile) 2>/dev/null || true`; michael@428: } michael@428: elsif (-f "$specdir/$specfile.orig") { michael@428: # package is patched via OSSP svs michael@428: $vcs = "svs"; michael@428: $diff = `(cd $specdir && svs diff $specfile) 2>/dev/null || true`; michael@428: } michael@428: if ($vcs ne '') { michael@428: $info->{"vcs"} = $vcs; michael@428: } michael@428: if ($content_old ne '') { michael@428: my $define = {}; michael@428: $content_old =~ s/\n\%define[ \t]+([^ \t\n]+)[ \t]+([^ \t\n]+)/$define->{$1} = $2, ''/sge; michael@428: $content_old =~ s/\n([^ \t\n]+):[ \t]+([^ \t\n]+)/$define->{lc($1)} = $2, ''/sge; michael@428: sub resolve { michael@428: my ($define, $name) = @_; michael@428: my $value = $define->{$name}; michael@428: $value = "" if (not defined $value); michael@428: $value =~ s/\%\{(.+?)\}/resolve($define, $1)/sge; michael@428: return $value; michael@428: } michael@428: $info->{"package-version-old"} = resolve($define, "version"); michael@428: $info->{"package-release-old"} = resolve($define, "release"); michael@428: } michael@428: if (( $info->{"package-version-old"} eq '' michael@428: or $info->{"package-release-old"} eq '') michael@428: and $diff ne '' ) { michael@428: if ($info->{"package-version-old"} eq '' and $diff =~ m/\n-Version:\s+(\S+)/s) { michael@428: $info->{"package-version-old"} = $1; michael@428: } michael@428: if ($info->{"package-release-old"} eq '' and $diff =~ m/\n-Release:\s+(\S+)/s) { michael@428: $info->{"package-release-old"} = $1; michael@428: } michael@428: } michael@428: } michael@428: michael@428: print STDOUT "-- determining commit message\n"; michael@428: $info->{"commit-message"} = ($lopts->{"m"} || ""); michael@428: if ($info->{"commit-message"} eq "") { michael@428: if ($info->{"package-version-old"} ne $info->{"package-version"}) { michael@428: # new version michael@428: $info->{"commit-message"} = "upgrading package: " . michael@428: $info->{"package-name"} . " " . michael@428: $info->{"package-version-old"} . " -> " . michael@428: $info->{"package-version"}; michael@428: } michael@428: elsif (!$lopts->{"f"}) { michael@428: print STDERR "openpkg:$prog_name:ERROR: package version not changed -- you have to manually provide a commit message\n"; michael@428: exit(1); michael@428: } michael@428: } michael@428: michael@428: # run external command michael@428: print STDOUT "\033[34m++ executing openpkg development release program\033[0m\n"; michael@428: $cmd .= " %{openpkg-prefix}"; michael@428: $cmd .= " %{spec-dir} %{source-dir} %{binary-rpm-file} %{source-rpm-file}"; michael@428: $cmd .= " %{package-name} %{package-version} %{package-release} %{package-version-old} %{package-release-old}"; michael@428: $cmd .= " %{commit-message} %{vcs}"; michael@428: $cmd .= " %{option-force}"; michael@428: $cmd =~ s/(\%\{([a-z][a-z-]+)\})/&subst($info, $1, $2)/sge; michael@428: sub subst { michael@428: my ($info, $text, $name) = @_; michael@428: if (exists($info->{$name})) { michael@428: $text = $info->{$name}; michael@428: $text =~ s/'/\\'/sg; michael@428: $text = "'$text'"; michael@428: } michael@428: } michael@428: if ($lopts->{"n"}) { michael@428: print STDOUT "-- DRY RUN:\n"; michael@428: print STDOUT "-- $cmd\n"; michael@428: $rc = 0; michael@428: } michael@428: else { michael@428: $rc = system($cmd); michael@428: } michael@428: michael@428: return $rc; michael@428: } michael@428: