From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id ANsOAj0komTJegEASxT56A (envelope-from ) for ; Mon, 03 Jul 2023 03:28:29 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id KJ8PAT0komQHyQAAG6o9tA (envelope-from ) for ; Mon, 03 Jul 2023 03:28:29 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 54A4210765 for ; Mon, 3 Jul 2023 03:28:28 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qG8ML-0006tQ-AQ; Sun, 02 Jul 2023 21:28:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qG8MF-0006tB-8I for guix-patches@gnu.org; Sun, 02 Jul 2023 21:28:03 -0400 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qG8ME-0005KO-Ux for guix-patches@gnu.org; Sun, 02 Jul 2023 21:28:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qG8ME-0008DZ-C4 for guix-patches@gnu.org; Sun, 02 Jul 2023 21:28:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#64149] WIP update u-boot to 2023.07-rc5 Resent-From: Vagrant Cascadian Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Mon, 03 Jul 2023 01:28:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 64149 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: To: 64149@debbugs.gnu.org Cc: ludo@gnu.org, efraim@flashner.co.il Received: via spool by 64149-submit@debbugs.gnu.org id=B64149.168834762431525 (code B ref 64149); Mon, 03 Jul 2023 01:28:02 +0000 Received: (at 64149) by debbugs.gnu.org; 3 Jul 2023 01:27:04 +0000 Received: from localhost ([127.0.0.1]:32965 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qG8LF-0008C3-Ho for submit@debbugs.gnu.org; Sun, 02 Jul 2023 21:27:04 -0400 Received: from cascadia.aikidev.net ([173.255.214.101]:43816) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qG8LA-0008Bm-GA for 64149@debbugs.gnu.org; Sun, 02 Jul 2023 21:27:00 -0400 Received: from localhost (unknown [IPv6:2600:3c01:e000:21:7:77:0:50]) (Authenticated sender: vagrant@cascadia.debian.net) by cascadia.aikidev.net (Postfix) with ESMTPSA id 50E831AB17; Sun, 2 Jul 2023 18:26:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=debian.org; s=1.vagrant.user; t=1688347607; bh=SkUTlKL9k5NntEi503tSIhySkscLIa1+B8twXsLN+h8=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=i2rpjRLOGx7mKv8o0vXXtQm61R8n1UhlJdyhliGXcBNoauOTzH4HCRXFO2b2wPcfk XQIdtDwFGvAsMKtEgduTX4AzlflxW5GeBInRdyEbas15hKmE0M52sT2pLEK2CtDky8 qrF7b8PkR4s/q0T6oB9FPFEbbQ0vnzr0gRAn4v3uJKqJzXmg/skGMKKdnVsyHjcWIC yvOjY1iPZ97BMaGihB+t/upg7YfyiPHIcD6j3zvoKa2FuUGw1E1WXriNBu0C9nBRNN QtHhzKZxRP9CLbPbUvZ93aO75Q2WXT10RF5KZAAF1knqOeX59K/0gZh5KohoJ/YW6f z7h/F0EkaPNqQ== From: Vagrant Cascadian In-Reply-To: <87o7ld9mu8.fsf@wireframe> References: <87o7ld9mu8.fsf@wireframe> Date: Sun, 02 Jul 2023 18:26:43 -0700 Message-ID: <87jzvhyecs.fsf@wireframe> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN ARC-Seal: i=1; s=key1; d=yhetil.org; t=1688347708; a=rsa-sha256; cv=none; b=ALyMICXdKpTjKl0qSA7loaLhgtbh9R4kqRxS8hQfO37phAEplQrK7e5THBRWpykms+FreW kmN9RbyNB7UzJOkIwbjvAj3ldA3RSG5nf0NR8sza4UzppvkKQ66vtecsjwKpfOPO9ZKEFF nKscYUtIti0CNyJrLZB72TW8Ymuml2ykSuYtxC3tS38ZHus9GlfTHLXegPQd79HZ3F2g0O mpif+mYKEtJtr/P9N6yOUMg8rSqVNnHU8qev7NWphGd0Ca4+Qvk7GneBxk/ZQcx9P1pQl0 8O6sBXdy5SkaHceSbahh9jUSWhHE7st48XJiZGjRfi9WOasOjnXEZccD22NFcw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=debian.org header.s=1.vagrant.user header.b=i2rpjRLO; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1688347708; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:resent-cc:resent-from:resent-sender: resent-message-id:in-reply-to:in-reply-to:references:references: list-id:list-help:list-unsubscribe:list-subscribe:list-post: dkim-signature; bh=bVUIDt1eLtG18Btf883jdhK+Hci8G13j6BhSgSBgtJ8=; b=pfP8YhN7ohsbZAX4+a75MWOIW+B0T9HAUZFkwoBETe0lbzflBwbjO+izxvmq7ywLC7bTJa QVSvO44TqPz6fjm7iRCbdGE1FcvJtWi9KFF+vTash3HYpS82qqrNn+tfUO2/1yH8E3kz+Y NxQkoUajme2JFrbL4/Dl3eA73k3YH3+ml1n/N952+qkr/09Dp3nHur0NgGI/syVSHJl9NH cmMtEPK5dbPRsGHciam2U7zjCKLhAinGRzX0rM/CxTwT62VxYPL7SpUIPqNM4KkbGz0RCJ dxi/pAHTXwbojnYwaP4Y9qzaPH3AZQ3Myj60XIySM3T3oWC0BRjn0RDd+vslSQ== Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=debian.org header.s=1.vagrant.user header.b=i2rpjRLO; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Scanner: scn0.migadu.com X-Migadu-Spam-Score: -4.96 X-Spam-Score: -4.96 X-Migadu-Queue-Id: 54A4210765 X-TUID: Yvt+BKeNJzrS --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain On 2023-06-18, Vagrant Cascadian wrote: > The attached patch updates u-boot to 2023.07-rc4... though mostly just > getting this patch out there for review purposes, but should probably > wait until 2023.07 is released in July. Alternately, could try to update > to 2023.04, although honestly that version had quite a few issues in > Debian and might be best skipped! This patch updates to 2023.07-rc5. 2023.07 is scheduled for upstream release tomorrow. > Builds most of the u-boot-* packages successfully, notable issues are > with u-boot-tools failing to build, and unable to cross-build > u-boot-puma-rk3399 and u-boot-rockpro64-rk3399 due to the dependency on > python-pyelftools not being cross-buildable ... though > u-boot-pinebook-pro-rk3399 uses python-pyelftools just fine, somehow?! Still similarly broken. > I have not boot-tested anything with this patch. Still have not done this either... > This patch depends on the patch updating python-pyelftools: > > https://issues.guix.gnu.org/64144 > > ...or fixing the failing build of python-pyelftools some other way! Merged that yesterday... > It also would be nice to pull in the updated arm-trusted-firmware: > > https://issues.guix.gnu.org/64142 > > ...although this is not strictly necessary. Still preferred, but not strictly necessary. > It also might be time to make some more noise on the forgotten > crust-firmware patch, as there is a workaround in this patch because > that is missing from guix: > > https://issues.guix.gnu.org/48371 This needs more research, may not be needed with recent arm-trusted-firmware... live well, vagrant --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0002-gnu-u-boot-Update-to-2023.07-rc5.patch Content-Transfer-Encoding: quoted-printable From=209f945a7192989567dee848266ea7023e59202202 Mon Sep 17 00:00:00 2001 From: Vagrant Cascadian Date: Sun, 2 Jul 2023 18:20:39 -0700 Subject: [PATCH 2/2] gnu: u-boot: Update to 2023.07-rc5. * gnu/packages/patches/u-boot-infodocs-target.patch: Remove file. * gnu/packages/patches/u-boot-patman-guix-integration.patch: Remove file. * gnu/local.mk: Remove patches. * gnu/packages/patches/u-boot-allow-disabling-openssl.patch: Refresh. * gnu/packages/patches/u-boot-sifive-prevent-reloc-initrd-fdt.patch: Refres= h. * gnu/packages/bootloaders.scm (u-boot): Update to 2023.07-rc5. [native-inputs]: Add python-pyelftools. [source]: Remove patches. (u-boot-tools): Update substitution for python3-coverage. (make-u-boot-sunxi64-package): Set SCP environment variable. (u-boot-sifive-unleashed): Update to use opensbi. =2D-- gnu/local.mk | 2 - gnu/packages/bootloaders.scm | 28 +- .../u-boot-allow-disabling-openssl.patch | 13 +- .../patches/u-boot-infodocs-target.patch | 84 -- .../u-boot-patman-guix-integration.patch | 1244 ----------------- ...boot-sifive-prevent-reloc-initrd-fdt.patch | 8 +- 6 files changed, 31 insertions(+), 1348 deletions(-) delete mode 100644 gnu/packages/patches/u-boot-infodocs-target.patch delete mode 100644 gnu/packages/patches/u-boot-patman-guix-integration.pat= ch diff --git a/gnu/local.mk b/gnu/local.mk index e65888a044..da9488e14e 100644 =2D-- a/gnu/local.mk +++ b/gnu/local.mk @@ -1996,8 +1996,6 @@ dist_patch_DATA =3D \ %D%/packages/patches/twinkle-bcg729.patch \ %D%/packages/patches/u-boot-allow-disabling-openssl.patch \ %D%/packages/patches/u-boot-fix-build-python-3.10.patch \ =2D %D%/packages/patches/u-boot-infodocs-target.patch \ =2D %D%/packages/patches/u-boot-patman-guix-integration.patch \ %D%/packages/patches/u-boot-nintendo-nes-serial.patch \ %D%/packages/patches/u-boot-rockchip-inno-usb.patch \ %D%/packages/patches/u-boot-sifive-prevent-reloc-initrd-fdt.patch \ diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm index a9685a9ef9..7cf11e5279 100644 =2D-- a/gnu/packages/bootloaders.scm +++ b/gnu/packages/bootloaders.scm @@ -648,23 +648,21 @@ (define %u-boot-rk3399-enable-emmc-phy-patch (define u-boot (package (name "u-boot") =2D (version "2022.10") + (version "2023.07-rc5") (source (origin (patches (list %u-boot-rockchip-inno-usb-patch %u-boot-allow-disabling-openssl-patch %u-boot-sifive-prevent-relocating-initrd-fdt %u-boot-rk3399-enable-emmc-phy-patch =2D (search-patch "u-boot-fix-build-python-3.10.patch") =2D (search-patch "u-boot-infodocs-target.patch") =2D (search-patch "u-boot-patman-guix-integration.patch= "))) + (search-patch "u-boot-fix-build-python-3.10.patch"))) (method url-fetch) (uri (string-append "https://ftp.denx.de/pub/u-boot/" "u-boot-" version ".tar.bz2")) (sha256 (base32 =2D "1y5x8vxdgsqdqlsvq01mn8lmw53fqairkhvhhjx83hjva0m4id2h"))= )) + "06hf8h036p2ij1qa5mh6932cry4hzp739ridr6qckcc3y4dhg3zl")))) (build-system gnu-build-system) (native-inputs (list bison @@ -676,6 +674,7 @@ (define u-boot perl pkg-config ;for 'make menuconfig' python + python-pyelftools swig (list util-linux "lib"))) (home-page "https://www.denx.de/wiki/U-Boot/") @@ -739,7 +738,7 @@ (define-public u-boot-tools (("/bin/false") (which "false"))) (substitute* "tools/dtoc/fdt_util.py" (("'cc'") "'gcc'")) =2D (substitute* "tools/patman/test_util.py" + (substitute* "tools/u_boot_pylib/test_util.py" ;; python3-coverage is simply called coverage in guix. (("python3-coverage") "coverage") =20 @@ -1009,6 +1008,8 @@ (define*-public (make-u-boot-sunxi64-package board tr= iplet #~(modify-phases #$phases (add-after 'unpack 'set-environment (lambda* (#:key native-inputs inputs #:allow-other-keys) + ;; Avoid dependency on crust-firmware https://issues.gui= x.gnu.org/48371 + (setenv "SCP" "/dev/null") (setenv "BL31" (search-input-file inputs "bl31.bin")))))= ))) (inputs (modify-inputs (package-inputs base) @@ -1170,7 +1171,20 @@ (define-public u-boot-sandbox (append sdl2)))))) =20 (define-public u-boot-sifive-unleashed =2D (make-u-boot-package "sifive_unleashed" "riscv64-linux-gnu")) + (let ((base (make-u-boot-package "sifive_unleashed" "riscv64-linux-gnu")= )) + (package + (inherit base) + (arguments + (substitute-keyword-arguments (package-arguments base) + ((#:phases phases) + #~(modify-phases #$phases + (add-after 'unpack 'set-environment + (lambda* (#:key inputs #:allow-other-keys) + (setenv "OPENSBI" (search-input-file inputs + "fw_dynamic.bin")))= ))))) + (inputs + (modify-inputs (package-inputs base) + (append opensbi-generic)))))) =20 (define-public u-boot-sifive-unmatched (let ((base (make-u-boot-package "sifive_unmatched" "riscv64-linux-gnu")= )) diff --git a/gnu/packages/patches/u-boot-allow-disabling-openssl.patch b/gn= u/packages/patches/u-boot-allow-disabling-openssl.patch index 5f2856dbb4..5195a7a6f8 100644 =2D-- a/gnu/packages/patches/u-boot-allow-disabling-openssl.patch +++ b/gnu/packages/patches/u-boot-allow-disabling-openssl.patch @@ -128,29 +128,28 @@ index 94b7685392..eec599b0ee 100644 datai =3D 0; for (cfgi =3D 0; cfgi < cfgn; cfgi++) { e =3D &image_cfg[cfgi]; =2D@@ -1552,9 +1568,11 @@ static void *image_create_v1(size_t *imagesz, str= uct image_tool_params *params, +@@ -1624,10 +1640,12 @@ static void *image_create_v1(size_t *dataoff, stru= ct image_tool_params *params, &datai, delay); } =20=20 +#if defined(CONFIG_KWB_SECURE) =2D if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz + header= sz, =2D headersz, image, secure_hdr)) + if (secure_hdr && add_secure_header_v1(params, ptr + *dataoff, payloadsz, + image, headersz, secure_hdr)) return NULL; +#endif =20=20 =2D *imagesz =3D headersz; + /* Calculate and set the header checksum */ + main_hdr->checksum =3D image_checksum8(main_hdr, headersz); =20=20 --- a/tools/image-host.c +++ b/tools/image-host.c =2D@@ -14,10 +14,12 @@ +@@ -14,8 +14,10 @@ #include #include =20=20 +#ifdef CONFIG_FIT_PRELOAD #include #include =2D=20 =2D #define IMAGE_PRE_LOAD_PATH "/image/pre-loa= d/sig" +#endif =20=20 /** diff --git a/gnu/packages/patches/u-boot-infodocs-target.patch b/gnu/packag= es/patches/u-boot-infodocs-target.patch deleted file mode 100644 index 5b21a99de3..0000000000 =2D-- a/gnu/packages/patches/u-boot-infodocs-target.patch +++ /dev/null @@ -1,84 +0,0 @@ =2DUpstream status: https://patchwork.ozlabs.org/project/uboot/list/?series= =3D333259 =2D =2Ddiff --git a/Makefile b/Makefile =2Dindex de5746399a..597a8886c3 100644 =2D--- a/Makefile =2D+++ b/Makefile =2D@@ -2372,7 +2372,7 @@ tcheck: =2D # Documentation targets =2D # ---------------------------------------------------------------------= ------ =2D DOC_TARGETS :=3D xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \ =2D- linkcheckdocs dochelp refcheckdocs =2D+ linkcheckdocs dochelp refcheckdocs texinfodocs infodocs =2D PHONY +=3D $(DOC_TARGETS) =2D $(DOC_TARGETS): scripts_basic FORCE =2D $(Q)$(MAKE) $(build)=3Ddoc $@ =2Ddiff --git a/doc/Makefile b/doc/Makefile =2Dindex f5de65e927..d0904a9f99 100644 =2D--- a/doc/Makefile =2D+++ b/doc/Makefile =2D@@ -69,6 +69,14 @@ quiet_cmd_sphinx =3D SPHINX $@ --> file://$(abspath = $(BUILDDIR)/$3/$4) =2D htmldocs: =2D @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(va= r))) =2D=20 =2D+texinfodocs: =2D+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,texinfo,$(var),te= xinfo,$(var))) =2D+ =2D+# Note: the 'info' Make target is generated by sphinx itself when =2D+# running the texinfodocs target defined above. =2D+infodocs: texinfodocs =2D+ $(MAKE) -C $(BUILDDIR)/texinfo info =2D+ =2D linkcheckdocs: =2D @$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,= $(var))) =2D=20 =2D@@ -109,6 +117,8 @@ cleandocs: =2D dochelp: =2D @echo ' U-Boot documentation in different formats from ReST:' =2D @echo ' htmldocs - HTML' =2D+ @echo ' texinfodocs - Texinfo' =2D+ @echo ' infodocs - Info' =2D @echo ' latexdocs - LaTeX' =2D @echo ' pdfdocs - PDF' =2D @echo ' epubdocs - EPUB' =2Ddiff --git a/doc/conf.py b/doc/conf.py =2Dindex 62c8d31270..3db70f80c1 100644 =2D--- a/doc/conf.py =2D+++ b/doc/conf.py =2D@@ -449,7 +449,7 @@ for fn in os.listdir('.'): =2D # One entry per manual page. List of tuples =2D # (source start file, name, description, authors, manual section). =2D man_pages =3D [ =2D- (master_doc, 'dasuboot', 'The U-Boot Documentation', =2D+ (master_doc, 'u-boot', 'The U-Boot Documentation', =2D [author], 1) =2D ] =2D=20 =2D@@ -463,8 +463,8 @@ man_pages =3D [ =2D # (source start file, target name, title, author, =2D # dir menu entry, description, category) =2D texinfo_documents =3D [ =2D- (master_doc, 'DasUBoot', 'The U-Boot Documentation', =2D- author, 'DasUBoot', 'One line description of project.', =2D+ (master_doc, 'u-boot', 'The U-Boot Documentation', =2D+ author, 'U-Boot', 'Boot loader for embedded systems', =2D 'Miscellaneous'), =2D ] =2D=20 =2Ddiff --git a/doc/media/Makefile b/doc/media/Makefile =2Dindex b9b43a34c3..9b32258696 100644 =2D--- a/doc/media/Makefile =2D+++ b/doc/media/Makefile =2D@@ -22,10 +22,11 @@ $(BUILDDIR)/linker_lists.h.rst: ${API}/linker_lists.= h ${PARSER} $(SRC_DIR)/linke =2D=20 =2D # Media build rules =2D=20 =2D-.PHONY: all html epub xml latex =2D+.PHONY: all html texinfo epub xml latex =2D=20 =2D all: $(IMGDOT) $(BUILDDIR) ${TARGETS} =2D html: all =2D+texinfo: all =2D epub: all =2D xml: all =2D latex: $(IMGPDF) all diff --git a/gnu/packages/patches/u-boot-patman-guix-integration.patch b/gn= u/packages/patches/u-boot-patman-guix-integration.patch deleted file mode 100644 index 3472656c99..0000000000 =2D-- a/gnu/packages/patches/u-boot-patman-guix-integration.patch +++ /dev/null @@ -1,1244 +0,0 @@ =2DThese changes correspond to commits 9ff7500ace..3154de3dd6 already merge= d to =2Dthe u-boot-dm custodian repo (at =2Dhttps://source.denx.de/u-boot/custodians/u-boot-dm/-/commits/next), sche= duled =2Dto be pulled after the next release. =2D =2Ddiff --git a/tools/patman/__init__.py b/tools/patman/__init__.py =2Dindex c9d3e35052..1b98ec7fee 100644 =2D--- a/tools/patman/__init__.py =2D+++ b/tools/patman/__init__.py =2D@@ -1,6 +1,6 @@ =2D # SPDX-License-Identifier: GPL-2.0+ =2D=20 =2D __all__ =3D ['checkpatch', 'command', 'commit', 'control', 'cros_subpro= cess', =2D- 'func_test', 'get_maintainer', 'gitutil', 'main', 'patchstre= am', =2D+ 'func_test', 'get_maintainer', 'gitutil', '__main__', 'patch= stream', =2D 'project', 'series', 'setup', 'settings', 'terminal', =2D 'test_checkpatch', 'test_util', 'tools', 'tout'] =2Ddiff --git a/tools/patman/main.py b/tools/patman/__main__.py =2Dsimilarity index 89% =2Drename from tools/patman/main.py =2Drename to tools/patman/__main__.py =2Dindex 8067a288ab..749e6348b6 100755 =2D--- a/tools/patman/main.py =2D+++ b/tools/patman/__main__.py =2D@@ -7,6 +7,7 @@ =2D """See README for more information""" =2D=20 =2D from argparse import ArgumentParser =2D+import importlib.resources =2D import os =2D import re =2D import sys =2D@@ -19,6 +20,7 @@ if __name__ =3D=3D "__main__": =2D=20 =2D # Our modules =2D from patman import control =2D+from patman import func_test =2D from patman import gitutil =2D from patman import project =2D from patman import settings =2D@@ -53,7 +55,8 @@ parser.add_argument('-H', '--full-help', action=3D'sto= re_true', dest=3D'full_help', =2D default=3DFalse, help=3D'Display the README file') =2D=20 =2D subparsers =3D parser.add_subparsers(dest=3D'cmd') =2D-send =3D subparsers.add_parser('send') =2D+send =3D subparsers.add_parser( =2D+ 'send', help=3D'Format, check and email patches (default command)') =2D send.add_argument('-i', '--ignore-errors', action=3D'store_true', =2D dest=3D'ignore_errors', default=3DFalse, =2D help=3D'Send patches email even if patch errors are found') =2D@@ -62,6 +65,12 @@ send.add_argument('-l', '--limit-cc', dest=3D'limit',= type=3Dint, default=3DNone, =2D send.add_argument('-m', '--no-maintainers', action=3D'store_false', =2D dest=3D'add_maintainers', default=3DTrue, =2D help=3D"Don't cc the file maintainers automatically") =2D+send.add_argument( =2D+ '--get-maintainer-script', dest=3D'get_maintainer_script', type=3Ds= tr, =2D+ action=3D'store', =2D+ default=3Dos.path.join(gitutil.get_top_level(), 'scripts', =2D+ 'get_maintainer.pl') + ' --norolestats', =2D+ help=3D'File name of the get_maintainer.pl (or compatible) script.') =2D send.add_argument('-n', '--dry-run', action=3D'store_true', dest=3D'dry= _run', =2D default=3DFalse, help=3D"Do a dry run (create but don't email pa= tches)") =2D send.add_argument('-r', '--in-reply-to', type=3Dstr, action=3D'store', =2D@@ -94,9 +103,11 @@ send.add_argument('--smtp-server', type=3Dstr, =2D=20 =2D send.add_argument('patchfiles', nargs=3D'*') =2D=20 =2D-test_parser =3D subparsers.add_parser('test', help=3D'Run tests') =2D-test_parser.add_argument('testname', type=3Dstr, default=3DNone, nargs= =3D'?', =2D- help=3D"Specify the test to run") =2D+# Only add the 'test' action if the test data files are available. =2D+if os.path.exists(func_test.TEST_DATA_DIR): =2D+ test_parser =3D subparsers.add_parser('test', help=3D'Run tests') =2D+ test_parser.add_argument('testname', type=3Dstr, default=3DNone, na= rgs=3D'?', =2D+ help=3D"Specify the test to run") =2D=20 =2D status =3D subparsers.add_parser('status', =2D help=3D'Check status of patches in patch= work') =2D@@ -113,7 +124,7 @@ status.add_argument('-f', '--force', action=3D'store= _true', =2D argv =3D sys.argv[1:] =2D args, rest =3D parser.parse_known_args(argv) =2D if hasattr(args, 'project'): =2D- settings.Setup(gitutil, parser, args.project, '') =2D+ settings.Setup(parser, args.project) =2D args, rest =3D parser.parse_known_args(argv) =2D=20 =2D # If we have a command, it is safe to parse all arguments =2D@@ -160,11 +171,8 @@ elif args.cmd =3D=3D 'send': =2D fd.close() =2D=20 =2D elif args.full_help: =2D- tools.print_full_help( =2D- os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), =2D- 'README.rst') =2D- ) =2D- =2D+ with importlib.resources.path('patman', 'README.rst') as readme: =2D+ tools.print_full_help(str(readme)) =2D else: =2D # If we are not processing tags, no need to warning about bad o= nes =2D if not args.process_tags: =2Ddiff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py =2Dindex d1b902dd96..012c0d895c 100644 =2D--- a/tools/patman/checkpatch.py =2D+++ b/tools/patman/checkpatch.py =2D@@ -211,7 +211,7 @@ def check_patch(fname, verbose=3DFalse, show_types= =3DFalse, use_tree=3DFalse): =2D stdout: Full output of checkpatch =2D """ =2D chk =3D find_check_patch() =2D- args =3D [chk] =2D+ args =3D [chk, '--u-boot', '--strict'] =2D if not use_tree: =2D args.append('--no-tree') =2D if show_types: =2Ddiff --git a/tools/patman/control.py b/tools/patman/control.py =2Dindex bf426cf7bc..38e98dab84 100644 =2D--- a/tools/patman/control.py =2D+++ b/tools/patman/control.py =2D@@ -94,8 +94,8 @@ def check_patches(series, patch_files, run_checkpatch,= verbose, use_tree): =2D=20 =2D=20 =2D def email_patches(col, series, cover_fname, patch_files, process_tags, = its_a_go, =2D- ignore_bad_tags, add_maintainers, limit, dry_run, in_= reply_to, =2D- thread, smtp_server): =2D+ ignore_bad_tags, add_maintainers, get_maintainer_scri= pt, limit, =2D+ dry_run, in_reply_to, thread, smtp_server): =2D """Email patches to the recipients =2D=20 =2D This emails out the patches and cover letter using 'git send-email'= . Each =2D@@ -123,6 +123,8 @@ def email_patches(col, series, cover_fname, patch_fi= les, process_tags, its_a_go, =2D ignore_bad_tags (bool): True to just print a warning for unknow= n tags, =2D False to halt with an error =2D add_maintainers (bool): Run the get_maintainer.pl script for ea= ch patch =2D+ get_maintainer_script (str): The script used to retrieve which =2D+ maintainers to cc =2D limit (int): Limit on the number of people that can be cc'd on = a single =2D patch or the cover letter (None if no limit) =2D dry_run (bool): Don't actually email the patches, just print ou= t what =2D@@ -134,7 +136,7 @@ def email_patches(col, series, cover_fname, patch_fi= les, process_tags, its_a_go, =2D smtp_server (str): SMTP server to use to send patches (None for= default) =2D """ =2D cc_file =3D series.MakeCcFile(process_tags, cover_fname, not ignore= _bad_tags, =2D- add_maintainers, limit) =2D+ add_maintainers, limit, get_maintainer_= script) =2D=20 =2D # Email the patches out (giving the user time to check / cancel) =2D cmd =3D '' =2D@@ -174,8 +176,8 @@ def send(args): =2D email_patches( =2D col, series, cover_fname, patch_files, args.process_tags, =2D its_a_go, args.ignore_bad_tags, args.add_maintainers, =2D- args.limit, args.dry_run, args.in_reply_to, args.thread, =2D- args.smtp_server) =2D+ args.get_maintainer_script, args.limit, args.dry_run, =2D+ args.in_reply_to, args.thread, args.smtp_server) =2D=20 =2D def patchwork_status(branch, count, start, end, dest_branch, force, =2D show_comments, url): =2Ddiff --git a/tools/patman/func_test.py b/tools/patman/func_test.py =2Dindex 7b92bc67be..c25a47bdeb 100644 =2D--- a/tools/patman/func_test.py =2D+++ b/tools/patman/func_test.py =2D@@ -6,7 +6,9 @@ =2D=20 =2D """Functional tests for checking that patman behaves correctly""" =2D=20 =2D+import contextlib =2D import os =2D+import pathlib =2D import re =2D import shutil =2D import sys =2D@@ -28,6 +30,21 @@ from patman.test_util import capture_sys_output =2D import pygit2 =2D from patman import status =2D=20 =2D+PATMAN_DIR =3D pathlib.Path(__file__).parent =2D+TEST_DATA_DIR =3D PATMAN_DIR / 'test/' =2D+ =2D+ =2D+@contextlib.contextmanager =2D+def directory_excursion(directory): =2D+ """Change directory to `directory` for a limited to the context blo= ck.""" =2D+ current =3D os.getcwd() =2D+ try: =2D+ os.chdir(directory) =2D+ yield =2D+ finally: =2D+ os.chdir(current) =2D+ =2D+ =2D class TestFunctional(unittest.TestCase): =2D """Functional tests for checking that patman behaves correctly""" =2D leb =3D (b'Lord Edmund Blackadd\xc3\xabr '. =2D@@ -57,8 +74,7 @@ class TestFunctional(unittest.TestCase): =2D Returns: =2D str: Full path to file in the test directory =2D """ =2D- return os.path.join(os.path.dirname(os.path.realpath(sys.argv[0= ])), =2D- 'test', fname) =2D+ return TEST_DATA_DIR / fname =2D=20 =2D @classmethod =2D def _get_text(cls, fname): =2D@@ -200,6 +216,8 @@ class TestFunctional(unittest.TestCase): =2D text =3D self._get_text('test01.txt') =2D series =3D patchstream.get_metadata_for_test(text) =2D cover_fname, args =3D self._create_patches_for_test(series) =2D+ get_maintainer_script =3D str(pathlib.Path(__file__).parent.par= ent.parent =2D+ / 'get_maintainer.pl') + ' --norole= stats' =2D with capture_sys_output() as out: =2D patchstream.fix_patches(series, args) =2D if cover_fname and series.get('cover'): =2D@@ -207,7 +225,7 @@ class TestFunctional(unittest.TestCase): =2D series.DoChecks() =2D cc_file =3D series.MakeCcFile(process_tags, cover_fname, =2D not ignore_bad_tags, add_mainta= iners, =2D- None) =2D+ None, get_maintainer_script) =2D cmd =3D gitutil.email_patches( =2D series, cover_fname, args, dry_run, not ignore_bad_tags, =2D cc_file, in_reply_to=3Din_reply_to, thread=3DNone) =2D@@ -502,6 +520,37 @@ complicated as possible''') =2D finally: =2D os.chdir(orig_dir) =2D=20 =2D+ def test_custom_get_maintainer_script(self): =2D+ """Validate that a custom get_maintainer script gets used.""" =2D+ self.make_git_tree() =2D+ with directory_excursion(self.gitdir): =2D+ # Setup git. =2D+ os.environ['GIT_CONFIG_GLOBAL'] =3D '/dev/null' =2D+ os.environ['GIT_CONFIG_SYSTEM'] =3D '/dev/null' =2D+ tools.run('git', 'config', 'user.name', 'Dummy') =2D+ tools.run('git', 'config', 'user.email', 'dumdum@dummy.com') =2D+ tools.run('git', 'branch', 'upstream') =2D+ tools.run('git', 'branch', '--set-upstream-to=3Dupstream') =2D+ tools.run('git', 'add', '.') =2D+ tools.run('git', 'commit', '-m', 'new commit') =2D+ =2D+ # Setup patman configuration. =2D+ with open('.patman', 'w', buffering=3D1) as f: =2D+ f.write('[settings]\n' =2D+ 'get_maintainer_script: dummy-script.sh\n' =2D+ 'check_patch: False\n') =2D+ with open('dummy-script.sh', 'w', buffering=3D1) as f: =2D+ f.write('#!/usr/bin/env python\n' =2D+ 'print("hello@there.com")\n') =2D+ os.chmod('dummy-script.sh', 0x555) =2D+ =2D+ # Finally, do the test =2D+ with capture_sys_output(): =2D+ output =3D tools.run(PATMAN_DIR / 'patman', '--dry-run') =2D+ # Assert the email address is part of the dry-run =2D+ # output. =2D+ self.assertIn('hello@there.com', output) =2D+ =2D def test_tags(self): =2D """Test collection of tags in a patchstream""" =2D text =3D '''This is a patch =2Ddiff --git a/tools/patman/get_maintainer.py b/tools/patman/get_maintaine= r.py =2Dindex e1d15ff6ab..f7011be1e4 100644 =2D--- a/tools/patman/get_maintainer.py =2D+++ b/tools/patman/get_maintainer.py =2D@@ -1,48 +1,61 @@ =2D # SPDX-License-Identifier: GPL-2.0+ =2D # Copyright (c) 2012 The Chromium OS Authors. =2D+# Copyright (c) 2022 Maxim Cournoyer =2D # =2D=20 =2D import os =2D+import shlex =2D+import shutil =2D=20 =2D from patman import command =2D+from patman import gitutil =2D=20 =2D-def find_get_maintainer(try_list): =2D- """Look for the get_maintainer.pl script. =2D=20 =2D- Args: =2D- try_list: List of directories to try for the get_maintainer.pl = script =2D+def find_get_maintainer(script_file_name): =2D+ """Try to find where `script_file_name` is. =2D=20 =2D- Returns: =2D- If the script is found we'll return a path to it; else None. =2D+ It searches in PATH and falls back to a path relative to the top =2D+ of the current git repository. =2D """ =2D- # Look in the list =2D- for path in try_list: =2D- fname =3D os.path.join(path, 'get_maintainer.pl') =2D- if os.path.isfile(fname): =2D- return fname =2D+ get_maintainer =3D shutil.which(script_file_name) =2D+ if get_maintainer: =2D+ return get_maintainer =2D+ =2D+ git_relative_script =3D os.path.join(gitutil.get_top_level(), =2D+ script_file_name) =2D+ if os.path.exists(git_relative_script): =2D+ return git_relative_script =2D=20 =2D- return None =2D=20 =2D-def get_maintainer(dir_list, fname, verbose=3DFalse): =2D- """Run get_maintainer.pl on a file if we find it. =2D+def get_maintainer(script_file_name, fname, verbose=3DFalse): =2D+ """Run `script_file_name` on a file. =2D=20 =2D- We look for get_maintainer.pl in the 'scripts' directory at the top= of =2D- git. If we find it we'll run it. If we don't find get_maintainer.= pl =2D- then we fail silently. =2D+ `script_file_name` should be a get_maintainer.pl-like script that =2D+ takes a patch file name as an input and return the email addresses =2D+ of the associated maintainers to standard output, one per line. =2D+ =2D+ If `script_file_name` does not exist we fail silently. =2D=20 =2D Args: =2D- dir_list: List of directories to try for the get_maintainer.pl = script =2D- fname: Path to the patch file to run get_maintainer.pl on. =2D+ script_file_name: The file name of the get_maintainer.pl script =2D+ (or compatible). =2D+ fname: File name of the patch to process with get_maintainer.pl. =2D=20 =2D Returns: =2D A list of email addresses to CC to. =2D """ =2D- get_maintainer =3D find_get_maintainer(dir_list) =2D+ # Expand `script_file_name` into a file name and its arguments, if =2D+ # any. =2D+ cmd_args =3D shlex.split(script_file_name) =2D+ file_name =3D cmd_args[0] =2D+ arguments =3D cmd_args[1:] =2D+ =2D+ get_maintainer =3D find_get_maintainer(file_name) =2D if not get_maintainer: =2D if verbose: =2D print("WARNING: Couldn't find get_maintainer.pl") =2D return [] =2D=20 =2D- stdout =3D command.output(get_maintainer, '--norolestats', fname) =2D+ stdout =3D command.output(get_maintainer, *arguments, fname) =2D lines =3D stdout.splitlines() =2D- return [ x.replace('"', '') for x in lines ] =2D+ return [x.replace('"', '') for x in lines] =2Ddiff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py =2Dindex ceaf2ce150..5e742102c2 100644 =2D--- a/tools/patman/gitutil.py =2D+++ b/tools/patman/gitutil.py =2D@@ -2,21 +2,19 @@ =2D # Copyright (c) 2011 The Chromium OS Authors. =2D # =2D=20 =2D-import re =2D import os =2D-import subprocess =2D import sys =2D=20 =2D from patman import command =2D from patman import settings =2D from patman import terminal =2D-from patman import tools =2D=20 =2D # True to use --no-decorate - we check this in setup() =2D use_no_decorate =3D True =2D=20 =2D+ =2D def log_cmd(commit_range, git_dir=3DNone, oneline=3DFalse, reverse=3DFa= lse, =2D- count=3DNone): =2D+ count=3DNone): =2D """Create a command to perform a 'git log' =2D=20 =2D Args: =2D@@ -49,6 +47,7 @@ def log_cmd(commit_range, git_dir=3DNone, oneline=3DFa= lse, reverse=3DFalse, =2D cmd.append('--') =2D return cmd =2D=20 =2D+ =2D def count_commits_to_branch(branch): =2D """Returns number of commits between HEAD and the tracking branch. =2D=20 =2D@@ -68,13 +67,14 @@ def count_commits_to_branch(branch): =2D rev_range =3D '@{upstream}..' =2D pipe =3D [log_cmd(rev_range, oneline=3DTrue)] =2D result =3D command.run_pipe(pipe, capture=3DTrue, capture_stderr=3D= True, =2D- oneline=3DTrue, raise_on_error=3DFalse) =2D+ oneline=3DTrue, raise_on_error=3DFalse) =2D if result.return_code: =2D raise ValueError('Failed to determine upstream: %s' % =2D result.stderr.strip()) =2D patch_count =3D len(result.stdout.splitlines()) =2D return patch_count =2D=20 =2D+ =2D def name_revision(commit_hash): =2D """Gets the revision name for a commit =2D=20 =2D@@ -91,6 +91,7 @@ def name_revision(commit_hash): =2D name =3D stdout.split(' ')[1].strip() =2D return name =2D=20 =2D+ =2D def guess_upstream(git_dir, branch): =2D """Tries to guess the upstream for a branch =2D=20 =2D@@ -109,7 +110,7 @@ def guess_upstream(git_dir, branch): =2D """ =2D pipe =3D [log_cmd(branch, git_dir=3Dgit_dir, oneline=3DTrue, count= =3D100)] =2D result =3D command.run_pipe(pipe, capture=3DTrue, capture_stderr=3D= True, =2D- raise_on_error=3DFalse) =2D+ raise_on_error=3DFalse) =2D if result.return_code: =2D return None, "Branch '%s' not found" % branch =2D for line in result.stdout.splitlines()[1:]: =2D@@ -121,6 +122,7 @@ def guess_upstream(git_dir, branch): =2D return name, "Guessing upstream as '%s'" % name =2D return None, "Cannot find a suitable upstream for branch '%s'" % br= anch =2D=20 =2D+ =2D def get_upstream(git_dir, branch): =2D """Returns the name of the upstream for a branch =2D=20 =2D@@ -135,10 +137,10 @@ def get_upstream(git_dir, branch): =2D """ =2D try: =2D remote =3D command.output_one_line('git', '--git-dir', git_dir,= 'config', =2D- 'branch.%s.remote' % branch) =2D+ 'branch.%s.remote' % branch) =2D merge =3D command.output_one_line('git', '--git-dir', git_dir, = 'config', =2D- 'branch.%s.merge' % branch) =2D- except: =2D+ 'branch.%s.merge' % branch) =2D+ except Exception: =2D upstream, msg =3D guess_upstream(git_dir, branch) =2D return upstream, msg =2D=20 =2D@@ -149,7 +151,8 @@ def get_upstream(git_dir, branch): =2D return '%s/%s' % (remote, leaf), None =2D else: =2D raise ValueError("Cannot determine upstream branch for branch " =2D- "'%s' remote=3D'%s', merge=3D'%s'" % (branch, remote, m= erge)) =2D+ "'%s' remote=3D'%s', merge=3D'%s'" =2D+ % (branch, remote, merge)) =2D=20 =2D=20 =2D def get_range_in_branch(git_dir, branch, include_upstream=3DFalse): =2D@@ -168,6 +171,7 @@ def get_range_in_branch(git_dir, branch, include_ups= tream=3DFalse): =2D rstr =3D '%s%s..%s' % (upstream, '~' if include_upstream else '', b= ranch) =2D return rstr, msg =2D=20 =2D+ =2D def count_commits_in_range(git_dir, range_expr): =2D """Returns the number of commits in the given range. =2D=20 =2D@@ -180,12 +184,13 @@ def count_commits_in_range(git_dir, range_expr): =2D """ =2D pipe =3D [log_cmd(range_expr, git_dir=3Dgit_dir, oneline=3DTrue)] =2D result =3D command.run_pipe(pipe, capture=3DTrue, capture_stderr=3D= True, =2D- raise_on_error=3DFalse) =2D+ raise_on_error=3DFalse) =2D if result.return_code: =2D return None, "Range '%s' not found or is invalid" % range_expr =2D patch_count =3D len(result.stdout.splitlines()) =2D return patch_count, None =2D=20 =2D+ =2D def count_commits_in_branch(git_dir, branch, include_upstream=3DFalse): =2D """Returns the number of commits in the given branch. =2D=20 =2D@@ -201,6 +206,7 @@ def count_commits_in_branch(git_dir, branch, include= _upstream=3DFalse): =2D return None, msg =2D return count_commits_in_range(git_dir, range_expr) =2D=20 =2D+ =2D def count_commits(commit_range): =2D """Returns the number of commits in the given range. =2D=20 =2D@@ -215,6 +221,7 @@ def count_commits(commit_range): =2D patch_count =3D int(stdout) =2D return patch_count =2D=20 =2D+ =2D def checkout(commit_hash, git_dir=3DNone, work_tree=3DNone, force=3DFal= se): =2D """Checkout the selected commit for this build =2D=20 =2D@@ -231,10 +238,11 @@ def checkout(commit_hash, git_dir=3DNone, work_tre= e=3DNone, force=3DFalse): =2D pipe.append('-f') =2D pipe.append(commit_hash) =2D result =3D command.run_pipe([pipe], capture=3DTrue, raise_on_error= =3DFalse, =2D- capture_stderr=3DTrue) =2D+ capture_stderr=3DTrue) =2D if result.return_code !=3D 0: =2D raise OSError('git checkout (%s): %s' % (pipe, result.stderr)) =2D=20 =2D+ =2D def clone(git_dir, output_dir): =2D """Checkout the selected commit for this build =2D=20 =2D@@ -243,10 +251,11 @@ def clone(git_dir, output_dir): =2D """ =2D pipe =3D ['git', 'clone', git_dir, '.'] =2D result =3D command.run_pipe([pipe], capture=3DTrue, cwd=3Doutput_di= r, =2D- capture_stderr=3DTrue) =2D+ capture_stderr=3DTrue) =2D if result.return_code !=3D 0: =2D raise OSError('git clone: %s' % result.stderr) =2D=20 =2D+ =2D def fetch(git_dir=3DNone, work_tree=3DNone): =2D """Fetch from the origin repo =2D=20 =2D@@ -263,6 +272,7 @@ def fetch(git_dir=3DNone, work_tree=3DNone): =2D if result.return_code !=3D 0: =2D raise OSError('git fetch: %s' % result.stderr) =2D=20 =2D+ =2D def check_worktree_is_available(git_dir): =2D """Check if git-worktree functionality is available =2D=20 =2D@@ -274,9 +284,10 @@ def check_worktree_is_available(git_dir): =2D """ =2D pipe =3D ['git', '--git-dir', git_dir, 'worktree', 'list'] =2D result =3D command.run_pipe([pipe], capture=3DTrue, capture_stderr= =3DTrue, =2D- raise_on_error=3DFalse) =2D+ raise_on_error=3DFalse) =2D return result.return_code =3D=3D 0 =2D=20 =2D+ =2D def add_worktree(git_dir, output_dir, commit_hash=3DNone): =2D """Create and checkout a new git worktree for this build =2D=20 =2D@@ -290,10 +301,11 @@ def add_worktree(git_dir, output_dir, commit_hash= =3DNone): =2D if commit_hash: =2D pipe.append(commit_hash) =2D result =3D command.run_pipe([pipe], capture=3DTrue, cwd=3Doutput_di= r, =2D- capture_stderr=3DTrue) =2D+ capture_stderr=3DTrue) =2D if result.return_code !=3D 0: =2D raise OSError('git worktree add: %s' % result.stderr) =2D=20 =2D+ =2D def prune_worktrees(git_dir): =2D """Remove administrative files for deleted worktrees =2D=20 =2D@@ -305,7 +317,8 @@ def prune_worktrees(git_dir): =2D if result.return_code !=3D 0: =2D raise OSError('git worktree prune: %s' % result.stderr) =2D=20 =2D-def create_patches(branch, start, count, ignore_binary, series, signoff= =3D True): =2D+ =2D+def create_patches(branch, start, count, ignore_binary, series, signoff= =3DTrue): =2D """Create a series of patches from the top of the current branch. =2D=20 =2D The patch files are written to the current directory using =2D@@ -321,9 +334,7 @@ def create_patches(branch, start, count, ignore_bina= ry, series, signoff =3D True): =2D Filename of cover letter (None if none) =2D List of filenames of patch files =2D """ =2D- if series.get('version'): =2D- version =3D '%s ' % series['version'] =2D- cmd =3D ['git', 'format-patch', '-M' ] =2D+ cmd =3D ['git', 'format-patch', '-M'] =2D if signoff: =2D cmd.append('--signoff') =2D if ignore_binary: =2D@@ -341,9 +352,10 @@ def create_patches(branch, start, count, ignore_bin= ary, series, signoff =3D True): =2D=20 =2D # We have an extra file if there is a cover letter =2D if series.get('cover'): =2D- return files[0], files[1:] =2D+ return files[0], files[1:] =2D else: =2D- return None, files =2D+ return None, files =2D+ =2D=20 =2D def build_email_list(in_list, tag=3DNone, alias=3DNone, warn_on_error= =3DTrue): =2D """Build a list of email addresses based on an input list. =2D@@ -385,40 +397,43 @@ def build_email_list(in_list, tag=3DNone, alias=3D= None, warn_on_error=3DTrue): =2D raw +=3D lookup_email(item, alias, warn_on_error=3Dwarn_on_erro= r) =2D result =3D [] =2D for item in raw: =2D- if not item in result: =2D+ if item not in result: =2D result.append(item) =2D if tag: =2D return ['%s %s%s%s' % (tag, quote, email, quote) for email in r= esult] =2D return result =2D=20 =2D+ =2D def check_suppress_cc_config(): =2D """Check if sendemail.suppresscc is configured correctly. =2D=20 =2D Returns: =2D True if the option is configured correctly, False otherwise. =2D """ =2D- suppresscc =3D command.output_one_line('git', 'config', 'sendemail.= suppresscc', =2D- raise_on_error=3DFalse) =2D+ suppresscc =3D command.output_one_line( =2D+ 'git', 'config', 'sendemail.suppresscc', raise_on_error=3DFalse) =2D=20 =2D # Other settings should be fine. =2D if suppresscc =3D=3D 'all' or suppresscc =3D=3D 'cccmd': =2D col =3D terminal.Color() =2D=20 =2D print((col.build(col.RED, "error") + =2D- ": git config sendemail.suppresscc set to %s\n" % (suppres= scc)) + =2D- " patman needs --cc-cmd to be run to set the cc list.\n" + =2D- " Please run:\n" + =2D- " git config --unset sendemail.suppresscc\n" + =2D- " Or read the man page:\n" + =2D- " git send-email --help\n" + =2D- " and set an option that runs --cc-cmd\n") =2D+ ": git config sendemail.suppresscc set to %s\n" =2D+ % (suppresscc)) + =2D+ " patman needs --cc-cmd to be run to set the cc list.\n"= + =2D+ " Please run:\n" + =2D+ " git config --unset sendemail.suppresscc\n" + =2D+ " Or read the man page:\n" + =2D+ " git send-email --help\n" + =2D+ " and set an option that runs --cc-cmd\n") =2D return False =2D=20 =2D return True =2D=20 =2D+ =2D def email_patches(series, cover_fname, args, dry_run, warn_on_error, cc= _fname, =2D- self_only=3DFalse, alias=3DNone, in_reply_to=3DNone, thread=3DF= alse, =2D- smtp_server=3DNone): =2D+ self_only=3DFalse, alias=3DNone, in_reply_to=3DNone, = thread=3DFalse, =2D+ smtp_server=3DNone, get_maintainer_script=3DNone): =2D """Email a patch series. =2D=20 =2D Args: =2D@@ -435,6 +450,7 @@ def email_patches(series, cover_fname, args, dry_run= , warn_on_error, cc_fname, =2D thread: True to add --thread to git send-email (make =2D all patches reply to cover-letter or first patch in series) =2D smtp_server: SMTP server to use to send patches =2D+ get_maintainer_script: File name of script to get maintainers e= mails =2D=20 =2D Returns: =2D Git command that was/would be run =2D@@ -487,9 +503,10 @@ send --cc-cmd cc-fname" cover p1 p2' =2D "git config sendemail.to u-boot@lists.denx.de") =2D return =2D cc =3D build_email_list(list(set(series.get('cc')) - set(series.get= ('to'))), =2D- '--cc', alias, warn_on_error) =2D+ '--cc', alias, warn_on_error) =2D if self_only: =2D- to =3D build_email_list([os.getenv('USER')], '--to', alias, war= n_on_error) =2D+ to =3D build_email_list([os.getenv('USER')], '--to', =2D+ alias, warn_on_error) =2D cc =3D [] =2D cmd =3D ['git', 'send-email', '--annotate'] =2D if smtp_server: =2D@@ -565,7 +582,7 @@ def lookup_email(lookup_name, alias=3DNone, warn_on_= error=3DTrue, level=3D0): =2D if not alias: =2D alias =3D settings.alias =2D lookup_name =3D lookup_name.strip() =2D- if '@' in lookup_name: # Perhaps a real email address =2D+ if '@' in lookup_name: # Perhaps a real email address =2D return [lookup_name] =2D=20 =2D lookup_name =3D lookup_name.lower() =2D@@ -581,7 +598,7 @@ def lookup_email(lookup_name, alias=3DNone, warn_on_= error=3DTrue, level=3D0): =2D return out_list =2D=20 =2D if lookup_name: =2D- if not lookup_name in alias: =2D+ if lookup_name not in alias: =2D msg =3D "Alias '%s' not found" % lookup_name =2D if warn_on_error: =2D print(col.build(col.RED, msg)) =2D@@ -589,11 +606,12 @@ def lookup_email(lookup_name, alias=3DNone, warn_o= n_error=3DTrue, level=3D0): =2D for item in alias[lookup_name]: =2D todo =3D lookup_email(item, alias, warn_on_error, level + 1) =2D for new_item in todo: =2D- if not new_item in out_list: =2D+ if new_item not in out_list: =2D out_list.append(new_item) =2D=20 =2D return out_list =2D=20 =2D+ =2D def get_top_level(): =2D """Return name of top-level directory for this git repo. =2D=20 =2D@@ -608,6 +626,7 @@ def get_top_level(): =2D """ =2D return command.output_one_line('git', 'rev-parse', '--show-toplevel= ') =2D=20 =2D+ =2D def get_alias_file(): =2D """Gets the name of the git alias file. =2D=20 =2D@@ -615,7 +634,7 @@ def get_alias_file(): =2D Filename of git alias file, or None if none =2D """ =2D fname =3D command.output_one_line('git', 'config', 'sendemail.alias= esfile', =2D- raise_on_error=3DFalse) =2D+ raise_on_error=3DFalse) =2D if not fname: =2D return None =2D=20 =2D@@ -625,6 +644,7 @@ def get_alias_file(): =2D=20 =2D return os.path.join(get_top_level(), fname) =2D=20 =2D+ =2D def get_default_user_name(): =2D """Gets the user.name from .gitconfig file. =2D=20 =2D@@ -634,6 +654,7 @@ def get_default_user_name(): =2D uname =3D command.output_one_line('git', 'config', '--global', 'use= r.name') =2D return uname =2D=20 =2D+ =2D def get_default_user_email(): =2D """Gets the user.email from the global .gitconfig file. =2D=20 =2D@@ -643,17 +664,19 @@ def get_default_user_email(): =2D uemail =3D command.output_one_line('git', 'config', '--global', 'us= er.email') =2D return uemail =2D=20 =2D+ =2D def get_default_subject_prefix(): =2D """Gets the format.subjectprefix from local .git/config file. =2D=20 =2D Returns: =2D Subject prefix found in local .git/config file, or None if none =2D """ =2D- sub_prefix =3D command.output_one_line('git', 'config', 'format.sub= jectprefix', =2D- raise_on_error=3DFalse) =2D+ sub_prefix =3D command.output_one_line( =2D+ 'git', 'config', 'format.subjectprefix', raise_on_error=3DFalse) =2D=20 =2D return sub_prefix =2D=20 =2D+ =2D def setup(): =2D """Set up git utils, by reading the alias files.""" =2D # Check for a git alias file also =2D@@ -666,6 +689,7 @@ def setup(): =2D use_no_decorate =3D (command.run_pipe([cmd], raise_on_error=3DFalse) =2D .return_code =3D=3D 0) =2D=20 =2D+ =2D def get_head(): =2D """Get the hash of the current HEAD =2D=20 =2D@@ -674,6 +698,7 @@ def get_head(): =2D """ =2D return command.output_one_line('git', 'show', '-s', '--pretty=3Dfor= mat:%H') =2D=20 =2D+ =2D if __name__ =3D=3D "__main__": =2D import doctest =2D=20 =2Ddiff --git a/tools/patman/patman b/tools/patman/patman =2Dindex 11a5d8e18a..5a427d1942 120000 =2D--- a/tools/patman/patman =2D+++ b/tools/patman/patman =2D@@ -1 +1 @@ =2D-main.py =2D\ No newline at end of file =2D+__main__.py =2D\ No newline at end of file =2Ddiff --git a/tools/patman/patman.rst b/tools/patman/patman.rst =2Dindex 8c5c9cc2cc..6113962fb4 100644 =2D--- a/tools/patman/patman.rst =2D+++ b/tools/patman/patman.rst =2D@@ -1,6 +1,7 @@ =2D .. SPDX-License-Identifier: GPL-2.0+ =2D .. Copyright (c) 2011 The Chromium OS Authors =2D .. Simon Glass =2D+.. Maxim Cournoyer =2D .. v1, v2, 19-Oct-11 =2D .. revised v3 24-Nov-11 =2D .. revised v4 Independence Day 2020, with Patchwork integration =2D@@ -68,13 +69,28 @@ this once:: =2D=20 =2D git config sendemail.aliasesfile doc/git-mailrc =2D=20 =2D-For both Linux and U-Boot the 'scripts/get_maintainer.pl' handles figur= ing =2D-out where to send patches pretty well. =2D+For both Linux and U-Boot the 'scripts/get_maintainer.pl' handles =2D+figuring out where to send patches pretty well. For other projects, =2D+you may want to specify a different script to be run, for example via =2D+a project-specific `.patman` file:: =2D+ =2D+ # .patman configuration file at the root of some project =2D+ =2D+ [settings] =2D+ get_maintainer_script: etc/teams.scm get-maintainer =2D+ =2D+The `get_maintainer_script` option corresponds to the =2D+`--get-maintainer-script` argument of the `send` command. It is =2D+looked relatively to the root of the current git repository, as well =2D+as on PATH. It can also be provided arguments, as shown above. The =2D+contract is that the script should accept a patch file name and return =2D+a list of email addresses, one per line, like `get_maintainer.pl` =2D+does. =2D=20 =2D During the first run patman creates a config file for you by taking the= default =2D user name and email address from the global .gitconfig file. =2D=20 =2D-To add your own, create a file ~/.patman like this:: =2D+To add your own, create a file `~/.patman` like this:: =2D=20 =2D # patman alias file =2D=20 =2D@@ -85,6 +101,12 @@ To add your own, create a file ~/.patman like this:: =2D wolfgang: Wolfgang Denk =2D others: Mike Frysinger , Fred Bloggs =2D=20 =2D+As hinted above, Patman will also look for a `.patman` configuration =2D+file at the root of the current project git repository, which makes it =2D+possible to override the `project` settings variable or anything else =2D+in a project-specific way. The values of this "local" configuration =2D+file take precedence over those of the "global" one. =2D+ =2D Aliases are recursive. =2D=20 =2D The checkpatch.pl in the U-Boot tools/ subdirectory will be located and =2D@@ -680,6 +702,16 @@ them: =2D=20 =2D $ tools/patman/patman test =2D=20 =2D+Note that since the test suite depends on data files only available in =2D+the git checkout, the `test` command is hidden unless `patman` is =2D+invoked from the U-Boot git repository. =2D+ =2D+Alternatively, you can run the test suite via Pytest: =2D+ =2D+.. code-block:: bash =2D+ =2D+ $ cd tools/patman && pytest =2D+ =2D Error handling doesn't always produce friendly error messages - e.g. =2D putting an incorrect tag in a commit may provide a confusing message. =2D=20 =2Ddiff --git a/tools/patman/pytest.ini b/tools/patman/pytest.ini =2Dnew file mode 100644 =2Dindex 0000000000..df3eb518d0 =2D--- /dev/null =2D+++ b/tools/patman/pytest.ini =2D@@ -0,0 +1,2 @@ =2D+[pytest] =2D+addopts =3D --doctest-modules =2Ddiff --git a/tools/patman/series.py b/tools/patman/series.py =2Dindex 3075378ac1..2eeeef71dc 100644 =2D--- a/tools/patman/series.py =2D+++ b/tools/patman/series.py =2D@@ -235,7 +235,7 @@ class Series(dict): =2D print(col.build(col.RED, str)) =2D=20 =2D def MakeCcFile(self, process_tags, cover_fname, warn_on_error, =2D- add_maintainers, limit): =2D+ add_maintainers, limit, get_maintainer_script): =2D """Make a cc file for us to use for per-commit Cc automation =2D=20 =2D Also stores in self._generated_cc to make ShowActions() faster. =2D@@ -249,6 +249,8 @@ class Series(dict): =2D True/False to call the get_maintainers to CC maintainers =2D List of maintainers to include (for testing) =2D limit: Limit the length of the Cc list (None if no limit) =2D+ get_maintainer_script: The file name of the get_maintainer.= pl =2D+ script (or compatible). =2D Return: =2D Filename of temp file created =2D """ =2D@@ -267,8 +269,9 @@ class Series(dict): =2D if type(add_maintainers) =3D=3D type(cc): =2D cc +=3D add_maintainers =2D elif add_maintainers: =2D- dir_list =3D [os.path.join(gitutil.get_top_level(), 'sc= ripts')] =2D- cc +=3D get_maintainer.get_maintainer(dir_list, commit.= patch) =2D+ =2D+ cc +=3D get_maintainer.get_maintainer(get_maintainer_sc= ript, =2D+ commit.patch) =2D for x in set(cc) & set(settings.bounces): =2D print(col.build(col.YELLOW, 'Skipping "%s"' % x)) =2D cc =3D list(set(cc) - set(settings.bounces)) =2Ddiff --git a/tools/patman/settings.py b/tools/patman/settings.py =2Dindex 903d6fcb0b..636983e32d 100644 =2D--- a/tools/patman/settings.py =2D+++ b/tools/patman/settings.py =2D@@ -1,18 +1,18 @@ =2D # SPDX-License-Identifier: GPL-2.0+ =2D # Copyright (c) 2011 The Chromium OS Authors. =2D+# Copyright (c) 2022 Maxim Cournoyer =2D # =2D=20 =2D try: =2D import configparser as ConfigParser =2D-except: =2D+except Exception: =2D import ConfigParser =2D=20 =2D import argparse =2D import os =2D import re =2D=20 =2D-from patman import command =2D-from patman import tools =2D+from patman import gitutil =2D=20 =2D """Default settings per-project. =2D=20 =2D@@ -32,7 +32,8 @@ _default_settings =3D { =2D }, =2D } =2D=20 =2D-class _ProjectConfigParser(ConfigParser.SafeConfigParser): =2D+ =2D+class _ProjectConfigParser(ConfigParser.ConfigParser): =2D """ConfigParser that handles projects. =2D=20 =2D There are two main goals of this class: =2D@@ -83,14 +84,14 @@ class _ProjectConfigParser(ConfigParser.SafeConfigPa= rser): =2D def __init__(self, project_name): =2D """Construct _ProjectConfigParser. =2D=20 =2D- In addition to standard SafeConfigParser initialization, this a= lso loads =2D- project defaults. =2D+ In addition to standard ConfigParser initialization, this also =2D+ loads project defaults. =2D=20 =2D Args: =2D project_name: The name of the project. =2D """ =2D self._project_name =3D project_name =2D- ConfigParser.SafeConfigParser.__init__(self) =2D+ ConfigParser.ConfigParser.__init__(self) =2D=20 =2D # Update the project settings in the config based on =2D # the _default_settings global. =2D@@ -102,31 +103,31 @@ class _ProjectConfigParser(ConfigParser.SafeConfig= Parser): =2D self.set(project_settings, setting_name, setting_value) =2D=20 =2D def get(self, section, option, *args, **kwargs): =2D- """Extend SafeConfigParser to try project_section before sectio= n. =2D+ """Extend ConfigParser to try project_section before section. =2D=20 =2D Args: =2D- See SafeConfigParser. =2D+ See ConfigParser. =2D Returns: =2D- See SafeConfigParser. =2D+ See ConfigParser. =2D """ =2D try: =2D- val =3D ConfigParser.SafeConfigParser.get( =2D+ val =3D ConfigParser.ConfigParser.get( =2D self, "%s_%s" % (self._project_name, section), option, =2D *args, **kwargs =2D ) =2D except (ConfigParser.NoSectionError, ConfigParser.NoOptionError= ): =2D- val =3D ConfigParser.SafeConfigParser.get( =2D+ val =3D ConfigParser.ConfigParser.get( =2D self, section, option, *args, **kwargs =2D ) =2D return val =2D=20 =2D def items(self, section, *args, **kwargs): =2D- """Extend SafeConfigParser to add project_section to section. =2D+ """Extend ConfigParser to add project_section to section. =2D=20 =2D Args: =2D- See SafeConfigParser. =2D+ See ConfigParser. =2D Returns: =2D- See SafeConfigParser. =2D+ See ConfigParser. =2D """ =2D project_items =3D [] =2D has_project_section =3D False =2D@@ -134,7 +135,7 @@ class _ProjectConfigParser(ConfigParser.SafeConfigPa= rser): =2D=20 =2D # Get items from the project section =2D try: =2D- project_items =3D ConfigParser.SafeConfigParser.items( =2D+ project_items =3D ConfigParser.ConfigParser.items( =2D self, "%s_%s" % (self._project_name, section), *args, *= *kwargs =2D ) =2D has_project_section =3D True =2D@@ -143,7 +144,7 @@ class _ProjectConfigParser(ConfigParser.SafeConfigPa= rser): =2D=20 =2D # Get top-level items =2D try: =2D- top_items =3D ConfigParser.SafeConfigParser.items( =2D+ top_items =3D ConfigParser.ConfigParser.items( =2D self, section, *args, **kwargs =2D ) =2D except ConfigParser.NoSectionError: =2D@@ -155,6 +156,7 @@ class _ProjectConfigParser(ConfigParser.SafeConfigPa= rser): =2D item_dict.update(project_items) =2D return {(item, val) for item, val in item_dict.items()} =2D=20 =2D+ =2D def ReadGitAliases(fname): =2D """Read a git alias file. This is in the form used by git: =2D=20 =2D@@ -170,7 +172,7 @@ def ReadGitAliases(fname): =2D print("Warning: Cannot find alias file '%s'" % fname) =2D return =2D=20 =2D- re_line =3D re.compile('alias\s+(\S+)\s+(.*)') =2D+ re_line =3D re.compile(r'alias\s+(\S+)\s+(.*)') =2D for line in fd.readlines(): =2D line =3D line.strip() =2D if not line or line[0] =3D=3D '#': =2D@@ -190,7 +192,8 @@ def ReadGitAliases(fname): =2D=20 =2D fd.close() =2D=20 =2D-def CreatePatmanConfigFile(gitutil, config_fname): =2D+ =2D+def CreatePatmanConfigFile(config_fname): =2D """Creates a config file under $(HOME)/.patman if it can't find one. =2D=20 =2D Args: =2D@@ -200,12 +203,12 @@ def CreatePatmanConfigFile(gitutil, config_fname): =2D None =2D """ =2D name =3D gitutil.get_default_user_name() =2D- if name =3D=3D None: =2D+ if name is None: =2D name =3D input("Enter name: ") =2D=20 =2D email =3D gitutil.get_default_user_email() =2D=20 =2D- if email =3D=3D None: =2D+ if email is None: =2D email =3D input("Enter email: ") =2D=20 =2D try: =2D@@ -220,7 +223,8 @@ me: %s <%s> =2D [bounces] =2D nxp =3D Zhikang Zhang =2D ''' % (name, email), file=3Df) =2D- f.close(); =2D+ f.close() =2D+ =2D=20 =2D def _UpdateDefaults(main_parser, config): =2D """Update the given OptionParser defaults based on config. =2D@@ -242,8 +246,8 @@ def _UpdateDefaults(main_parser, config): =2D # Find all the parsers and subparsers =2D parsers =3D [main_parser] =2D parsers +=3D [subparser for action in main_parser._actions =2D- if isinstance(action, argparse._SubParsersAction) =2D- for _, subparser in action.choices.items()] =2D+ if isinstance(action, argparse._SubParsersAction) =2D+ for _, subparser in action.choices.items()] =2D=20 =2D # Collect the defaults from each parser =2D defaults =3D {} =2D@@ -270,8 +274,9 @@ def _UpdateDefaults(main_parser, config): =2D # Set all the defaults and manually propagate them to subparsers =2D main_parser.set_defaults(**defaults) =2D for parser, pdefs in zip(parsers, parser_defaults): =2D- parser.set_defaults(**{ k: v for k, v in defaults.items() =2D- if k in pdefs }) =2D+ parser.set_defaults(**{k: v for k, v in defaults.items() =2D+ if k in pdefs}) =2D+ =2D=20 =2D def _ReadAliasFile(fname): =2D """Read in the U-Boot git alias file if it exists. =2D@@ -298,6 +303,7 @@ def _ReadAliasFile(fname): =2D if bad_line: =2D print(bad_line) =2D=20 =2D+ =2D def _ReadBouncesFile(fname): =2D """Read in the bounces file if it exists =2D=20 =2D@@ -311,6 +317,7 @@ def _ReadBouncesFile(fname): =2D continue =2D bounces.add(line.strip()) =2D=20 =2D+ =2D def GetItems(config, section): =2D """Get the items from a section of the config. =2D=20 =2D@@ -323,31 +330,50 @@ def GetItems(config, section): =2D """ =2D try: =2D return config.items(section) =2D- except ConfigParser.NoSectionError as e: =2D+ except ConfigParser.NoSectionError: =2D return [] =2D- except: =2D- raise =2D=20 =2D-def Setup(gitutil, parser, project_name, config_fname=3D''): =2D+ =2D+def Setup(parser, project_name, config_fname=3DNone): =2D """Set up the settings module by reading config files. =2D=20 =2D+ Unless `config_fname` is specified, a `.patman` config file local =2D+ to the git repository is consulted, followed by the global =2D+ `$HOME/.patman`. If none exists, the later is created. Values =2D+ defined in the local config file take precedence over those =2D+ defined in the global one. =2D+ =2D Args: =2D- parser: The parser to update =2D+ parser: The parser to update. =2D project_name: Name of project that we're working on; we'll lo= ok =2D for sections named "project_section" as well. =2D- config_fname: Config filename to read ('' for default) =2D+ config_fname: Config filename to read. An error is raised if= it =2D+ does not exist. =2D """ =2D # First read the git alias file if available =2D _ReadAliasFile('doc/git-mailrc') =2D config =3D _ProjectConfigParser(project_name) =2D- if config_fname =3D=3D '': =2D+ =2D+ if config_fname and not os.path.exists(config_fname): =2D+ raise Exception(f'provided {config_fname} does not exist') =2D+ =2D+ if not config_fname: =2D config_fname =3D '%s/.patman' % os.getenv('HOME') =2D+ has_config =3D os.path.exists(config_fname) =2D+ =2D+ git_local_config_fname =3D os.path.join(gitutil.get_top_level(), '.= patman') =2D+ has_git_local_config =3D os.path.exists(git_local_config_fname) =2D=20 =2D- if not os.path.exists(config_fname): =2D- print("No config file found ~/.patman\nCreating one...\n") =2D- CreatePatmanConfigFile(gitutil, config_fname) =2D+ # Read the git local config last, so that its values override =2D+ # those of the global config, if any. =2D+ if has_config: =2D+ config.read(config_fname) =2D+ if has_git_local_config: =2D+ config.read(git_local_config_fname) =2D=20 =2D- config.read(config_fname) =2D+ if not (has_config or has_git_local_config): =2D+ print("No config file found.\nCreating ~/.patman...\n") =2D+ CreatePatmanConfigFile(config_fname) =2D=20 =2D for name, value in GetItems(config, 'alias'): =2D alias[name] =3D value.split(',') =2D@@ -358,6 +384,7 @@ def Setup(gitutil, parser, project_name, config_fnam= e=3D''): =2D=20 =2D _UpdateDefaults(parser, config) =2D=20 =2D+ =2D # These are the aliases we understand, indexed by alias. Each member is= a list. =2D alias =3D {} =2D bounces =3D set() =2Ddiff --git a/tools/patman/setup.py b/tools/patman/setup.py =2Dindex 5643bf1503..2ff791da0f 100644 =2D--- a/tools/patman/setup.py =2D+++ b/tools/patman/setup.py =2D@@ -7,6 +7,6 @@ setup(name=3D'patman', =2D scripts=3D['patman'], =2D packages=3D['patman'], =2D package_dir=3D{'patman': ''}, =2D- package_data=3D{'patman': ['README']}, =2D+ package_data=3D{'patman': ['README.rst']}, =2D classifiers=3D['Environment :: Console', =2D 'Topic :: Software Development']) =2Ddiff --git a/tools/patman/test_settings.py b/tools/patman/test_settings.= py =2Dnew file mode 100644 =2Dindex 0000000000..c768a2fc64 =2D--- /dev/null =2D+++ b/tools/patman/test_settings.py =2D@@ -0,0 +1,67 @@ =2D+# SPDX-License-Identifier: GPL-2.0+ =2D+# =2D+# Copyright (c) 2022 Maxim Cournoyer =2D+# =2D+ =2D+import argparse =2D+import contextlib =2D+import os =2D+import sys =2D+import tempfile =2D+ =2D+from patman import settings =2D+from patman import tools =2D+ =2D+ =2D+@contextlib.contextmanager =2D+def empty_git_repository(): =2D+ with tempfile.TemporaryDirectory() as tmpdir: =2D+ os.chdir(tmpdir) =2D+ tools.run('git', 'init', raise_on_error=3DTrue) =2D+ yield tmpdir =2D+ =2D+ =2D+@contextlib.contextmanager =2D+def cleared_command_line_args(): =2D+ old_value =3D sys.argv[:] =2D+ sys.argv =3D [sys.argv[0]] =2D+ try: =2D+ yield =2D+ finally: =2D+ sys.argv =3D old_value =2D+ =2D+ =2D+def test_git_local_config(): =2D+ # Clearing the command line arguments is required, otherwise =2D+ # arguments passed to the test running such as in 'pytest -k =2D+ # filter' would be processed by _UpdateDefaults and fail. =2D+ with cleared_command_line_args(): =2D+ with empty_git_repository(): =2D+ with tempfile.NamedTemporaryFile() as global_config: =2D+ global_config.write(b'[settings]\n' =2D+ b'project=3Du-boot\n') =2D+ global_config.flush() =2D+ parser =3D argparse.ArgumentParser() =2D+ parser.add_argument('-p', '--project', default=3D'unkno= wn') =2D+ subparsers =3D parser.add_subparsers(dest=3D'cmd') =2D+ send =3D subparsers.add_parser('send') =2D+ send.add_argument('--no-check', action=3D'store_false', =2D+ dest=3D'check_patch', default=3DTrue) =2D+ =2D+ # Test "global" config is used. =2D+ settings.Setup(parser, 'unknown', global_config.name) =2D+ args, _ =3D parser.parse_known_args([]) =2D+ assert args.project =3D=3D 'u-boot' =2D+ send_args, _ =3D send.parse_known_args([]) =2D+ assert send_args.check_patch =2D+ =2D+ # Test local config can shadow it. =2D+ with open('.patman', 'w', buffering=3D1) as f: =2D+ f.write('[settings]\n' =2D+ 'project: guix-patches\n' =2D+ 'check_patch: False\n') =2D+ settings.Setup(parser, 'unknown', global_config.name) =2D+ args, _ =3D parser.parse_known_args([]) =2D+ assert args.project =3D=3D 'guix-patches' =2D+ send_args, _ =3D send.parse_known_args([]) =2D+ assert not send_args.check_patch diff --git a/gnu/packages/patches/u-boot-sifive-prevent-reloc-initrd-fdt.pa= tch b/gnu/packages/patches/u-boot-sifive-prevent-reloc-initrd-fdt.patch index a5b92e3e8f..858f42efe7 100644 =2D-- a/gnu/packages/patches/u-boot-sifive-prevent-reloc-initrd-fdt.patch +++ b/gnu/packages/patches/u-boot-sifive-prevent-reloc-initrd-fdt.patch @@ -5,12 +5,12 @@ Index: u-boot-2021.07~rc4+dfsg/include/configs/sifive-unm= atched.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- u-boot-2021.07~rc4+dfsg.orig/include/configs/sifive-unmatched.h +++ u-boot-2021.07~rc4+dfsg/include/configs/sifive-unmatched.h =2D@@ -62,6 +62,8 @@ +@@ -55,6 +55,8 @@ "name=3Dsystem,size=3D-,bootable,type=3D${type_guid_gpt_system};" =20=20 =2D #define CONFIG_EXTRA_ENV_SETTINGS \ + #define CFG_EXTRA_ENV_SETTINGS \ + "fdt_high=3D0xffffffffffffffff\0" \ + "initrd_high=3D0xffffffffffffffff\0" \ "kernel_addr_r=3D0x84000000\0" \ =2D "fdt_addr_r=3D0x88000000\0" \ =2D "scriptaddr=3D0x88100000\0" \ + "kernel_comp_addr_r=3D0x88000000\0" \ + "kernel_comp_size=3D0x4000000\0" \ =2D-=20 2.39.2 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCZKIj0wAKCRDcUY/If5cW qgElAQDa1YBStDGNtkkY2Wb7gU8R3UhH4Ppigl19ekgCmhHCQgEAtNjml0m9gRaf EKq9g5bZCWUnbyx2jt+A+toHvmqf7Qw= =5wlv -----END PGP SIGNATURE----- --==-=-=--