head	1.71;
access;
symbols
	RELEASE_2_4_6:1.60
	RELEASE_2_4_5:1.60
	RELEASE_2_4_3:1.52
	RELEASE_2_4_2:1.49
	RELEASE_2_4_1:1.47
	RELEASE_2_4_0:1.42
	RELEASE_2_3_2:1.40
	RELEASE_2_3_1:1.33.2.3
	STABLE_2_3:1.33.0.2
	RELEASE_2_3_0:1.30
	RELEASE_2_2_6:1.24.2.1
	RELEASE_2_2_5:1.24.2.1
	RELEASE_2_2_4:1.26
	RELEASE_2_2_3:1.24.2.1
	STABLE_2_2:1.24.0.2
	RELEASE_2_2_2:1.24
	RELEASE_2_2_1:1.22
	RELEASE_2_2_0:1.20
	RELEASE_2_1_3_3:1.1.1.1.2.5
	RELEASE_2_1_7:1.16
	RELEASE_2_1_6:1.12
	RELEASE_2_1_3_2:1.1.1.1.2.2
	RELEASE_2_1_5:1.11
	RELEASE_2_1_3_1:1.1.1.1.2.1.0.2
	STABLE:1.1.1.1.0.2
	PKGTOOLS_2_1_4:1.8
	PKGTOOLS_2_1_3:1.1.1.1
	sem:1.1.1;
locks; strict;
comment	@# @;


1.71
date	2011.08.19.00.57.22;	author stas;	state dead;
branches;
next	1.70;

1.70
date	2011.07.25.12.34.43;	author swills;	state Exp;
branches;
next	1.69;

1.69
date	2010.11.23.20.29.14;	author stas;	state Exp;
branches;
next	1.68;

1.68
date	2010.11.08.04.37.25;	author stas;	state Exp;
branches;
next	1.67;

1.67
date	2009.12.22.01.24.51;	author stas;	state Exp;
branches;
next	1.66;

1.66
date	2009.12.21.22.19.23;	author stas;	state Exp;
branches;
next	1.65;

1.65
date	2009.10.29.00.31.15;	author stas;	state Exp;
branches;
next	1.64;

1.64
date	2009.10.27.16.59.20;	author stas;	state Exp;
branches;
next	1.63;

1.63
date	2009.10.27.14.59.37;	author stas;	state Exp;
branches;
next	1.62;

1.62
date	2009.10.26.14.47.49;	author stas;	state Exp;
branches;
next	1.61;

1.61
date	2008.07.17.00.26.38;	author sem;	state Exp;
branches;
next	1.60;

1.60
date	2008.07.01.11.32.25;	author sem;	state Exp;
branches;
next	1.59;

1.59
date	2008.06.30.23.22.24;	author sem;	state Exp;
branches;
next	1.58;

1.58
date	2008.06.30.17.37.31;	author sem;	state Exp;
branches;
next	1.57;

1.57
date	2008.06.30.17.35.05;	author sem;	state Exp;
branches;
next	1.56;

1.56
date	2008.06.30.17.28.21;	author sem;	state Exp;
branches;
next	1.55;

1.55
date	2008.06.30.15.38.39;	author sem;	state Exp;
branches;
next	1.54;

1.54
date	2008.06.17.12.11.14;	author sem;	state Exp;
branches;
next	1.53;

1.53
date	2008.06.17.11.11.38;	author sem;	state Exp;
branches;
next	1.52;

1.52
date	2008.02.10.23.20.02;	author sem;	state Exp;
branches;
next	1.51;

1.51
date	2008.02.10.22.01.40;	author sem;	state Exp;
branches;
next	1.50;

1.50
date	2008.02.10.12.04.39;	author sem;	state Exp;
branches;
next	1.49;

1.49
date	2008.02.04.11.34.20;	author sem;	state Exp;
branches;
next	1.48;

1.48
date	2008.02.04.10.54.47;	author sem;	state Exp;
branches;
next	1.47;

1.47
date	2008.01.29.13.38.52;	author sem;	state Exp;
branches;
next	1.46;

1.46
date	2008.01.28.14.56.08;	author sem;	state Exp;
branches;
next	1.45;

1.45
date	2008.01.27.22.33.51;	author sem;	state Exp;
branches;
next	1.44;

1.44
date	2008.01.27.18.56.19;	author sem;	state Exp;
branches;
next	1.43;

1.43
date	2008.01.27.17.56.30;	author sem;	state Exp;
branches;
next	1.42;

1.42
date	2008.01.26.16.01.16;	author sem;	state Exp;
branches;
next	1.41;

1.41
date	2008.01.26.14.30.36;	author sem;	state Exp;
branches;
next	1.40;

1.40
date	2008.01.12.18.26.52;	author sem;	state Exp;
branches;
next	1.39;

1.39
date	2008.01.08.11.32.27;	author sem;	state Exp;
branches;
next	1.38;

1.38
date	2007.08.09.15.28.05;	author sem;	state Exp;
branches;
next	1.37;

1.37
date	2007.07.03.10.37.58;	author sem;	state Exp;
branches;
next	1.36;

1.36
date	2007.07.03.09.57.35;	author sem;	state Exp;
branches;
next	1.35;

1.35
date	2007.07.03.09.41.41;	author sem;	state Exp;
branches;
next	1.34;

1.34
date	2007.07.03.09.40.18;	author sem;	state Exp;
branches;
next	1.33;

1.33
date	2007.03.08.10.38.39;	author sem;	state Exp;
branches
	1.33.2.1;
next	1.32;

1.32
date	2007.03.03.19.33.20;	author sem;	state Exp;
branches;
next	1.31;

1.31
date	2007.03.03.19.31.26;	author sem;	state Exp;
branches;
next	1.30;

1.30
date	2007.02.26.16.00.26;	author sem;	state Exp;
branches;
next	1.29;

1.29
date	2007.02.26.14.43.00;	author sem;	state Exp;
branches;
next	1.28;

1.28
date	2007.02.26.14.36.59;	author sem;	state Exp;
branches;
next	1.27;

1.27
date	2007.02.24.12.38.00;	author sem;	state Exp;
branches;
next	1.26;

1.26
date	2007.02.22.13.36.34;	author sem;	state Exp;
branches;
next	1.25;

1.25
date	2007.02.16.09.09.32;	author sem;	state Exp;
branches;
next	1.24;

1.24
date	2006.11.18.18.10.10;	author sem;	state Exp;
branches
	1.24.2.1;
next	1.23;

1.23
date	2006.11.17.20.57.21;	author sem;	state Exp;
branches;
next	1.22;

1.22
date	2006.11.12.18.58.56;	author sem;	state Exp;
branches;
next	1.21;

1.21
date	2006.11.12.11.16.34;	author sem;	state Exp;
branches;
next	1.20;

1.20
date	2006.11.06.15.58.43;	author sem;	state Exp;
branches;
next	1.19;

1.19
date	2006.11.06.13.02.56;	author sem;	state Exp;
branches;
next	1.18;

1.18
date	2006.11.04.12.39.42;	author sem;	state Exp;
branches;
next	1.17;

1.17
date	2006.10.15.12.54.17;	author sem;	state Exp;
branches;
next	1.16;

1.16
date	2006.08.13.11.42.22;	author sem;	state Exp;
branches;
next	1.15;

1.15
date	2006.08.13.11.23.14;	author sem;	state Exp;
branches;
next	1.14;

1.14
date	2006.08.13.11.15.21;	author sem;	state Exp;
branches;
next	1.13;

1.13
date	2006.08.09.17.00.33;	author sem;	state Exp;
branches;
next	1.12;

1.12
date	2006.07.13.06.01.03;	author sem;	state Exp;
branches;
next	1.11;

1.11
date	2006.06.30.20.19.24;	author sem;	state Exp;
branches;
next	1.10;

1.10
date	2006.06.30.20.09.28;	author sem;	state Exp;
branches;
next	1.9;

1.9
date	2006.06.30.19.21.00;	author sem;	state Exp;
branches;
next	1.8;

1.8
date	2006.06.18.15.14.02;	author sem;	state Exp;
branches;
next	1.7;

1.7
date	2006.06.18.14.24.45;	author sem;	state Exp;
branches;
next	1.6;

1.6
date	2006.06.17.13.13.33;	author sem;	state Exp;
branches;
next	1.5;

1.5
date	2006.06.15.15.54.30;	author sem;	state Exp;
branches;
next	1.4;

1.4
date	2006.06.15.11.32.11;	author sem;	state Exp;
branches;
next	1.3;

1.3
date	2006.06.14.14.33.59;	author sem;	state Exp;
branches;
next	1.2;

1.2
date	2006.06.14.11.52.38;	author sem;	state Exp;
branches;
next	1.1;

1.1
date	2006.06.13.12.59.01;	author sem;	state Exp;
branches
	1.1.1.1;
next	;

1.33.2.1
date	2007.07.03.09.43.21;	author sem;	state Exp;
branches;
next	1.33.2.2;

1.33.2.2
date	2007.07.03.10.07.40;	author sem;	state Exp;
branches;
next	1.33.2.3;

1.33.2.3
date	2007.07.03.10.58.27;	author sem;	state Exp;
branches;
next	;

1.24.2.1
date	2007.02.22.14.00.37;	author sem;	state Exp;
branches;
next	;

1.1.1.1
date	2006.06.13.12.59.01;	author sem;	state Exp;
branches
	1.1.1.1.2.1;
next	;

1.1.1.1.2.1
date	2006.06.29.18.02.12;	author sem;	state Exp;
branches;
next	1.1.1.1.2.2;

1.1.1.1.2.2
date	2006.07.01.06.40.10;	author sem;	state Exp;
branches;
next	1.1.1.1.2.3;

1.1.1.1.2.3
date	2006.07.13.06.02.02;	author sem;	state Exp;
branches;
next	1.1.1.1.2.4;

1.1.1.1.2.4
date	2006.08.09.17.04.59;	author sem;	state Exp;
branches;
next	1.1.1.1.2.5;

1.1.1.1.2.5
date	2006.08.23.09.25.00;	author sem;	state Exp;
branches;
next	;


desc
@@


1.71
log
@- The project data has moved to github (https://github.com/stass/pkgtools).
@
text
@#!/usr/bin/env ruby
# -*- ruby -*-
#
# Copyright (c) 2000-2004 Akinori MUSHA
# Copyright (c) 2005,2006 KOMATSU Shinichiro
# Copyright (c) 2006-2008 Sergey Matveychuk <sem@@FreeBSD.org>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD: projects/pkgtools/bin/portupgrade,v 1.70 2011-07-25 12:34:43 swills Exp $
#

MYREVISION = %w$Rev: 71 $[1]
MYDATE = %w$Date: 2008/07/01 11:32:25 $[1]
MYNAME = File.basename($0)

require "optparse"
require "pkgtools"

REASON_COMMENT = {
  :badcpp => "bad C++ code",
  :bison => "bison error",
  :categories => "invalid category",
  :cc => "compiler error",
  :checksum => "checksum mismatch",
  :chown => "chown error",
  :configure => "configure error",
  :coredump => "coredump",
  :dependobj => "depend object",
#  :dependpkg => "depend package",
#  :diskfull => "disk full",
  :display => "X DISPLAY error",
  :distinfo => "distinfo incorrect",
  :elf => "ELF",
#  :extra => 'extra files',
#  :fetch_timeout => "fetch timeout",
  :fetch => "fetch error",
  :gcc_bug => "gcc bug",
  :header => "missing header",
  :install => "install error",
  :interrupt => "interrupted by user",
  :ld => "linker error",
  :libdepends => "dependent libraries",
  :malloc_h => "reference to malloc.h",
  :manpage => "manpage error",
  :motif => "Motif error",
  :motiflib => "Motif libraries error",
  :newgcc => "new compiler error",
#  :nfs => "NFS error",
  :patch => "patch error",
  :perm => "permission denied",
  :perl => "perl missing",
  :perl5 => "Perl5 error (h2ph)",
  :plist => "package error",
#  :runaway => "runaway process",
  :segfault => "segmentation fault",
  :soundcard_h => "reference to soundcard.h",
  :stdio => "stdio compatibility",
  :struct => "struct changes",
  :texinfo => "texinfo error",
  :union => "union wait error",
  :unknown => "unknown build error",
  :usexlib => "X libraries missing",
#  :wrkdir => "WRKDIR error",
  :values_h => "reference to values.h",
  :xfree4man => "X manpage error",
}

class OriginMissingError < StandardError
  def message
    "missing origin"
  end
end
class PortDirError < StandardError
  def message
    "port directory error"
  end
end
class ConfigError < StandardError
  def message
    "make config failed"
  end
end
class MakefileBrokenError < StandardError
  def message
    "Makefile broken"
  end
end
class IgnoreMarkError < StandardError
  def message
    "marked as IGNORE"
  end
end
class InvalidPkgNameError < StandardError
  def message
    "invalid package name"
  end
end
class BackupError < StandardError
  def message
    "backup error"
  end
end
class UninstallError < StandardError
#  def message
#    "uninstall error"
#  end
end
class FetchError < StandardError
  def message
    "fetch error"
  end
end
class BuildError < StandardError
#  def message
#    "build error"
#  end
end
class InstallError < StandardError
#  def message
#    "install error"
#  end
end
class PkgNotFoundError < StandardError
  def message
    "package not found"
  end
end
class RecursiveDependencyError < StandardError
  def message
    "recursive dependency"
  end
end

begin
  $initial_pwd = Dir.pwd

  if $initial_pwd.empty?
    raise Errno::ENOENT, 'No such file or directory'
  end
rescue => e
  # XXX: the .sub(/ - .*/, '') part should be removed later
  STDERR.puts "Cannot locate current working directory: #{e.message.sub(/ - .*/, '')}"
  exit 1
end

COLUMNSIZE = 24
NEXTLINE = "\n%*s" % [5 + COLUMNSIZE, '']

def init_global
  $afterinstall = ''
  $all = false
  $backup_packages = false
  $batch_mode = false
  $beforebuild = ''
  $clean = true
  $cleanup = true
  $config = false
  $force_config = false
  $current_pkgname = ''
  $depends = Hash.new
  $distclean = 0
  $emit_summaries = false
  $exclude_packages = []
  $fetch_only = false
  $fetch_recursive = false
  $force = false
  $keep_going = false
  $ignore_moved = false
  $interactive = false
  $logfilename_format = nil
  $make_args = ""
  $make_env = []
  $new = MYNAME == 'portinstall'
  $noexecute = false
  $noconfig = false
  $origin = nil
  $package = false
  $pkg_cache = {}
  $pkgdb_update = false
  $quiet = false
  $recursive = false
  $resultsfile = nil
  $sanity_check = true
  $tmpdir = ""
  $uninstall_extra_flags = 'P'
  $upward_recursive = false
  $use_packages = false
  $use_packages_only = false
  $without_env_upgrade = false
  $yestoall = false
end

def main(argv)
  usage = <<-"EOF"
usage: #{MYNAME} [-habcCDDefFiklnOpPPqrRsuvwWy] [-A command] [-B command]
        [-L format] [-S command] [-x pkgname_glob]
        [[-o origin] [-m make_args] [-M make_env] pkgname_glob ...]
  EOF

  banner = <<-"EOF"
#{MYNAME} #{Version} (#{MYDATE})

#{usage}
  EOF

  dry_parse = true
  $results = PkgResultSet.new

  OptionParser.new(banner, COLUMNSIZE) do |opts|
    opts.def_option("-h", "--help",
		    "Show this message") {
      print opts
      exit 0
    }

    opts.def_option("-a", "--all",
		    "Do with all the installed packages") { |v|
      $all = v
      $recursive = false
      $upward_recursive = false
    }

    opts.def_option("-A", "--afterinstall=CMD",
		    "Run the command after each installation") { |v|
      $afterinstall = v
      $afterinstall.strip!
    }

    opts.def_option("-b", "--backup-packages",
		    "Keep backup packages of the old versions") { |v|
      $backup_packages = v
    }

    opts.def_option("--batch",
		    "Run an upgrading process in a batch mode" << NEXTLINE <<
    		    "(with BATCH=yes)") { |v|
      $batch_mode = v
    }

    opts.def_option("-B", "--beforebuild=CMD",
		    "Run the command before each build; If the command" << NEXTLINE <<
		    "exits in failure, then the port will be skipped") { |v|
      $beforebuild = v
      $beforebuild.strip!
    }

    opts.def_option("-c", "--config",
		    "Run \"make config-conditional\" before everything for all tasks") { |v|
      $config = v
    }

    opts.def_option("-C", "--force-config",
		    "Run \"make config\" before everything for all tasks") { |v|
      $force_config = v
      $config = true
    }

    opts.def_option("-D", "--distclean",
		    "Delete failed distfiles and retry if checksum fails" << NEXTLINE <<
		    "Specified twice, do \"make distclean\" before each" << NEXTLINE <<
		    "fetch or build") {
      $distclean += 1
    }

    opts.def_option("-e", "--emit-summaries",
		    "Emit summary info after each port processing" << NEXTLINE ) { |v|
      $emit_summaries = v
    }

    opts.def_option("-f", "--force",
		    "Force the upgrade of a port even if it is to be a" << NEXTLINE <<
		    "downgrade or just a reinstall, or the port is held") { |v|
      $force = v
    }

    opts.def_option("-F", "--fetch-only",
		    "Only fetch distfiles or packages (if -P is given);" << NEXTLINE <<
		    "Do not build or install anything") { |v|
      $fetch_only = v
    }

    opts.def_option("--ignore-moved",
		    "Ignore MOVED file") { |v|
      $ignore_moved = v
    }

    opts.def_option("-i", "--interactive",
		    "Turn on interactive mode") { |v|
      $interactive = v
      $verbose = true
    }

    opts.def_option("-k", "--keep-going",
		    "Force the upgrade of a port even if some of the" << NEXTLINE <<
		    "requisite ports have failed to upgrade") { |v|
      $keep_going = v
    }

    opts.def_option("-l", "--results-file=FILE",
		    "Specify a file name to save the results to" << NEXTLINE <<
		    "(default: do not save results)") { |resultsfile|
      $resultsfile = File.expand_path(resultsfile)
    }

    opts.def_option("-L", "--log-file=FORMAT",
		    "Specify a printf(3) style format to determine the" << NEXTLINE <<
		    "log file name for each port; '%s::%s' is appended" << NEXTLINE <<
		    "if it does not contain a %; category and portname" << NEXTLINE <<
		    "are given as arguments (default: do not save logs)") { |fmt|
      fmt.include?(?%) or fmt << '%s::%s'

      $logfilename_format = File.expand_path(fmt)
    }

    opts.def_option("-m", "--make-args=ARGS",
		    "Specify arguments to append to each make(1)" << NEXTLINE <<
		    "command line") { |v|
      $make_args = v
    } 

    opts.def_option("-M", "--make-env=ARGS",
		    "Specify arguments to prepend to each make(1)" << NEXTLINE <<
		    "command line") { |make_env|
      $make_env = shellwords(make_env) unless make_env.empty?

      if $make_env[0].include?('=')
	$make_env.unshift('env')
      end
    }

    opts.def_option("-n", "--noexecute",
		    "Do not upgrade any ports, but just show what would" << NEXTLINE <<
		    "be done") { |v|
      $noexecute = v
      $verbose = true
      $interactive = true
      $yestoall = false
    }

    opts.def_option("-N", "--new",
		    "Install a new one when a specified package is" << NEXTLINE <<
		    "not installed, after upgrading all the dependent" << NEXTLINE <<
		    "packages (default: #{MYNAME == 'portinstall' ? 'on' : 'off'})") { |v|
      $new = v
    }

    opts.def_option("-o", "--origin=ORIGIN",
		    "Specify a port to upgrade the following pkg with") { |origin|
      $origin = $portsdb.strip(origin) || origin
    }

    opts.def_option("-O", "--omit-check",
		    "Omit sanity checks for dependencies.") {
      $sanity_check = false
      $uninstall_extra_flags << 'O'
    }

    opts.def_option("-p", "--package",
		    "Build package when each port is installed") { |v|
      $package = v
    }

    opts.def_option("-P", "--use-packages",
		    "Use packages instead of ports whenever available;" << NEXTLINE <<
		    "Specified twice, --use-packages-only is implied") {
      if $use_packages and !dry_parse
	$use_packages_only = true
      else
	$use_packages = true
      end
    }

    opts.def_option("--use-packages-only",
		    "Or -PP; Use no ports but packages only") { |v|
      $use_packages_only = v
      $use_packages = true
    }

    opts.def_option("-q", "--quiet",
		    "Be quiet when -N option specified and the package already installed") { |v|
      $quiet = v
    }

    opts.def_option("--noconfig",
		    "Do not read pkgtools.conf") { |v|
      $noconfig = v
    }

    opts.def_option("-r", "--recursive",
		    "Do with all those depending on the given packages" << NEXTLINE <<
		    "as well") {
      $recursive = true unless $all
    }

    opts.def_option("-R", "--upward-recursive",
		    "Do with all those required by the given packages" << NEXTLINE <<
		    "as well / Fetch recursively if -F is specified") {
      $upward_recursive = true unless $all
      $fetch_recursive = true
    }

    opts.def_option("-s", "--sudo",
		    "Run commands under sudo(8) where needed") { |v|
      $sudo = v
    }

    opts.def_option("-S", "--sudo-command=CMD",
		    "Specify an alternative to sudo(8)" << NEXTLINE <<
		    "e.g. 'su root -c \"%s\"' (default: sudo)") { |sudo_command|
      $sudo_args = shellwords(sudo_command)
    }

    opts.def_option("-u", "--uninstall-shlibs",
		    "Do not preserve old shared libraries") {
      $uninstall_extra_flags.sub!(/P/, '');
    }

    opts.def_option("-v", "--verbose",
		    "Be verbose") { |v|
      $verbose = v
    }

    opts.def_option("-w", "--noclean",
		    "Do not \"make clean\" before each build") { |noclean|
      $clean = false
    }

    opts.def_option("-W", "--nocleanup",
		    "Do not \"make clean\" after each installation") { |nocleanup|
      $cleanup = false
    }

    opts.def_option("--without-env-upgrade",
      		    "Do not set UPGRADE_* environment variables") { |v|
      $without_env_upgrade = v
    }

    opts.def_option("-x", "--exclude=GLOB",
		    "Exclude packages matching the specified glob" << NEXTLINE <<
		    "pattern") { |arg|
      begin
	pattern = parse_pattern(arg)
      rescue RegexpError => e
	warning_message e.message.capitalize
	break
      end

      $exclude_packages |= $pkgdb.glob(pattern, false) unless dry_parse
    }

    opts.def_option("-y", "--yes",
		    "Answer yes to all the questions") { |v|
      $yestoall = v
      $verbose = true
      $noexecute = false
    }

    opts.def_tail_option '
pkgname_glob is one of these: a full pkgname, a pkgname w/o version,
a shell glob pattern in which you can use wildcards *, ?, and [..],
an extended regular expression preceded by a colon (:), or a date range
specification preceded by either < or >.  See pkg_glob(1) for details.
The package list is automatically sorted in dependency order.

Environment Variables [default]:
    PACKAGES         packages directory [$PORTSDIR/packages]
    PKGTOOLS_CONF    configuration file [$PREFIX/etc/pkgtools.conf]
    PKG_BACKUP_DIR   directory for keeping old packages [$PKG_PATH]
    PKG_DBDIR        packages DB directory [/var/db/pkg]
    PKG_PATH         packages search path [$PACKAGES/All]
    PKG_TMPDIR       temporary directory for backup etc. [$TMPDIR]
    (Note: This must have enough free space when upgrading a big package)
    PORTSDIR         ports directory [/usr/ports]
    PORTS_DBDIR      ports db directory [$PORTSDIR]
    PORTS_INDEX      ports index file [$PORTSDIR/INDEX]
    PORTUPGRADE      default options (e.g. -v) [none]
    TMPDIR           temporary directory [/var/tmp]'

    upgrade_tasks = []
    install_tasks = []
    $package_tasks = []
    $dep_hash = {}
    $task_options = Hash.new({})

    result_proc = proc {
      if $pkgdb_update
	$pkgdb.close_db

	$pkgdb.autofix(true)
      end

      ret = $results.show($fetch_only ? 'fetched' : 'installed or upgraded')
      $results.save($resultsfile) if $resultsfile
      ret
    }

    $interrupt_proc = result_proc

    begin
      init_global
      init_pkgtools_global

      rest = opts.order(*argv)

      unless $noconfig
        init_global
	load_config
      else
	argv = rest
      end

      dry_parse = false

      opts.order!(argv)

      if envopt = config_value(:PORTUPGRADE_ARGS)
	progress_message "Reading default options: " + envopt if $verbose

	opts.parse(*shellwords(envopt))
      end

      if argv.empty? && !$all
	if o = guess_missing_origin
	  argv << o
	else
	  print opts, "\n"
	  warning_message "No package names given."
	  return 0
	end
      end

      all = '*'
      argv << all

      timer_start("Session")

      opts.order(*argv) do |arg|
	first = nil

	if arg.equal? all
	  next unless $all

	  pattern = arg
	else
	  pattern = $pkgdb.strip(arg) || arg

	  begin
	    pattern = parse_pattern(pattern)
	  rescue RegexpError => e
	    warning_message e.message.capitalize
	    next
	  end
	end

	list = []

	found = false

	unless $new
	  catch(:pkg) {
	    begin
	      $pkgdb.glob(pattern, false).each do |pkgname|
		first ||= pkgname

		list |= $pkgdb.recurse(pkgname, $recursive, false, $sanity_check)
	      end
	    rescue => e
	      STDERR.puts e.message
	      exit 1
	    end

	    list -= ['']
	    list.each do |i|
	      if i == first
		$task_options[i][:origin] = $origin
	      end
	    end

	    upgrade_tasks |= list

	    found = true

	    # Check packages for updates and gather dependecies
	    depends = []
	    not_need_upgrade = []
	    upgrade_tasks.each do |task|
	      pkg = PkgInfo.new(task)
	      if task == first && $origin
		origin = $origin
	      else
		origin = $pkgdb.origin(task)
	      end
	      if !origin.nil?
		begin
		  name = get_pkgname(origin)
		rescue IgnoreMarkError => e
		  $results << PkgResult.new(origin, :ignored, e.message)
		  not_need_upgrade << task
		  next
		rescue PortDirError => e
		  $results << PkgResult.new(origin, :ignored, e.message)
		  not_need_upgrade << task
		  next
		end
		if name == ''
		  warning_message "There are errors in a meta info for #{task}"
		  warning_message "Run 'pkgdb -F' to interactively fix them."
		  exit 1
		end
		if $upward_recursive || $config
		  dep = []
		  get_all_depends(origin).each do |d|
		    newdep = $pkgdb.deorigin(d)
		    unless newdep.nil? then
		      dep << newdep.to_s
		    end
		  end
		  depends |= dep if $upward_recursive
		end
		name =~ /^(.+)-([^-]+)$/
		newversion = PkgVersion.new($2)
		if newversion <= pkg.version && !$force
		  not_need_upgrade << task
		  next
		end
		# XXX It makes more problems than solves
		#install_tasks |= get_notinstalled_depends(origin)
	      end
	    end
	    upgrade_tasks -= not_need_upgrade

	    # Check dependencies for updates
	    depends -= ['']
	    if $upward_recursive
	      STDERR.print '[Exclude up-to-date packages '
	      not_need_upgrade = []
	      depends.each do |task|
		STDERR.print '.'
		next if task.nil? or task.empty?
		begin
		  pkg = PkgInfo.new(task)
	        rescue ArgumentError => e
		  $results << PkgResult.new(task, :ignored, e.message)
		  not_need_upgrade << task
		  next
		end
		origin = $pkgdb.origin(task)
		if !origin.nil?
		  begin
		    name = get_pkgname(origin)
		  rescue IgnoreMarkError => e
		    $results << PkgResult.new(origin, :ignored, e.message)
		    not_need_upgrade << task
		    next
		  rescue PortDirError => e
		    $results << PkgResult.new(origin, :ignored, e.message)
		    not_need_upgrade << task
		    next
		  end
		  if name == ''
		    warning_message "There are errors in a meta info for #{task}"
		    warning_message "Run 'pkgdb -F' to interactively fix them."
		    exit 1
		  end
		  name =~ /^(.+)-([^-]+)$/
		  newversion = PkgVersion.new($2)
		  if newversion <= pkg.version && !$force
		    not_need_upgrade << task
		    next
		  end
		end
	      end
	      STDERR.puts ' done]'
	      depends -= not_need_upgrade
	    end
	    upgrade_tasks += depends

	    if upgrade_tasks.empty?
	      throw :pkg
	    end

	    upgrade_tasks -= $exclude_packages

	    if upgrade_tasks.empty?
	      warning_message "No matching packages left after exclusion: #{arg}"
	      throw :pkg
	    end

	  }
	  unless found
	    warning_message "No such installed package: #{arg}"
	  end

	else		# User wants install, not upgdate

	  pattern = $portsdb.strip(arg) || arg	# allow pkgname_glob

	  begin
	    pattern = parse_pattern(pattern)
	  rescue RegexpError => e
	    warning_message e.message.capitalize
	    next
	  end

	  stty_sane

	  ports = $portsdb.glob(pattern).each.map { |i| i.origin }

	  unique = false

	  case ports.size
	  when 0
	    if $portsdb.exist?(arg)
	      # The specified port does not have an entry in the INDEX but
	      # the port directory actually exists.

	      unique = true

	      ports << arg
	    else
	      warning_message "No such package or port: #{arg}"
	      next
	    end
	  when 1
	    unique = true
	  else
	    progress_message "Found #{ports.size} ports matching '#{arg}':"
	    ports.each { |origin| puts "\t#{origin}" }
	  end

	  ports.each do |origin|
	    if pkgnames = $pkgdb.deorigin(origin)
	      if !$quiet
		warning_message "Found already installed package(s) of '#{origin}': " + pkgnames.join(' ')
	      end
	      next
	    else
	      interactive = $interactive || !unique
	      yes_by_default = true
	    end

	    if $noexecute
	      puts "Install '#{origin}'? [no]" if interactive
	      next
	    elsif $yestoall
	      puts "Install '#{origin}'? [yes]" if interactive
	    elsif interactive
	      prompt_yesno("Install '#{origin}'?", yes_by_default) or next	# "
	    end

	    install_tasks << origin
	    # Track all not installed
	    get_notinstalled_depends(origin).each do |dep|
	      install_tasks << dep
	    end
	  end
	end
      end	# Arguments parsing done

      if $package && !$fetch_only
	t = $pkgdb.tsort(upgrade_tasks)
	h = t.dump
	upgrade_tasks.each do |k|
	  $dep_hash[k] = h[k] & upgrade_tasks
	end
	upgrade_tasks = t.tsort! & upgrade_tasks
      else
	$pkgdb.sort_build!(upgrade_tasks)
      end

      $portsdb.sort!(install_tasks)
    rescue OptionParser::ParseError => e
      STDERR.puts "#{MYNAME}: #{e}", usage
      exit 64
    end

    ntasks = upgrade_tasks.size + install_tasks.size
    ctask = 0

    $current_pkgname = ''
    install_tasks.each do |origin| 
      ctask += 1
      setproctitle('[%d/%d] %s', ctask, ntasks, origin)
      do_install(origin)
      progress_message "** Install tasks #{install_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
    end

    upgrade_tasks.each do |pkgname|
      ctask += 1
      setproctitle('[%d/%d] %s', ctask, ntasks, pkgname)
      $current_pkgname = pkgname
      do_upgrade(pkgname)
      progress_message "** Upgrade tasks #{upgrade_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
    end

    return result_proc.call
  end
ensure
  stty_sane unless $results.empty?

  timer_end("Session")
end

# Returns:
#      Set: all recursive depends list
def get_all_depends(origin, parents_list = nil)
  if $use_packages_only
    depends_vars = %w{LIB_DEPENDS RUN_DEPENDS}
  else
  depends_vars = %w{FETCH_DEPENDS EXTRACT_DEPENDS PATCH_DEPENDS
		      BUILD_DEPENDS LIB_DEPENDS RUN_DEPENDS}
  end

  unless $depends.has_key?(origin)
    depends = Set.new

    portdir = $portsdb.portdir(origin)
    return [] if not File.directory?(portdir)

    begin
      run_make_config(portdir, origin) if $config
    rescue => e
      puts "#{e.message}. Ignored."
    end

    first = false
    if parents_list.nil?
      parents_list = Set.new
      STDERR.print "[Gathering depends for #{origin} "
      first = true
    end
    raise RecursiveDependencyError if parents_list.include?(origin)
    parents_list.add(origin)

    make_env = get_make_env(origin)
    cmdargs = make_env << 'make'

    cmdargs.concat(get_make_args(origin))

    `cd #{portdir} && #{shelljoin(*cmdargs)} -V #{depends_vars.join(' -V ')} 2>&1`.each_line do |line|
	line.split(/\s+/).each do |dep|
	  dep.sub!(/.*?:/,'')
	  if dep.rindex(':') != nil
	    (dep, target) = dep.split(':')
	    next if target != "install"
	  end
	  depends.add($portsdb.strip(dep)) if !dep.empty?
	end
    end

    STDERR.print '.'*depends.length if depends.length > 0

    children_deps = Set.new
    depends.each do |dep|
      children_deps.merge(get_all_depends(dep, parents_list)) if !dep.nil?
    end
    if !children_deps.nil?
      depends.merge(children_deps)
    end

    STDERR.puts ' done]' if first
    $depends[origin] = depends.to_a.compact
  else
    $depends[origin]
  end
end

def get_notinstalled_depends(origin)
  notinstalled = Array.new

  get_all_depends(origin).each do |dep|
    next if alt_dep('', dep)
    if !$pkgdb.deorigin(dep)
      notinstalled.push(dep)
    end
  end
  
  notinstalled
end

# raises:
#   ConfigError
def run_make_config(portdir, origin)
  make_args = get_make_args(origin)
  make_env = get_make_env(origin)

  cmdargs = make_env << 'make'

  cmdargs.concat(make_args)

  setproctitle('[make config] %s', origin)

  unless $verbose
    cmdargs << 'ECHO_MSG=/usr/bin/true'
  end

  if $force_config
    cmdargs << 'config'
  else
    cmdargs << 'config-conditional'
  end

  if ! system "cd #{portdir} && #{shelljoin(*cmdargs)}"
    warning_message "make config failed for #{origin}"
    raise ConfigError
  end
end

def do_upgrade(pkgname)
  pkg = PkgInfo.new(pkgname)

  origin = $task_options[pkgname][:origin]

  if !origin || !File.directory?($portsdb.ports_dir() + '/' + origin)
    if !$ignore_moved and \
       !config_ignore_moved?(pkg) and \
       (moved = $portsdb.moved.trace(pkg.origin))
      if origin = moved.last.to
	if pkg.origin != origin
	  warning_message "Package origin of '#{pkg.name}' has been changed: '#{pkg.origin}' -> '#{origin}'"
	end
      else
	warning_message "Package '#{pkg.name}' has been removed from ports tree."
#	$results << PkgResult.new(origin, :ignored, pkgname)
	return
      end
    else
      origin = pkg.origin
    end
  end

  if origin
    if result = $results[origin]
      progress_message "Skipping '#{origin}' (#{pkgname}) because it has already #{result.phrase(true)}"

      $results << PkgResult.new(origin, :skipped, pkgname)
      return
    elsif !$keep_going
      deps = pkg.pkgdep || []

      deps.each do |dep|
	o = $pkgdb.origin(dep)	# perhaps nil

	result = $results[o]

	if result && result.failed?
	  progress_message "Skipping '#{origin}' (#{pkgname}) because a requisite package '#{dep}' (#{o}) failed (specify -k to force)"
	  $results << PkgResult.new(origin, :skipped, pkgname)
	  return
	end
      end
    end
  end

  stty_sane

  upgraded = false

  use_packages, use_packages_only = $use_packages, $use_packages_only

  if (origin && config_use_packages_only?(origin)) || config_use_packages_only?(pkgname)
    $use_packages = $use_packages_only = true
  elsif (origin && config_use_packages?(origin)) || config_use_packages?(pkgname)
    $use_packages = true
  end

  begin
    if result = upgrade_pkg(pkg, origin)
      upgraded = true

      if $package && !$fetch_only
	$dep_hash.each do |key, deps|
	  $package_tasks << key if deps.include?(pkgname)
	end
      end
    end

    $results << PkgResult.new(origin, result ? :done : :ignored, pkgname)
  rescue IgnoreMarkError => e
    $results << PkgResult.new(origin, :ignored, pkgname)
  rescue => e
    $results << PkgResult.new(origin, e, pkgname)
  ensure
    $use_packages, $use_packages_only = use_packages, use_packages_only
  end

  if !upgraded && $package_tasks.include?(pkgname)
    $pkgdb.close_db

    progress_message "Fixing up dependencies before creating a package" if $verbose

    $pkgdb.autofix

    progress_message "Packaging '#{pkgname}' as dependency"

    if $noexecute
      puts "OK? [no]" if $interactive
      return
    elsif $yestoall
      puts "OK? [yes]" if $interactive
    elsif $interactive
      prompt_yesno('OK?', true) or return
    end

    system!(PkgDB::command(:pkg_create), '-vb', pkgname,
	    File.join($packages_dir, pkgname + $portsdb.pkg_sufx))
  end
end

def do_install(origin)
  if origin.nil? then
    warning_message "NIL origin passed to do_install"
    return
  end
  if result = $results[origin]
    progress_message "Skipping '#{origin}' because it has already #{result.phrase(true)}"

    $results << PkgResult.new(origin, :skipped)
    return
  else
    unless $keep_going
      make_args = get_make_args(origin)
      make_env = get_make_env(origin, true)

      $portsdb.all_depends_list!(origin, shelljoin(*make_env), make_args).each do |o|
	result = $results[o]

	if result && result.failed?
	  progress_message "Skipping '#{origin}' because a requisite port '#{o}' failed (specify -k to force)"
	  $results << PkgResult.new(origin, :skipped)
	  return
	end
      end
    end
  end

  stty_sane

  use_packages, use_packages_only = $use_packages, $use_packages_only

  if config_use_packages_only?(origin)
    $use_packages = $use_packages_only = true
  elsif config_use_packages?(origin)
    $use_packages = true
  end

  begin
    if install_new_port(origin, false)	# confirmed in advance
      $results << PkgResult.new(origin, :done)
    else
      $results << PkgResult.new(origin, :skipped)
    end
  rescue IgnoreMarkError => e
    $results << PkgResult.new(origin, :ignored)
  rescue => e
    $results << PkgResult.new(origin, e)
  ensure
    $use_packages, $use_packages_only = use_packages, use_packages_only
  end
  $pkgdb.autofix
end

def get_make_args(origin, pkgname = nil)
  args = []
  if conf_args = config_make_args(origin, pkgname)
    args = conf_args.split(' ')
    args.concat($make_args.split(' '))
  else
    args = $make_args.split(' ')
  end
  quoted = 0
  n = 0
  is_quoted = false
  while n < args.length
    if /\"/ =~ args[n]
      if is_quoted
        args[quoted] << " " << args[n]
        args[n] = nil
        is_quoted = false
      else
        quoted = n
        is_quoted = true
        n+=1
        next
      end
    end

    if is_quoted
      args[quoted] << " " << args[n]
      args[n] = nil
    end
    n+=1
  end
  args.compact
end

def get_make_env(origin, is_new = false)
  make_env = $make_env.dup
  if make_env.empty?
    make_env << 'env'
  end

  unless is_new or $without_env_upgrade
    make_env.concat(get_upgrade_env_vars($current_pkgname))
  end

  config_env = config_make_env(origin)
  if !config_env.empty?
    make_env.concat(config_env)
  end
  make_env
end

def get_upgrade_env_vars(pkgname)
  env_vars = Array.new

  unless pkgname.empty?
    env_vars << 'UPGRADE_TOOL=portupgrade'
    env_vars << 'UPGRADE_PORT='+pkgname
    pkgname =~ %r{^.*-(.*)$}
    env_vars << 'UPGRADE_PORT_VER='+$1
  end

  env_vars
end

def get_beforebuild_command(origin)
  commands = if $beforebuild.empty? then [] else [$beforebuild] end

  commands[commands.size, 0] = config_beforebuild(origin)	# maybe nil

  commands.uniq!
  commands.each { |cmd| cmd.sub!(/^[;\s]+/, '') if !cmd.nil? }
  commands.reject! { |cmd| cmd.nil? || cmd.empty? }

  if commands.empty?
    nil
  else
    commands.join('; ')
  end
end

def get_afterinstall_command(origin)
  commands = if $afterinstall.empty? then [] else [$afterinstall] end

  commands[0, 0] = config_afterinstall(origin)	# maybe nil

  commands.uniq!
  commands.each { |cmd| cmd.sub!(/^[;\s]+/, '') if !cmd.nil? }
  commands.reject! { |cmd| cmd.nil? || cmd.empty? }

  if commands.empty?
    nil
  else
    commands.join('; ')
  end
end

def process_old_package(pkgfile)
  pkg_backup_dir = ENV['PKG_BACKUP_DIR']
  pkg_backup_dir ||= ENV['PKG_PATH']

  if $backup_packages
    progress_message "Keeping old package in '#{pkg_backup_dir}'" if $verbose
    unless File.directory?(pkg_backup_dir)
      xsystem! '/bin/mkdir', '-p', pkg_backup_dir
    end
    xsystem! '/bin/mv', '-f', pkgfile, pkg_backup_dir
  else
    progress_message "Removing old package'" if $verbose
    xsystem! '/bin/rm', '-f', pkgfile
  end
end

# raises:
#   OriginMissingError, InvalidPkgNameError,
#   InstallError
#   (BuildError - build_port)
#   (StandardError - update_pkgdep)
#   (PortDirError, MakefileBrokenError, IgnoreMarkError - check_pkgname, find_pkg)
#   (BackupError, UninstallError) - uninstall_pkg)
def upgrade_pkg(oldpkg, origin = nil, interactive = $interactive)
  logfile = nil
  f = Tempfile.new(MYNAME)
  f.close

  oldpkgname = oldpkg.fullname
  origin ||= oldpkg.origin

  if origin && config_held?(origin)
    if $force
      warning_message "Forcing upgrade of a held package: #{origin}"
    else
      progress_message "Skipping '#{origin}' because it is held by user (specify -f to force)"
      return false
    end
  elsif config_held?(oldpkgname)
    if $force
      warning_message "Forcing upgrade of a held package: #{oldpkgname}"
    else
      progress_message "Skipping '#{oldpkgname}' because it is held by user (specify -f to force)"
      return false
    end
  end

  if origin.nil?
    warning_message "No origin recorded: #{oldpkgname}"
    warning_message "Specify one with -o option, or run 'pkgdb -F' to interactively fix it."
    raise OriginMissingError
  end

  logfile = f.path

  portpkgname = check_pkgname(origin, logfile)	# raises CommandFailedError

  begin
    portpkg = PkgInfo.new(portpkgname)
  rescue ArgumentError => e
    warning_message "Invalid package name: #{origin}: #{e}"
    raise InvalidPkgNameError
  end

  have_package = false
  newpkg = nil

  if (oldpkg.version < portpkg.version || $force) && $use_packages
    newpkg = catch(:newpkg) {
      make_args = get_make_args(origin)

      if !make_args.empty?
        warning_message "Custom MAKE_ARGS or -m option is specified (#{shellwords(make_args.join(','))})"

        unless $use_packages_only
          warning_message "Skipping package"
          throw :newpkg, nil
        end

        warning_message "Trying package anyway, since -PP/--use-packages-only is specified"
      end

      progress_message "Checking for the latest package of '#{origin}'"

      pkg, pkgfile = find_pkg(origin)

      if !pkg || pkg.version < oldpkg.version || pkg.version < portpkg.version
        if fetch_pkg(origin, logfile)
          pkg, pkgfile = find_pkg(origin)
        end

        if !pkg
          warning_message "Could not find the latest version (#{portpkg.version})"
          throw :newpkg, nil
        end

        progress_message "Located a package version #{pkg.version} (#{pkgfile})"

        throw :newpkg, pkg if $force

        if pkg.version < oldpkg.version
          warning_message "Ignoring the package, which is older than what is installed (#{oldpkg.version})"
          throw :newpkg, nil
        end

        if pkg.version == oldpkg.version
          warning_message "Ignoring the package, which is the same version as is installed (#{oldpkg.version})"
          throw :newpkg, nil
        end

        if pkg.version < portpkg.version
          unless $use_packages_only
            warning_message "Ignoring the package which is not the latest version (#{portpkg.version})"
            throw :newpkg, nil
          end

          progress_message "Using it anyway although it is not the latest version (#{portpkg.version}), since -PP/--use-packages-only is specified"
	end
      end

      pkg
    }

    if $fetch_only
      return newpkg ? true : false
    end

    if newpkg
      have_package = true
    elsif $use_packages_only
      warning_message "No package available: #{origin}"
      raise PkgNotFoundError
    else
      progress_message "Using the port instead of a package"
    end
  end

  if newpkg
    newpkgname = newpkg.fullname
  else
    newpkgname = portpkgname

    begin
      newpkg = PkgInfo.new(newpkgname)
    rescue ArgumentError => e
      warning_message "Invalid package name: #{origin}: #{e}"
      raise InvalidPkgNameError
    end
  end

  cmp = newpkg.version <=> oldpkg.version

  if cmp > 0
    service = :upgrade
  elsif cmp == 0
    service = :reinstall
  else
    service = :downgrade
  end

  if newpkg.name != oldpkg.name
    warning_message "Detected a package name change: #{oldpkg.name} (#{oldpkg.origin || 'unknown'}) -> '#{newpkg.name}' (#{origin})"
  end

  if service != :upgrade && !$force
    if $verbose || oldpkgname != newpkgname
      warning_message "No need to upgrade '#{oldpkgname}' (>= #{newpkgname}). (specify -f to force)"
    end

    return false
  end

  if $fetch_only
    timer_start(time_key = "Fetch for #{origin}")
    progress_message "Fetching the distfile(s) for '#{newpkgname}' (#{origin})"
  else
    case service
    when :upgrade
      time_key = "Upgrade of #{origin}"
      msg = "Upgrading '#{oldpkgname}' to '#{newpkgname}' (#{origin})"
    when :downgrade
      time_key = "Downgrade of #{origin}"
      msg = "Downgrading '#{oldpkgname}' to '#{newpkgname}' (#{origin})"
    when :reinstall
      time_key = "Reinstallation of #{origin}"
      msg = "Reinstalling '#{oldpkgname}' (#{origin})"
    end

    if have_package
      msg << " using a package"
    end

    timer_start(time_key)
    progress_message msg
  end

  if $noexecute
    puts "OK? [no]" if interactive
    return true
  elsif $yestoall
    puts "OK? [yes]" if interactive
  elsif interactive
    prompt_yesno('OK?', true) or return false
  end

  unless have_package
    build_port(origin, logfile)

    return true if $fetch_only
  end

  update_pkgdep(oldpkgname, newpkgname, origin)

  teardown_proc1 = proc { |behavior|
    if behavior == :restore
      update_pkgdep(newpkgname, oldpkgname, origin)
    end
  }

  teardown_proc2 = uninstall_pkg(oldpkgname, logfile, $uninstall_extra_flags)

  if have_package
    install_pkg(newpkgname, origin, logfile, false, teardown_proc1, teardown_proc2)
  else
    install_port(origin, logfile, false, teardown_proc1, teardown_proc2)
  end

  progress_message "Cleaning out obsolete shared libraries"
  system!(PkgDB::command(:portsclean), '-QL')

  true
rescue CommandFailedError => e
  warning_message e.message
  progress_message "Skipping '#{origin}'"
  return false
ensure
  if $logfilename_format && logfile &&
      File.exist?(logfile) && !File.zero?(logfile)
    file = $logfilename_format % origin.split('/')

    progress_message "Saving the log as '#{file}'" if $verbose

    begin
      install_data(logfile, file)
    rescue => e
      warning_message "Failed to save the log file: #{e.message}"
    end
  end

  timer_end(time_key)
end

# raises:
#   PortDirError, CommandFailedError
#   (CommandFailedError - xscript)
#   (PortDirError, MakefileBrokenError, IgnoreMarkError - get_pkgname)
def check_pkgname(origin, logfile = nil)
  portdir = $portsdb.portdir(origin)

  if command = get_beforebuild_command(origin)
    progress_message "Executing a pre-build command for '#{origin}': " + command

    unless $noexecute
      Dir.chdir(portdir) {
	xscript(logfile, '/bin/sh', '-c', command)	# raises CommandFailedError
      }
    end
  end

  get_pkgname(origin)
end

# raises:
#   PortDirError, MakefileBrokenError, IgnoreMarkError
def get_pkgname(origin)
  portdir = $portsdb.portdir(origin)

  if not File.directory?(portdir)
    warning_message "Port directory not found: #{origin}"
    raise PortDirError
  end

  make_env = get_make_env(origin)
  cmdargs = make_env << 'make'

  cmdargs.concat(get_make_args(origin))

  output = `cd #{portdir} && #{shelljoin(*cmdargs)} -V PKGNAME -V IGNORE -V NO_IGNORE -V ECHO_MSG 2>&1`.scan(/.*\n/)

  if output.size != 4
    warning_message "Makefile possibly broken: #{origin}:"
    output.each { |line| STDERR.print "\t" + line }
    raise MakefileBrokenError
  end

  ignore_message = output[1].chomp
  no_ignore = !output[2].chomp.empty?
  echo_cmd = output[3].chomp
  ignore = `#{echo_cmd} "#{ignore_message}"`

  # Some packages ouptut a ':\n ' to try to look nice when using the normal
  # ports build process. That looks really bad here, so we undo that.
  ignore.slice!(0..2) if (ignore.match /^:\n /)

  if not ignore_message.empty?
    warning_message "Port marked as IGNORE: #{origin}:"
    STDERR.puts "\t" + ignore
    raise IgnoreMarkError unless no_ignore

    warning_message "Proceeding anyway since NO_IGNORE is defined"
  end

  output[0].chomp
end

def fetch_pkg(origin, logfile = nil)
  cmdargs = [PkgDB::command(:pkg_fetch)]

  cmdargs << '-f' if $force
  cmdargs << '-R' if $fetch_recursive
  cmdargs << '-v' if $verbose

  newpkgname = check_pkgname(origin, logfile)	# raises CommandFailedError

  cmdargs << newpkgname

  progress_message "Fetching the package(s) for '#{newpkgname}' (#{origin})"

  if not script(logfile, *cmdargs)
    unless $use_packages_only
      return false
    end

    if latest_link = $portsdb.latest_link(origin)
      progress_message "Fetching the latest package(s) for '#{latest_link}' (#{origin})"

      cmdargs[-1] = latest_link + '@@'

      script(logfile, *cmdargs) or return false
    else
      warning_message "No latest link for '#{latest_link}' (#{origin}) -- giving up"
    end
  end

  $pkg_cache.delete(origin)

  return true
rescue CommandFailedError => e
  warning_message e.message
  progress_message "Skipping '#{origin}'"
  return false
end

# raises:
#   PkgNotFoundError, InvalidPkgNameError
#   (PortDirError, MakefileBrokenError, IgnoreMarkError - check_pkgname)
#   (BuildError - build_port)
#   (InstallError - install_port, install_pkg)
def install_new_port(origin, interactive = $interactive)
  timer_start(time_key = "Fresh installation of #{origin}")

  logfile = nil
  f = Tempfile.new(MYNAME)
  f.close

  if config_held?(origin)
    if $force
      warning_message "Forcing installation of a held package: #{origin}"
    else
      progress_message "Skipping '#{origin}' because it is held by user (specify -f to force)"
      return false
    end
  end

  logfile = f.path

  portpkgname = check_pkgname(origin, logfile)	# raises CommandFailedError

  begin
    portpkg = PkgInfo.new(portpkgname)
  rescue ArgumentError => e
    warning_message "Invalid package name: #{origin}: #{e}"
    raise InvalidPkgNameError
  end

  have_package = false
  newpkg = newpkgname = nil

  if $use_packages
    progress_message "Checking for the latest package of '#{origin}'"

    newpkg, pkgfile = find_pkg(origin)

    if !newpkg || newpkg < portpkg
      if fetch_pkg(origin, logfile)
	newpkg, pkgfile = find_pkg(origin)
      end

      if !newpkg
	warning_message "Could not find the latest version (#{portpkg.version})"
      else
        progress_message "Located a package version #{newpkg.version} (#{pkgfile})"

        if newpkg < portpkg
          if $use_packages_only
            progress_message "Using it anyway although it is not the latest version (#{portpkg.version}), since -PP/--use-packages-only is specified"
          else
            warning_message "Ignoring the package which is not the latest version (#{portpkg.version})"
            newpkg = nil
          end
	end
      end
    end

    if $fetch_only
      return newpkg ? true : false
    end

    if newpkg
      have_package = true
    elsif $use_packages_only
      warning_message "No package available: #{origin}"
      raise PkgNotFoundError
    else
      progress_message "Using the port instead of a package"
    end
  end

  if newpkg
    newpkgname = newpkg.fullname
  else
    newpkgname ||= portpkgname

    begin
      newpkg = PkgInfo.new(newpkgname)
    rescue ArgumentError => e
      warning_message "Invalid package name: #{origin}: #{e}"
      raise InvalidPkgNameError
    end
  end

  if have_package
    progress_message "Installing '#{newpkgname}' from a package"
  else
    progress_message "Installing '#{newpkgname}' from a port (#{origin})"
  end

  if $noexecute
    puts "OK? [no]" if interactive
    return true
  elsif $yestoall
    puts "OK? [yes]" if interactive
  elsif interactive
    prompt_yesno or return false
  end

  if have_package
    return true if $fetch_only

    install_pkg(newpkgname, origin, logfile, true)
  else
    build_port(origin, logfile, false, true)

    return true if $fetch_only

    install_port(origin, logfile, true)
  end
rescue CommandFailedError => e
  warning_message e.message
  progress_message "Skipping '#{origin}'"
  return false
ensure
  if $logfilename_format && logfile &&
      File.exist?(logfile) && !File.zero?(logfile)
    file = $logfilename_format % origin.split('/')

    progress_message "Saving the log as '#{file}'" if $verbose

    begin
      install_data(logfile, file)
    rescue => e
      warning_message "Failed to save the log file: #{e.message}"
    end
  end

  timer_end(time_key)
end

# raises:
#   BuildError
def build_port(origin, logfile = nil, retried = false, is_new = false)
  timer_start(time_key = "Build of #{origin}") unless retried

  portdir = $portsdb.portdir(origin)

  distclean_mismatched(logfile) if retried

  msg = $fetch_only ? 'Fetching' : 'Building'
  msg << " '#{portdir}'"

  make_env = get_make_env(origin, is_new)
  cmdargs = make_env << 'make'

  cmdargs << 'BATCH=yes' if $batch_mode

  make_args = get_make_args(origin)

  unless make_args.empty?
    cmdargs.concat(make_args)

    msg << ' with make flags: ' << shelljoin(*make_args)
  end

  progress_message msg

  cmdargs << 'MASTER_SORT_REGEX=' << 'MASTER_SORT=' if retried

  cmdargs << "FETCH_CMD=#{$fetch_cmd}" if retried && ! $fetch_cmd.nil?

  Dir.chdir(portdir) {
    $fetch_cmd = `make -V FETCH_CMD`.chomp

    if ! STDOUT.tty?
      cmdargs << "FETCH_BEFORE_ARGS=-q"
    end

    if $fetch_only
      cmdargs << '-DBATCH'

      if $distclean >= 2
	script!(logfile, *(cmdargs.dup << 'distclean')) or
	  raise BuildError, 'distclean error'
      end

      if $fetch_recursive
	cmdargs << 'checksum-recursive'
      else
	cmdargs << 'checksum'
      end

      xscript!(logfile, *cmdargs)	# raises CommandFailedError
    else
      if $distclean >= 2
	script(logfile, *(cmdargs.dup << 'distclean')) or
	  raise BuildError, 'distclean error'
      elsif $clean
	script(logfile, *(cmdargs.dup << 'clean')) or
	  raise BuildError, 'clean error'
      end

      if $package
	cmdargs << 'DEPENDS_TARGET=package'
      end

      if $sudo && Process.euid != 0
	dep_cmdargs = cmdargs.dup << 'fetch-depends' << 'build-depends' << 'lib-depends'

	if not system(shelljoin(*dep_cmdargs) + ' DEPENDS_TARGET="-n nonexistent_target" >/dev/null 2>&1')
	  script!(logfile, *dep_cmdargs) or
	    raise BuildError, 'dependent ports'
	end
      end

      xscript(logfile, *cmdargs)	# raises CommandFailedError
    end
  }

  true
rescue CommandFailedError => e
  reason = guess_reason(logfile)
  comment = REASON_COMMENT[reason]

  if !retried && reason == :checksum && $distclean == 1
    progress_message "Retrying #{origin}"

    $fetch_cmd = nil

    return build_port(origin, logfile, true)
  end

  warning_message e.message
  warning_message "Fix the problem and try again."
  raise BuildError, comment
ensure
  timer_end(time_key) unless retried
end

# raises:
#   CommandFailedError and Errno::*
def distclean_mismatched(logfile)
  progress_message "Deleting mismatched files"

  if File.size(logfile) >= 65536	# 64KB
    obj = "| grep '^=> \\(MD5\\|SHA256\\) Checksum mismatch for ' #{logfile}"
  else
    obj = logfile
  end

  files = []

  open(obj) do |f|
    f.each do |line|
      case line
      when /^=> (MD5|SHA256) Checksum mismatch for (\S+)\.\r?$/
	distfile = File.join($portsdb.dist_dir, $2)

	information_message "Deleting #{distfile}"

	unlink_file(distfile)
      end
    end
  end

  true
end

# raises:
#   InstallError
def install_port(origin, logfile = nil, is_new = false, *teardown_procs)
  timer_start(time_key = "Installation of #{origin}")

  portdir = $portsdb.portdir(origin)

  msg = 'Installing the new version via the port'

  make_env = get_make_env(origin, is_new)
  cmdargs = make_env << 'make'

  cmdargs << 'BATCH=yes' if $batch_mode

  make_args = get_make_args(origin)

  unless make_args.empty?
    cmdargs.concat(make_args)

    msg << ' with make flags: ' << shelljoin(*make_args)
  end

  progress_message msg

  if $package
    cmdargs << 'DEPENDS_TARGET=package'
  end

  if $force
    cmdargs << '-DFORCE_PKG_REGISTER'
  end

  # timestamp hack - let PkgDB detect the update
  $pkgdb.close_db
  sleep 1
  $pkgdb_update = true

  Dir.chdir(portdir) {
    xscript!(logfile, *(cmdargs.dup << 'reinstall'))	# raises CommandFailedError

    if $package
      script!(logfile, *(cmdargs.dup << 'package'))
    end

    if $cleanup
      script!(logfile, *(cmdargs.dup << 'clean'))
    end

    teardown_procs.each { |f|
      f.call(:cleanup) if f
    }

    if command = get_afterinstall_command(origin)
      progress_message "Executing a post-install command for '#{origin}': " + command

      unless $noexecute
	script!(logfile, '/bin/sh', '-c', command)
      end
    end
  }

  true
rescue CommandFailedError => e
  warning_message e.message

  teardown_procs.each { |f|
    f.call(:restore) if f
  }

  warning_message "Fix the installation problem and try again."
  raise InstallError, "install error"
ensure
  timer_end(time_key)
end

# raises:
#   InstallError
def install_pkg(pkgname, origin, logfile = nil, is_new = false, *teardown_procs)
  newpkg, pkgfile = find_pkg(origin)

  if pkgfile and deporigins = extract_pkgfile_deporigins(pkgfile)
    deporigins.each do |deporigin|
      $pkgdb.deorigin(deporigin) and next

      progress_message "Installing #{deporigin} as dependency required by #{pkgname}"

      do_install(deporigin)
    end
  end

  timer_start(time_key = "Installation of #{pkgname}")

  unless $is_new or $without_env_upgrade
    cmdargs = [ '/usr/bin/env' ]
    cmdargs.concat(get_upgrade_env_vars(pkgname))
  else
    cmdargs = []
  end

  cmdargs << PkgDB::command(:pkg_add) << '-f' << pkgfile

  progress_message "Installing the new version via the package"

  # timestamp hack - let PkgDB detect the update
  $pkgdb.close_db
  sleep 1
  $pkgdb_update = true

  xscript!(logfile, *cmdargs)	# raises CommandFailedError

  teardown_procs.each { |f|
    f.call(:cleanup) if f
  }

  if command = get_afterinstall_command(origin)
    progress_message "Executing a post-install command for '#{origin}': " + command

    unless $noexecute
      script!(logfile, '/bin/sh', '-c', command)
    end
  end

  true
rescue CommandFailedError => e
  warning_message e.message

  teardown_procs.each { |f|
    f.call(:restore) if f
  }

  warning_message "Fix the package's problem and try again."
  raise InstallError, "pkg_add failed"
ensure
  timer_end(time_key)
end

# raises:
#   BackupError, UninstallError
def uninstall_pkg(pkgname, logfile = nil, extra_flags = '')
  timer_start(time_key = "Uninstallation of #{pkgname}")

  $pkgdb.close_db

  progress_message "Fixing up dependencies before creating a package" if $verbose

  $pkgdb.autofix

  progress_message "Backing up the old version"

  backup_pkgfile = nil

  if str = backquote!(PkgDB::command(:pkg_create), '-vb', pkgname,
		      File.join($tmpdir, pkgname + $portsdb.pkg_sufx))
    str.each_line { |line|
      if /^Creating .*tar ball in \'(.*)\'/ =~ line
	backup_pkgfile = $1
	break
      end
    }
  end

  if backup_pkgfile.nil? || !File.file?(backup_pkgfile)
    warning_message "Backup failed."
    raise BackupError
  end

  pkgdir = $pkgdb.pkgdir(pkgname)
  backup_dir = File.join($tmpdir, pkgname + '.bak')

  system!('/bin/cp', '-RPp', pkgdir, backup_dir) or
    raise BackupError

  origin = $pkgdb.origin(pkgname)

  progress_message "Uninstalling the old version"

  # pkg_deinstall will update the pkgdb
  $pkgdb.close_db
  # sleep 1	# pkg_deinstall does the timestamp hack
  $pkgdb_update = false

  unless $without_env_upgrade
    cmd = [ '/usr/bin/env' ]
    cmd.concat(get_upgrade_env_vars(pkgname))
  else
    cmd = []
  end

  cmd << PkgDB::command(:pkg_deinstall) << '-f' + extra_flags << pkgname

  system!(*cmd) or
    raise UninstallError, "uninstall error"

  proc { |behavior|
    case behavior
    when :restore
      progress_message "Restoring the old version"

      xsystem! PkgDB::command(:pkg_add), '-f', backup_pkgfile

      if origin and command = get_afterinstall_command(origin)
	progress_message "Executing a post-install command for '#{origin}': " + command
	
	unless $noexecute
	  script!(logfile, '/bin/sh', '-c', command) 
	end
      end

      $pkgdb_update = true

      process_old_package(backup_pkgfile)
    when :cleanup
      progress_message "Removing temporary files and directories" if $verbose

      process_old_package(backup_pkgfile)
      system! '/bin/rm', '-rf', backup_dir
    end
  }
ensure
  timer_end(time_key)
end

# raises:
#   (PortDirError, MakefileBrokenError, IgnoreMarkError - get_pkgname)
def find_pkg(origin)
  if $pkg_cache.include?(origin)
    return $pkg_cache[origin]
  end

  pkgname = get_pkgname(origin) or return nil

  name = pkgname.sub(/-[^\-]+$/, '')

  glob_pkgfile = name + '-*.t[bgx]z'
  re_pkgfile = /^#{Regexp.quote(name)}-[^\-]+\.t[bgx]z$/

  if latest_link = $portsdb.latest_link(origin)
    glob_pkgfile = "{#{glob_pkgfile},#{latest_link}.t[bgx]z}"
    re_pkgfile = /(?:#{re_pkgfile.source}|^#{Regexp.quote(latest_link)}\.t[bgx]z$)/
  end

  pkglist = []

  $pkg_path.split(':').each do |dir|
    begin
      Dir.chdir(dir) {
	Dir.glob(glob_pkgfile).grep(re_pkgfile) { |file|
          id_pkgname, id_origin, pkgdep = identify_pkg(file)

          if id_origin == origin
            pkglist << [PkgInfo.new(id_pkgname), File.join(dir, file)]
          end
        }
      }
    rescue => e
      warning_message e.message
    end
  end

  latest_pkg, pkgfile = *pkglist.max { |(pkg1, file1), (pkg2, file2)|
    pkg1 <=> pkg2
  }

  if latest_pkg
    progress_message "Found a package of '#{origin}': #{pkgfile} (#{latest_pkg.fullname})"
  end

  $pkg_cache[origin] = [latest_pkg, pkgfile]
end

def extract_pkgfile_deporigins(pkgfile)
  dir, file = File.split(pkgfile)

  deporigins = []

  IO.popen("cd #{dir} && #{PkgDB::command(:pkg_info)} -qfo #{file}") do |r|
    r.each do |line|
      case line
      when /^@@comment\s+DEPORIGIN:(\S*)/
	deporigins << $1
      end
    end
  end

  return deporigins
rescue => e
  warning_message e.message
  return nil
end

def guess_reason(logfile)
  if grep_q_file(/\^C/, logfile)
    reason = :interrupt
#  elsif grep_q_file(/list of extra files and directories/, logfile)
#    reason = :mtree
  elsif grep_q_file(/See <URL:http:\/\/www.gnu.org\/software\/gcc\/bugs\.html> for instructions\./, logfile)
    reason = :gcc_bug
  elsif grep_q_file(/Checksum mismatch/, logfile)
    reason = :checksum
  elsif grep_q_file(/perl: Perl is not installed, try .pkg_add -r perl./, logfile)
    reason = :perl
  elsif grep_q_file(/(No checksum recorded for|(Maybe|Either) .* is out of date, or)/, logfile)
    reason = :distinfo
  elsif grep_q_file(/(configure: error:|script.*failed: here are the contents of)/, logfile)
    reason = :configure
  elsif grep_q_file(/(bison:.*(No such file|not found)|multiple definition of \`yy)/, logfile)
    reason = :bison
  elsif grep_q_file(/Couldn't fetch it - please try/, logfile) #'
    reason = :fetch
  elsif grep_q_file(/out of .* hunks .*--saving rejects to/, logfile)
    reason = :patch
  elsif grep_q_file(/Error: category .* not in list of valid categories/, logfile)
    reason = :categories
  elsif grep_q_file(/make: don.t know how to make .*\.man. Stop/, logfile)
    reason = :xfree4man
  elsif grep_q_file(/Xm\/Xm\.h: No such file/, logfile)
    reason = :motif
  elsif grep_q_file(/undefined reference to \`Xp/, logfile)
    reason = :motiflib
#  elsif grep_q_file(/read-only file system/, logfile)
#    reason = :wrkdir
  elsif grep_q_file(/makeinfo: .* use --force/, logfile)
    reason = :texinfo
  elsif grep_q_file(/means that you did not run the h2ph script/, logfile)
    reason = :perl5
  elsif grep_q_file(/Error: shared library ".*" does not exist/, logfile)
    reason = :libdepends
  elsif grep_q_file(/(crt0|c\+\+rt0)\.o: No such file/, logfile)
    reason = :elf
  elsif grep_q_file(/machine\/soundcard\.h: No such file or directory/, logfile)
    reason = :soundcard_h
  elsif grep_q_file(/values\.h: No such file or directory/, logfile)
    reason = :values_h
  elsif grep_q_file(/.*\.h: No such file/, logfile)
    if grep_q_file(/(X11\/.*|Xosdefs)\.h: No such file/, logfile)
      if $pkgdb.glob('XFree86-*').empty?
	reason = :usexlib
      else
	reason = :header
      end
    else
      reason = :header
    end
#  elsif grep_q_file(/pnohang: killing make checksum/, logfile)
#    reason = :fetch_timeout
#  elsif grep_q_file(/pnohang: killing make package/, logfile)
#    reason = :runaway
#  elsif grep_q_file(/cd: can't cd to/, logfile) #'
#    reason = :nfs
#  elsif grep_q_file(/pkg_add: (can't find enough temporary space|projected size of .* exceeds available free space)/, logfile) #'
#    reason = :diskfull
  elsif grep_q_file(/(parse error|too (many|few) arguments to|argument.*doesn.*prototype|incompatible type for argument|conflicting types for|undeclared \(first use (in |)this function\)|incorrect number of parameters|has incomplete type and cannot be initialized)/, logfile)
    reason = :cc
  elsif grep_q_file(/(ANSI C.. forbids|is a contravariance violation|changed for new ANSI .for. scoping|[0-9]: passing .* changes signedness|discards qualifiers|lacks a cast|redeclared as different kind of symbol|invalid type .* for default argument to|wrong type argument to unary exclamation mark|duplicate explicit instantiation of|incompatible types in assignment|assuming . on overloaded member function|call of overloaded .* is ambiguous|declaration of C function .* conflicts with|initialization of non-const reference type|using typedef-name .* after|[0-9]: implicit declaration of function|[0-9]: size of array .* is too large|fixed or forbidden register .* for class)/, logfile)
    reason = :newgcc
  elsif grep_q_file(/(syntax error before|ISO C\+\+ forbids|friend declaration|no matching function for call to|.main. must return .int.|invalid conversion from|cannot be used as a macro name as it is an operator in C\+\+|is not a member of type|after previous specification in|no class template named|because worst conversion for the former|better than worst conversion|no match for.*operator|no match for call to|undeclared in namespace|is used as a type, but is not)/, logfile)
    reason = :badcpp
  elsif grep_q_file(/(\/usr\/libexec\/elf\/ld: cannot find|undefined reference to|cannot open -l.*: No such file)/, logfile)
    reason = :ld
  elsif grep_q_file(/install: .*: No such file/, logfile)
    reason = :install
  elsif grep_q_file(/chown:.*invalid argument/, logfile)
    reason = :chown
  elsif grep_q_file(/\/usr\/.*\/man\/.*: No such file or directory/, logfile)
    reason = :manpage
  elsif grep_q_file(/tar: can't add file|pkg_create: make_dist: tar command failed with code/, logfile) #'
    reason = :plist
  elsif grep_q_file(/Can't open display/, logfile) #'
    reason = :display
  elsif grep_q_file(/ is already installed - perhaps an older version/, logfile)
    reason = :dependobj
#  elsif grep_q_file(/error in dependency .*, exiting/, logfile)
#    reason = :dependpkg
  elsif grep_q_file(/\#error "<malloc\.h> has been replaced by <stdlib\.h>"/, logfile)
    reason = :malloc_h
  elsif grep_q_file(/core dumped/, logfile)
    reason = :coredump
  elsif grep_q_file(/Segmentation fault/, logfile)
    reason = :segfault
  elsif grep_q_file(/storage size of.*isn't known/, logfile)
    reason = :wait
  elsif grep_q_file(/initializer element is not constant/, logfile)
    reason = :stdio
  elsif grep_q_file(/structure has no member named/, logfile)
    reason = :struct
  elsif grep_q_file(/Permission denied/, logfile)
    reason = :perm
  else
    reason = :unknown
  end

  reason
end

def guess_missing_origin
  require 'pathname'

  portsdir = Pathname.new($portsdb.ports_dir).realpath.to_s
  if %r|^#{portsdir}/([^/]+/[^/]+)| =~ Dir.pwd
    return $1
  else
    return nil
  end
end

class PkgResultSet
  def save(file)
    progress_message "Saving the results to '#{file}'" if $verbose

    f = Tempfile.new(MYNAME)
    write(f, '', true)
    f.close

    install_data(f.path, file)
  rescue => e
    warning_message "Failed to save the results: #{e.message}"
  end
end

if $0 == __FILE__
  set_signal_handlers

  exit(main(ARGV) || 1)
end
@


1.70
log
@- Improve Ruby 1.9 compatibility
- Add FreeBSD keyword to lib/portsdb.rb so that I can check in
@
text
@d31 1
a31 1
# $FreeBSD$
@


1.69
log
@- Add .txz packages support.

PR:		ports/152526
Submitted by:	Martin Matuska <mm@@FreeBSD.org>
@
text
@d729 1
a729 1
	  ports = $portsdb.glob(pattern).map { |i| i.origin }
d862 1
a862 1
    `cd #{portdir} && #{shelljoin(*cmdargs)} -V #{depends_vars.join(' -V ')} 2>&1`.each do |line|
@


1.68
log
@- Don't install and/or build dependencies when only using packages.

PR:		ports/143979
Submitted by:	Bryan Drewery  bryan at shatow net
Reviewed by:	Yusuke Hoshizuki  hoshizuki at chaos cs tsukuba ac jp
@
text
@d2030 2
a2031 2
  glob_pkgfile = name + '-*.t[bg]z'
  re_pkgfile = /^#{Regexp.quote(name)}-[^\-]+\.t[bg]z$/
d2034 2
a2035 2
    glob_pkgfile = "{#{glob_pkgfile},#{latest_link}.t[bg]z}"
    re_pkgfile = /(?:#{re_pkgfile.source}|^#{Regexp.quote(latest_link)}\.t[bg]z$)/
@


1.67
log
@- Set#scan only exists in ruby 1.9.  Revert this change.
@
text
@d594 1
d655 1
d829 3
d834 1
@


1.66
log
@- Do not choke on when port's dir does not exists.

PR:		ports/140192: ports-mgmt/portupgrade-devel fails to install a new port.
Submitted by:	"KISHIMOTO, Makoto" <ksmakoto@@dd.iij4u.or.jp>
Reviewed by:	"Akinori MUSHA" <knu@@iDaemons.org>
@
text
@d878 1
a878 1
    $depends[origin] = depends.scan(/.*\n/).compact
@


1.65
log
@- Do not file if pkg origin has not been passed into do_upgrade.
- Do not insert the package record into the results set if the port
  has been removed from the ports tree and no upgrade has been performed.
@
text
@d834 1
a834 1
    return nil if not File.directory?(portdir)
@


1.64
log
@- Add more nil origin check/workarounds before the real solution is
  found.  Because there's no such place where the origin is checked for
  being not-null it's not easy to fix this in the right way currently.
@
text
@a928 4
  if origin.nil? then
    warning_message "Cannot find origin for #{pkgname}"
    return
  end
d930 1
a930 1
  if not File.directory?($portsdb.ports_dir() + '/' + origin)
d940 1
a940 1
	$results << PkgResult.new(origin, :ignored, pkgname)
d1479 1
a1479 1
  if not ignore.empty?
@


1.63
log
@- Do not try to update dependency if it is not installed.  Several
  people reported failures that may be related to this.

PR:		ports/125936 (possibly)
@
text
@d659 1
a659 1
		next if task == ''
d929 4
d934 1
a934 1
  if !origin || !File.directory?($portsdb.ports_dir()+'/'+origin)
d1031 4
@


1.62
log
@- Perform correct formatting of IGNORE message if the port redefines ECHO_MSG
  to something not equal to 'echo'.

PR:		ports/125823
Submitted by:	Trevor Johns <trevor@@tjohns.net>
@
text
@d634 4
a637 1
		    dep << $pkgdb.deorigin(d).to_s
@


1.61
log
@Adapt to ruby 1.9
@
text
@d31 2
d1455 1
a1455 1
  output = `cd #{portdir} && #{shelljoin(*cmdargs)} -V PKGNAME -V IGNORE -V NO_IGNORE 2>&1`.scan(/.*\n/)
d1457 1
a1457 1
  if output.size != 3
d1463 1
a1463 1
  ignore = output[1].chomp
d1465 6
@


1.60
log
@update DB after package install
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/30 23:22:24 $[1]
d237 2
a238 2
		    "Do with all the installed packages") {
      |$all|
d244 2
a245 2
		    "Run the command after each installation") {
      |$afterinstall|
d250 2
a251 2
		    "Keep backup packages of the old versions") {
      |$backup_packages|
d256 2
a257 2
    		    "(with BATCH=yes)") {
      |$batch_mode|
d262 2
a263 2
		    "exits in failure, then the port will be skipped") {
      |$beforebuild|
d268 2
a269 2
		    "Run \"make config-conditional\" before everything for all tasks") {
      |$config|
d273 2
a274 2
		    "Run \"make config\" before everything for all tasks") {
      |$force_config|
d286 2
a287 2
		    "Emit summary info after each port processing" << NEXTLINE ) {
      |$emit_summaries|
d292 2
a293 2
		    "downgrade or just a reinstall, or the port is held") {
      |$force|
d298 2
a299 2
		    "Do not build or install anything") {
      |$fetch_only|
d303 2
a304 2
		    "Ignore MOVED file") {
      |$ignore_moved|
d308 2
a309 2
		    "Turn on interactive mode") {
      |$interactive|
d315 2
a316 2
		    "requisite ports have failed to upgrade") {
      |$keep_going|
d321 1
a321 2
		    "(default: do not save results)") {
      |resultsfile|
d329 1
a329 2
		    "are given as arguments (default: do not save logs)") {
      |fmt|
d337 3
a339 3
		    "command line") {
      |$make_args|
    }
d343 1
a343 2
		    "command line") {
      |make_env|
d353 2
a354 2
		    "be done") {
      |$noexecute|
d363 2
a364 2
		    "packages (default: #{MYNAME == 'portinstall' ? 'on' : 'off'})") {
      |$new|
d368 1
a368 2
		    "Specify a port to upgrade the following pkg with") {
      |origin|
d379 2
a380 2
		    "Build package when each port is installed") {
      |$package|
d394 2
a395 2
		    "Or -PP; Use no ports but packages only") {
      |$use_packages_only|
d400 2
a401 2
		    "Be quiet when -N option specified and the package already installed") {
      |$quiet|
d405 2
a406 2
		    "Do not read pkgtools.conf") {
      |$noconfig|
d423 2
a424 2
		    "Run commands under sudo(8) where needed") {
      |$sudo|
d429 1
a429 2
		    "e.g. 'su root -c \"%s\"' (default: sudo)") {
      |sudo_command|
d439 2
a440 2
		    "Be verbose") {
      |$verbose|
d444 1
a444 2
		    "Do not \"make clean\" before each build") {
      |noclean|
d449 1
a449 2
		    "Do not \"make clean\" after each installation") {
      |nocleanup|
d454 2
a455 2
      		    "Do not set UPGRADE_* environment variables") {
      |$without_env_upgrade|
d460 1
a460 2
		    "pattern") {
      |arg|
d472 2
a473 2
		    "Answer yes to all the questions") {
      |$yestoall|
d868 1
a868 3
    if children_deps.nil?
      next
    else
d873 1
a873 1
    $depends[origin] = depends.to_a.compact
d1140 2
a1141 2
  commands.each { |cmd| cmd.sub!(/^[;\s]+/, '') }
  commands.reject! { |cmd| cmd.empty? }
d1156 2
a1157 2
  commands.each { |cmd| cmd.sub!(/^[;\s]+/, '') }
  commands.reject! { |cmd| cmd.empty? }
d1453 1
a1453 1
  output = `cd #{portdir} && #{shelljoin(*cmdargs)} -V PKGNAME -V IGNORE -V NO_IGNORE 2>&1`.to_a
d1929 1
a1929 1
    str.each { |line|
@


1.59
log
@Show a port name when `make config`. And ignore errors if `make config`
fails.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/30 17:37:31 $[1]
d1077 1
@


1.58
log
@Disable install uninstalled depends by portupgade. They will install
with bsd.port.mk without portupgrade attention.

Required by:	pav@@FreeBSD.org
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/30 17:35:05 $[1]
d637 1
a637 1
		if $upward_recursive
d642 1
a642 1
		  depends |= dep
d839 5
a843 1
    run_make_config(portdir, origin) if $config
d912 2
@


1.57
log
@Prevent a crash when something wrong with a dependency name. Just ignore it.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/30 17:28:21 $[1]
d650 2
a651 1
		install_tasks |= get_notinstalled_depends(origin)
@


1.56
log
@If specified -r or -R options, check depends even when specified
package is up to date.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/30 15:38:39 $[1]
d661 1
@


1.55
log
@Fix a problem with command line arguments. When a quoted argument with spaces
was passed, it was splitted with spaces.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/17 12:11:14 $[1]
a636 6
		name =~ /^(.+)-([^-]+)$/
		newversion = PkgVersion.new($2)
		if newversion <= pkg.version && !$force
		  not_need_upgrade << task
		  next
		end
d644 6
@


1.54
log
@Fixed failure when -PP specified.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/06/17 11:11:38 $[1]
d1079 24
a1102 1
  args
@


1.53
log
@Catch an exception when task is an invalid package name.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/02/10 23:20:02 $[1]
d1216 1
a1216 1
        warning_message "Custom MAKE_ARGS or -m option is specified (#{shellwords(make_args)})"
@


1.52
log
@Change semantic of -q option. Now it's 'quite' - don't show a message
when -N specified and there is already installed package with this origin.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/02/10 22:01:40 $[1]
d661 7
a667 1
		pkg = PkgInfo.new(task)
@


1.51
log
@Add second trace through dependency to detect what ports should not update
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/02/10 12:04:39 $[1]
d200 1
d403 6
a408 1
    opts.def_option("-q", "--noconfig",
d748 3
a750 1
	      warning_message "Found already installed package(s) of '#{origin}': " + pkgnames.join(' ')
@


1.50
log
@- ignore ports without a ports dir. don't crash
- fix origin where will taken dependencies if -o option specified
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/02/04 11:34:20 $[1]
d587 1
a587 1
		list |= $pkgdb.recurse(pkgname, $recursive, $upward_recursive, $sanity_check)
a593 11
	    if list.empty?
	      throw :pkg
	    end

	    list -= $exclude_packages

	    if list.empty?
	      warning_message "No matching packages left after exclusion: #{arg}"
	      throw :pkg
	    end

d604 2
a605 2
	    # Track all depends when $upward recursive and all
	    # not istalled ports are appeared after updating
d638 1
a638 1
		  depends = []
d640 1
a640 1
		    depends << $pkgdb.deorigin(d).to_s
d642 1
a642 1
		  upgrade_tasks |= depends
d648 50
@


1.49
log
@I think better to be silent when there is no origin. The error will be
processed bellow.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/02/04 10:54:47 $[1]
d620 5
a624 1
	      origin = $pkgdb.origin(task)
d632 4
@


1.48
log
@Show a message for running pkgdb -F instead of unknown crash.
The same for situation whe there is no origin.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/29 13:38:52 $[1]
a647 3
	      else
		$results << PkgResult.new(origin, :ignored, "there is no origin")
		not_need_upgrade << task
@


1.47
log
@Fix broken MAKE_ARGS
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/28 14:56:08 $[1]
d629 5
d648 3
@


1.46
log
@Raise RecursiveDependencyError exception instead of return nil
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/27 22:33:51 $[1]
d707 1
a707 1
	    # Track all uninstalled
d785 1
a785 1
    cmdargs.concat(shellwords($make_args))
d838 1
a838 1
  cmdargs.concat(shellwords($make_args))
d1006 4
a1009 2
  if args = config_make_args(origin, pkgname)
    args + ' ' + $make_args
d1011 1
a1011 1
    $make_args
d1013 1
d1147 1
a1147 1
      make_args = shellwords($make_args)
d1150 1
a1150 1
        warning_message "Custom MAKE_ARGS or -m option is specified (#{$make_args})"
d1363 1
a1363 1
  cmdargs.concat(shellwords($make_args))
d1577 1
a1577 1
  make_args = shellwords($make_args)
d1702 1
a1702 1
  make_args = shellwords($make_args)
@


1.45
log
@Fix a wrong function name
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/27 18:56:19 $[1]
d148 5
d779 1
a779 1
    return nil if parents_list.include?(origin)
@


1.44
log
@Show a message on ignored ports.
The meaning of 'ignored' has changed. Before it was a port that should not
be upgrade, now it's a port that be ignored for some reasons for upgrade.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/27 17:56:30 $[1]
d703 1
a703 1
	    get_uninstalled_depends(origin).each do |dep|
@


1.43
log
@when met a port with IGNORE option, failed all process. Now just write a log
and ignore the port.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/26 16:01:16 $[1]
d620 1
a620 1
		  $results << PkgResult.new(origin, :ignored)
@


1.42
log
@Change -c and -C flags semantic. Now they runs config-conditional and
config accordingly.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/26 14:30:36 $[1]
d617 7
a623 1
		name = get_pkgname(origin)
@


1.41
log
@it's a first version where dependencies processing is correct now.
Many refacroting and code rewritting.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/12 18:26:52 $[1]
d170 4
a173 2
  $clean = true			# now cleaned by default
  $cleanup = true		# not cleaned up by default
d209 1
a209 1
usage: #{MYNAME} [-habcCDDefFijklnOpPPqrRsuvwWy] [-A command] [-B command]
d261 3
a263 3
    opts.def_option("-c", "--clean",
		    "Do \"make clean\" before each build [default]") {
      |$clean|
d266 4
a269 3
    opts.def_option("-C", "--cleanup",
		    "Do \"make clean\" after each installation [default]") {
      |$cleanup|
a306 5
    opts.def_option("-j", "--jet-mode",
		    "Turn on jet mode. It is not implemented yet") {
      |$jet_mode|
    }

d760 2
d820 2
a821 9
#   PortDirError, ConfigError
def run_make_config(origin)
  portdir = $portsdb.portdir(origin)

  if not File.directory?(portdir)
    warning_message "Port directory not found: #{origin}"
    raise PortDirError
  end

d824 1
d833 5
a837 1
  cmdargs << 'config-conditional'
a838 1
  progress_message "Run options config for #{origin}"
a844 10
def do_config(origin)
  run_make_config(origin)

  make_args = get_make_args(origin)
  make_env = get_make_env(origin)
  $portsdb.all_depends_list!(origin, shelljoin(*make_env), make_args).each do |o|
    run_make_config(o)
  end
end

@


1.40
log
@Fix getting uninstall list packages when portupgrade -N
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2008/01/08 11:32:27 $[1]
d578 5
a582 4
	catch(:pkg) {
	  begin
	    $pkgdb.glob(pattern, false).each do |pkgname|
	      first ||= pkgname
d584 5
a588 1
	      list |= $pkgdb.recurse(pkgname, $recursive, $upward_recursive, $sanity_check)
a589 4
	  rescue => e
	    STDERR.puts e.message
	    exit 1
	  end
d591 3
a593 3
	  if list.empty?
	    throw :pkg
	  end
d595 1
a595 1
	  list -= $exclude_packages
d597 4
a600 4
	  if list.empty?
	    warning_message "No matching packages left after exclusion: #{arg}"
	    throw :pkg
	  end
d602 4
a605 7
	  list.each do |i|
	    $task_options[i] = {
	      :make_args => $make_args
	    }

	    if i == first
	      $task_options[i][:origin] = $origin
a606 1
	  end
d608 1
a608 1
	  upgrade_tasks |= list
d610 1
a610 1
	  $origin = nil
d612 28
a639 6
	  found = true

	  # Track unistalled ports is appeared after updating
	  upgrade_tasks.each do |task|
	    o = $pkgdb.origin(task)
	    install_tasks |= get_uninstalled_depends(o) if !o.nil?
a640 1
	}
d642 1
a642 1
	next if found
d644 1
a644 4
	unless $new
	  warning_message "No such installed package: #{arg}"
	  next
	end
d646 6
a651 1
	pattern = $portsdb.strip(arg) || arg	# allow pkgname_glob
d653 1
a653 6
	begin
	  pattern = parse_pattern(pattern)
	rescue RegexpError => e
	  warning_message e.message.capitalize
	  next
	end
d655 1
a655 1
	stty_sane
d657 1
a657 1
	ports = $portsdb.glob(pattern).map { |i| i.origin }
d659 5
a663 1
	unique = false
d665 1
a665 5
	case ports.size
	when 0
	  if $portsdb.exist?(arg)
	    # The specified port does not have an entry in the INDEX but
	    # the port directory actually exists.
d667 6
a673 2

	    ports << arg
d675 2
a676 2
	    warning_message "No such installed package or port: #{arg}"
	    next
a677 6
	when 1
	  unique = true
	else
	  progress_message "Found #{ports.size} ports matching '#{arg}':"
	  ports.each { |origin| puts "\t#{origin}" }
	end
d679 8
a686 9
	ports.each do |origin|
	  if pkgnames = $pkgdb.deorigin(origin)
	    warning_message "Found already installed package(s) of '#{origin}': " + pkgnames.join(' ')
	    interactive = true
	    yes_by_default = false
	  else
	    interactive = $interactive || !unique
	    yes_by_default = true
	  end
d688 8
a695 11
	  if $noexecute
	    puts "Install '#{origin}'? [no]" if interactive
	    next
	  elsif $yestoall
	    puts "Install '#{origin}'? [yes]" if interactive
	  elsif interactive
	    prompt_yesno("Install '#{origin}'?", yes_by_default) or next	# "
	  end

	  make_args = get_make_args(origin)
	  make_env = get_make_env(origin)
d697 4
a700 36
	  install_tasks << origin
	  $task_options[origin] = {
	    :make_args => make_args
	  }
	  # Track all uninstalled
	  get_uninstalled_depends(origin).each do |dep|
	    make_args = get_make_args(dep)
	    make_env = get_make_env(dep)

	    install_tasks << dep
	    $task_options[dep] = {
	      :make_args => make_args
	    }
	  end

	  if $upward_recursive
	    get_all_depends(origin).each do |o|
	      make_args = get_make_args(o)

	      if pkgnames = $pkgdb.deorigin(o)
		pkgnames.each do |p|
		  upgrade_tasks << p
		  $task_options[p] = {
		    :make_args => make_args,
		    :origin => o,
		    :dependency => origin
		  } unless $task_options.include?(p)
		end
	      else
		install_tasks << o
		$task_options[o] = {
		  :make_args => make_args,
		  :origin => o,
		  :dependency => origin
		} unless $task_options.include?(o)
	      end
d704 1
a704 1
      end
a722 2
    upgrade_tasks -= $exclude_packages

a725 18
#    if ! $jet_mode
#      config_tasks = upgrade_tasks.dup
#      config_tasks.concat(install_tasks)
#
#      config_tasks.each do |pname|
#	unless pname.index('/')
#	  pkg = PkgInfo.new(pname)
#	  pname = pkg.origin
#	  puts pname
#	end
#      end
#      
#      config_tasks.sort!
#      config_tasks.each do |pname|
#	do_config(pname)
#      end
#    end

d806 2
a807 2
def get_uninstalled_depends(origin)
  uninstalled = Array.new
d812 1
a812 1
      uninstalled.push(dep)
d816 1
a816 1
  uninstalled
d861 1
a861 4
  options = $task_options[pkgname]
  $origin = options[:origin]
  $make_args = options[:make_args]
  dependency = options[:dependency]
a862 1
  origin = $origin
d873 1
a873 1
	$results << PkgResult.new($origin, :ignored, pkgname)
a881 2
    $make_args = options[:make_args] = get_make_args(origin, pkgname)

a983 9
  if !$task_options.key?(origin)
    # When the port to install is not given from the command line
    $task_options[origin] = {
      :make_args => get_make_args(origin)
    }
  end

  $make_args = $task_options[origin][:make_args]

@


1.39
log
@New year in COPYRIGHTS
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/08/09 15:28:05 $[1]
d697 4
a700 7
	    # If has not yet installed
	    if $pkgdb.deorigin(origin)
	      install_tasks << dep
	      $task_options[dep] = {
	        :make_args => make_args
	      }
	    end
@


1.38
log
@When checksum mismatch is occured and portupgrade retries to fetch mismatched
distfiles, an error occurs and refetch fails. One of a reason is a message
about checksum failed has changed

Submitted by:	KOMATSU Shinichiro <koma2@@lovepeers.org>
@
text
@d6 1
a6 1
# Copyright (c) 2006,2007 Sergey Matveychuk <sem@@FreeBSD.org>
d33 1
a33 1
MYDATE = %w$Date: 2007/07/03 10:37:58 $[1]
@


1.37
log
@Don't try install a port if it's already installed (even older version)
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/07/03 09:57:35 $[1]
d1707 1
a1707 5
    if /fetch/ =~ $fetch_cmd
      $fetch_cmd.gsub!(/[Rr]/, '')
    else
      $fetch_cmd = nil
    end
d1725 1
a1725 1
    obj = "| grep '^>> Checksum mismatch for ' #{logfile}"
d1735 2
a1736 2
      when /^>> Checksum mismatch for (\S+)\.\r?$/
	distfile = File.join($portsdb.dist_dir, $1)
@


1.36
log
@Fix working with ports without origins (e.g. bsdpan-*) and moved ports.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/07/03 09:41:41 $[1]
d697 7
a703 4
	    install_tasks << dep
	    $task_options[dep] = {
	      :make_args => make_args
	    }
@


1.35
log
@Back out the last commit. it's in a wron branch.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/07/03 09:40:18 $[1]
d802 3
a813 2
    portdir = $portsdb.portdir(origin)

d910 1
a910 1
  if !origin
d920 2
@


1.34
log
@Comment out gathering dependencies in updating task for STABLE branch
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/03/08 10:38:39 $[1]
d618 4
a621 5
	  # XXX
#	  upgrade_tasks.each do |task|
#	    o = $pkgdb.origin(task)
#	    install_tasks |= get_uninstalled_depends(o) if !o.nil?
#	  end
@


1.33
log
@Fix two errors
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/03/03 19:33:20 $[1]
d618 5
a622 4
	  upgrade_tasks.each do |task|
	    o = $pkgdb.origin(task)
	    install_tasks |= get_uninstalled_depends(o) if !o.nil?
	  end
@


1.33.2.1
log
@Comment out gathering dependencies for update tasks in STABLE.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/03/08 10:38:39 $[1]
d618 4
a621 5
	  # XXX
#	  upgrade_tasks.each do |task|
#	    o = $pkgdb.origin(task)
#	    install_tasks |= get_uninstalled_depends(o) if !o.nil?
#	  end
@


1.33.2.2
log
@Merge from HEAD two patches to fix working with ports without origins and
moved ones.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/07/03 09:57:35 $[1]
a802 3
    portdir = $portsdb.portdir(origin)
    return nil if not File.directory?(portdir)

d812 2
d910 1
a910 1
  if !origin || !File.directory?($portsdb.ports_dir()+'/'+origin)
a919 2
	$results << PkgResult.new($origin, :ignored, pkgname)
	return
@


1.33.2.3
log
@Merge from HEAD: Don't try install a port if it's already installed
(even older version)

Reported by:	Jonathan Liu
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/07/03 10:37:58 $[1]
d698 4
a701 7
	    # If has not yet installed
	    if $pkgdb.deorigin(origin)
	      install_tasks << dep
	      $task_options[dep] = {
	        :make_args => make_args
	      }
	    end
@


1.32
log
@One more forgotten debug puts()
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/03/03 19:31:26 $[1]
d619 2
a620 1
	    install_tasks |= get_uninstalled_depends($pkgdb.origin(task))
d842 1
a842 1
    $depends[origin] = depends.compact
@


1.31
log
@Remove debug output
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/02/26 16:00:26 $[1]
a715 1
		puts "*->#{o}"
@


1.30
log
@- Move alt_dep() from pkgdb to pkgtools.rb
- Use alt_dep() in portupgrade to test if dependency installed
- Add numbers (divicible by 100) in progress bar for pkgdb
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/02/26 14:43:00 $[1]
a703 1
	      puts "*>#{o}"
d833 1
a833 1
      children_deps.merge(get_all_depends(dep, parents_list))
d842 1
a842 1
    $depends[origin] = depends
@


1.29
log
@Add a port origin in progress bar and finish it with "done]"
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/02/26 14:36:59 $[1]
d173 1
d800 2
a801 1
  depends = Set.new
d803 24
a826 22
  first = false
  if parents_list.nil?
    parents_list = Set.new
    STDERR.print "[Gathering depends for #{origin} "
    first = true
  end
  return nil if parents_list.include?(origin)
  parents_list.add(origin)

  portdir = $portsdb.portdir(origin)

  make_env = get_make_env(origin)
  cmdargs = make_env << 'make'

  cmdargs.concat(shellwords($make_args))

  `cd #{portdir} && #{shelljoin(*cmdargs)} -V #{depends_vars.join(' -V ')} 2>&1`.each do |line|
      line.split(/\s+/).each do |dep|
	dep.sub!(/.*?:/,'')
	if dep.rindex(':') != nil
	  (dep, target) = dep.split(':')
	  next if target != "install"
d828 1
a828 3
	depends.add($portsdb.strip(dep)) if !dep.empty?
      end
  end
d830 1
a830 1
  STDERR.print '.'*depends.length if depends.length > 0
d832 4
a835 3
  children_deps = Set.new
  depends.each do |dep|
    children_deps = get_all_depends(dep, parents_list)
d841 5
a846 3

  STDERR.puts ' done]' if first
  depends
d853 1
@


1.28
log
@Add a progress bar when gathering dependencies recursive.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/02/24 12:38:00 $[1]
d804 1
a804 1
    STDERR.print '[Gathering depends '
d840 1
a840 1
  STDERR.puts ']' if first
@


1.27
log
@Rework dependencies processing. Now all depends install under portupgrade
controll.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/02/22 13:36:34 $[1]
d800 7
a806 1
  parents_list = Set.new if parents_list.nil?
d828 2
d840 1
@


1.26
log
@Update COPYRIGHTS
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2007/02/16 09:09:32 $[1]
d615 5
d690 10
d702 2
a703 1
	    $portsdb.all_depends_list!(origin, shelljoin(*make_env), make_args).each do |o|
d716 7
a722 7
		# XXX: needs to be aware of :extract, :patch, :configure, etc. before enabling this.
		# install_tasks << o
		# $task_options[o] = {
		#   :make_args => make_args
		#   :origin => o,
		#   :dependency => origin
		# } unless $task_options.include?(o)
d769 8
a784 8
    $current_pkgname = ''
    install_tasks.each do |origin| 
      ctask += 1
      setproctitle('[%d/%d] %s', ctask, ntasks, origin)
      do_install(origin)
      progress_message "** Install tasks #{install_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
    end

d793 54
@


1.25
log
@Fixes reflected last changes in the ports tree.
@
text
@d5 2
a6 2
# Copyright (c) 2005, 2006 KOMATSU Shinichiro
# Copyright (c) 2006 Sergey Matveychuk <sem@@FreeBSD.org>
d33 1
a33 1
MYDATE = %w$Date: 2006/11/18 18:10:10 $[1]
@


1.24
log
@Check if pkgname is empty in get_upgrade_env_vars()
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/11/17 20:57:21 $[1]
d1597 1
a1597 1
	dep_cmdargs = cmdargs.dup << 'fetch-depends' << 'build-depends' << 'lib-depends' << 'misc-depends'
@


1.24.2.1
log
@Merge patches from HEAD
@
text
@d5 2
a6 2
# Copyright (c) 2005,2006 KOMATSU Shinichiro
# Copyright (c) 2006,2007 Sergey Matveychuk <sem@@FreeBSD.org>
d33 1
a33 1
MYDATE = %w$Date: 2007/02/22 13:36:34 $[1]
d1597 1
a1597 1
	dep_cmdargs = cmdargs.dup << 'fetch-depends' << 'build-depends' << 'lib-depends'
@


1.23
log
@Make preparing of UPGRADE_* variables in own function.
Add UPGRADE_PORT_VER variable.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/11/12 18:58:56 $[1]
d992 1
a992 1
  unless is_new
d1006 1
a1006 1
  unless $without_env_upgrade
@


1.22
log
@Change PORT_UPGRADE environment variable with UPGRADE_PORT (contains
a package name for updating port) and UPGRADE_TOOL=portupgrade.

Discussed with skv@@FreeBSD.org and DougB@@FreeBSD.org.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/11/12 11:16:34 $[1]
d451 1
a451 1
      		    "Do not set UPGRADE_PORT and UPGRADE_TOOL variables" << NEXTLINE << "in an environment") {
d992 2
a993 3
  unless is_new or $without_env_upgrade
    make_env << 'UPGRADE_TOOL=portupgrade'
    make_env << 'UPGRADE_PORT='+$current_pkgname
d1003 13
d1755 2
a1756 2
    cmdargs = ['/usr/bin/env', 'UPGRADE_TOOL=portupgrade',
      'UPGRADE_PORT='+pkgname]
d1844 2
a1845 2
    cmd = ['/usr/bin/env', 'UPGRADE_TOOL=portupgrade',
      'UPGRADE_PORT='+pkgname]
@


1.21
log
@Fix a bug when -P treats always as -PP
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/11/06 15:58:43 $[1]
d172 1
d304 1
a304 1
		    "Turn on jet mode. Is not implemented yet") {
d451 1
a451 1
      		    "Do not set PORT_UPGRADE=yes in an environment") {
d756 1
d761 1
d992 4
a995 1
  make_env << 'PORT_UPGRADE=yes' unless is_new or $without_env_upgrade
d1743 2
a1744 1
    cmdargs = ['/usr/bin/env', 'PORT_UPGRADE=yes']
d1832 2
a1833 1
    cmd = ['/usr/bin/env', 'PORT_UPGRADE=yes']
@


1.20
log
@config_make_env() now returns Array always.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/11/06 13:02:56 $[1]
d384 1
a384 1
      if $use_packages
@


1.19
log
@Refactoring get_make_env(). Move make(1) enviornment constructing
into pkgtools.rb for public availability.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/11/04 12:39:42 $[1]
d993 1
a993 1
    make_env << confg_env
@


1.18
log
@Remove -DPACKAGE_BUILDING from command line (it was there in fetch-only mode).
It's only for build cluster, not users.

Requested by:	kris
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/10/15 12:54:17 $[1]
a983 4
  $make_env_table ||= compile_config_table(config_value(:MAKE_ENV))

  envset = (lookup_config_table($make_env_table, origin, nil) or Array.new)

d991 3
a993 10
  envset.each do |envs|
    if envs.is_a?(Proc)
      make_env << String.new(envs.call(origin)) rescue nil
    elsif envs.is_a?(Array)
      envs.each do |entry|
	make_env << entry
      end
    else
      make_env << envs
    end
@


1.17
log
@* Add --batch - build in batch mode.
* Add --without-env-upgrade - don't set PORT_UPGRADE=yes
* Note --jet-mode is not implemented yet
* Add me in authors section in a man page
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/08/13 11:42:22 $[1]
d1562 1
a1562 1
      cmdargs << '-DBATCH' << '-DPACKAGE_BUILDING'
@


1.16
log
@Do not pass PORT_UPGRADE as make(1) argument. An environment variable is enough.
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/08/13 11:23:14 $[1]
d168 1
d199 1
d240 1
a240 1
		    "Keep backup packages of the old versions'") {
d244 6
d303 1
a303 1
		    "Turn on jet mode: do not run options config for each port") {
d449 5
d993 1
a993 1
  make_env << 'PORT_UPGRADE=yes' unless is_new
d1538 2
d1667 2
d1747 1
a1747 1
  unless $is_new
d1835 9
a1843 2
  system!('/usr/bin/env', 'PORT_UPGRADE=yes', PkgDB::command(:pkg_deinstall), 
	  '-f' + extra_flags, pkgname) or
@


1.15
log
@Add missing -e and -j in command line description
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/08/13 11:15:21 $[1]
a1534 2
  cmdargs << 'PORT_UPGRADE=yes' unless $is_new

a1661 2
  cmdargs << 'PORT_UPGRADE=yes' unless $is_new

@


1.14
log
@Adjust Copyright notices
@
text
@d33 1
a33 1
MYDATE = %w$Date: 2006/08/09 17:00:33 $[1]
d203 1
a203 1
usage: #{MYNAME} [-habcCDDfFiklnOpPPqrRsuvwWy] [-A command] [-B command]
@


1.13
log
@- Make fetch(1) quiet when STDOUT is not a tty
@
text
@a4 1
# All rights reserved.
d6 2
d33 1
a33 1
MYDATE = %w$Date: 2006/07/13 06:01:03 $[1]
@


1.12
log
@Fix a bug when -M value was ignored in some cases.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/30 20:19:24 $[1]
d1543 4
@


1.11
log
@Highlight summary messages with '**'
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/30 20:09:28 $[1]
d972 1
a972 2
  envset = lookup_config_table($make_env_table, origin, nil) or
    return Array.new
@


1.10
log
@Get back second init_global. It's necessary for doubled options like -DD.
Really it's needed only for portupgrade and portsclean, but be consistent.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/30 19:21:00 $[1]
d742 1
a742 1
      progress_message "Upgrade tasks #{upgrade_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
d749 1
a749 1
      progress_message "Install tasks #{install_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
@


1.9
log
@- Rewrite messages for 'make config*' running
- Change 'make config' with 'make config-conditional'
- ... and disable it. config commant should be running when dependencies
  is parsed and rerun parsing dependencies after config
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/18 15:14:02 $[1]
d509 1
@


1.8
log
@- Fix the last commit. Redirecting stdout to /dev/null was a not good
  decision. Set ECHO_MSG to /usr/bin/true is the better one.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/18 14:24:45 $[1]
d294 1
a294 1
		    "Turn on jet mode: do not run \"make config\" for each port") {
d719 17
a735 15
    if ! $jet_mode
      config_tasks = upgrade_tasks.dup
      config_tasks.concat(install_tasks)

      config_tasks.each do |pname|
	origin = nil
	if pname.index('/')
	  origin = pname
	else
	  pkg = PkgInfo.new(pname)
	  origin = pkg.origin
	end
	do_config(origin)
      end
    end
d779 1
a779 1
  cmdargs << 'config'
d781 1
a781 1
  progress_message "Run 'make config' for #{origin}"
@


1.7
log
@- Shut up 'make config' unless verbose
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/17 13:13:33 $[1]
d773 2
a774 4
  if $verbose
    config_cmd = 'config'
  else
    config_cmd = 'config > /dev/null'
d777 2
d780 1
a780 1
  if ! system "cd #{portdir} && #{shelljoin(*cmdargs)} #{config_cmd}"
@


1.6
log
@- Run 'make config' before all operation unless -j (--jet-mode) option set
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/15 15:54:30 $[1]
d773 6
d780 1
a780 1
  if ! system "cd #{portdir} && #{shelljoin(*cmdargs)} config"
@


1.5
log
@- Add -e (--emit-summaries) option to show summary info after each
  port processing. The summary info is showed with -v mode too.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/15 11:32:11 $[1]
d97 5
d293 5
d719 16
d757 33
@


1.4
log
@- Show a statistics message after each port only if verbose (-v)
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/14 14:33:59 $[1]
d166 1
d260 5
d713 1
a713 1
      progress_message "Upgrade tasks #{upgrade_tasks.length}: #{$results.summary}" if $verbose
d720 1
a720 1
      progress_message "Install tasks #{install_tasks.length}: #{$results.summary}" if $verbose
@


1.3
log
@- Show Summaries info with one line. Looks better.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/14 11:52:38 $[1]
d707 1
a707 1
      progress_message "Upgrade tasks #{upgrade_tasks.length}: #{$results.summary}"
d714 1
a714 1
      progress_message "Install tasks #{install_tasks.length}: #{$results.summary}"
@


1.2
log
@- Refactoring:
  * Get rid of warnings with ruby --debug
  * Rework ugly init_pkgtools_global call. Now it's more consistent.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/13 12:59:01 $[1]
d707 1
a707 2
      progress_message "Upgrade tasks: #{upgrade_tasks.length}"
      progress_message "Summary: #{$results.summary}"
d714 1
a714 2
      progress_message "Install tasks: #{install_tasks.length}"
      progress_message "Summary: #{$results.summary}"
@


1.1
log
@Initial revision
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006-01-04 01:25:27 +0900 (Wed, 04 Jan 2006) $[1]
d186 1
d488 1
a492 1
	init_global
@


1.1.1.1
log
@Initial import
@
text
@@


1.1.1.1.2.1
log
@Remove summary messages
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/13 12:59:01 $[1]
d706 2
d714 2
@


1.1.1.1.2.2
log
@MFD: emit summary messages (-e/--emit-sumaries options)
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/06/29 18:02:12 $[1]
a165 1
  $emit_summaries = false
a257 5
    opts.def_option("-e", "--emit-summaries",
		    "Emit summary info after each port processing" << NEXTLINE ) {
      |$emit_summaries|
    }

a705 1
      progress_message "** Upgrade tasks #{upgrade_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
a711 1
      progress_message "** Install tasks #{install_tasks.length}: #{$results.summary}" if $emit_summaries || $verbose
@


1.1.1.1.2.3
log
@Fix a bug when -M value was ignored in some cases.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/07/01 06:40:10 $[1]
d903 2
a904 1
  envset = (lookup_config_table($make_env_table, origin, nil) or Array.new)
@


1.1.1.1.2.4
log
@MFD: Make fetch(1) quiet when STDOUT is not a tty
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/07/13 06:02:02 $[1]
a1473 4
    if ! STDOUT.tty?
      cmdargs << "FETCH_BEFORE_ARGS=-q"
    end

@


1.1.1.1.2.5
log
@MFD: Do not pass PORT_UPGRADE as make(1) argument.
@
text
@d32 1
a32 1
MYDATE = %w$Date: 2006/08/13 11:42:22 $[1]
d1465 2
d1594 2
@


