Mon, 28 Jan 2013 17:37:18 +0100
Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.
michael@428 | 1 | ## |
michael@428 | 2 | ## openpkg dev -- OpenPKG Package Development Tool |
michael@428 | 3 | ## Copyright (c) 2008-2012 OpenPKG GmbH <http://openpkg.com/> |
michael@428 | 4 | ## |
michael@428 | 5 | ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
michael@428 | 6 | ## All rights reserved. Licenses which grant limited permission to use, |
michael@428 | 7 | ## copy, modify and distribute this software are available from the |
michael@428 | 8 | ## OpenPKG GmbH. |
michael@428 | 9 | ## |
michael@428 | 10 | ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
michael@428 | 11 | ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
michael@428 | 12 | ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
michael@428 | 13 | ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
michael@428 | 14 | ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@428 | 15 | ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@428 | 16 | ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
michael@428 | 17 | ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
michael@428 | 18 | ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
michael@428 | 19 | ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
michael@428 | 20 | ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
michael@428 | 21 | ## SUCH DAMAGE. |
michael@428 | 22 | ## |
michael@428 | 23 | |
michael@428 | 24 | require 5; |
michael@428 | 25 | |
michael@428 | 26 | # OpenPKG instance prefix and RPM |
michael@428 | 27 | my $openpkg_prefix = $ENV{'OPENPKG_PREFIX'}; |
michael@428 | 28 | delete $ENV{'OPENPKG_PREFIX'}; |
michael@428 | 29 | |
michael@428 | 30 | # program identification |
michael@428 | 31 | my $prog_name = "dev"; |
michael@428 | 32 | my $prog_vers = "20100111"; |
michael@428 | 33 | |
michael@428 | 34 | # home-brewn getopt(3) style option parser |
michael@428 | 35 | sub getopts ($$@) { |
michael@428 | 36 | my ($opt_spec, $opts, @argv_orig) = @_; |
michael@428 | 37 | my (%optf) = map { m/(\w)/; $1 => $_ } $opt_spec =~ m/(\w:|\w)/g; |
michael@428 | 38 | my (@argv, $optarg); |
michael@428 | 39 | |
michael@428 | 40 | foreach (@argv_orig) { |
michael@428 | 41 | if (@argv) { |
michael@428 | 42 | push @argv, $_; |
michael@428 | 43 | } elsif (defined $optarg) { |
michael@428 | 44 | if (exists $opts->{$optarg}) { |
michael@428 | 45 | $opts->{$optarg} .= " $_"; |
michael@428 | 46 | } else { |
michael@428 | 47 | $opts->{$optarg} = $_; |
michael@428 | 48 | } |
michael@428 | 49 | $optarg = undef; |
michael@428 | 50 | } elsif (!/^[-]/) { |
michael@428 | 51 | push @argv, $_; |
michael@428 | 52 | } else { |
michael@428 | 53 | while (/^\-(\w)(.*)/) { |
michael@428 | 54 | if (exists $optf{$1}) { |
michael@428 | 55 | if (length($optf{$1}) > 1) { |
michael@428 | 56 | if ($2 ne '') { |
michael@428 | 57 | if (exists $opts->{$1}) { |
michael@428 | 58 | $opts->{$1} .= " $2"; |
michael@428 | 59 | } else { |
michael@428 | 60 | $opts->{$1} = $2; |
michael@428 | 61 | } |
michael@428 | 62 | } else { |
michael@428 | 63 | $optarg = $1; |
michael@428 | 64 | } |
michael@428 | 65 | last; |
michael@428 | 66 | } else { |
michael@428 | 67 | $opts->{$1} = 1; |
michael@428 | 68 | } |
michael@428 | 69 | } else { |
michael@428 | 70 | warn "openpkg:$prog_name:WARNING: unknown option $_\n"; |
michael@428 | 71 | } |
michael@428 | 72 | $_ = "-$2"; |
michael@428 | 73 | } |
michael@428 | 74 | } |
michael@428 | 75 | } |
michael@428 | 76 | if (defined $optarg) { |
michael@428 | 77 | warn "openpkg:$prog_name:WARNING: option $optarg requires an argument\n"; |
michael@428 | 78 | } |
michael@428 | 79 | foreach my $opt (keys %optf) { |
michael@428 | 80 | if (not exists $opts->{$opt}) { |
michael@428 | 81 | $opts->{$opt} = (length($optf{$opt}) > 1 ? "" : 0); |
michael@428 | 82 | } |
michael@428 | 83 | } |
michael@428 | 84 | return @argv; |
michael@428 | 85 | } |
michael@428 | 86 | |
michael@428 | 87 | # determine reasonable temporary directory |
michael@428 | 88 | my $tmpdir = ($ENV{"TMPDIR"} || "/tmp"); |
michael@428 | 89 | $tmpdir .= "/openpkg-$prog_name-$$"; |
michael@428 | 90 | my $rc = system("umask 022; $openpkg_prefix/lib/openpkg/shtool mkdir -f -p -m 755 $tmpdir || exit $?"); |
michael@428 | 91 | if ($rc != 0) { |
michael@428 | 92 | die "failed to create temporary directory: $tmpdir"; |
michael@428 | 93 | } |
michael@428 | 94 | |
michael@428 | 95 | # parse command line options |
michael@428 | 96 | my $opts = {}; |
michael@428 | 97 | @ARGV = getopts("h", $opts, @ARGV); |
michael@428 | 98 | |
michael@428 | 99 | # usage sanity check and usage help |
michael@428 | 100 | sub usage { |
michael@428 | 101 | my ($rc) = @_; |
michael@428 | 102 | my $usage = |
michael@428 | 103 | "openpkg:$prog_name:USAGE: openpkg dev <command> [<options>]\n"; |
michael@428 | 104 | if ($rc == 0) { |
michael@428 | 105 | print STDOUT $usage; |
michael@428 | 106 | } |
michael@428 | 107 | else { |
michael@428 | 108 | print STDERR $usage; |
michael@428 | 109 | } |
michael@428 | 110 | exit($rc); |
michael@428 | 111 | } |
michael@428 | 112 | if ($opts->{"h"}) { |
michael@428 | 113 | usage(0); |
michael@428 | 114 | } |
michael@428 | 115 | if (@ARGV == 0) { |
michael@428 | 116 | usage(1); |
michael@428 | 117 | } |
michael@428 | 118 | |
michael@428 | 119 | # command map |
michael@428 | 120 | my $map = { |
michael@428 | 121 | "unpack " => { -alias => qr/^(up|ex)$/, -key => "x" }, |
michael@428 | 122 | "edit\n" => { -alias => qr/^(ed|vi)$/, -key => "v" }, |
michael@428 | 123 | "build -s track\n" => { -alias => qr/^(bt|tr)$/, -key => "t" }, |
michael@428 | 124 | "build -s fetch\n" => { -alias => qr/^(bf|fe)$/, -key => "f" }, |
michael@428 | 125 | "build\n" => { -alias => qr/^(ba|bu)$/, -key => "b" }, |
michael@428 | 126 | "build -s prep\n" => { -alias => qr/^bp$/, -key => "1" }, |
michael@428 | 127 | "build -s compile\n" => { -alias => qr/^bc$/, -key => "2" }, |
michael@428 | 128 | "build -s install\n" => { -alias => qr/^bi$/, -key => "3" }, |
michael@428 | 129 | "build -s binary\n" => { -alias => qr/^bb$/, -key => "4" }, |
michael@428 | 130 | "build -s source\n" => { -alias => qr/^bs$/, -key => "s" }, |
michael@428 | 131 | "peek\n" => { -alias => qr/^pe$/, -key => "p" }, |
michael@428 | 132 | "diff\n" => { -alias => qr/^di$/, -key => "d" }, |
michael@428 | 133 | "install\n" => { -alias => qr/^in(?:st)?$/, -key => "i" }, |
michael@428 | 134 | "erase\n" => { -alias => qr/^er$/, -key => "e" }, |
michael@428 | 135 | "lint\n" => { -alias => qr/^li$/, -key => "l" }, |
michael@428 | 136 | "release " => { -alias => qr/^rel?$/, -key => "r" }, |
michael@428 | 137 | }; |
michael@428 | 138 | |
michael@428 | 139 | # dispatch command |
michael@428 | 140 | my $cmd = shift(@ARGV); |
michael@428 | 141 | foreach my $c (keys %{$map}) { |
michael@428 | 142 | my $a = $map->{$c}->{-alias}; |
michael@428 | 143 | if ($cmd =~ $a) { |
michael@428 | 144 | $c =~ s/\n$//; |
michael@428 | 145 | my @args = split(/\s+/, $c); |
michael@428 | 146 | $cmd = shift(@args); |
michael@428 | 147 | unshift(@ARGV, @args); |
michael@428 | 148 | print STDOUT "\033[34m\$ opd $cmd " . join(" ", map { |
michael@428 | 149 | my $x = $_; |
michael@428 | 150 | $x =~ s/"/\\"/g; |
michael@428 | 151 | $x =~ s/^(.*[ \t].*)$/"$1"/; |
michael@428 | 152 | $x |
michael@428 | 153 | } @ARGV) . "\033[0m\n"; |
michael@428 | 154 | } |
michael@428 | 155 | } |
michael@428 | 156 | my $func = "cmd_$cmd"; |
michael@428 | 157 | if (not defined(&$func)) { |
michael@428 | 158 | print STDERR "openpkg:$prog_name:ERROR: invalid command \"$cmd\"\n"; |
michael@428 | 159 | usage(1); |
michael@428 | 160 | } |
michael@428 | 161 | my $rc = &$func($opts, @ARGV); |
michael@428 | 162 | exit($rc); |
michael@428 | 163 | |
michael@428 | 164 | # execute a shell command |
michael@428 | 165 | sub run { |
michael@428 | 166 | my ($cmd) = @_; |
michael@428 | 167 | print STDOUT "\033[34m\$ $cmd\033[0m\n"; |
michael@428 | 168 | my $rc = system($cmd); |
michael@428 | 169 | return $rc; |
michael@428 | 170 | } |
michael@428 | 171 | |
michael@428 | 172 | # determine path to package specification |
michael@428 | 173 | sub specfile { |
michael@428 | 174 | my $specfile = (glob("*.spec"))[0]; |
michael@428 | 175 | if (not defined $specfile) { |
michael@428 | 176 | $specfile = (glob("src/*.spec"))[0]; |
michael@428 | 177 | if (not defined $specfile) { |
michael@428 | 178 | $specfile = (glob("*/*.spec"))[0]; |
michael@428 | 179 | if (not defined $specfile) { |
michael@428 | 180 | print STDERR "openpkg:$prog_name:ERROR: unable to determine package specification file\n"; |
michael@428 | 181 | exit(1); |
michael@428 | 182 | } |
michael@428 | 183 | } |
michael@428 | 184 | } |
michael@428 | 185 | return $specfile; |
michael@428 | 186 | } |
michael@428 | 187 | |
michael@428 | 188 | # command: interactive shell |
michael@428 | 189 | sub cmd_shell ($@) { |
michael@428 | 190 | my ($gopts, @argv) = @_; |
michael@428 | 191 | my $rc = 0; |
michael@428 | 192 | |
michael@428 | 193 | # command line argument processing |
michael@428 | 194 | my $lopts = {}; |
michael@428 | 195 | @argv = getopts("s", $lopts, @argv); |
michael@428 | 196 | |
michael@428 | 197 | # determine release |
michael@428 | 198 | my $release = `$openpkg_prefix/bin/openpkg release -F '%t'`; |
michael@428 | 199 | $release =~ s/\n$//s; |
michael@428 | 200 | |
michael@428 | 201 | # create dot files |
michael@428 | 202 | my $screenrc = "$tmpdir/dot.screenrc"; |
michael@428 | 203 | my $bashsh = "$tmpdir/bash.sh"; |
michael@428 | 204 | my $bashrc = "$tmpdir/dot.bashrc"; |
michael@428 | 205 | my $inputrc = "$tmpdir/dot.inputrc"; |
michael@428 | 206 | unlink("$screenrc"); |
michael@428 | 207 | unlink("$bashsh"); |
michael@428 | 208 | unlink("$bashrc"); |
michael@428 | 209 | unlink("$inputrc"); |
michael@428 | 210 | my $title = "openpkg dev"; |
michael@428 | 211 | $title .= '%? %{= rW} %n %{-}%?'; |
michael@428 | 212 | $title .= ' %=%-w%{= rW}%50>%n %t%{-}%+w'; |
michael@428 | 213 | my $screenrc_data = ""; |
michael@428 | 214 | $screenrc_data .= "source \"$ENV{HOME}/.screenrc\"\n" if (-f "$ENV{HOME}/.screenrc"); |
michael@428 | 215 | $screenrc_data .= |
michael@428 | 216 | "escape ^Aa\n" . |
michael@428 | 217 | "startup_message off\n" . |
michael@428 | 218 | "vbell off\n" . |
michael@428 | 219 | "defscrollback 10000\n" . |
michael@428 | 220 | "defmonitor off\n" . |
michael@428 | 221 | "msgminwait 1\n" . |
michael@428 | 222 | "msgwait 1\n" . |
michael@428 | 223 | "hardstatus alwayslastline \" $title \"\n" . |
michael@428 | 224 | "shell $bashsh\n"; |
michael@428 | 225 | my $bashsh_data = |
michael@428 | 226 | "##\n" . |
michael@428 | 227 | "##\ bash.sh -- \"openpkg dev shell\" GNU bash wrapper script\n" . |
michael@428 | 228 | "##\n" . |
michael@428 | 229 | "\n" . |
michael@428 | 230 | "OPENPKG_PREFIX=\"$openpkg_prefix\"\n" . |
michael@428 | 231 | "export OPENPKG_PREFIX\n" . |
michael@428 | 232 | "INPUTRC=\"$inputrc\"\n" . |
michael@428 | 233 | "export INPUTRC\n" . |
michael@428 | 234 | "SHELL=\"$openpkg_prefix/lib/openpkg/bash\"\n" . |
michael@428 | 235 | "export SHELL\n" . |
michael@428 | 236 | "eval `$openpkg_prefix/bin/openpkg rpm --eval 'T=\"\%{_tmppath}\"; S=\"\%{_specdir}\"; D=\"\%{_sourcedir}\"'`\n" . |
michael@428 | 237 | "export T S D\n" . |
michael@428 | 238 | "\$SHELL --rcfile $bashrc"; |
michael@428 | 239 | my $bashrc_data = |
michael@428 | 240 | "##\n" . |
michael@428 | 241 | "## dot.bashrc -- \"openpkg dev shell\" GNU bash configuration\n" . |
michael@428 | 242 | "##\n" . |
michael@428 | 243 | "\n" . |
michael@428 | 244 | "# load user's standard bash run-command script\n" . |
michael@428 | 245 | "if [ -f ~/.bashrc ]; then\n" . |
michael@428 | 246 | " . ~/.bashrc\n" . |
michael@428 | 247 | "fi\n" . |
michael@428 | 248 | "\n" . |
michael@428 | 249 | "# configure a special command-line prompt\n" . |
michael@428 | 250 | "if [ \".\$TERM\" = .screen ]; then\n" . |
michael@428 | 251 | " PS1=\"\\\\u@\\\\h:\\\\w [P=\\\\e[1m\\\${OPENPKG_PREFIX}\\\\e[0m]\\n\\\\\\\$ \\\\ek\\\\W\\\\e\\\\\\\\\"\n" . |
michael@428 | 252 | "else\n" . |
michael@428 | 253 | " PS1=\"\\\\u@\\\\h:\\\\w [P=\\\\e[1m\\\${OPENPKG_PREFIX}\\\\e[0m]\\n\\\\\\\$ \"\n" . |
michael@428 | 254 | "fi\n" . |
michael@428 | 255 | "alias openpkg=\"\\\${OPENPKG_PREFIX}/bin/openpkg\"\n" . |
michael@428 | 256 | "alias opd=\"\\\${OPENPKG_PREFIX}/bin/openpkg dev\"\n" . |
michael@428 | 257 | "\n"; |
michael@428 | 258 | my $inputrc_data = |
michael@428 | 259 | "##\n" . |
michael@428 | 260 | "## dot.inputrc -- \"openpkg dev shell\" GNU readline configuration\n" . |
michael@428 | 261 | "##\n" . |
michael@428 | 262 | "\n"; |
michael@428 | 263 | foreach my $c (keys %{$map}) { |
michael@428 | 264 | my $k = $map->{$c}->{-key}; |
michael@428 | 265 | $c =~ s/\n/\\n/sg; |
michael@428 | 266 | $inputrc_data .= "\"\\e$k\": \"opd $c\"\n"; |
michael@428 | 267 | } |
michael@428 | 268 | $inputrc_data .= "\n"; |
michael@428 | 269 | open(SCREENRC, ">$screenrc"); |
michael@428 | 270 | print(SCREENRC $screenrc_data); |
michael@428 | 271 | close(SCREENRC); |
michael@428 | 272 | open(BASHSH, ">$bashsh"); |
michael@428 | 273 | print(BASHSH $bashsh_data); |
michael@428 | 274 | close(BASHSH); |
michael@428 | 275 | system("chmod a+x $bashsh"); |
michael@428 | 276 | open(BASHRC, ">$bashrc"); |
michael@428 | 277 | print(BASHRC $bashrc_data); |
michael@428 | 278 | close(BASHRC); |
michael@428 | 279 | open(INPUTRC, ">$inputrc"); |
michael@428 | 280 | print(INPUTRC $inputrc_data); |
michael@428 | 281 | close(INPUTRC); |
michael@428 | 282 | |
michael@428 | 283 | # run interactive shell |
michael@428 | 284 | print STDOUT "\033[34m++ entering OpenPKG $release development shell\033[0m\n"; |
michael@428 | 285 | my $rc; |
michael@428 | 286 | if ($lopts->{"s"}) { |
michael@428 | 287 | $rc = system("screen -c $screenrc -S 'openpkg-dev-shell' -d -R"); |
michael@428 | 288 | } |
michael@428 | 289 | else { |
michael@428 | 290 | $rc = system("$bashsh"); |
michael@428 | 291 | } |
michael@428 | 292 | |
michael@428 | 293 | # cleanup |
michael@428 | 294 | unlink("$tmpdir/dot.screenrc"); |
michael@428 | 295 | unlink("$tmpdir/bash.sh"); |
michael@428 | 296 | unlink("$tmpdir/dot.bashrc"); |
michael@428 | 297 | unlink("$tmpdir/dot.inputrc"); |
michael@428 | 298 | unlink("$tmpdir"); |
michael@428 | 299 | |
michael@428 | 300 | return $rc; |
michael@428 | 301 | } |
michael@428 | 302 | |
michael@428 | 303 | # command: unpack source RPM |
michael@428 | 304 | sub cmd_unpack ($@) { |
michael@428 | 305 | my ($gopts, @argv) = @_; |
michael@428 | 306 | my $rc = 0; |
michael@428 | 307 | |
michael@428 | 308 | # command line argument processing |
michael@428 | 309 | my $lopts = {}; |
michael@428 | 310 | @argv = getopts("l:b:sd", $lopts, @argv); |
michael@428 | 311 | if ($lopts->{"l"} eq "") { |
michael@428 | 312 | $lopts->{"l"} = "structured"; |
michael@428 | 313 | } |
michael@428 | 314 | if ($lopts->{"l"} !~ m/^(global|local|simple|structured|distributed)$/) { |
michael@428 | 315 | die sprintf("invalid layout type \"%s\"", $lopts->{"l"}); |
michael@428 | 316 | } |
michael@428 | 317 | if (@argv != 1) { |
michael@428 | 318 | die sprintf("exactly one SRPM has to be given"); |
michael@428 | 319 | } |
michael@428 | 320 | my $srpm = $argv[0]; |
michael@428 | 321 | if (not -f $srpm) { |
michael@428 | 322 | die sprintf("SRPM \"%s\" has to be a regular file", $srpm); |
michael@428 | 323 | } |
michael@428 | 324 | my $name = `$openpkg_prefix/bin/openpkg rpm -qp --qf '\%{NAME}' $srpm 2>/dev/null || true`; |
michael@428 | 325 | $name =~ s/\r?\n$//s; |
michael@428 | 326 | if ($name eq '') { |
michael@428 | 327 | die sprintf("unable to determine package name from SRPM \"%s\"", $srpm); |
michael@428 | 328 | } |
michael@428 | 329 | if ($lopts->{"b"} eq "") { |
michael@428 | 330 | $lopts->{"b"} = $srpm; |
michael@428 | 331 | if ($lopts->{"b"} =~ m/\.src\.rpm$/) { |
michael@428 | 332 | $lopts->{"b"} =~ s/\.src\.rpm$//; |
michael@428 | 333 | } |
michael@428 | 334 | else { |
michael@428 | 335 | my $subdir = `$openpkg_prefix/bin/openpkg rpm -qp --qf '\%{NAME}-\%{VERSION}-\%{RELEASE}' $srpm 2>/dev/null || true`; |
michael@428 | 336 | $lopts->{"b"} = $subdir; |
michael@428 | 337 | } |
michael@428 | 338 | } |
michael@428 | 339 | |
michael@428 | 340 | # determine result directory |
michael@428 | 341 | my $basedir = $lopts->{"b"}; |
michael@428 | 342 | my ($macrosfile, $specdir, $sourcedir); |
michael@428 | 343 | if ($lopts->{"l"} eq "global") { |
michael@428 | 344 | $macrosdir = "$openpkg_prefix/etc/openpkg"; |
michael@428 | 345 | $macrosfile = "$openpkg_prefix/etc/openpkg/rpmmacros"; |
michael@428 | 346 | $specdir = "$openpkg_prefix/RPM/SRC/$name"; |
michael@428 | 347 | $sourcedir = "$openpkg_prefix/RPM/SRC/$name"; |
michael@428 | 348 | $builddir = "$openpkg_prefix/RPM/TMP"; |
michael@428 | 349 | $tmpdir = "$openpkg_prefix/RPM/TMP"; |
michael@428 | 350 | $binrpmdir = "$openpkg_prefix/RPM/PKG"; |
michael@428 | 351 | $srcrpmdir = "$openpkg_prefix/RPM/PKG"; |
michael@428 | 352 | } |
michael@428 | 353 | elsif ($lopts->{"l"} eq "local") { |
michael@428 | 354 | $macrosdir = "$basedir/.openpkg"; |
michael@428 | 355 | $macrosfile = "$basedir/.openpkg/rpmmacros"; |
michael@428 | 356 | $specdir = "$basedir"; |
michael@428 | 357 | $sourcedir = "$basedir"; |
michael@428 | 358 | $builddir = "$basedir"; |
michael@428 | 359 | $tmpdir = "$basedir"; |
michael@428 | 360 | $binrpmdir = "$basedir"; |
michael@428 | 361 | $srcrpmdir = "$basedir"; |
michael@428 | 362 | } |
michael@428 | 363 | elsif ($lopts->{"l"} eq "simple") { |
michael@428 | 364 | $macrosdir = "$basedir/.openpkg"; |
michael@428 | 365 | $macrosfile = "$basedir/.openpkg/rpmmacros"; |
michael@428 | 366 | $specdir = "$basedir"; |
michael@428 | 367 | $sourcedir = "$basedir"; |
michael@428 | 368 | $builddir = "$tmpdir"; |
michael@428 | 369 | $tmpdir = "$tmpdir"; |
michael@428 | 370 | $binrpmdir = "$basedir/.."; |
michael@428 | 371 | $srcrpmdir = "$basedir/.."; |
michael@428 | 372 | } |
michael@428 | 373 | elsif ($lopts->{"l"} eq "structured") { |
michael@428 | 374 | $macrosdir = "$basedir/.openpkg"; |
michael@428 | 375 | $macrosfile = "$basedir/.openpkg/rpmmacros"; |
michael@428 | 376 | $specdir = "$basedir/src"; |
michael@428 | 377 | $sourcedir = "$basedir/dst"; |
michael@428 | 378 | $builddir = "$basedir/tmp"; |
michael@428 | 379 | $tmpdir = "$basedir/tmp"; |
michael@428 | 380 | $binrpmdir = "$basedir/pkg/bin"; |
michael@428 | 381 | $srcrpmdir = "$basedir/pkg/src"; |
michael@428 | 382 | } |
michael@428 | 383 | elsif ($lopts->{"l"} eq "distributed") { |
michael@428 | 384 | $macrosdir = "$basedir/.openpkg"; |
michael@428 | 385 | $macrosfile = "$basedir/.openpkg/rpmmacros"; |
michael@428 | 386 | $specdir = "$basedir/src/$name"; |
michael@428 | 387 | $sourcedir = "$basedir/dst/$name"; |
michael@428 | 388 | $builddir = "$basedir/tmp"; |
michael@428 | 389 | $tmpdir = "$basedir/tmp"; |
michael@428 | 390 | $binrpmdir = "$basedir/pkg/bin"; |
michael@428 | 391 | $srcrpmdir = "$basedir/pkg/src"; |
michael@428 | 392 | } |
michael@428 | 393 | |
michael@428 | 394 | # create still missing directories |
michael@428 | 395 | foreach my $dir ($macrosdir, $specdir, $sourcedir, $builddir, $tmpdir, $binrpmdir, $srcrpmdir) { |
michael@428 | 396 | if (not -d $dir) { |
michael@428 | 397 | print STDOUT "openpkg:$prog_name: creating directory \"$dir\"\n"; |
michael@428 | 398 | system("$openpkg_prefix/lib/openpkg/shtool mkdir -f -p -m 755 $dir"); |
michael@428 | 399 | } |
michael@428 | 400 | } |
michael@428 | 401 | |
michael@428 | 402 | # unpack SRPM |
michael@428 | 403 | print STDOUT "openpkg:$prog_name: unpacking source: \"$srpm\"\n"; |
michael@428 | 404 | print STDOUT "openpkg:$prog_name: unpacking target: \"$specdir\"\n"; |
michael@428 | 405 | print STDOUT "openpkg:$prog_name: unpacking target: \"$sourcedir\"\n"; |
michael@428 | 406 | my $abs_specdir = $specdir; |
michael@428 | 407 | my $abs_sourcedir = $sourcedir; |
michael@428 | 408 | my $pwd = `pwd`; $pwd =~ s/\r?\n$//s; |
michael@428 | 409 | $abs_specdir = "$pwd/$abs_specdir" if ($abs_specdir !~ m/^\//); |
michael@428 | 410 | $abs_sourcedir = "$pwd/$abs_sourcedir" if ($abs_sourcedir !~ m/^\//); |
michael@428 | 411 | my $rc = system( |
michael@428 | 412 | "$openpkg_prefix/bin/openpkg" . |
michael@428 | 413 | " --keep-privileges" . |
michael@428 | 414 | " rpm" . |
michael@428 | 415 | " -i" . |
michael@428 | 416 | " --define '_specdir $abs_specdir'" . |
michael@428 | 417 | " --define '_sourcedir $abs_sourcedir'" . |
michael@428 | 418 | " $srpm" |
michael@428 | 419 | ); |
michael@428 | 420 | |
michael@428 | 421 | # fix location of files |
michael@428 | 422 | if (not -f "$specdir/$name.spec") { |
michael@428 | 423 | die sprintf("failed to install package \"%s\": file \"%s\" not found\n", $srpm, "$specdir/$name.spec"); |
michael@428 | 424 | } |
michael@428 | 425 | open(SPEC, "<$specdir/$name.spec"); |
michael@428 | 426 | my $spec = ""; { local $/; $spec = <SPEC>; } |
michael@428 | 427 | close(SPEC); |
michael@428 | 428 | my $src = {}; |
michael@428 | 429 | $spec =~ s/^(?:Source|Patch)\d+:\s+(\S+)/$src->{$1} = 1, ''/mgei; |
michael@428 | 430 | foreach my $file (keys %{$src}) { |
michael@428 | 431 | if ($file !~ m/^(https?|ftp):\/\//) { |
michael@428 | 432 | if (not -f "$specdir/$file" and -f "$sourcedir/$file") { |
michael@428 | 433 | system("mv $sourcedir/$file $specdir/$file"); |
michael@428 | 434 | } |
michael@428 | 435 | } |
michael@428 | 436 | } |
michael@428 | 437 | |
michael@428 | 438 | # create .openpkg/rpmmacros file |
michael@428 | 439 | if (not -f $macrosfile) { |
michael@428 | 440 | print STDOUT "openpkg:$prog_name: creating file: \"$macrosfile\"\n"; |
michael@428 | 441 | my $rpmmacros = |
michael@428 | 442 | "##\n" . |
michael@428 | 443 | "## .openpkg/rpmmacros -- local OpenPKG RPM macro definitions\n" . |
michael@428 | 444 | "##\n" . |
michael@428 | 445 | "\n" . |
michael@428 | 446 | "\%openpkg_layout" . |
michael@428 | 447 | " macrosfile=\%{macrosfile}" . |
michael@428 | 448 | " layout=" . $lopts->{"l"} . |
michael@428 | 449 | " shared=" . ($lopts->{"s"} ? "yes" : "no") . |
michael@428 | 450 | " debug=" . ($lopts->{"d"} ? "yes" : "no") . |
michael@428 | 451 | "\n" . |
michael@428 | 452 | "\n"; |
michael@428 | 453 | open(MACROS, ">$macrosfile"); |
michael@428 | 454 | print(MACROS $rpmmacros); |
michael@428 | 455 | close(MACROS); |
michael@428 | 456 | } |
michael@428 | 457 | |
michael@428 | 458 | return $rc; |
michael@428 | 459 | } |
michael@428 | 460 | |
michael@428 | 461 | # command: edit package specification |
michael@428 | 462 | sub cmd_edit ($@) { |
michael@428 | 463 | my ($gopts, @argv) = @_; |
michael@428 | 464 | my $rc = 0; |
michael@428 | 465 | |
michael@428 | 466 | # run editor |
michael@428 | 467 | my $editor = ($ENV{"EDITOR"} || "vi"); |
michael@428 | 468 | my $specfile = ($argv[0] || specfile()); |
michael@428 | 469 | run("$editor $specfile"); |
michael@428 | 470 | |
michael@428 | 471 | return $rc; |
michael@428 | 472 | } |
michael@428 | 473 | |
michael@428 | 474 | # command: build package |
michael@428 | 475 | sub cmd_build ($@) { |
michael@428 | 476 | my ($gopts, @argv) = @_; |
michael@428 | 477 | my $rc = 0; |
michael@428 | 478 | |
michael@428 | 479 | # command line argument processing |
michael@428 | 480 | my $lopts = {}; |
michael@428 | 481 | @argv = getopts("s:D:w:", $lopts, @argv); |
michael@428 | 482 | if ($lopts->{"s"} eq '') { |
michael@428 | 483 | $lopts->{"s"} = "all"; |
michael@428 | 484 | } |
michael@428 | 485 | if ($lopts->{"s"} !~ m/^(track|fetch|prep|compile|install|binary|source|all)$/) { |
michael@428 | 486 | die "invalid step"; |
michael@428 | 487 | } |
michael@428 | 488 | |
michael@428 | 489 | # assembly defines |
michael@428 | 490 | my $defs = ""; |
michael@428 | 491 | if ($lopts->{"D"}) { |
michael@428 | 492 | foreach my $def (split(/\s+/, $lopts->{"D"})) { |
michael@428 | 493 | if ($def =~ m/^([^=]+)=(.+)$/) { |
michael@428 | 494 | $defs .= "--define '$1 $2' "; |
michael@428 | 495 | } |
michael@428 | 496 | else { |
michael@428 | 497 | $defs .= "--define '$def yes' "; |
michael@428 | 498 | } |
michael@428 | 499 | } |
michael@428 | 500 | } |
michael@428 | 501 | if ($lopts->{"w"}) { |
michael@428 | 502 | foreach my $def (split(/\s+/, $lopts->{"w"})) { |
michael@428 | 503 | $defs .= "--with $def "; |
michael@428 | 504 | } |
michael@428 | 505 | } |
michael@428 | 506 | |
michael@428 | 507 | # run build command |
michael@428 | 508 | my $specfile = ($argv[0] || specfile()); |
michael@428 | 509 | if ($lopts->{"s"} eq 'track') { |
michael@428 | 510 | run("$openpkg_prefix/bin/openpkg rpm -bt $defs$specfile"); |
michael@428 | 511 | } |
michael@428 | 512 | elsif ($lopts->{"s"} eq 'fetch') { |
michael@428 | 513 | run("$openpkg_prefix/bin/openpkg rpm -bf $defs$specfile"); |
michael@428 | 514 | } |
michael@428 | 515 | elsif ($lopts->{"s"} eq 'prep') { |
michael@428 | 516 | run("$openpkg_prefix/bin/openpkg rpm -bp $defs$specfile"); |
michael@428 | 517 | } |
michael@428 | 518 | elsif ($lopts->{"s"} eq 'compile') { |
michael@428 | 519 | run("$openpkg_prefix/bin/openpkg rpm -bc --short-circuit $defs$specfile"); |
michael@428 | 520 | } |
michael@428 | 521 | elsif ($lopts->{"s"} eq 'install') { |
michael@428 | 522 | run("$openpkg_prefix/bin/openpkg rpm -bi --short-circuit $defs$specfile"); |
michael@428 | 523 | } |
michael@428 | 524 | elsif ($lopts->{"s"} eq 'binary') { |
michael@428 | 525 | run("$openpkg_prefix/bin/openpkg rpm -bb --short-circuit $defs$specfile"); |
michael@428 | 526 | } |
michael@428 | 527 | elsif ($lopts->{"s"} eq 'source') { |
michael@428 | 528 | run("$openpkg_prefix/bin/openpkg rpm -bs $defs$specfile"); |
michael@428 | 529 | } |
michael@428 | 530 | elsif ($lopts->{"s"} eq 'all') { |
michael@428 | 531 | run("$openpkg_prefix/bin/openpkg rpm -ba $defs$specfile"); |
michael@428 | 532 | } |
michael@428 | 533 | |
michael@428 | 534 | return $rc; |
michael@428 | 535 | } |
michael@428 | 536 | |
michael@428 | 537 | # command: peek into package |
michael@428 | 538 | sub cmd_peek ($@) { |
michael@428 | 539 | my ($gopts, @argv) = @_; |
michael@428 | 540 | my $rc = 0; |
michael@428 | 541 | |
michael@428 | 542 | # run query command |
michael@428 | 543 | my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{_rpmfilename}'`; |
michael@428 | 544 | $template =~ s/\n$//s; |
michael@428 | 545 | my $specfile = specfile(); |
michael@428 | 546 | my $rpm = `$openpkg_prefix/bin/openpkg rpm -q --specfile '$specfile' --qf 'XXX$template'`; |
michael@428 | 547 | $rpm =~ s/^XXX//s; |
michael@428 | 548 | $rpm =~ s/\n$//s; |
michael@428 | 549 | |
michael@428 | 550 | # determine files |
michael@428 | 551 | print STDOUT "\033[34m++ determining configuration files\033[0m\n"; |
michael@428 | 552 | my @cfgfiles = split(/\n/, `$openpkg_prefix/bin/openpkg rpm -qplc $rpm`); |
michael@428 | 553 | print STDOUT "\033[34m++ determining documentation files\033[0m\n"; |
michael@428 | 554 | my @docfiles = split(/\n/, `$openpkg_prefix/bin/openpkg rpm -qpld $rpm`); |
michael@428 | 555 | print STDOUT "\033[34m++ determining all file information\033[0m\n"; |
michael@428 | 556 | my @allfiles = split(/\n/, `$openpkg_prefix/bin/openpkg rpm -qplv $rpm`); |
michael@428 | 557 | |
michael@428 | 558 | # create package file listing |
michael@428 | 559 | foreach my $line (@allfiles) { |
michael@428 | 560 | $prefix = ""; |
michael@428 | 561 | foreach my $docfile (@docfiles) { |
michael@428 | 562 | if ($line =~ m/\s+$docfile\b/s) { |
michael@428 | 563 | $prefix .= "D"; |
michael@428 | 564 | last; |
michael@428 | 565 | } |
michael@428 | 566 | } |
michael@428 | 567 | foreach my $cfgfile (@cfgfiles) { |
michael@428 | 568 | if ($line =~ m/\s+$cfgfile\b/s) { |
michael@428 | 569 | $prefix .= "C"; |
michael@428 | 570 | last; |
michael@428 | 571 | } |
michael@428 | 572 | } |
michael@428 | 573 | $prefix .= "--"; |
michael@428 | 574 | $prefix = substr($prefix, 0, 2); |
michael@428 | 575 | if ($line =~ m/^d/) { |
michael@428 | 576 | $line =~ s/(\s+\/\S+)/\033[34m$1\033[0m/s; |
michael@428 | 577 | } |
michael@428 | 578 | print "$prefix $line\n"; |
michael@428 | 579 | } |
michael@428 | 580 | |
michael@428 | 581 | return $rc; |
michael@428 | 582 | } |
michael@428 | 583 | |
michael@428 | 584 | # command: show modifications via VCS |
michael@428 | 585 | sub cmd_diff ($@) { |
michael@428 | 586 | my ($gopts, @argv) = @_; |
michael@428 | 587 | my $rc = 0; |
michael@428 | 588 | |
michael@428 | 589 | my $vcs = ""; |
michael@428 | 590 | my $cmd = ""; |
michael@428 | 591 | if (-d "CVS") { |
michael@428 | 592 | $vcs = "CVS"; |
michael@428 | 593 | $cmd = "cvs diff -u3"; |
michael@428 | 594 | } |
michael@428 | 595 | elsif (-d ".svn") { |
michael@428 | 596 | $vcs = "Subversion"; |
michael@428 | 597 | $cmd = "svn diff"; |
michael@428 | 598 | } |
michael@428 | 599 | elsif (-d "_MTN" or -d ".mtn" or |
michael@428 | 600 | -d "../_MTN" or -d "../.mtn" or |
michael@428 | 601 | -d "../../_MTN" or -d "../../.mtn" or |
michael@428 | 602 | -d "../../../_MTN" or -d "../../../.mtn") { |
michael@428 | 603 | $vcs = "Monotone"; |
michael@428 | 604 | $cmd = "mtn diff ."; |
michael@428 | 605 | } |
michael@428 | 606 | elsif (-d ".git" or |
michael@428 | 607 | -d "../.git" or |
michael@428 | 608 | -d "../../.git" or |
michael@428 | 609 | -d "../../../.git") { |
michael@428 | 610 | $vcs = "Git"; |
michael@428 | 611 | $cmd = "git diff . "; |
michael@428 | 612 | } |
michael@428 | 613 | elsif (-d ".hg" or |
michael@428 | 614 | -d "../.hg" or |
michael@428 | 615 | -d "../../.hg" or |
michael@428 | 616 | -d "../../../.hg") { |
michael@428 | 617 | $vcs = "Mercurial"; |
michael@428 | 618 | $cmd = "hg diff ." |
michael@428 | 619 | } |
michael@428 | 620 | else { |
michael@428 | 621 | $vcs = "OSSP svs"; |
michael@428 | 622 | $cmd = "svs diff"; |
michael@428 | 623 | } |
michael@428 | 624 | print STDOUT "\033[34m++ modifications as known to underlying $vcs VCS\033[0m\n"; |
michael@428 | 625 | run($cmd); |
michael@428 | 626 | } |
michael@428 | 627 | |
michael@428 | 628 | # command: install package |
michael@428 | 629 | sub cmd_install ($@) { |
michael@428 | 630 | my ($gopts, @argv) = @_; |
michael@428 | 631 | my $rc = 0; |
michael@428 | 632 | |
michael@428 | 633 | # command line argument processing |
michael@428 | 634 | my $lopts = {}; |
michael@428 | 635 | @argv = getopts("fnos", $lopts, @argv); |
michael@428 | 636 | |
michael@428 | 637 | # run install command |
michael@428 | 638 | my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{_rpmfilename}'`; |
michael@428 | 639 | $template =~ s/\n$//s; |
michael@428 | 640 | my $specfile = specfile(); |
michael@428 | 641 | my $rpm = `$openpkg_prefix/bin/openpkg rpm -q --specfile '$specfile' --qf 'XXX$template'`; |
michael@428 | 642 | $rpm =~ s/^XXX//s; |
michael@428 | 643 | $rpm =~ s/\n$//s; |
michael@428 | 644 | chdir("/"); |
michael@428 | 645 | run(($lopts->{"s"} ? "sudo " : "") . |
michael@428 | 646 | "$openpkg_prefix/bin/openpkg rpm -Uvh" |
michael@428 | 647 | . ($lopts->{"f"} ? " --force" : "") |
michael@428 | 648 | . ($lopts->{"n"} ? " --nodeps" : "") |
michael@428 | 649 | . ($lopts->{"o"} ? " --oldpackage" : "") |
michael@428 | 650 | . " $rpm"); |
michael@428 | 651 | |
michael@428 | 652 | return $rc; |
michael@428 | 653 | } |
michael@428 | 654 | |
michael@428 | 655 | # command: erase package |
michael@428 | 656 | sub cmd_erase ($@) { |
michael@428 | 657 | my ($gopts, @argv) = @_; |
michael@428 | 658 | my $rc = 0; |
michael@428 | 659 | |
michael@428 | 660 | # command line argument processing |
michael@428 | 661 | my $lopts = {}; |
michael@428 | 662 | @argv = getopts("fnas", $lopts, @argv); |
michael@428 | 663 | |
michael@428 | 664 | # run erase command |
michael@428 | 665 | my $specfile = specfile(); |
michael@428 | 666 | my $name = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '%{NAME}'`; |
michael@428 | 667 | $name =~ s/\n$//s; |
michael@428 | 668 | chdir("/"); |
michael@428 | 669 | run(($lopts->{"s"} ? "sudo " : "") . |
michael@428 | 670 | "$openpkg_prefix/bin/openpkg rpm -e" |
michael@428 | 671 | . ($lopts->{"f"} ? " --force" : "") |
michael@428 | 672 | . ($lopts->{"n"} ? " --nodeps" : "") |
michael@428 | 673 | . ($lopts->{"a"} ? " --allmatches" : "") |
michael@428 | 674 | . " $name"); |
michael@428 | 675 | |
michael@428 | 676 | return $rc; |
michael@428 | 677 | } |
michael@428 | 678 | |
michael@428 | 679 | # command: lint package |
michael@428 | 680 | sub cmd_lint ($@) { |
michael@428 | 681 | my ($gopts, @argv) = @_; |
michael@428 | 682 | my $rc = 0; |
michael@428 | 683 | |
michael@428 | 684 | # command line argument processing |
michael@428 | 685 | my $lopts = {}; |
michael@428 | 686 | @argv = getopts("vb", $lopts, @argv); |
michael@428 | 687 | |
michael@428 | 688 | # run source linting commands |
michael@428 | 689 | my $specfile = specfile(); |
michael@428 | 690 | my $fslfile = $specfile; |
michael@428 | 691 | $fslfile =~ s/([^\/]+)\.spec$/fsl.$1/s; |
michael@428 | 692 | my $rcfile = $specfile; |
michael@428 | 693 | $rcfile =~ s/([^\/]+)\.spec$/rc.$1/s; |
michael@428 | 694 | my $name = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '%{NAME}'`; |
michael@428 | 695 | $name =~ s/\n$//s; |
michael@428 | 696 | my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{_rpmfilename}'`; |
michael@428 | 697 | $template =~ s/\n$//s; |
michael@428 | 698 | my $rpm = `$openpkg_prefix/bin/openpkg rpm -q --specfile '$specfile' --qf 'XXX$template'`; |
michael@428 | 699 | $rpm =~ s/^XXX//s; |
michael@428 | 700 | $rpm =~ s/\n$//s; |
michael@428 | 701 | my $rc = 0; |
michael@428 | 702 | $rc += run("$openpkg_prefix/bin/openpkg lint-spec" . ($lopts->{"v"} ? " --verbose" : "") . " $specfile"); |
michael@428 | 703 | $rc += run("$openpkg_prefix/bin/openpkg lint-fsl" . ($lopts->{"v"} ? " --verbose" : "") . " $fslfile") if (-f $fslfile); |
michael@428 | 704 | $rc += run("$openpkg_prefix/bin/openpkg lint-rc" . ($lopts->{"v"} ? " --verbose" : "") . " $rcfile") if (-f $rcfile); |
michael@428 | 705 | |
michael@428 | 706 | # optionally run binary linting command |
michael@428 | 707 | run("$openpkg_prefix/bin/openpkg lint-rpm" . ($lopts->{"v"} ? " --verbose" : "") . " $rpm") if (-f $rpm and not $lopts->{"b"}); |
michael@428 | 708 | |
michael@428 | 709 | return $rc; |
michael@428 | 710 | } |
michael@428 | 711 | |
michael@428 | 712 | # command: release package |
michael@428 | 713 | sub cmd_release ($@) { |
michael@428 | 714 | my ($gopts, @argv) = @_; |
michael@428 | 715 | my $rc = 0; |
michael@428 | 716 | |
michael@428 | 717 | # command line argument processing |
michael@428 | 718 | my $lopts = {}; |
michael@428 | 719 | @argv = getopts("nm:f", $lopts, @argv); |
michael@428 | 720 | |
michael@428 | 721 | # implicit linting |
michael@428 | 722 | if (not $lopts->{"f"}) { |
michael@428 | 723 | my $rc = cmd_lint($gopts); |
michael@428 | 724 | if ($rc != 0 and !$lopts->{"f"}) { |
michael@428 | 725 | return $rc; |
michael@428 | 726 | } |
michael@428 | 727 | } |
michael@428 | 728 | |
michael@428 | 729 | # sanity check environment |
michael@428 | 730 | my $cmd = $ENV{"OPENPKG_DEV_RELEASE"} |
michael@428 | 731 | || `$openpkg_prefix/bin/openpkg rpm --eval '%{openpkg_dev_release}' 2>/dev/null || true` || ""; |
michael@428 | 732 | $cmd =~ s/\n$//s; |
michael@428 | 733 | if ($cmd eq "") { |
michael@428 | 734 | print STDERR "openpkg:$prog_name:ERROR: no \$OPENPKG_DEV_RELEASE command defined\n"; |
michael@428 | 735 | exit(1); |
michael@428 | 736 | } |
michael@428 | 737 | |
michael@428 | 738 | # |
michael@428 | 739 | # determine package information |
michael@428 | 740 | # |
michael@428 | 741 | |
michael@428 | 742 | print STDOUT "\033[34m++ determining package information\033[0m\n"; |
michael@428 | 743 | my $info = {}; |
michael@428 | 744 | $info->{"openpkg-prefix"} = $openpkg_prefix; |
michael@428 | 745 | $info->{"option-force"} = $lopts->{"f"} ? "yes" : "no"; |
michael@428 | 746 | |
michael@428 | 747 | print STDOUT "-- determining package name/version/release\n"; |
michael@428 | 748 | my $specfile = specfile(); |
michael@428 | 749 | my $result = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '::%{NAME}::%{VERSION}::%{RELEASE}'`; |
michael@428 | 750 | $result =~ s/\n$//s; |
michael@428 | 751 | $result =~ s/^:://s; |
michael@428 | 752 | my @result = split(/::/, $result); |
michael@428 | 753 | $info->{"package-name"} = $result[0]; |
michael@428 | 754 | $info->{"package-version"} = $result[1]; |
michael@428 | 755 | $info->{"package-release"} = $result[2]; |
michael@428 | 756 | |
michael@428 | 757 | print STDOUT "-- determining package source and distribution location\n"; |
michael@428 | 758 | my $defines = "--define '\%name " . $info->{"package-name"} . "'"; |
michael@428 | 759 | $defines .= " --define '\%version " . $info->{"package-version"} . "'"; |
michael@428 | 760 | $defines .= " --define '\%release " . $info->{"package-release"} . "'"; |
michael@428 | 761 | my $result = `$openpkg_prefix/bin/openpkg rpm $defines --eval '%{_specdir}::%{_sourcedir}'`; |
michael@428 | 762 | $result =~ s/\n$//s; |
michael@428 | 763 | @result = split(/::/, $result); |
michael@428 | 764 | $info->{"spec-dir"} = $result[0]; |
michael@428 | 765 | $info->{"source-dir"} = $result[1]; |
michael@428 | 766 | |
michael@428 | 767 | print STDOUT "-- determining package source and binary RPM files\n"; |
michael@428 | 768 | my $template = `$openpkg_prefix/bin/openpkg rpm --eval '%{_rpmdir}/%{l_binrpmfilename}::%{_srcrpmdir}/%{l_srcrpmfilename}'`; |
michael@428 | 769 | $template =~ s/\n$//s; |
michael@428 | 770 | $result = `$openpkg_prefix/bin/openpkg rpm -q --specfile $specfile --qf '::$template'`; |
michael@428 | 771 | $result =~ s/\n$//s; |
michael@428 | 772 | $result =~ s/^:://s; |
michael@428 | 773 | @result = split(/::/, $result); |
michael@428 | 774 | $info->{"binary-rpm-file"} = $result[0]; |
michael@428 | 775 | $info->{"source-rpm-file"} = $result[1]; |
michael@428 | 776 | $info->{"package-version-old"} = ""; |
michael@428 | 777 | $info->{"package-release-old"} = ""; |
michael@428 | 778 | $info->{"vcs"} = "none"; |
michael@428 | 779 | |
michael@428 | 780 | print STDOUT "-- determining previous package version/release\n"; |
michael@428 | 781 | my $vcs = ""; |
michael@428 | 782 | my $diff = ""; |
michael@428 | 783 | my $content_old = ""; |
michael@428 | 784 | my $specdir = $info->{"spec-dir"}; |
michael@428 | 785 | my $specfile = $info->{"package-name"} . ".spec"; |
michael@428 | 786 | if (-f "$specdir/$specfile") { |
michael@428 | 787 | open(FP, "<$specdir/$specfile"); |
michael@428 | 788 | $content_new .= $_ while (<FP>); |
michael@428 | 789 | close(FP); |
michael@428 | 790 | if ($content_new =~ m/\n\%No(?:Source|Patch)\s+/s) { |
michael@428 | 791 | $info->{"source-rpm-file"} =~ s/\.src\.rpm$/.nosrc.rpm/s; |
michael@428 | 792 | } |
michael@428 | 793 | if (-d "$specdir/CVS") { |
michael@428 | 794 | # package is version controlled via CVS |
michael@428 | 795 | $vcs = "cvs"; |
michael@428 | 796 | $diff = `(cd $specdir && cvs diff -u3 $specfile) 2>/dev/null || true`; |
michael@428 | 797 | } |
michael@428 | 798 | elsif (-d "$specdir/.svn") { |
michael@428 | 799 | # package is version controlled via Subverson (SVN) |
michael@428 | 800 | $vcs = "svn"; |
michael@428 | 801 | $diff = `(cd $specdir && svn diff $specfile) 2>/dev/null || true`; |
michael@428 | 802 | } |
michael@428 | 803 | elsif (-d "$specdir/_MTN" or -d "$specdir/.mtn" or |
michael@428 | 804 | -d "$specdir/../_MTN" or -d "$specdir/../.mtn" or |
michael@428 | 805 | -d "$specdir/../../_MTN" or -d "$specdir/../../.mtn" or |
michael@428 | 806 | -d "$specdir/../../../_MTN" or -d "$specdir/../../../.mtn") { |
michael@428 | 807 | # package is version controlled via Monotone (MTN) |
michael@428 | 808 | $vcs = "mtn"; |
michael@428 | 809 | $diff = `(cd $specdir && mtn diff $specfile) 2>/dev/null || true`; |
michael@428 | 810 | $content_old = `(cd $specdir && mtn automate get_file_of -r h: $specfile) 2>/dev/null || true`; |
michael@428 | 811 | } |
michael@428 | 812 | elsif (-d "$specdir/.git" or |
michael@428 | 813 | -d "$specdir/../.git" or |
michael@428 | 814 | -d "$specdir/../../.git" or |
michael@428 | 815 | -d "$specdir/../../../.git") { |
michael@428 | 816 | # package is version controlled via Git |
michael@428 | 817 | $vcs = "git"; |
michael@428 | 818 | $diff = `(cd $specdir && git diff $specfile) 2>/dev/null || true`; |
michael@428 | 819 | } |
michael@428 | 820 | elsif (-d "$specdir/.hg" or |
michael@428 | 821 | -d "$specdir/../.hg" or |
michael@428 | 822 | -d "$specdir/../../.hg" or |
michael@428 | 823 | -d "$specdir/../../../.hg") { |
michael@428 | 824 | # package is version controlled via Mercurial (Hg) |
michael@428 | 825 | $vcs = "hg"; |
michael@428 | 826 | $diff = `(cd $specdir && hg diff $specfile) 2>/dev/null || true`; |
michael@428 | 827 | } |
michael@428 | 828 | elsif (-f "$specdir/$specfile.orig") { |
michael@428 | 829 | # package is patched via OSSP svs |
michael@428 | 830 | $vcs = "svs"; |
michael@428 | 831 | $diff = `(cd $specdir && svs diff $specfile) 2>/dev/null || true`; |
michael@428 | 832 | } |
michael@428 | 833 | if ($vcs ne '') { |
michael@428 | 834 | $info->{"vcs"} = $vcs; |
michael@428 | 835 | } |
michael@428 | 836 | if ($content_old ne '') { |
michael@428 | 837 | my $define = {}; |
michael@428 | 838 | $content_old =~ s/\n\%define[ \t]+([^ \t\n]+)[ \t]+([^ \t\n]+)/$define->{$1} = $2, ''/sge; |
michael@428 | 839 | $content_old =~ s/\n([^ \t\n]+):[ \t]+([^ \t\n]+)/$define->{lc($1)} = $2, ''/sge; |
michael@428 | 840 | sub resolve { |
michael@428 | 841 | my ($define, $name) = @_; |
michael@428 | 842 | my $value = $define->{$name}; |
michael@428 | 843 | $value = "" if (not defined $value); |
michael@428 | 844 | $value =~ s/\%\{(.+?)\}/resolve($define, $1)/sge; |
michael@428 | 845 | return $value; |
michael@428 | 846 | } |
michael@428 | 847 | $info->{"package-version-old"} = resolve($define, "version"); |
michael@428 | 848 | $info->{"package-release-old"} = resolve($define, "release"); |
michael@428 | 849 | } |
michael@428 | 850 | if (( $info->{"package-version-old"} eq '' |
michael@428 | 851 | or $info->{"package-release-old"} eq '') |
michael@428 | 852 | and $diff ne '' ) { |
michael@428 | 853 | if ($info->{"package-version-old"} eq '' and $diff =~ m/\n-Version:\s+(\S+)/s) { |
michael@428 | 854 | $info->{"package-version-old"} = $1; |
michael@428 | 855 | } |
michael@428 | 856 | if ($info->{"package-release-old"} eq '' and $diff =~ m/\n-Release:\s+(\S+)/s) { |
michael@428 | 857 | $info->{"package-release-old"} = $1; |
michael@428 | 858 | } |
michael@428 | 859 | } |
michael@428 | 860 | } |
michael@428 | 861 | |
michael@428 | 862 | print STDOUT "-- determining commit message\n"; |
michael@428 | 863 | $info->{"commit-message"} = ($lopts->{"m"} || ""); |
michael@428 | 864 | if ($info->{"commit-message"} eq "") { |
michael@428 | 865 | if ($info->{"package-version-old"} ne $info->{"package-version"}) { |
michael@428 | 866 | # new version |
michael@428 | 867 | $info->{"commit-message"} = "upgrading package: " . |
michael@428 | 868 | $info->{"package-name"} . " " . |
michael@428 | 869 | $info->{"package-version-old"} . " -> " . |
michael@428 | 870 | $info->{"package-version"}; |
michael@428 | 871 | } |
michael@428 | 872 | elsif (!$lopts->{"f"}) { |
michael@428 | 873 | print STDERR "openpkg:$prog_name:ERROR: package version not changed -- you have to manually provide a commit message\n"; |
michael@428 | 874 | exit(1); |
michael@428 | 875 | } |
michael@428 | 876 | } |
michael@428 | 877 | |
michael@428 | 878 | # run external command |
michael@428 | 879 | print STDOUT "\033[34m++ executing openpkg development release program\033[0m\n"; |
michael@428 | 880 | $cmd .= " %{openpkg-prefix}"; |
michael@428 | 881 | $cmd .= " %{spec-dir} %{source-dir} %{binary-rpm-file} %{source-rpm-file}"; |
michael@428 | 882 | $cmd .= " %{package-name} %{package-version} %{package-release} %{package-version-old} %{package-release-old}"; |
michael@428 | 883 | $cmd .= " %{commit-message} %{vcs}"; |
michael@428 | 884 | $cmd .= " %{option-force}"; |
michael@428 | 885 | $cmd =~ s/(\%\{([a-z][a-z-]+)\})/&subst($info, $1, $2)/sge; |
michael@428 | 886 | sub subst { |
michael@428 | 887 | my ($info, $text, $name) = @_; |
michael@428 | 888 | if (exists($info->{$name})) { |
michael@428 | 889 | $text = $info->{$name}; |
michael@428 | 890 | $text =~ s/'/\\'/sg; |
michael@428 | 891 | $text = "'$text'"; |
michael@428 | 892 | } |
michael@428 | 893 | } |
michael@428 | 894 | if ($lopts->{"n"}) { |
michael@428 | 895 | print STDOUT "-- DRY RUN:\n"; |
michael@428 | 896 | print STDOUT "-- $cmd\n"; |
michael@428 | 897 | $rc = 0; |
michael@428 | 898 | } |
michael@428 | 899 | else { |
michael@428 | 900 | $rc = system($cmd); |
michael@428 | 901 | } |
michael@428 | 902 | |
michael@428 | 903 | return $rc; |
michael@428 | 904 | } |
michael@428 | 905 |