Date: Wed, 6 Aug 2008 03:32:12 GMT From: Alejandro Pulver <alepulver@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 146748 for review Message-ID: <200808060332.m763WCAi013607@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=146748 Change 146748 by alepulver@alepulver_deimos on 2008/08/06 03:31:31 - Implement basic LICENSE_COMPAT/LICENSE_INCOMPAT support. - Add LICENSE_TEXT in case LICENSE_FILE is not available locally. - Add aliases for LICENSE_PERMS: pkg, dist, sell and redist. - Use '_' prefix for most internal variables. - Check for invalid and ambiguous entries in LICENSE_PERMS. - Add variable LICENSES_CONFIG (if defined acts as "make config"). - Avoid whitespace in configuration files, and store more information. - Allow missing LICENSE_FILE if license is present in database. Affected files ... .. //depot/projects/soc2008/alepulver-portslicense/ports/Mk/README#3 edit .. //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.licenses.mk#3 edit Differences ... ==== //depot/projects/soc2008/alepulver-portslicense/ports/Mk/README#3 (text+ko) ==== @@ -74,39 +74,31 @@ Interface: * incorporate pattern matching in licenses/groups/distfiles/lic files + -> only if variables are solely used in commands * extend LICENSE=... for dual/multiple use (), [], {} or <> (use shell/commands as make can't parse this notation) LICENSE= dual(BSD,GPLv2,multi(ART,etc)) dual/multiple licenses (need parsing code), start with only one of them -* implement LICENSE_COMPAT for packaging/linking (check *_DEPENDS - appropiately), but should be allowed by default first (maybe should be - INCOMPAT instead)? -* Consider licenses that need manual agreement/manual fetching - provide framework help for manual distfile placing, etc - maybe also add pkg-fetch-message or some variables to avoid manual IGNORE/printf? -* how do you know if a license has changed? Save checksum? Maybe license - revison number suffixed by a _n? Or not needed (this is only for changes of - the same license type: e.g. BSD-based to BSD-based, but with no-pkg-sell). - only for license "variant" and "unknown", save checksum in port cfg and compare -* provide useful aliases like "no-sell" for a general no-pkg-sell no-dist-sell, - and groups for the same purpose + -> For now use =LIC1|LIC2 LIC2|LIC3 ('|' is OR and ' ' is AND) General: * additional targets (show-license, show-license-report, show-known-licenses, etc) + and ports framework configuration * add common licenses (check a web page or try FOSSology) -* avoid whitespace in saved files (reports and cfg) -* add LICENSE_TEXT for when there is no LICENSE_FILE, and show instead (not - with a license but maybe for a URL to read it) + +NOW: +- * make list of error messages (by component/type) and the like, so targets are more dynamic +- * unify echo messages, use ECHO_MSG, add a debug variable maybe +- * prepare for multiple licenses support: + -> use _LICENSE in for loops, with AND criteria -Configuration: +Maybe: +* separate groups into another variable (either internally and/or externally->better) * provide target to assist cleaning LICENSES_ACCEPTED and LICENSES_REJECTED, - and ports framework configuration -* provide root credential switching like make-config -* allow approving a previously rejected and saved license with a target like - license-config (or by defining a variable) -* separate groups into another variable (either internally and/or externally->better) -* make list of error messages (by component/type) and the like, so targets are more dynamic +* Consider licenses that need manual agreement/manual fetching + provide framework help for manual distfile placing, etc + maybe also add pkg-fetch-message or some variables to avoid manual IGNORE/printf? Reports: ==== //depot/projects/soc2008/alepulver-portslicense/ports/Mk/bsd.licenses.mk#3 (text+ko) ==== @@ -33,31 +33,35 @@ # Variables provided to users # -# LICENSES_ACCEPTED - Accepted licenses and groups -# LICENSES_REJECTED - Rejected licenses and groups +# 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 +# present in configuration nor LICENSES_ACCEPTED. # # The components of LICENSES_{ACCEPTED,REJECTED} can be one of: # - A license code (like "GPLv2"). # - A license group prefixed by '@' (like "@OSI"). # -# Note that the framework configuration format is the same, but stored in -# ${LICENSE_CFG} or ${LICENSE_CFG_PORT}. The user variables take precedence -# (anyways the other configuration is also made by the user). +# 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 -# LICENSE_NAME - Full license name (for the reports) +# 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 - Path to license (or "none") -# LICENSE_DISTFILE - Name of licensed files (defaults to ${DISTFILES}) +# 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}). # # The following cases are supported (see _LICENSE_TYPE): # @@ -69,7 +73,7 @@ # 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. +# its base license or just let it fall in Case 3 (as now). # # Case 3: license only known by the port (aka "unknown"). # All license variables must be defined by the port. @@ -77,7 +81,7 @@ # 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). +# 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: @@ -86,28 +90,26 @@ # LICENSE_NOTES= GPLv2:"No sell" BSD:"Allows everything" # # Available components for LICENSE_PERMS: -# dist-redist - 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-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) +# dist-redist - 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-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. # -# Available components for LICENSE_COMPAT: -# link Linking -# package - Packaging together .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 +# - 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. # XXX Start of editable section @@ -124,18 +126,21 @@ # _LICENSE_NAME_xxx - Full name/description of license/group # _LICENSE_PERMS_xxx - Permissions # _LICENSE_COMPAT_xxx - Compatibility +# _LICENSE_INCOMPAT_xxx - Incompatibility # List of licenses _LICENSE_NAME_GPLv2= GNU General Public License version 2 _LICENSE_PERMS_GPLv2= dist-redist dist-sell pkg-redist pkg-sell auto-accept _LICENSE_COMPAT_GPLv2= # +_LICENSE_INCOMPAT_GPLv2=# # List of groups _LICENSE_NAME_FSF= Free Software Foundation approved _LICENSE_PERMS_FSF= # _LICENSE_COMPAT_FSF= # +_LICENSE_INCOMPAT_FSF= # # Grouping # @@ -168,25 +173,33 @@ # _LICENSE_LIST_GROUP_VARS - License variables inherited from groups # _LICENSE_LIST_SAVE_VARS - License variables present in the report -_LICENSE_LIST_PERMS= dist-redist distsell pkg-redist pkg-sell auto-accept none -_LICENSE_LIST_PORT_VARS= PERMS GROUPS NAME # COMPAT -_LICENSE_LIST_GROUP_VARS= PERMS # COMPAT -_LICENSE_LIST_SAVE_VARS= LICENSE ${_LICENSE_LIST_PORT_VARS:S/^/LICENSE_/} LICENSE_NOTES LICENSE_DISTFILE +_LICENSE_LIST_PERMS= dist-redist dist-sell pkg-redist pkg-sell auto-accept none +_LICENSE_LIST_PORT_VARS= PERMS GROUPS NAME +_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_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_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_DISTFILE?= ${DISTFILES} -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_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 # Check if single or dual/multiple license # @@ -230,7 +243,7 @@ _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" +. elif ${_LICENSE_TYPE} == "variant" && defined(LICENSE_${var}) _LICENSE_${var}= ${LICENSE_${var}} . endif . endfor @@ -242,35 +255,61 @@ _LICENSE_${var}= ${LICENSE_${var}} . endif . endfor +. endif +# XXX here it does not affect _LICENSE_TYPE +_LICENSE_COMPAT?= # +_LICENSE_INCOMPAT?= # # Check everything needed is defined. -. for var in ${_LICENSE_LIST_PORT_VARS} -. if !defined(_LICENSE_${var}) -. if ${_LICENSE_TYPE} == "variant" +. 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" +. elif ${_LICENSE_TYPE} == "unknown" _LICENSE_ERROR?= for a new/unknown license, defining LICENSE_${var} is mandatory (otherwise use a known LICENSE) -. endif . endif -. endfor -. endif +. 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}} . endfor . endfor -# Remove ambiguous and duplicate components -__LICENSE_PERMS:= ${_LICENSE_PERMS} -_LICENSE_PERMS:= # -. for comp in ${_LICENSE_LIST_PERMS} -. if ${__LICENSE_PERMS:M${comp}} != "" && ${__LICENSE_PERMS:Mno-${comp}} == "" && \ - ${_LICENSE_PERMS:M${comp}} == "" -_LICENSE_PERMS+= ${comp} +# 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 -# Check LICENSE_FILE (XXX Should be mandatory in all cases?) +_LICENSE_PERMS:= ${__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) -_LICENSE_ERROR?= LICENSE_FILE must be defined for unknown licenses +. if !defined(LICENSE_TEXT) +. if ${_LICENSE_TYPE} != "known" +LICENSE_TEXT= License ${lic} is in internal database, please check ... +. else +_LICENSE_ERROR?= LICENSE_FILE or LICENSE_TEXT must be defined for unknown licenses +. endif +. else +LICENSE_FILE= ${WRKDIR}/License-freebsd-port +_LICENSE_FILE_SIM= yes +. endif . endif . endfor .else @@ -279,7 +318,7 @@ # Check if the user agrees with the license # -# LICENSE_CFG - Path to cfg file (either global or per port) +# _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) @@ -290,15 +329,15 @@ # If _LICENSE_TYPE is "known", configuration is global, otherwise per port. .if ${_LICENSE_TYPE} == "known" -LICENSE_CFG= ${LICENSE_CFG_GLOB} +_LICENSE_CFG= ${_LICENSE_CFG_GLOB} _LICENSE_CFG_TYPE= global .else -LICENSE_CFG= ${LICENSE_CFG_PORT} +_LICENSE_CFG= ${_LICENSE_CFG_PORT} _LICENSE_CFG_TYPE= port .endif -.if exists(${LICENSE_CFG}) -. include "${LICENSE_CFG}" +.if exists(${_LICENSE_CFG}) +. include "${_LICENSE_CFG}" .endif # Make sure these are defined @@ -386,58 +425,100 @@ . elif ${_LICENSE_STATUS} == "ask" @${ECHO_MSG} "===> License ${LICENSE} needs agreement, will ask later (by ${_LICENSE_STATUS_FROM})" . endif +. if defined(_LICENSE_FILE_SIM) +# XXX escape shell chars + @${ECHO_CMD} ${LICENSE_TEXT} > ${LICENSE_FILE} +. endif .else # XXX dual/multiple licenses .endif +.if defined(LICENSES_CONFIG) +_LICENSES_CONFIG= yes +.else +_LICENSES_CONFIG= no +.endif + # Display, ask and save preference if requested ask-license: -# XXX verify checksum if accepted by port cfg file -.if ${_LICENSE_STATUS} == "ask" @if [ ! -f ${LICENSE_FILE} ]; then \ ${ECHO_CMD} "License not found in \"${LICENSE_FILE}\", aborting."; \ exit 1; \ fi - @until [ "$$status" = done ]; do \ + @if [ ${_LICENSE_STATUS} = "accepted" ]; then \ + status=done; \ + fi; \ + if [ ${_LICENSE_STATUS} = "accepted" -a ${_LICENSE_TYPE} != "known" ]; then \ + if [ ${_LICENSE_${LICENSE}_CHK} != `${SHA256} -q ${LICENSE_FILE}` ]; then \ + ${ECHO_MSG} "===> License has changed, reconfiguring..."; \ + status=ask; \ + fi; \ + fi; \ + if [ ${_LICENSE_STATUS} != "ask" -a ${_LICENSES_CONFIG} = "yes" ]; then \ + if [ ${_LICENSE_STATUS_FROM} = "user" ]; then \ + ${ECHO_MSG} "===> Can't reconfigure, as user is manually defining the status"; \ + exit 1; \ + else \ + status=ask; \ + fi \ + fi; \ + until [ "$$status" = done ]; do \ ${ECHO_CMD} "Press 'Y' to accept, 'S' to accept and save, 'N' to reject or 'V' to view." | ${FMT}; \ read ans; \ case $$ans in \ - [Yy]) ${ECHO_CMD} "License was accepted."; \ - status=done;; \ - [Nn]) ${ECHO_CMD} "License was rejected."; \ - exit 1;; \ - [Ss]) ${ECHO_CMD} "License was accepted and saved."; \ - ${MKDIR} ${LICENSE_CFG:H}; \ - ${ECHO_CMD} _LICENSES_ACCEPTED=${LICENSE} > ${LICENSE_CFG}; \ - status=done;; \ - [Vv]) more ${LICENSE_FILE}; \ + [Yy]) ${ECHO_CMD} "License was accepted."; \ + status=done;; \ + [Nn]) ${ECHO_CMD} "License was rejected."; \ + exit 1;; \ + [Ss]) if [ ${UID} != 0 ]; then \ + ${ECHO_CMD} "You don't have permissions to save the license"; \ + else \ + ${MKDIR} ${_LICENSE_CFG:H}; \ + (${ECHO_CMD} _LICENSES_ACCEPTED=${LICENSE}; \ + if [ ${_LICENSE_TYPE} != "known" ]; then \ + ${ECHO_CMD} _LICENSE_${LICENSE}_CHK=`${SHA256} -q ${LICENSE_FILE}`; \ + fi) > ${LICENSE_FILE}; \ + ${ECHO_CMD} "License was accepted and saved."; \ + status=done; \ + fi;; \ + [Vv]) more ${LICENSE_FILE}; \ esac; \ done -.elif defined(LICENSES_CONFIG) -. if ${_LICENSE_STATUS_FROM} == "user" -# XXX fail here -. else -# XXX replace cfg -. endif + +# License compatibility check (XXX is it useful? empty vaules of COMPAT do not +# mean "nothing") + +.if !empty(_LICENSE_COMPAT) || !empty(_LICENSE_INCOMPAT) +. for port in ${RUN_DEPENDS} +_LICENSE_RESULT!= cd ${port} && ${MAKE} -V LICENSE +. for lic in ${_LICENSE_RESULT} +. if (!empty(_LICENSE_COMPAT) && ${LICENSE_COMPAT:M${lic}} == "") || \ + (!empty(_LICENSE_INCOMPAT) && ${LICENSE_INCOMPAT:M${lic}} != "") +IGNORE= depends on ${port:T} that uses license "${lic}" which is incompatible with "${LICENSE}" used by this port +. endif +. endfor +. endfor .endif # Package list entries, and installation -PLIST_FILES+= ${LICENSE_DIR_REL}/${LICENSE_REPORT:T} -PLIST_DIRS+= ${LICENSE_DIR_REL} +PLIST_FILES+= ${_LICENSE_DIR_REL}/${_LICENSE_REPORT:T} +PLIST_DIRS+= ${_LICENSE_DIR_REL} .if defined(LICENSE_FILE) -PLIST_FILES+= ${LICENSE_DIR_REL}/${LICENSE_FILE:T} +PLIST_FILES+= ${_LICENSE_DIR_REL}/${LICENSE_FILE:T} .endif install-license: - @${MKDIR} ${LICENSE_DIR} - @test -f ${LICENSE_FILE} && ${INSTALL_DATA} ${LICENSE_FILE} ${LICENSE_DIR} - @${TRUE} > ${LICENSE_REPORT} + @${MKDIR} ${_LICENSE_DIR} +.if defined(LICENSE_FILE) + @test -f ${LICENSE_FILE} && ${INSTALL_DATA} ${LICENSE_FILE} ${_LICENSE_DIR} +.endif + @${TRUE} > ${_LICENSE_REPORT} . for var in ${_LICENSE_LIST_SAVE_VARS} . if !empty(${var}) - @${ECHO_CMD} '${var}=${${var}}' >> ${LICENSE_REPORT} + @${ECHO_CMD} ${var}=${${var}:C/^[[:blank:]]*//} >> ${_LICENSE_REPORT} . endif . endfor
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808060332.m763WCAi013607>