git: 3d9f300e01f5 - main - Mk/bsd.port.{subdir}.mk: create describe-json

From: Fernando Apesteguía <fernape_at_FreeBSD.org>
Date: Wed, 18 Oct 2023 11:16:56 UTC
The branch main has been updated by fernape:

URL: https://cgit.FreeBSD.org/ports/commit/?id=3d9f300e01f5ecdb140027096c603623264ecc07

commit 3d9f300e01f5ecdb140027096c603623264ecc07
Author:     Fernando Apesteguía <fernape@FreeBSD.org>
AuthorDate: 2023-09-27 15:32:12 +0000
Commit:     Fernando Apesteguía <fernape@FreeBSD.org>
CommitDate: 2023-10-18 11:16:36 +0000

    Mk/bsd.port.{subdir}.mk: create describe-json
    
    Summary:
    Create "describe-json" target to get a JSON-compliant representation of the
    ports tree.
    
    It can be invoked from a single port directory, a category directory or from the
    ports tree top directory.
    
    It supports FLAVORS. E.g. It is possible to execute the following:
    
    cd math/qalculate-qt && make describe-json-qt6
    
    Performance-wise it is equivalent to a simple "make describe" although it
    offers a more complete vision of the port in an easily parseable format.
    
    Times for describe:
         1345.39 real       933.06 user       403.01 sys
         1317.00 real       929.22 user       406.43 sys
         1316.83 real       930.82 user       404.70 sys
         1316.75 real       928.05 user       407.39 sys
         1316.58 real       930.69 user       404.59 sys
    Times for describe-json:
         1320.38 real       924.80 user       414.48 sys
         1320.66 real       926.14 user       413.41 sys
         1320.41 real       924.08 user       415.30 sys
         1320.37 real       922.96 user       416.35 sys
         1320.25 real       924.25 user       414.95 sys
    
    Some examples assuming the output is saved in the `describe.json` file.
    
    Show all ports in the "accessibility" category:
    
    jq '.accessibility' describe.json
    
    Show ports in the "accessibility" category with a USES=iconv dependency:
    
    jq '.accessibility.[] | select(.uses | index("iconv")) | .pkgorigin' describe.json
    
    Show ports in the tree that Uses=kmod:
    
    jq '.[].[] | select(.uses | index("kmod")) | .pkgorigin' describe.json
    
    Show ports having a LIB_DEPENDS on devel/binutils:
    
    jq '.[].[] | select(.lib_depends | map(test("devel/binutils")) | any) | .pkgorigin' describe.json
    
    Show ports in the "database" category which have no maintainer and are marked as
    deprecated:
    
    jq '.databases.[] | select(.maintainer=="ports@FreeBSD.org" and .deprecated!=" ") | .pkgorigin, .deprecated' describe.json
    
    Approved by:            portmgr (bapt@)
    Differential Revision:  https://reviews.freebsd.org/D42131
---
 Mk/bsd.port.mk        | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
 Mk/bsd.port.subdir.mk | 20 ++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/Mk/bsd.port.mk b/Mk/bsd.port.mk
index 4679774d9640..6b3522d559a0 100644
--- a/Mk/bsd.port.mk
+++ b/Mk/bsd.port.mk
@@ -619,6 +619,7 @@ FreeBSD_MAINTAINER=	portmgr@FreeBSD.org
 #				- Create a package for a port and _all_ of its dependencies.
 # describe		- Try to generate a one-line description for each port for
 #				  use in INDEX files and the like.
+# describe-json - Generate a JSON-compliant representation of each port.
 # check-plist		- Checks for files missing from the plist, and files in the plist
 #				  that are not installed by the port.
 # check-sanity		- Perform some basic checks of the port layout.
@@ -4406,6 +4407,78 @@ describe-${f}:
 .      endif # empty(FLAVORS)
 .    endif
 
+.	if empty(FLAVORS) || defined(_DESCRIBE_WITH_FLAVOR)
+
+.		if defined(_DESCRIBE_WITH_FLAVOR)
+_JSON_OBJ_NAME="\"${FLAVOR}-${.CURDIR:T}\":"
+.		endif
+
+describe-json:
+	@(${ECHO_CMD} "${_JSON_OBJ_NAME} { ";\
+	${ECHO_CMD} \"uses\":[\"${USES:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"flavors\":[\"${FLAVORS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"options_default\":[\"${OPTIONS_DEFAULT:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"fetch_depends\":[\"${FETCH_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"extract_depends\":[\"${EXTRACT_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"patch_depends\":[\"${PATCH_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"build_depends\":[\"${BUILD_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"lib_depends\":[\"${LIB_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"run_depends\":[\"${RUN_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"test_depends\":[\"${TEST_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"pkg_depends\":[\"${PKG_DEPENDS:ts,:Q:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"complete_options_list\":[\"${COMPLETE_OPTIONS_LIST:ts,:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"categories\":[\"${CATEGORIES:ts,:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"license\":[\"${LICENSE:ts,:S/,/\",\"/g}\"], ;\
+	${ECHO_CMD} \"deprecated\":\""${DEPRECATED:S/"/\\\"/g:S/\\\\*/*/g:S/\\\'/'/g}" \", ;\
+	${ECHO_CMD} \"broken\":\"${BROKEN:Q:S/"/\\\"/g:S/\\\\*/*/g:S/\\\'/'/g}\", ;\
+	${ECHO_CMD} \"distversion\":\"${DISTVERSION}\", ;\
+	${ECHO_CMD} \"distversionprefix\":\"${DISTVERSIONPREFIX}\", ;\
+	${ECHO_CMD} \"distversionsuffix\":\"${DISTVERSIONSUFFIX}\", ;\
+	${ECHO_CMD} \"expiration_date\":\"${EXPIRATION_DATE}\", ;\
+	${ECHO_CMD} \"flavor\":\"${FLAVOR}\", ;\
+	${ECHO_CMD} \"gh_account\":\"${GH_ACCOUNT}\", ;\
+	${ECHO_CMD} \"gh_project\":\"${GH_PROJECT}\", ;\
+	${ECHO_CMD} \"gh_tagname\":\"${GH_TAGNAME}\", ;\
+	${ECHO_CMD} \"gl_account\":\"${GL_ACCOUNT}\", ;\
+	${ECHO_CMD} \"gl_commit\":\"${GL_COMMIT}\", ;\
+	${ECHO_CMD} \"gl_project\":\"${GL_PROJECT}\", ;\
+	${ECHO_CMD} \"gl_site\":\"${GL_SITE}\", ;\
+	${ECHO_CMD} \"maintainer\":\"${MAINTAINER}\", ;\
+	${ECHO_CMD} \"makefiles\":\"${MAKEFILES}\", ;\
+	${ECHO_CMD} \"pkgbase\":\"${PKGBASE}\", ;\
+	${ECHO_CMD} \"pkgname\":\"${PKGNAME}\", ;\
+	${ECHO_CMD} \"pkgnamesuffix\":\"${PKGNAMESUFFIX}\", ;\
+	${ECHO_CMD} \"pkgorigin\":\"${PKGORIGIN}\", ;\
+	${ECHO_CMD} \"pkg_depends\":\"${PKG_DEPENDS}\", ;\
+	${ECHO_CMD} \"portepoch\":\"${PORTEPOCH}\", ;\
+	${ECHO_CMD} \"portname\":\"${PORTNAME}\", ;\
+	${ECHO_CMD} \"portrevision\":\"${PORTREVISION}\", ;\
+	${ECHO_CMD} \"portversion\":\"${PORTVERSION}\", ;\
+	${ECHO_CMD} \"use_github\":\"${USE_GITHUB}\", ;\
+	${ECHO_CMD} \"use_gitlab\":\"${USE_GITLAB}\", ;\
+	${ECHO_CMD} \"www\":\"${WWW:Q}\" ;\
+	${ECHO_CMD} "}" >> ${INDEX_OUT})
+.	else # empty(FLAVORS)
+describe-json: ${FLAVORS:S/^/describe-json-/}
+_LAST_FLAVOR = ${FLAVORS:[-1]}
+.	for f in ${FLAVORS}
+describe-json-${f}:
+	@if [ "${f}" == "${FLAVORS:[1]}" ]; then \
+		${ECHO_CMD} "{" ;\
+	fi;
+	@cd ${.CURDIR} && ${SETENV} FLAVOR=${f} ${MAKE} -B -D_DESCRIBE_WITH_FLAVOR describe-json
+	@if [ "${f}" != "${_LAST_FLAVOR}" ]; then \
+		${ECHO_MSG} "," ;\
+	else \
+		${ECHO_CMD} "}" ;\
+	fi; \
+
+
+.	endfor
+.	endif # empty(FLAVORS)
+
+
+
 www-site:
 	@${ECHO_CMD} ${_WWW}
 
diff --git a/Mk/bsd.port.subdir.mk b/Mk/bsd.port.subdir.mk
index 724fa4505f53..cc2cc81da01b 100644
--- a/Mk/bsd.port.subdir.mk
+++ b/Mk/bsd.port.subdir.mk
@@ -300,6 +300,26 @@ describe:
 .  endif
 .endif
 
+# Store last subdir name
+_LAST_DIR = ${SUBDIR:[-1]}
+describe-json:
+	@${ECHO_MSG} "{"
+	@for sub in ${SUBDIR}; do \
+	if ${TEST} -d ${.CURDIR}/$${sub}; then \
+		cd ${.CURDIR}/$${sub}; \
+		${ECHO_MSG} "\"$${sub}\": " ;\
+		${MAKE} -B describe-json || \
+			(${ECHO_CMD} "===> ${DIRPRFX}$${sub} failed" >&2; \
+			exit 1) ;\
+		if [ "$${sub}" != "${_LAST_DIR}" ]; then \
+			(${ECHO_MSG} ",") ; \
+		fi; \
+	else \
+		${ECHO_MSG} "===> ${DIRPRFX}$${sub} non-existent"; \
+	fi; \
+	done
+	@${ECHO_MSG} "}"
+
 .if !target(readmes)
 .  if defined(PORTSTOP)
 readmes: readme ${SUBDIR:S/^/_/:S/$/.readmes/}