PERFORCE change 167348 for review

Alejandro Pulver alepulver at FreeBSD.org
Sat Aug 15 01:16:12 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=167348

Change 167348 by alepulver at alepulver_deimos on 2009/08/15 01:16:05

	- Move ask-license to _PATCH_SEQ, and add private cookie to avoid
	  asking twice if patch target fails.
	- Rework bsd.licenses.mk to include dual/multiple licenses support.
	- Add dialog based GUI interface, and text interface (similar to NetBSD).
	- Remove inheritance from groups and leave them as tags for now
	  (otherwise it overcomplicates things unnecessarily)
	- No more saving for now (there were 3 sources of configuration before).
	- Rename "redist" to "mirror" to avoid confusing with "dist" (of distfiles).
	- Add reports with an option to disable.
	- Replace current bsd.port.mk section for restricted files removal if
	  LICENSE is defined (some clean-* targets).
	- Some minor changes and fixes.

Affected files ...

.. //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.licenses.db.mk#4 edit
.. //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.licenses.mk#9 edit
.. //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.port.mk#8 edit
.. //depot/projects/soc2008/alepulver-portslicense/ports/Mk/test-license-1/Makefile#4 edit

Differences ...

==== //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.licenses.db.mk#4 (text+ko) ====

@@ -18,6 +18,12 @@
 #   http://en.wikipedia.org/wiki/Comparison_of_free_software_licences
 #
 # Probably will be automatically incorporated from FOSSology's software.
+#
+# IMPORTANT: as this file is going to be included by most ports, we may
+# consider having licenses here only as "tags" as most of them will be free,
+# to remove some loops and additional variables here. This will not affect the
+# rest of bsd.licenses.mk, and anyways restricted licenses that aren't used by
+# many ports should be defined in each one's Makefile.
 
 # XXX Start of editable section
 
@@ -30,68 +36,60 @@
 _LICENSE_LIST=			ASL BSD BSL CDDL GPLv2 GPLv3 LGPL MIT MPL
 _LICENSE_LIST_GROUPS=	FSF GPL OSI
 
-# Properties of license/group "xxx" (similar to port's variables, but single)
+# List of groups (only names must be present)
+
+_LICENSE_NAME_FSF=		Free Software Foundation Approved
+
+_LICENSE_NAME_GPL=		GPL Compatible
+
+_LICENSE_NAME_OSI=		OSI Approved
+
+# Default permissions for licenses here, if not defined
+
+_LICENSE_PERMS_DEFAULT=	dist-mirror dist-sell pkg-mirror pkg-sell auto-accept
+
+# Properties of license "xxx" (similar to port variables, but single)
+#
 # _LICENSE_NAME_xxx		- Full name/description of license/group
-# _LICENSE_PERMS_xxx	- Permissions
-# _LICENSE_COMPAT_xxx	- Compatibility
-# _LICENSE_INCOMPAT_xxx	- Incompatibility
+# _LICENSE_PERMS_xxx	- Permissions (if not defined defaults to
+# 						  ${_LICENSE_PERMS_DEFAULT}.
+# _LICENSE_GROUPS_xxx	- Groups (optional)
+#
+# Notes:
+# - General permissions from groups are added to each license, if not defined.
+#
 
-# List of licenses
-
 _LICENSE_NAME_ASL=		Apache License
+_LICENSE_GROUPS_ASL=	FSF OSI
 
 _LICENSE_NAME_BSD=		BSD license
+_LICENSE_GROUPS_BSD=	FSF OSI
 
 _LICENSE_NAME_BSL=		Boost Software License
+_LICENSE_GROUPS_BSL=	FSF OSI
 
 _LICENSE_NAME_CDDL=		Common Development and Distribution License
+_LICENSE_GROUPS_CDDL=	FSF OSI
 
 _LICENSE_NAME_GPLv2=	GNU General Public License version 2
+_LICENSE_NAME_GPLv2=	FSF GPL OSI
 
 _LICENSE_NAME_GPLv3=	GNU General Public License version 3
-_LICENSE_PERMS_GPLv3=	no-pkg
+_LICENSE_GROUPS_GPLv3=	FSF GPL OSI
 
 _LICENSE_NAME_LGPL=		GNU Lesser General Public License
+_LICENSE_GROUPS_LGPL=	FSF GPL OSI
 
 _LICENSE_NAME_MIT=		MIT license / X11 license
+_LICENSE_GROUPS_MIT=	FSF GPL OSI
 
 _LICENSE_NAME_MPL=		Mozilla Public License
+_LICENSE_GROUPS_MPL=	FSF OSI
 
-# List of groups
+# Set default permissions if not defined
 
-_LICENSE_NAME_FSF=		Free Software Foundation Approved
-_LICENSE_PERMS_FSF=		pkg-redist dist-redist pkg-sell dist-sell auto-accept
-
-_LICENSE_NAME_GPL=		GPL Compatible
-_LICENSE_PERMS_GPL=		pkg-redist dist-redist pkg-sell dist-sell auto-accept
-
-_LICENSE_NAME_OSI=		OSI Approved
-_LICENSE_PERMS_OSI=		pkg-redist dist-redist pkg-sell dist-sell auto-accept
-
-# Grouping
-#
-# - Method 1:
-# _LICENSE_LIST_GROUP_xxx	- List of licenses under the "xxx" group
-
-_LICENSE_LIST_GROUP_FSF=	ASL BSD BSL CDDL GPLv2 GPLv3 LGPL MIT MPL
-
-_LICENSE_LIST_GROUP_GPL=	GPLv2 GPLv3 LGPL MIT
-
-_LICENSE_LIST_GROUP_OSI=	ASL BSD BSL CDDL GPLv2 GPLv3 LGPL MIT MPL
-
-# - Method 2:
-# _LICENSE_GROUPS_xxx		- Groups the license/group belongs to
-
-# empty
-
-# XXX End of editable section
-
-# Method 1 expands to method 2
-.for group in ${_LICENSE_LIST_GROUPS}
-.	for lic in ${_LICENSE_LIST_GROUP_${group}}
-_LICENSE_GROUPS_${lic}?=	#
-.		if ${_LICENSE_GROUPS_${lic}:M${group}} == ""
-_LICENSE_GROUPS_${lic}+=	${group}
-.		endif
-.	endfor
+.for lic in ${_LICENSE_LIST}
+.	if !defined(_LICENSE_PERMS_${lic})
+_LICENSE_PERMS_${lic}=	${_LICENSE_PERMS_DEFAULT}
+.	endif
 .endfor

==== //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.licenses.mk#9 (text+ko) ====

@@ -10,108 +10,117 @@
 # Please view me with 4 column tabs!
 #
 
+# TODO:
+# - Bring back save and checksum with new dialog interface (only offers to do
+#   so if ran by root, otherwise silently remove the options). Also only allow
+#   saving per-port options (known or unknown), and only when accepted.
+# - Add custom restriction targets for better integration (now some files are
+#   removed from FTP if restricted for CDROM for example, as the old
+#   behavior).
+
 # The following cases are not considered:
 #
-# - Redistribution of modified distfiles, because is never been done.
+# - Redistribution of modified distfiles, because is never done.
 # - Creating binaries from modified sources, because packages almost always
-#   contain modifications to the source, and can not be autodetected (i.e.
+#   contain modifications to the source, can not be autodetected (i.e.
 #   patch-* in ${FILESDIR}, post-* targets, etc), and these licenses tend to
-#   have more restrictions.
+#   have more restrictions anyways.
 #
 
 # Integration with target sequences
 #
 # _SANITY_SEQ+=		check-license (after check-vulnerable)
-# _EXTRACT_SEQ+=	ask-license (after post-extract-script)
+# _PATCH_SEQ+=		ask-license (before any other targets)
 # _INSTALL_SUSEQ+=	install-license (after install-desktop-entries)
 #
-# The 'check-license' target will determine if the license was rejected or has
-# to be asked later in 'ask-license' (by then LICENSE_FILE should be available
-# for presenting to the user).
-# The 'install-license' target installs both the application's license and a
-# restriction report (to be used by ports scripts and similar tools).
+# The 'check-license' target will determine if the license was accepted,
+# rejected or has to be asked later to the user in 'ask-license' (by then
+# licenses should be extracted).  The 'install-license' target installs the
+# applications' licenses, a general package license mentioning them, and a
+# restriction report (to be used by ports, scripts and similar tools).
 
-# Variables provided to users
+# Variables provided to the ports system and users in general, to modify the
+# behavior of the framework
 #
-# LICENSES_ACCEPTED	- Accepted licenses and groups.
-# LICENSES_REJECTED	- Rejected licenses and groups.
-# LICENSE_ASK		- Require explicit user approval for all licenses not
-#					  present in configuration nor LICENSES_ACCEPTED.
-# LICENSES_CONFIG	- If defined, will ask again when already saved
+# NO_LICENSES_INSTALL		- Do not install catalog, report and licenses.
+# NO_LICENSES_DIALOGS		- Disable interactive menus for asking licenses.
+
+#NO_LICENSES_INSTALL=		yes
+#NO_LICENSES_DIALOGS=		yes
+
+# Variables provided to users (can be passed to make or set in /etc/make.conf)
 #
-# The components of LICENSES_{ACCEPTED,REJECTED} can be one of:
-# - A license code (like "GPLv2").
-# - A license group prefixed by '@' (like "@OSI").
+# LICENSES_ACCEPTED	- Accepted licenses.
+# LICENSES_REJECTED	- Rejected licenses.
+# LICENSES_GROUPS_ACCEPTED	- Accepted license groups.
+# LICENSES_GROUPS_REJECTED	- Rejected license groups.
+# LICENSES_ASK		- Require explicit user approval for all licenses not
+#					  present in previous variables (for example, stock
+#					  accepted licenses will ask confirmation).
 #
-# Note that the framework configuration format is the same (without groups
-# syntax), but stored in ${LICENSE_CFG} or ${LICENSE_CFG_PORT}. The user
-# variables take precedence (anyways the other configuration is also made by
-# the user).
-#
 
 # Variables provided to ports
 #
 # LICENSE			- Code of license (short name).
 # LICENSE_PERMS		- Permissions; use "none" if empty.
 # LICENSE_GROUPS	- Groups the license belongs.
-# LICENSE_COMPAT	- Compatibility with other licenses/groups (default: all).
-# LICENSE_INCOMPAT	- Incompatibility with other licenses/groups (default: none).
 # LICENSE_NAME		- Full license name (for the reports).
-# LICENSE_NOTES		- A note about restrictions (not needed), to replace
-# 					  RESTRICTED and ports/LEGAL.
 # LICENSE_FILE		- Full path to license (or use LICENSE_TEXT).
 # LICENSE_TEXT		- Text to use as a license, useful when referencing to
 #					  another place if it's not in the distfile.
-# LICENSE_DISTFILE	- Name of licensed files (defaults to ${DISTFILES}).
+# LICENSE_DISTFILES	- Name of licensed files (defaults to ${_DISTFILES}).
+# LICENSE_COMB		- Set to "dual" or "multi", for OR/AND behavior
+# 					  (defaults to "single" if undefined, the common case)
 #
-# The following cases are supported (see _LICENSE_TYPE):
+# The following cases are supported after defining LICENSE:
 #
 # Case 1: license defined in the framework (aka "known").
-# Define LICENSE; framework defines license variables, by redefining any of
-# them the port falls in Case 2.
 #
-# Case 2: license is based on a defined one (aka "variant").
-# All license variables must be defined by the port (but LICENSE is set to
-# a known value).
-# XXX This case is being considered, and if it has to inherit properties from
-#     its base license or just let it fall in Case 3 (as now).
+# In this case the only allowed variables to set are LICENSE_FILE and
+# LICENSE_DISTFILES. The rest are managed by the framework and are not allowed
+# to change.
 #
-# Case 3: license only known by the port (aka "unknown").
-# All license variables must be defined by the port.
+# Case 2: license only known by the port (aka "unknown").
 #
-# Notes:
-# - Permissions use a default-deny policy (that's why groups are there).
-# - Adding a license to a group makes it inherit their properties (PERMS,
-#   GROUPS and COMPAT/INCOMPAT).
-# - Components can be negated by prefixing them with "no-" (like
-#   "no-pkg-sell"). Useful for exceptions.
-# - For multiple licenses components can be grouped, for example:
-#   LICENSE=		GPLv2 BSD
-#   LICENSE_PERMS=	GPLv2:no-pkg-sell,pkg-redist BSD:no-pkg-sell,pkg-redist
-#   LICENSE_NOTES=	GPLv2:"No sell" BSD:"Allows everything"
+# In this case LICENSE_{PERMS,NAME} are mandatory, in addition to
+# either LICENSE_FILE or LICENSE_TEXT. Optional variables are
+# LICENSE_{GROUPS,NOTES}.
 #
 # Available components for LICENSE_PERMS:
-# dist-redist	- No free redistribution of distfile (like FTP mirroring; RESTRICTED).
+# dist-mirror	- No free redistribution of distfile (like FTP mirroring; RESTRICTED).
 # dist-sell		- No selling of distfile (like in CD-ROM; NO_CDROM).
-# pkg-redist	- No free redistribution of package (like FTP upload; NO_PACKAGE).
+# pkg-mirror	- No free redistribution of package (like FTP upload; NO_PACKAGE).
 # pkg-sell		- No selling of package (like in CD-ROM; NO_CDROM).
-# auto-accept	- If license is accepted by default, without presented agreement.
-# none			- Explicit universal restriction (to make sure that is the intention).
-# And the following aliases (can also be negated): pkg, dist, sell and redist.
+# auto-accept	- If license is accepted by default, without presented
+# 				  agreement, at least the user defines LICENSES_ASK.
+#
+# Notes about permissions:
+# - Permissions use a default-deny policy.
+# - Components can be negated by prefixing them with "no-" (like
+#   "no-pkg-sell").
+# - In case a component is present and also excluded (i.e. no-dist-sell and
+#   dist-sell together in LICENSE_PERMS), it will be excluded.
+# - XXX Currently there is no point in "no-" prefixes, as permissions are not
+#   inherited from groups. Maybe it looks more clear that way than leaving the
+#   variable empty?
+#
+# Dual/multiple licenses:
+#
+# If LICENSE_COMB is set to "dual", then LICENSE can (must, actually) have
+# more than one component. After that each license "lic" in LICENSE falls in
+# previous cases (known or unknown), but their variables are prefixed by
+# _LICENSE_ and suffixed by _lic. The main license name, perms and groups will
+# be set automatically (following appropiate logic). The idea is that any
+# license from LICENSE can be chosen to use the package.
+#
+# The case when LICENSE_COMB is set to "multi" is similar. But the idea is
+# that all of the licenses in LICENSE must be agreed to use the package.
 #
 
 .if defined(_POSTMKINCLUDED) && !defined(BEFOREPORTMK)
 
 .if defined(LICENSE)
 
-# Organization
-# - Define common license properties.
-# - Define internal variables.
-# - Check for single or multiple port licenses.
-# - Check defined properties and compare with database.
-# - Check user and framework configuration.
-# - Define targets.
-
 # Include known licenses from database
 
 .include "${PORTSDIR}/Mk/bsd.licenses.db.mk"
@@ -120,244 +129,418 @@
 #
 # _LICENSE_LIST_PERMS		- Valid permission components
 # _LICENSE_LIST_PORT_VARS	- License variables defined by the port
-# _LICENSE_LIST_GROUP_VARS	- License variables inherited from groups
-# _LICENSE_LIST_SAVE_VARS	- License variables present in the report
 
-_LICENSE_LIST_PERMS=		dist-redist dist-sell pkg-redist pkg-sell auto-accept none
-_LICENSE_LIST_PORT_VARS=	PERMS GROUPS NAME COMPAT INCOMPAT
-_LICENSE_LIST_GROUP_VARS=	PERMS COMPAT INCOMPAT
-_LICENSE_LIST_SAVE_VARS=	_LICENSE _LICENSE_NOTES _LICENSE_DISTFILES \
-							_LICENSE_COMPAT _LICENSE_INCOMPAT ${_LICENSE_LIST_PORT_VARS:S/^/_LICENSE_/}
-
-# Defaults
+_LICENSE_LIST_PERMS=		dist-mirror dist-sell pkg-mirror pkg-sell auto-accept none
+_LICENSE_LIST_PORT_VARS=	PERMS NAME GROUPS
 
-LICENSE_DISTFILE?=	${DISTFILES}
-# XXX internal variables will be useful for multiple licenses
-_LICENSE=			${LICENSE}
-_LICENSE_NOTES=		${LICENSE_NOTES}
-_LICENSE_DISTFILE=	${LICENSE_DISTFILE}
-
 # Path variables
 #
 # _LICENSE_DIR		- Directory to install licenses
 # _LICENSE_DIR_REL	- Same as above, without ${PREFIX}
-# _LICENSE_CFG_GLOB	- Global license configuration file
-# _LICENSE_CFG_PORT	- Per port license configuration file
-# _LICENSE_REPORT	- License report to be created (under ${LICENSE_DIR})
+# _LICENSE_CATALOG	- License catalog (make include file) to be created (dst)
+# _LICENSE_CATALOG_TMP	- Same as above, but in WRKDIR (src)
+# _LICENSE_REPORT	- License summary, shows licenses and how they are combined (dst)
+# _LICENSE_REPORT_TMP	- Same as above, but in WRKDIR (src)
+# _LICENSE_COOKIE	- Set when license is accepted, it is not present in
+# 					  bsd.port.mk to avoid creating LICENSE_{REQ,SEQ} for a
+# 					  few more targets only.
+
+_LICENSE_DIR?=		${PREFIX}/share/licenses/${PKGNAME}
+_LICENSE_DIR_REL?=	share/licenses/${PKGNAME}
+_LICENSE_CATALOG?=	${_LICENSE_DIR}/catalog.mk
+_LICENSE_CATALOG_TMP?=	${WRKDIR}/.license-catalog.mk
+_LICENSE_REPORT?=	${_LICENSE_DIR}/LICENSE
+_LICENSE_REPORT_TMP?=	${WRKDIR}/.license-report
+_LICENSE_COOKIE?=	${WRKDIR}/.license_done.${PORTNAME}.${PREFIX:S/\//_/g}
+
+# Defaults (never overriden for now)
+#
+# _LICENSE			- Copy of LICENSE (for now)
+# _LICENSE_COMB		- Copy of LICENSE_COMB (but "single" instead of empty)
 
-_LICENSE_DIR?=		${PREFIX}/share/licenses/${UNIQUENAME}
-_LICENSE_DIR_REL?=	share/licenses/${UNIQUENAME}
-_LICENSE_CFG_GLOB?=	${PORT_DBDIR}/license-config
-_LICENSE_CFG_PORT?=	${PORT_DBDIR}/${UNIQUENAME}/license
-_LICENSE_REPORT?=	${_LICENSE_DIR}/report
+_LICENSE?=			${LICENSE}
+.if !defined(LICENSE_COMB)
+_LICENSE_COMB=		single
+.else
+_LICENSE_COMB=		${LICENSE_COMB}
+.endif
 
 # Check if single or dual/multiple license
 #
-# _LICENSE_SINGLE	- Defined for a single license
-# _LICENSE_MULTI	- Set to "and"/"or"? (XXX Not implemented)
+# Make sure LICENSE_COMB is only used with more than one license.
+
+.if ${_LICENSE_COMB} != "single" && ${_LICENSE_COMB} != "dual" && ${_LICENSE_COMB} != "multi"
+_LICENSE_ERROR?=	invalid value for LICENSE_COMB: "${_LICENSE_COMB}" (should be "single", "dual" or "multi")
+.endif
 
-#.for lic in ${_LICENSE}
-#.	if defined(_LICENSE_DEFINED)
-#_LICENSE_MULTI=		yes
-#.	else
-#_LICENSE_DEFINED?=	${lic}
-#.	endif
-#.endfor
-#.if !defined(_LICENSE_MULTI)
-#_LICENSE_SINGLE=	yes
-#.endif
-#.undef _LICENSE_DEFINED
+.for lic in ${_LICENSE}
+.	if defined(_LICENSE_DEFINED)
+.		if ${_LICENSE_COMB} == "single"
+_LICENSE_ERROR?=	multiple licenses in LICENSE, but LICENSE_COMB is set to "single" (or undefined)
+.		else
+_LICENSE_MULTI=		yes
+.		endif
+.	else
+_LICENSE_DEFINED=	yes
+.	endif
+.endfor
+.if ${_LICENSE_COMB} != "single" && !defined(_LICENSE_MULTI)
+_LICENSE_ERROR?=	single license in LICENSE, but LICENSE_COMB is set to "${_LICENSE_COMB}" (requires more than one)
+.endif
+.if !defined(_LICENSE_DEFINED)
+_LICENSE_ERROR?=	no licenses present in LICENSE (empty string)
+.endif
+.undef _LICENSE_DEFINED
+.undef _LICENSE_MULTI
 
 # Evaluate port license groups and permissions
 #
 # Available values for _LICENSE_TYPE:
+#
 # Case 1: "known" (license info taken from internal database)
-# Case 2: "variant" (LICENSE is known, but info taken from port)
-# Case 3: "unknown" (LICENSE is not known, and info taken from port)
-# # Make sure required variables are defined, and remove conflicting (positive
-# and negative) and duplicated components.
+# Case 2: "unknown" (LICENSE is not known, and info taken from port)
+#
+# Make sure required variables are defined, and remove conflicting (positive
+# and negative) duplicated components.
 
-#.if defined(_LICENSE_SINGLE)
+.if ${_LICENSE_COMB} == "single"
+# Defaults to empty
+_LICENSE_GROUPS?=	#
+# Start
 .	for lic in ${_LICENSE}
 .		if ${_LICENSE_LIST:M${lic}} != ""
+# Case 1: license defined in the framework.
+_LICENSE_TYPE=		known
 .			for var in ${_LICENSE_LIST_PORT_VARS}
 .				if defined(LICENSE_${var})
-_LICENSE_TYPE=	variant
+_LICENSE_ERROR?=	redefining LICENSE_${var} is not allowed for known licenses, to define a custom license try another LICENSE name like ${_LICENSE}-variant
 .				endif
-.			endfor
-_LICENSE_TYPE?=	known
-.			for var in ${_LICENSE_LIST_PORT_VARS}
-# Case 1: license defined in the framework.
-.				if ${_LICENSE_TYPE} == "known"
+.				if !defined(_LICENSE_${var}_${lic})
+_LICENGE_ERROR?=	ERROR: missing _LICENSE_${var}_${lic} in bsd.licenses.db.mk
+.				else
 _LICENSE_${var}=	${_LICENSE_${var}_${lic}}
-# Case 2: license is based on a defined one.
-# XXX Should here be inheritance of non defined values?
-.				elif ${_LICENSE_TYPE} == "variant" && defined(LICENSE_${var})
-_LICENSE_${var}=	${LICENSE_${var}}
 .				endif
 .			endfor
-# Case 3: license only known by the port.
+# Check for LICENSE_FILE or at least LICENSE_TEXT (which simulates it)
+.			if !defined(LICENSE_FILE)
+.				if !defined(LICENSE_TEXT)
+# XXX Until we have a license pool under /usr/ports/Licenses use this
+_LICENSE_TEXT=		The license: ${_LICENSE} (${_LICENSE_NAME}) is standard, please read from the web.
+_LICENSE_FILE=		${WRKDIR}/${lic}
+.				else
+_LICENSE_ERROR?=	defining LICENSE_TEXT is not allowed for known licenses
+.				endif
+.			else
+_LICENSE_FILE=		${LICENSE_FILE}
+.			endif
+
 .		else
-_LICENSE_TYPE?=	unknown
+# Case 2: license only known by the port.
+_LICENSE_TYPE=		unknown
 .			for var in ${_LICENSE_LIST_PORT_VARS}
 .				if defined(LICENSE_${var})
 _LICENSE_${var}=	${LICENSE_${var}}
+.				else
+_LICENSE_ERROR?=	for a new/unknown license, defining LICENSE_${var} is mandatory (otherwise use a known LICENSE)
 .				endif
 .			endfor
+# Check LICENSE_PERMS for invalid, ambiguous and duplicate components
+__LICENSE_PERMS:=	#
+.			for comp in ${_LICENSE_PERMS}
+.				if ${_LICENSE_LIST_PERMS:M${comp:C/^no-//}} == ""
+_LICENSE_ERROR?=	invalid LICENSE_PERMS component "${comp}"
+.				elif ${__LICENSE_PERMS:M${comp}} == "" && \
+					 ${_LICENSE_PERMS:Mno-${comp:C/^no-//}} == ""
+__LICENSE_PERMS+=	${comp}
+.				endif
+.			endfor
+_LICENSE_PERMS:=	${__LICENSE_PERMS}
+.			undef __LICENSE_PERMS
+# Check for LICENSE_FILE or at least LICENSE_TEXT (which simulates it)
+.			if !defined(LICENSE_FILE)
+.				if !defined(LICENSE_TEXT)
+_LICENSE_ERROR?=	either LICENSE_FILE or LICENSE_TEXT must be defined
+.				else
+_LICENSE_TEXT=		${LICENSE_TEXT}
+_LICENSE_FILE=		${WRKDIR}/${lic}
+.				endif
+.			else
+_LICENSE_FILE=		${LICENSE_FILE}
+.			endif
+.		endif
+
+# Only one is allowed
+.		if defined(LICENSE_FILE) && defined(LICENSE_TEXT)
+_LICENSE_ERROR?=	defining both LICENSE_FILE and LICENSE_TEXT is not allowed
 .		endif
-# XXX Some defaults (here they do not affect _LICENSE_TYPE).
-_LICENSE_COMPAT?=	#
-_LICENSE_INCOMPAT?=	#
-_LICENSE_GROUPS?=	#
-# Check everything needed is defined.
-.		for var in ${_LICENSE_LIST_PORT_VARS}
-.			if !defined(_LICENSE_${var})
-.				if ${_LICENSE_TYPE} == "variant"
-_LICENSE_ERROR?=	for a modified license, defining LICENSE_${var} is mandatory (otherwise define LICENSE alone)
-.				elif ${_LICENSE_TYPE} == "unknown"
-_LICENSE_ERROR?=	for a new/unknown license, defining LICENSE_${var} is mandatory (otherwise use a known LICENSE)
+# Distfiles
+.		if !defined(LICENSE_DISTFILES)
+_LICENSE_DISTFILES=	${_DISTFILES}
+.		else
+_LICENSE_DISTFILES=	${LICENSE_DISTFILES}
+.		endif
+.	endfor
+
+.else
+.	for lic in ${_LICENSE}
+# Defaults to empty
+_LICENSE_GROUPS_${lic}?=#
+.		if ${_LICENSE_LIST:M${lic}} != ""
+# Case 1: license defined in the framework.
+_LICENSE_TYPE_${lic}=	known
+.			for var in ${_LICENSE_LIST_PORT_VARS}
+.				if defined(LICENSE_${var}_${lic})
+_LICENSE_ERROR?=	redefining LICENSE_${var}_${lic} is not allowed for known licenses, to define a custom license try another LICENSE name for ${lic} like ${lic}-variant
+.				endif
+.				if !defined(_LICENSE_${var}_${lic})
+_LICENGE_ERROR?=	ERROR: missing _LICENSE_${var}_${lic} in bsd.licenses.db.mk
+.				endif
+.			endfor
+# Check for LICENSE_FILE or at least LICENSE_TEXT (which simulates it)
+.			if !defined(LICENSE_FILE_${lic})
+.				if !defined(LICENSE_TEXT_${lic})
+# XXX Until we have a license pool under /usr/ports/Licenses use this
+_LICENSE_TEXT_${lic}=	The license: ${lic} (${_LICENSE_NAME_${lic}}) is standard, please read from the web.
+_LICENSE_FILE_${lic}=	${WRKDIR}/${lic}
+.				else
+_LICENSE_ERROR?=		defining LICENSE_TEXT_${lic} is not allowed for known licenses
 .				endif
+.			else
+_LICENSE_FILE_${lic}=	${LICENSE_FILE_${lic}}
 .			endif
-.		endfor
-# Groups are always inherited (and were expanded so no recursion)
-.		for group in ${_LICENSE_LIST_GROUPS}
-.			for var in ${_LICENSE_LIST_GROUP_VARS}
-_LICENSE_${var}+=	${_LICENSE_${var}_${group}}
+
+.		else
+# Case 2: license only known by the port.
+_LICENSE_TYPE_${lic}=	unknown
+.			for var in ${_LICENSE_LIST_PORT_VARS}
+.				if defined(LICENSE_${var}_${lic})
+_LICENSE_${var}_${lic}=	${LICENSE_${var}_${lic}}
+.				else
+_LICENSE_ERROR?=	for a new/unknown license, defining LICENSE_${var}_${lic} is mandatory (otherwise use a known LICENSE)
+.				endif
 .			endfor
-.		endfor
-# Expand LICENSE_PERMS aliases
-# pkg		-> pkg-redist pkg-sell
-# dist		-> dist-redist dist-sell
-# redist	-> pkg-redist dist-redist
-# sell		-> pkg-sell dist-sell
-_LICENSE_PERMS:=	${_LICENSE_PERMS:Nno-*:C/^(pkg|dist)$/\1-redist \1-sell/:C/^(sell|redist)$/dist-\1 pkg-\1/} \
-					${_LICENSE_PERMS:Mno-*:C/^(no-)(pkg|dist)$/\1\2-redist \1\2-sell/:C/^(no-)(sell|redist)$/\1dist-\2 \1pkg-\2/}
-# XXX Cleaner, but outputs an error when (no-)? is not found but referenced later by \1
-#_LICENSE_PERMS:=	${_LICENSE_PERMS:C/^(no-)?(pkg|dist)$/\1\2-redist \1\2-sell/:C/^(no-)?(sell|redist)$/\1dist-\2 \1pkg-\2/}
 # Check LICENSE_PERMS for invalid, ambiguous and duplicate components
 __LICENSE_PERMS:=	#
-.		for comp in ${_LICENSE_PERMS}
-.			if ${_LICENSE_LIST_PERMS:M${comp:C/^no-//}} == ""
-_LICENSE_ERROR?=	invalid LICENSE_PERMS component "${comp}"
-.			elif ${__LICENSE_PERMS:M${comp}} == "" && \
-				 ${_LICENSE_PERMS:Mno-${comp:C/^no-//}} == ""
-__LICENSE_PERMS+=	${comp}
-.			endif
-.		endfor
-_LICENSE_PERMS:=	${__LICENSE_PERMS}
-.		undef __LICENSE_PERMS
+.			for comp in ${_LICENSE_PERMS_${lic}}
+.				if ${_LICENSE_LIST_PERMS:M${comp:C/^no-//}} == ""
+_LICENSE_ERROR?=		invalid LICENSE_PERMS_${var} component "${comp}"
+.				elif ${__LICENSE_PERMS:M${comp}} == "" && \
+					 ${_LICENSE_PERMS_${lic}:Mno-${comp:C/^no-//}} == ""
+__LICENSE_PERMS+=		${comp}
+.				endif
+.			endfor
+_LICENSE_PERMS_${lic}:=	${__LICENSE_PERMS}
+.			undef __LICENSE_PERMS
 # Check for LICENSE_FILE or at least LICENSE_TEXT (which simulates it)
-# XXX License file is optional for licenses present in database, maybe an option
-#     could be added to avoid installing licenses present in the database
-.		if !defined(LICENSE_FILE)
-.			if !defined(LICENSE_TEXT)
-.				if ${_LICENSE_TYPE} == "known"
-LICENSE_TEXT=		License ${lic} is in internal database, check repository.
+.			if !defined(LICENSE_FILE_${lic})
+.				if !defined(LICENSE_TEXT_${lic})
+_LICENSE_ERROR?=		either LICENSE_FILE_${lic} or LICENSE_TEXT_${lic} must be defined
 .				else
-_LICENSE_ERROR?=	LICENSE_FILE or LICENSE_TEXT must be defined for unknown licenses
+_LICENSE_TEXT_${lic}=	${LICENSE_TEXT_${lic}}
+_LICENSE_FILE_${lic}=	${WRKDIR}/${lic}
 .				endif
+.			else
+_LICENSE_FILE_${lic}=	${LICENSE_FILE_${lic}}
 .			endif
-_LICENSE_FILE=		${WRKDIR}/License-freebsd-port
+.		endif
+
+# Only one is allowed
+.		if defined(LICENSE_FILE_${lic}) && defined(LICENSE_TEXT_${lic})
+_LICENSE_ERROR?=		defining both LICENSE_FILE_${lic} and LICENSE_TEXT_${lic}is not allowed
+.		endif
+# Distfiles
+.		if !defined(LICENSE_DISTFILES_${lic})
+_LICENSE_DISTFILES_${lic}=	${_DISTFILES}
 .		else
-_LICENSE_FILE=		${LICENSE_FILE}
+_LICENSE_DISTFILES_${lic}=	${LICENSE_DISTFILES_${lic}}
 .		endif
 .	endfor
-#.else
-# XXX dual/multiple licenses
-#.endif
+.endif
 
 # Check if the user agrees with the license
-#
-# _LICENSE_CFG			- Path to cfg file (either global or per port)
-# _LICENSE_CFG_TYPE		- "global" or "port", according to the previous
-#
-# LICENSES_ACCEPTED		- List of accepted licenses (user version)
-# LICENSES_REJECTED		- List of rejected licenses (user version)
-# _LICENSES_ACCEPTED	- List of accepted licenses (configuration file)
-# _LICENSES_REJECTED	- List of rejected licenses (configuration file)
+
+# Make sure these are defined
+
+LICENSES_ACCEPTED?=			#
+LICENSES_REJECTED?=			#
+LICENSES_GROUPS_ACCEPTED?=	#
+LICENSES_GROUPS_REJECTED?=	#
+
+# Evaluate per-license status
 
-# If _LICENSE_TYPE is "known", configuration is global, otherwise per port.
+.if ${_LICENSE_COMB} == "single"
+.	for lic in ${_LICENSE}
+.		if ${LICENSES_REJECTED:M${lic}} != ""
+_LICENSE_STATUS?=	rejected
+.		endif
+.		for group in ${_LICENSE_GROUPS}
+.			if ${LICENSES_GROUPS_REJECTED:M${group}} != ""
+_LICENSE_STATUS?=	rejected
+.			endif
+.			if ${LICENSES_GROUPS_ACCEPTED:M${group}} != ""
+_LICENSE_STATUS?=	accepted
+.			endif
+.		endfor
+.		if ${LICENSES_ACCEPTED:M${lic}} != ""
+_LICENSE_STATUS?=	accepted
+.		endif
+.		if ${_LICENSE_PERMS:Mauto-accept} != "" && !defined(LICENSES_ASK)
+_LICENSE_STATUS?=	accepted
+.		endif
+_LICENSE_STATUS?=	ask
+.	endfor
 
-.if ${_LICENSE_TYPE} == "known"
-_LICENSE_CFG=		${_LICENSE_CFG_GLOB}
-_LICENSE_CFG_TYPE=	global
 .else
-_LICENSE_CFG=	${_LICENSE_CFG_PORT}
-_LICENSE_CFG_TYPE=	port
+.	for lic in ${_LICENSE}
+.		if ${LICENSES_REJECTED:M${lic}} != ""
+_LICENSE_STATUS_${lic}?=	rejected
+.		endif
+.		for group in ${_LICENSE_GROUPS_${lic}}
+.			if ${LICENSES_GROUPS_REJECTED:M${group}} != ""
+_LICENSE_STATUS_${lic}?=	rejected
+.			endif
+.			if ${LICENSES_GROUPS_ACCEPTED:M${group}} != ""
+_LICENSE_STATUS_${lic}?=	accepted
+.			endif
+.		endfor
+.		if ${LICENSES_ACCEPTED:M${lic}} != ""
+_LICENSE_STATUS_${lic}?=	accepted
+.		endif
+.		if ${_LICENSE_PERMS_${lic}:Mauto-accept} != "" && !defined(LICENSES_ASK)
+_LICENSE_STATUS_${lic}?=	accepted
+.		endif
+_LICENSE_STATUS_${lic}?=	ask
+.	endfor
 .endif
 
-.if exists(${_LICENSE_CFG})
-.	include "${_LICENSE_CFG}"
-.endif
+# Evaluate general status
 
-# Make sure these are defined
-LICENSES_ACCEPTED?=		#
-LICENSES_REJECTED?=		#
-_LICENSES_ACCEPTED?=	#
-_LICENSES_REJECTED?=	#
+.if ${_LICENSE_COMB} == "dual"
+.	for lic in ${_LICENSE}
+.		if ${_LICENSE_STATUS_${lic}} == "accepted"
+_LICENSE_STATUS=	accepted
+.		elif ${_LICENSE_STATUS_${lic}} == "ask"
+_LICENSE_STATUS?=	ask
+_LICENSE_TO_ASK+=	${lic}
+.		endif
+_LICENSE_STATUS?=	rejected
+.	endfor
 
-# Evaluate status (accepted, rejected or ask)
-#
-# _LICENSE_STATUS			- Status: "accepted", "rejected" or "ask"
-# _LICENSE_STATUS_FROM		- Status origin: "user", "config" or "default"
-# _LICENSE_STATUS_REASON	- Text reason of license status (XXX Required?)
+.elif ${_LICENSE_COMB} == "multi"
+.	for lic in ${_LICENSE}
+.		if ${_LICENSE_STATUS_${lic}} == "rejected"
+_LICENSE_STATUS=	rejected
+.		elif ${_LICENSE_STATUS_${lic}} == "ask"
+_LICENSE_STATUS?=	ask
+_LICENSE_TO_ASK+=	${lic}
+.		endif
+.	endfor
+_LICENSE_STATUS?=	accepted
+.endif
 
-_LICENSE_TYPE_PAIRS_known=		LICENSES,user _LICENSES,config
-_LICENSE_TYPE_PAIRS_variant=	_LICENSES,config
-_LICENSE_TYPE_PAIRS_unknown=	_LICENSES,config
+# For dual/multi licenses, after processing all sub-licenses, the following
+# must be determined: _LICENSE_NAME, _LICENSE_PERMS and _LICENSE_GROUPS.
 
-#.if defined(_LICENSE_SINGLE)
-# User and saved configuration
+.if ${_LICENSE_COMB} == "dual"
+_LICENSE_NAME=		Dual (any of): ${_LICENSE}
+# Calculate least restrictive permissions (union)
+_LICENSE_PERMS:=	#
+.	for lic in ${_LICENSE}
+.		for comp in ${_LICENSE_LIST_PERMS}
+.			if ${_LICENSE_PERMS_${lic}:M${comp}} != "" && \
+			   ${_LICENSE_PERMS:M${comp}} == ""
+_LICENSE_PERMS+=	${comp}
+.			endif
+.		endfor
+.	endfor
+# Calculate least restrictive groups (union)
+_LICENSE_GROUPS:=	#
 .	for lic in ${_LICENSE}
-.		for pair in ${_LICENSE_TYPE_PAIRS_${_LICENSE_TYPE}}
-_LC_VAR:=	${pair:C/,.*//}
-_LC_TYPE:=	${pair:C/.*,//}
-.			if ${${_LC_VAR}_REJECTED:M${lic}} != "" && !defined(_LICENSE_STATUS)
-_LICENSE_STATUS=		rejected
-_LICENSE_STATUS_FROM:=	${_LC_TYPE}
-.			elif ${${_LC_VAR}_ACCEPTED:M${lic}} != "" && !defined(_LICENSE_STATUS)
-_LICENSE_STATUS=		accepted
-_LICENSE_STATUS_FROM:=	${_LC_TYPE}
+.		for comp in ${_LICENSE_LIST_GROUPS}
+.			if ${_LICENSE_GROUPS_${lic}:M${comp}} != "" && \
+			   ${_LICENSE_GROUPS:M${comp}} == ""
+_LICENSE_GROUPS+=	${comp}
 .			endif
 .		endfor
+.	endfor
 
-# Automatic configuration
-.		if !defined(_LICENSE_STATUS)
-# Check groups (only available for user configuration)
-.			for group in ${_LICENSE_LIST_GROUPS}
-.				if ${LICENSES_REJECTED:M\@${group}} != ""
-_LICENSE_STATUS?=		rejected
-_LICENSE_STATUS_FROM?=	user
-.				endif
-.				if ${LICENSES_ACCEPTED:M\@${group}} != ""
-_LICENSE_STATUS?=		accepted
-_LICENSE_STATUS_FROM?=	user
-.				endif
-.			endfor
-# Auto-accept if LICENSE_PERMS has auto-accept, and !LICENSES_ASK
-.			if ${_LICENSE_PERMS:Mauto-accept} != ""
-.				if !defined(LICENSES_ASK)
-_LICENSE_STATUS?=		accepted
-_LICENSE_STATUS_FROM?=	default
-.				else
-_LICENSE_STATUS?=		ask
-_LICENSE_STATUS_FROM?=	user
-.				endif
+.elif ${_LICENSE_COMB} == "multi"
+_LICENSE_NAME=		Multiple (all of): ${_LICENSE}
+# Calculate most restrictive permissions (intersection)
+_LICENSE_PERMS:=	${_LICENSE_LIST_PERMS}
+.	for lic in ${_LICENSE}
+.		for comp in ${_LICENSE_LIST_PERMS}
+.			if ${_LICENSE_PERMS_${lic}:M${comp}} == ""
+_LICENSE_PERMS:=	${_LICENSE_PERMS:N${comp}}
 .			endif
-# If defined BATCH and need to ask, it fails
-.			if defined(BATCH)
-_LICENSE_STATUS?=		rejected
-_LICENSE_STATUS_FROM?=	user
+.		endfor
+.	endfor
+# Calculate most restrictive groups (intersection)
+_LICENSE_GROUPS:=	${_LICENSE_LIST_GROUPS}
+.	for lic in ${_LICENSE}
+.		for comp in ${_LICENSE_LIST_GROUPS}
+.			if ${_LICENSE_GROUPS_${lic}:M${comp}} == ""
+_LICENSE_GROUPS:=	${_LICENSE_GROUPS:N${comp}}
 .			endif
-# Otherwise ask to the user
-_LICENSE_STATUS?=		ask
-_LICENSE_STATUS_FROM?=	default
+.		endfor
+.	endfor
+.endif
+
+# Prepare information for asking license to the user
+
+.if ${_LICENSE_STATUS} == "ask" && ${_LICENSE_COMB} != "single"
+_LICENSE_ASK_DATA!=	mktemp -t portslicense
+.endif
+
+# Calculate restrictions and set RESTRICTED_FILES when
+# appropiate, together with cleaning targets.
+#
+# XXX For multiple licenses restricted distfiles are always removed from both
+# CDROM and FTP, but the current framework supports separating them (would
+# require better/new delete-package and delete-distfiles targets)
+
+.if ${_LICENSE_PERMS:Mpkg-mirror} == ""
+_LICENSE_RESTRICTED+=	delete-package
+.elif ${_LICENSE_PERMS:Mpkg-sell} == ""
+_LICENSE_CDROM+=		delete-package
+.endif
+
+.if ${_LICENSE_COMB} == "multi"
+.	for lic in ${_LICENSE}
+.		if ${_LICENSE_PERMS_${lic}:Mdist-mirror} == "" || ${_LICENSE_PERMS_${lic}:Mdist-sell} == ""
+RESTRICTED_FILES+=		${_LICENSE_DISTFILES_${lic}}
 .		endif
 .	endfor
+.	if defined(RESTRICTED_FILES)
+RESTRICTED_FILES+=		${_PATCHFILES}
+_LICENSE_RESTRICTED+=	delete-distfiles
+_LICENSE_CDROM+=		delete-distfiles
+.	endif
+.else
+.	if ${_LICENSE_PERMS:Mdist-mirror} == ""
+_LICENSE_RESTRICTED+=	delete-distfiles
+RESTRICTED_FILES=		${_PATCHFILES} ${_DISTFILES}
+.	elif ${_LICENSE_PERMS:Mdist-sell} == ""
+_LICENSE_CDROM+=		delete-distfiles
+RESTRICTED_FILES=		${_PATCHFILES} ${_DISTFILES}
+.	endif
+.endif
 
-#.else
-# XXX dual/multiple licenses
-#.endif
+.if defined(_LICENSE_RESTRICTED)
+clean-restricted:	${_LICENSE_RESTRICTED}
+clean-restricted-list: ${_LICENSE_RESTRICTED:C/$/-list/}
+.else
+clean-restricted:
+clean-restricted-list:
+.endif
+
+.if defined(_LICENSE_CDROM)
+clean-cdrom:	${_LICENSE_CDROM}
+clean-cdrom-list: ${_LICENSE_CDROM:C/$/-list/}
+.else
+clean-cdrom:
+clean-cdrom-list:
+.endif
 
 # Check variables are correctly defined and print status up to here
 
@@ -366,160 +549,206 @@
 		@${ECHO_MSG} "===>  License not correctly defined: ${_LICENSE_ERROR}"
 		@exit 1
 .endif
-#.if defined(_LICENSE_SINGLE)
 .	if ${_LICENSE_STATUS} == "rejected"
-		@${ECHO_MSG} "===>  License ${_LICENSE} rejected by the user (by ${_LICENSE_STATUS_FROM})"
+		@${ECHO_MSG} "===>  License rejected by the user"
+		@${ECHO_MSG}
+		@${ECHO_MSG} "If you want to install this port make sure the following license/s are not present in LICENSES_REJECTED, either in make arguments or /etc/make.conf: ${_LICENSE}. Also check LICENSES_GROUPS_REJECTED in case they contain a group this license/s belong to." | ${FMT}
+		@${ECHO_MSG}
 		@exit 1
 .	elif ${_LICENSE_STATUS} == "accepted"
-		@${ECHO_MSG} "===>  License ${_LICENSE} accepted by the user (by ${_LICENSE_STATUS_FROM})"
+		@${ECHO_MSG} "===>  License accepted by the user"
 .	elif ${_LICENSE_STATUS} == "ask"
-		@${ECHO_MSG} "===>  License ${_LICENSE} needs agreement, will ask later (by ${_LICENSE_STATUS_FROM})"
+.		if defined(BATCH)
+		@${ECHO_MSG} "===>  License needs confirmation, but BATCH is defined"
+		@exit 1
+.		else
+		@${ECHO_MSG} "===>  License needs confirmation, will ask later"
+.		endif
 .	endif
-#.else
-# XXX dual/multiple licenses
-#.endif
+
+# Display, ask and save preference if requested
+
+ask-license: ${_LICENSE_COOKIE}
 
-.if defined(LICENSES_CONFIG)
-_LICENSES_CONFIG=	yes
+${_LICENSE_COOKIE}:
+# Make sure all required license files exist
+.if ${_LICENSE_COMB} == "single"
+.	if !defined(LICENSE_FILE) && defined(_LICENSE_TEXT)
+	@test -f ${_LICENSE_FILE} || ${ECHO_CMD} "${_LICENSE_TEXT}" | ${FMT} > ${_LICENSE_FILE}
+.	endif
+	@test -f ${_LICENSE_FILE} || \
+		(${ECHO_MSG} "===>  Missing license file for ${_LICENSE} in ${_LICENSE_FILE}"; exit 1)
 .else
-_LICENSES_CONFIG=	no
+.	for lic in ${_LICENSE}
+.		if !defined(LICENSE_FILE_${lic}) && defined(_LICENSE_TEXT_${lic})
+	@test -f ${_LICENSE_FILE_${lic}} || ${ECHO_CMD} "${_LICENSE_TEXT_${lic}}" | ${FMT} > ${_LICENSE_FILE_${lic}}
+.		endif
+	@test -f ${_LICENSE_FILE_${lic}} || \
+		(${ECHO_MSG} "===>  Missing license file for ${lic} in ${_LICENSE_FILE_${lic}}"; exit 1)
+.	endfor
 .endif
 
-# For config when user accepts
-_LICENSES_ACCEPTED_YES=	${_LICENSES_ACCEPTED} ${_LICENSE}
-.for lic in ${_LICENSE}
-_LICENSES_REJECTED_YES=	${_LICENSES_REJECTED:N${lic}}
-.endfor
-# For config when user rejects
-.for lic in ${_LICENSE}
-_LICENSES_ACCEPTED_NO=	${_LICENSES_ACCEPTED:N${lic}}
-.endfor
-_LICENSES_REJECTED_NO=	${_LICENSES_REJECTED} ${_LICENSE}
+.if ${_LICENSE_STATUS} == "ask"
+.	if !defined(NO_LICENSES_DIALOGS)
+# Dialog interface
+.		if ${_LICENSE_COMB} == "single"
+	@while true; do \
+		tmpfile=$$(mktemp -t portlicenses); \
+		${DIALOG} --menu "License for ${PKGNAME} (${_LICENSE})" 21 70 15 accept "Accept license" reject "Reject license" view "View license" 2>"$${tmpfile}"; \
+		result=`${CAT} $${tmpfile}`; \
+		case $${result} in \
+		accept) break ;; \
+		reject) exit 1;; \
+		view)   ${DIALOG} --textbox "${_LICENSE_FILE}" 21 70 ;; \
+		esac; \
+	done
 
-# Display, ask and save preference if requested
+.		elif ${_LICENSE_COMB} == "dual"
+	@${RM} -f ${_LICENSE_ASK_DATA}
+.			for lic in ${_LICENSE_TO_ASK}

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list