openSUSE Commits
Threads by month
- ----- 2024 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
August 2024
- 2 participants
- 1399 discussions
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package 000product for openSUSE:Factory checked in at 2024-08-10 19:14:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/000product (Old)
and /work/SRC/openSUSE:Factory/.000product.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "000product"
Sat Aug 10 19:14:43 2024 rev:4103 rq: version:unknown
Changes:
--------
New Changes file:
NO CHANGES FILE!!!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ MicroOS-dvd5-dvd-x86_64.kiwi ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:49.655291244 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:49.699293071 +0200
@@ -1,4 +1,4 @@
-<image name="OBS__MicroOS___20240809" schemaversion="4.1">
+<image name="OBS__MicroOS___20240810" schemaversion="4.1">
<description type="system">
<author>The SUSE Team</author>
<contact>build(a)opensuse.org</contact>
@@ -35,11 +35,11 @@
<productvar name="SEPARATE_MEDIA">true</productvar>
<productvar name="SHA1OPT">-x -2</productvar>
<productvar name="VENDOR">openSUSE</productvar>
- <productvar name="VERSION">20240809</productvar>
+ <productvar name="VERSION">20240810</productvar>
<productinfo name="CONTENTSTYLE">11</productinfo>
- <productinfo name="DISTRO">cpe:/o:opensuse:microos:20240809,openSUSE MicroOS</productinfo>
+ <productinfo name="DISTRO">cpe:/o:opensuse:microos:20240810,openSUSE MicroOS</productinfo>
<productinfo name="LINGUAS">en_US </productinfo>
- <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/MicroOS/20240809/x86_64</productinfo>
+ <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/MicroOS/20240810/x86_64</productinfo>
<productinfo name="VENDOR">openSUSE</productinfo>
<productoption name="INI_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
<productoption name="PLUGIN_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
++++++ openSUSE-Addon-NonOss-ftp-ftp-x86_64.kiwi ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:50.071308521 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:50.103309850 +0200
@@ -1,4 +1,4 @@
-<image name="OBS__openSUSE-Addon-NonOss___20240809" schemaversion="4.1">
+<image name="OBS__openSUSE-Addon-NonOss___20240810" schemaversion="4.1">
<description type="system">
<author>The SUSE Team</author>
<contact>build(a)opensuse.org</contact>
@@ -35,11 +35,11 @@
<productvar name="SEPARATE_MEDIA">true</productvar>
<productvar name="SHA1OPT">-x -2</productvar>
<productvar name="VENDOR">openSUSE</productvar>
- <productvar name="VERSION">20240809</productvar>
+ <productvar name="VERSION">20240810</productvar>
<productinfo name="CONTENTSTYLE">11</productinfo>
- <productinfo name="DISTRO">cpe:/o:opensuse:opensuse-addon-nonoss:20240809,openSUSE NonOSS Addon</productinfo>
+ <productinfo name="DISTRO">cpe:/o:opensuse:opensuse-addon-nonoss:20240810,openSUSE NonOSS Addon</productinfo>
<productinfo name="LINGUAS">af ar be_BY bg br ca cy el et ga gl gu_IN he hi_IN hr ka km ko lt mk nn pa_IN rw sk sl sr_CS ss st tg th tr uk ve vi xh zu </productinfo>
- <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/openSUSE-Addon-NonOss/2024…</productinfo>
+ <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/openSUSE-Addon-NonOss/2024…</productinfo>
<productinfo name="VENDOR">openSUSE</productinfo>
<productoption name="INI_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
<productoption name="PLUGIN_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
++++++ openSUSE-cd-mini-x86_64.kiwi ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:50.303318156 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:50.335319485 +0200
@@ -1,4 +1,4 @@
-<image name="OBS__openSUSE___20240809" schemaversion="4.1">
+<image name="OBS__openSUSE___20240810" schemaversion="4.1">
<description type="system">
<author>The SUSE Team</author>
<contact>build(a)opensuse.org</contact>
@@ -35,11 +35,11 @@
<productvar name="SEPARATE_MEDIA">true</productvar>
<productvar name="SHA1OPT">-x -2</productvar>
<productvar name="VENDOR">openSUSE</productvar>
- <productvar name="VERSION">20240809</productvar>
+ <productvar name="VERSION">20240810</productvar>
<productinfo name="CONTENTSTYLE">11</productinfo>
- <productinfo name="DISTRO">cpe:/o:opensuse:opensuse:20240809,openSUSE Tumbleweed</productinfo>
+ <productinfo name="DISTRO">cpe:/o:opensuse:opensuse:20240810,openSUSE Tumbleweed</productinfo>
<productinfo name="LINGUAS">cs da de el en en_GB en_US es fr hu it ja pl pt pt_BR ru zh zh_CN zh_TW </productinfo>
- <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/openSUSE/20240809/x86_64</productinfo>
+ <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/openSUSE/20240810/x86_64</productinfo>
<productinfo name="VENDOR">openSUSE</productinfo>
<productoption name="INI_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
<productoption name="PLUGIN_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
openSUSE-dvd5-dvd-x86_64.kiwi: same change
++++++ openSUSE-ftp-ftp-x86_64.kiwi ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:50.699334602 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:50.727335765 +0200
@@ -1,4 +1,4 @@
-<image name="OBS__openSUSE___20240809" schemaversion="4.1">
+<image name="OBS__openSUSE___20240810" schemaversion="4.1">
<description type="system">
<author>The SUSE Team</author>
<contact>build(a)opensuse.org</contact>
@@ -23,7 +23,7 @@
<productvar name="DISTNAME">openSUSE</productvar>
<productvar name="FLAVOR">ftp</productvar>
<productvar name="MAKE_LISTINGS">true</productvar>
- <productvar name="MEDIUM_NAME">openSUSE-20240809-x86_64</productvar>
+ <productvar name="MEDIUM_NAME">openSUSE-20240810-x86_64</productvar>
<productvar name="MULTIPLE_MEDIA">true</productvar>
<productvar name="PRODUCT_DIR">/</productvar>
<productvar name="PRODUCT_NAME">$DISTNAME-$FLAVOR</productvar>
@@ -35,11 +35,11 @@
<productvar name="SEPARATE_MEDIA">true</productvar>
<productvar name="SHA1OPT">-x -2</productvar>
<productvar name="VENDOR">openSUSE</productvar>
- <productvar name="VERSION">20240809</productvar>
+ <productvar name="VERSION">20240810</productvar>
<productinfo name="CONTENTSTYLE">11</productinfo>
- <productinfo name="DISTRO">cpe:/o:opensuse:opensuse:20240809,openSUSE Tumbleweed</productinfo>
+ <productinfo name="DISTRO">cpe:/o:opensuse:opensuse:20240810,openSUSE Tumbleweed</productinfo>
<productinfo name="LINGUAS">cs da de el en en_GB en_US es fr hu it ja pl pt pt_BR ru zh zh_CN zh_TW </productinfo>
- <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/openSUSE/20240809/x86_64</productinfo>
+ <productinfo name="REPOID">obsproduct://build.opensuse.org/openSUSE:Factory/openSUSE/20240810/x86_64</productinfo>
<productinfo name="VENDOR">openSUSE</productinfo>
<productoption name="DEBUGMEDIUM">2</productoption>
<productoption name="INI_DIR">/usr/share/kiwi/modules/plugins/tumbleweed</productoption>
++++++ Aeon.product ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:51.087350715 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:51.111351712 +0200
@@ -6,7 +6,7 @@
<name>Aeon</name>
<releasepkgname>Aeon-release</releasepkgname>
<endoflife/>
- <version>20240809</version>
+ <version>20240810</version>
<!-- release is no longer optional -->
<release>0</release>
<productline>Aeon</productline>
++++++ Kalpa.product ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:51.347361513 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:51.399363672 +0200
@@ -6,7 +6,7 @@
<name>Kalpa</name>
<releasepkgname>Kalpa-release</releasepkgname>
<endoflife/>
- <version>20240809</version>
+ <version>20240810</version>
<!-- release is no longer optional -->
<release>0</release>
<productline>Kalpa</productline>
++++++ MicroOS.product ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:51.567370649 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:51.599371978 +0200
@@ -6,7 +6,7 @@
<name>MicroOS</name>
<releasepkgname>MicroOS-release</releasepkgname>
<endoflife/>
- <version>20240809</version>
+ <version>20240810</version>
<!-- release is no longer optional -->
<release>0</release>
<productline>MicroOS</productline>
++++++ openSUSE-Addon-NonOss.product ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:52.103392910 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:52.135394239 +0200
@@ -4,7 +4,7 @@
<product>
<vendor>openSUSE</vendor>
<name>openSUSE-Addon-NonOss</name>
- <version>20240809</version>
+ <version>20240810</version>
<release>0</release>
<summary>openSUSE NonOSS Addon</summary>
<shortsummary>non oss addon</shortsummary>
++++++ openSUSE.product ++++++
--- /var/tmp/diff_new_pack.kzgCwc/_old 2024-08-10 19:14:52.319401880 +0200
+++ /var/tmp/diff_new_pack.kzgCwc/_new 2024-08-10 19:14:52.351403209 +0200
@@ -4,7 +4,7 @@
<product>
<vendor>openSUSE</vendor>
<name>openSUSE</name>
- <version>20240809</version>
+ <version>20240810</version>
<release>0</release>
<productline>openSUSE</productline>
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python38 for openSUSE:Factory checked in at 2024-08-10 19:08:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python38 (Old)
and /work/SRC/openSUSE:Factory/.python38.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python38"
Sat Aug 10 19:08:15 2024 rev:52 rq:1193121 version:3.8.19
Changes:
--------
--- /work/SRC/openSUSE:Factory/python38/python38.changes 2024-07-30 11:56:59.747656679 +0200
+++ /work/SRC/openSUSE:Factory/.python38.new.7232/python38.changes 2024-08-10 19:14:02.101316411 +0200
@@ -1,0 +2,15 @@
+Thu Aug 8 19:30:36 UTC 2024 - Matej Cepl <mcepl(a)cepl.eu>
+
+- Adding bso1227999-reproducible-builds.patch fixing bsc#1227999
+ adding reproducibility patches from gh#python/cpython!121872
+ and gh#python/cpython!121883.
+- Add CVE-2024-6923-email-hdr-inject.patch to prevent email
+ header injection due to unquoted newlines (bsc#1228780,
+ CVE-2024-6923).
+- Add CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch removing
+ support for anything but OpenSSL 1.1.1 or newer (bsc#1227233,
+ CVE-2024-5642).
+- %{profileopt} variable is set according to the variable
+ %{do_profiling} (bsc#1227999)
+
+-------------------------------------------------------------------
New:
----
CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch
CVE-2024-6923-email-hdr-inject.patch
bso1227999-reproducible-builds.patch
BETA DEBUG BEGIN:
New: CVE-2024-6923).
- Add CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch removing
support for anything but OpenSSL 1.1.1 or newer (bsc#1227233,
New: and gh#python/cpython!121883.
- Add CVE-2024-6923-email-hdr-inject.patch to prevent email
header injection due to unquoted newlines (bsc#1228780,
New:
- Adding bso1227999-reproducible-builds.patch fixing bsc#1227999
adding reproducibility patches from gh#python/cpython!121872
BETA DEBUG END:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python38.spec ++++++
--- /var/tmp/diff_new_pack.QG95qJ/_old 2024-08-10 19:14:03.605378872 +0200
+++ /var/tmp/diff_new_pack.QG95qJ/_new 2024-08-10 19:14:03.605378872 +0200
@@ -36,6 +36,12 @@
%bcond_without general
%endif
+%if 0%{?do_profiling}
+%bcond_without profileopt
+%else
+%bcond_with profileopt
+%endif
+
%define python_pkg_name python38
%if "%{python_pkg_name}" == "%{primary_python}"
%define primary_interpreter 1
@@ -192,6 +198,15 @@
# PATCH-FIX-UPSTREAM CVE-2024-4032-private-IP-addrs.patch bsc#1226448 mcepl(a)suse.com
# rearrange definition of private v global IP addresses
Patch45: CVE-2024-4032-private-IP-addrs.patch
+# PATCH-FIX-UPSTREAM bso1227999-reproducible-builds.patch bsc#1227999 mcepl(a)suse.com
+# reproducibility patches
+Patch46: bso1227999-reproducible-builds.patch
+# PATCH-FIX-UPSTREAM CVE-2024-6923-email-hdr-inject.patch bsc#1228780 mcepl(a)suse.com
+# prevent email header injection, patch from gh#python/cpython!122608
+Patch47: CVE-2024-6923-email-hdr-inject.patch
+# PATCH-FIX-UPSTREAM CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch bsc#1227233 mcepl(a)suse.com
+# Remove for support for anything but OpenSSL 1.1.1 or newer
+Patch48: CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch
BuildRequires: autoconf-archive
BuildRequires: automake
BuildRequires: fdupes
@@ -444,28 +459,31 @@
%patch -P 05 -p1
%endif
-%patch -P 06 -p1
-%patch -P 07 -p1
-%patch -P 08 -p1
-%patch -P 09 -p1
-%patch -P 15 -p1
-%patch -P 23 -p1
-%patch -P 24 -p1
-%patch -P 25 -p1
-%patch -P 27 -p1
-%patch -P 28 -p1
-%patch -P 29 -p1
-%patch -P 32 -p1
-%patch -P 33 -p1
-%patch -P 34 -p1
-%patch -P 36 -p1
-%patch -P 37 -p1
-%patch -P 38 -p1
-%patch -P 41 -p1
-%patch -P 42 -p1
-%patch -P 43 -p1
-%patch -P 44 -p1
-%patch -P 45 -p1
+%patch -p1 -P 06
+%patch -p1 -P 07
+%patch -p1 -P 08
+%patch -p1 -P 09
+%patch -p1 -P 15
+%patch -p1 -P 23
+%patch -p1 -P 24
+%patch -p1 -P 25
+%patch -p1 -P 27
+%patch -p1 -P 28
+%patch -p1 -P 29
+%patch -p1 -P 32
+%patch -p1 -P 33
+%patch -p1 -P 34
+%patch -p1 -P 36
+%patch -p1 -P 37
+%patch -p1 -P 38
+%patch -p1 -P 41
+%patch -p1 -P 42
+%patch -p1 -P 43
+%patch -p1 -P 44
+%patch -p1 -P 45
+%patch -p1 -P 46
+%patch -p1 -P 47
+%patch -p1 -P 48
# drop Autoconf version requirement
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
++++++ CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch ++++++
++++ 1743 lines (skipped)
++++++ CVE-2024-6923-email-hdr-inject.patch ++++++
From d7cf62cf9f630975a0e876708c4a23907a23aba3 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <encukou(a)gmail.com>
Date: Wed, 31 Jul 2024 00:19:48 +0200
Subject: [PATCH 1/4] [3.8] gh-121650: Encode newlines in headers, and verify
headers are sound (GH-122233)
Per RFC 2047:
> [...] these encoding schemes allow the
> encoding of arbitrary octet values, mail readers that implement this
> decoding should also ensure that display of the decoded data on the
> recipient's terminal will not cause unwanted side-effects
It seems that the "quoted-word" scheme is a valid way to include
a newline character in a header value, just like we already allow
undecodable bytes or control characters.
They do need to be properly quoted when serialized to text, though.
This should fail for custom fold() implementations that aren't careful
about newlines.
(cherry picked from commit 097633981879b3c9de9a1dd120d3aa585ecc2384)
Co-authored-by: Petr Viktorin <encukou(a)gmail.com>
Co-authored-by: Bas Bloemsaat <bas(a)bloemsaat.org>
Co-authored-by: Serhiy Storchaka <storchaka(a)gmail.com>
---
Doc/library/email.errors.rst | 6
Doc/library/email.policy.rst | 18 ++
Doc/whatsnew/3.8.rst | 12 +
Lib/email/_header_value_parser.py | 12 +
Lib/email/_policybase.py | 8 +
Lib/email/errors.py | 4
Lib/email/generator.py | 16 ++
Lib/test/test_email/test_generator.py | 62 ++++++++++
Lib/test/test_email/test_policy.py | 26 ++++
Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst | 5
10 files changed, 165 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst
--- a/Doc/library/email.errors.rst
+++ b/Doc/library/email.errors.rst
@@ -59,6 +59,12 @@ The following exception classes are defi
:class:`~email.mime.image.MIMEImage`).
+.. exception:: HeaderWriteError()
+
+ Raised when an error occurs when the :mod:`~email.generator` outputs
+ headers.
+
+
Here is the list of the defects that the :class:`~email.parser.FeedParser`
can find while parsing messages. Note that the defects are added to the message
where the problem was found, so for example, if a message nested inside a
--- a/Doc/library/email.policy.rst
+++ b/Doc/library/email.policy.rst
@@ -229,6 +229,24 @@ added matters. To illustrate::
.. versionadded:: 3.6
+
+ .. attribute:: verify_generated_headers
+
+ If ``True`` (the default), the generator will raise
+ :exc:`~email.errors.HeaderWriteError` instead of writing a header
+ that is improperly folded or delimited, such that it would
+ be parsed as multiple headers or joined with adjacent data.
+ Such headers can be generated by custom header classes or bugs
+ in the ``email`` module.
+
+ As it's a security feature, this defaults to ``True`` even in the
+ :class:`~email.policy.Compat32` policy.
+ For backwards compatible, but unsafe, behavior, it must be set to
+ ``False`` explicitly.
+
+ .. versionadded:: 3.8.20
+
+
The following :class:`Policy` method is intended to be called by code using
the email library to create policy instances with custom settings:
--- a/Doc/whatsnew/3.8.rst
+++ b/Doc/whatsnew/3.8.rst
@@ -2364,3 +2364,15 @@ ipaddress
* Fixed ``is_global`` and ``is_private`` behavior in ``IPv4Address``,
``IPv6Address``, ``IPv4Network`` and ``IPv6Network``.
+
+email
+-----
+
+* Headers with embedded newlines are now quoted on output.
+
+ The :mod:`~email.generator` will now refuse to serialize (write) headers
+ that are improperly folded or delimited, such that they would be parsed as
+ multiple headers or joined with adjacent data.
+ If you need to turn this safety feature off,
+ set :attr:`~email.policy.Policy.verify_generated_headers`.
+ (Contributed by Bas Bloemsaat and Petr Viktorin in :gh:`121650`.)
--- a/Lib/email/_header_value_parser.py
+++ b/Lib/email/_header_value_parser.py
@@ -92,6 +92,8 @@ TOKEN_ENDS = TSPECIALS | WSP
ASPECIALS = TSPECIALS | set("*'%")
ATTRIBUTE_ENDS = ASPECIALS | WSP
EXTENDED_ATTRIBUTE_ENDS = ATTRIBUTE_ENDS - set('%')
+NLSET = {'\n', '\r'}
+SPECIALSNL = SPECIALS | NLSET
def quote_string(value):
return '"'+str(value).replace('\\', '\\\\').replace('"', r'\"')+'"'
@@ -2778,9 +2780,13 @@ def _refold_parse_tree(parse_tree, *, po
wrap_as_ew_blocked -= 1
continue
tstr = str(part)
- if part.token_type == 'ptext' and set(tstr) & SPECIALS:
- # Encode if tstr contains special characters.
- want_encoding = True
+ if not want_encoding:
+ if part.token_type == 'ptext':
+ # Encode if tstr contains special characters.
+ want_encoding = not SPECIALSNL.isdisjoint(tstr)
+ else:
+ # Encode if tstr contains newlines.
+ want_encoding = not NLSET.isdisjoint(tstr)
try:
tstr.encode(encoding)
charset = encoding
--- a/Lib/email/_policybase.py
+++ b/Lib/email/_policybase.py
@@ -157,6 +157,13 @@ class Policy(_PolicyBase, metaclass=abc.
message_factory -- the class to use to create new message objects.
If the value is None, the default is Message.
+ verify_generated_headers
+ -- if true, the generator verifies that each header
+ they are properly folded, so that a parser won't
+ treat it as multiple headers, start-of-body, or
+ part of another header.
+ This is a check against custom Header & fold()
+ implementations.
"""
raise_on_defect = False
@@ -165,6 +172,7 @@ class Policy(_PolicyBase, metaclass=abc.
max_line_length = 78
mangle_from_ = False
message_factory = None
+ verify_generated_headers = True
def handle_defect(self, obj, defect):
"""Based on policy, either raise defect or call register_defect.
--- a/Lib/email/errors.py
+++ b/Lib/email/errors.py
@@ -29,6 +29,10 @@ class CharsetError(MessageError):
"""An illegal charset was given."""
+class HeaderWriteError(MessageError):
+ """Error while writing headers."""
+
+
# These are parsing defects which the parser was able to work around.
class MessageDefect(ValueError):
"""Base class for a message defect."""
--- a/Lib/email/generator.py
+++ b/Lib/email/generator.py
@@ -14,12 +14,14 @@ import random
from copy import deepcopy
from io import StringIO, BytesIO
from email.utils import _has_surrogates
+from email.errors import HeaderWriteError
UNDERSCORE = '_'
NL = '\n' # XXX: no longer used by the code below.
NLCRE = re.compile(r'\r\n|\r|\n')
fcre = re.compile(r'^From ', re.MULTILINE)
+NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
@@ -223,7 +225,19 @@ class Generator:
def _write_headers(self, msg):
for h, v in msg.raw_items():
- self.write(self.policy.fold(h, v))
+ folded = self.policy.fold(h, v)
+ if self.policy.verify_generated_headers:
+ linesep = self.policy.linesep
+ if not folded.endswith(self.policy.linesep):
+ raise HeaderWriteError(
+ f'folded header does not end with {linesep!r}: {folded!r}')
+ folded_no_linesep = folded
+ if folded.endswith(linesep):
+ folded_no_linesep = folded[:-len(linesep)]
+ if NEWLINE_WITHOUT_FWSP.search(folded_no_linesep):
+ raise HeaderWriteError(
+ f'folded header contains newline: {folded!r}')
+ self.write(folded)
# A blank line always separates headers from body
self.write(self._NL)
--- a/Lib/test/test_email/test_generator.py
+++ b/Lib/test/test_email/test_generator.py
@@ -6,6 +6,7 @@ from email.message import EmailMessage
from email.generator import Generator, BytesGenerator
from email.headerregistry import Address
from email import policy
+import email.errors
from test.test_email import TestEmailBase, parameterize
@@ -216,6 +217,44 @@ class TestGeneratorBase:
g.flatten(msg)
self.assertEqual(s.getvalue(), self.typ(expected))
+ def test_keep_encoded_newlines(self):
+ msg = self.msgmaker(self.typ(textwrap.dedent("""\
+ To: nobody
+ Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection(a)example.com
+
+ None
+ """)))
+ expected = textwrap.dedent("""\
+ To: nobody
+ Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection(a)example.com
+
+ None
+ """)
+ s = self.ioclass()
+ g = self.genclass(s, policy=self.policy.clone(max_line_length=80))
+ g.flatten(msg)
+ self.assertEqual(s.getvalue(), self.typ(expected))
+
+ def test_keep_long_encoded_newlines(self):
+ msg = self.msgmaker(self.typ(textwrap.dedent("""\
+ To: nobody
+ Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection(a)example.com
+
+ None
+ """)))
+ expected = textwrap.dedent("""\
+ To: nobody
+ Subject: Bad subject
+ =?utf-8?q?=0A?=Bcc:
+ injection(a)example.com
+
+ None
+ """)
+ s = self.ioclass()
+ g = self.genclass(s, policy=self.policy.clone(max_line_length=30))
+ g.flatten(msg)
+ self.assertEqual(s.getvalue(), self.typ(expected))
+
class TestGenerator(TestGeneratorBase, TestEmailBase):
@@ -224,6 +263,29 @@ class TestGenerator(TestGeneratorBase, T
ioclass = io.StringIO
typ = str
+ def test_verify_generated_headers(self):
+ """gh-121650: by default the generator prevents header injection"""
+ class LiteralHeader(str):
+ name = 'Header'
+ def fold(self, **kwargs):
+ return self
+
+ for text in (
+ 'Value\r\nBad Injection\r\n',
+ 'NoNewLine'
+ ):
+ with self.subTest(text=text):
+ message = message_from_string(
+ "Header: Value\r\n\r\nBody",
+ policy=self.policy,
+ )
+
+ del message['Header']
+ message['Header'] = LiteralHeader(text)
+
+ with self.assertRaises(email.errors.HeaderWriteError):
+ message.as_string()
+
class TestBytesGenerator(TestGeneratorBase, TestEmailBase):
--- a/Lib/test/test_email/test_policy.py
+++ b/Lib/test/test_email/test_policy.py
@@ -26,6 +26,7 @@ class PolicyAPITests(unittest.TestCase):
'raise_on_defect': False,
'mangle_from_': True,
'message_factory': None,
+ 'verify_generated_headers': True,
}
# These default values are the ones set on email.policy.default.
# If any of these defaults change, the docs must be updated.
@@ -277,6 +278,31 @@ class PolicyAPITests(unittest.TestCase):
with self.assertRaises(email.errors.HeaderParseError):
policy.fold("Subject", subject)
+ def test_verify_generated_headers(self):
+ """Turning protection off allows header injection"""
+ policy = email.policy.default.clone(verify_generated_headers=False)
+ for text in (
+ 'Header: Value\r\nBad: Injection\r\n',
+ 'Header: NoNewLine'
+ ):
+ with self.subTest(text=text):
+ message = email.message_from_string(
+ "Header: Value\r\n\r\nBody",
+ policy=policy,
+ )
+ class LiteralHeader(str):
+ name = 'Header'
+ def fold(self, **kwargs):
+ return self
+
+ del message['Header']
+ message['Header'] = LiteralHeader(text)
+
+ self.assertEqual(
+ message.as_string(),
+ f"{text}\nBody",
+ )
+
# XXX: Need subclassing tests.
# For adding subclassed objects, make sure the usual rules apply (subclass
# wins), but that the order still works (right overrides left).
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst
@@ -0,0 +1,5 @@
+:mod:`email` headers with embedded newlines are now quoted on output. The
+:mod:`~email.generator` will now refuse to serialize (write) headers that
+are unsafely folded or delimited; see
+:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas
+Bloemsaat and Petr Viktorin in :gh:`121650`.)
++++++ bso1227999-reproducible-builds.patch ++++++
From ac2b8869724d7a57d9b5efbdce2f20423214e8bb Mon Sep 17 00:00:00 2001
From: "Bernhard M. Wiedemann" <bwiedemann(a)suse.de>
Date: Tue, 16 Jul 2024 21:39:33 +0200
Subject: [PATCH] Allow to override build date with SOURCE_DATE_EPOCH
to make builds reproducible.
See https://reproducible-builds.org/ for why this is good
and https://reproducible-builds.org/specs/source-date-epoch/
for the definition of this variable.
---
Doc/conf.py | 3 ++-
Doc/library/functions.rst | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -78,7 +78,8 @@ html_short_title = '%s Documentation' %
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
+html_time = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
+html_last_updated_fmt = time.strftime('%b %d, %Y (%H:%M UTC)', time.gmtime(html_time))
# Path to find HTML templates.
templates_path = ['tools/templates']
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1238,7 +1238,7 @@ are always available. They are listed h
(where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`,
and :mod:`shutil`.
- .. audit-event:: open file,mode,flags open
+ .. audit-event:: open path,mode,flags open
The ``mode`` and ``flags`` arguments may have been modified or inferred from
the original call.
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ast-grep for openSUSE:Factory checked in at 2024-08-10 19:08:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ast-grep (Old)
and /work/SRC/openSUSE:Factory/.ast-grep.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ast-grep"
Sat Aug 10 19:08:12 2024 rev:36 rq:1193093 version:0.26.1+0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ast-grep/ast-grep.changes 2024-08-08 10:58:05.190850864 +0200
+++ /work/SRC/openSUSE:Factory/.ast-grep.new.7232/ast-grep.changes 2024-08-10 19:13:57.989145640 +0200
@@ -1,0 +2,9 @@
+Sat Aug 10 04:37:33 UTC 2024 - Michael Vetter <mvetter(a)suse.com>
+
+- Update to 0.26.1:
+ * feat: support dynamic language in pyo3 #1143
+ * test: add test for load dynamic lang in python 236f4ab
+ * feat: add py_lang registration function 43e74e7
+ * feat: add pytype for register language 8b660cf
+
+-------------------------------------------------------------------
Old:
----
ast-grep-0.26.0+0.tar.zst
New:
----
ast-grep-0.26.1+0.tar.zst
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ast-grep.spec ++++++
--- /var/tmp/diff_new_pack.ej11Tj/_old 2024-08-10 19:13:59.997229032 +0200
+++ /var/tmp/diff_new_pack.ej11Tj/_new 2024-08-10 19:13:59.997229032 +0200
@@ -17,7 +17,7 @@
Name: ast-grep
-Version: 0.26.0+0
+Version: 0.26.1+0
Release: 0
Summary: A CLI tool for code structural search, lint and rewriting
License: MIT
++++++ _service ++++++
--- /var/tmp/diff_new_pack.ej11Tj/_old 2024-08-10 19:14:00.037230693 +0200
+++ /var/tmp/diff_new_pack.ej11Tj/_new 2024-08-10 19:14:00.041230859 +0200
@@ -3,7 +3,7 @@
<param name="url">https://github.com/ast-grep/ast-grep.git</param>
<param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param>
<param name="scm">git</param>
- <param name="revision">0.26.0</param>
+ <param name="revision">0.26.1</param>
<param name="match-tag">*</param>
<param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param>
<param name="versionrewrite-replacement">\1</param>
++++++ ast-grep-0.26.0+0.tar.zst -> ast-grep-0.26.1+0.tar.zst ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/CHANGELOG.md new/ast-grep-0.26.1+0/CHANGELOG.md
--- old/ast-grep-0.26.0+0/CHANGELOG.md 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/CHANGELOG.md 2024-08-10 00:13:30.000000000 +0200
@@ -4,8 +4,17 @@
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
+#### [0.26.1](https://github.com/ast-grep/ast-grep/compare/0.26.0...0.26.1)
+
+- feat: support dynamic language in pyo3 [`#1143`](https://github.com/ast-grep/ast-grep/issues/1143)
+- test: add test for load dynamic lang in python [`236f4ab`](https://github.com/ast-grep/ast-grep/commit/236f4ab4d3faef4438c0516e406f3ca415d5dac7)
+- feat: add py_lang registration function [`43e74e7`](https://github.com/ast-grep/ast-grep/commit/43e74e73cd458ef4635d24221206bda673206b0d)
+- feat: add pytype for register language [`8b660cf`](https://github.com/ast-grep/ast-grep/commit/8b660cf816de3afcfcd124951924521afcb2d445)
+
#### [0.26.0](https://github.com/ast-grep/ast-grep/compare/0.25.7...0.26.0)
+> 7 August 2024
+
- feat: Additional impls for language types [`#1379`](https://github.com/ast-grep/ast-grep/pull/1379)
- feat: append note to error message if available [`#1384`](https://github.com/ast-grep/ast-grep/issues/1384)
- fix: LSP should skip files outside the workspace root [`#1382`](https://github.com/ast-grep/ast-grep/issues/1382)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/Cargo.lock new/ast-grep-0.26.1+0/Cargo.lock
--- old/ast-grep-0.26.0+0/Cargo.lock 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/Cargo.lock 2024-08-10 00:13:30.000000000 +0200
@@ -113,7 +113,7 @@
[[package]]
name = "ast-grep"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"ansi_term",
"anyhow",
@@ -144,7 +144,7 @@
[[package]]
name = "ast-grep-config"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"anyhow",
"ast-grep-core",
@@ -160,7 +160,7 @@
[[package]]
name = "ast-grep-core"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"bit-set",
"regex",
@@ -171,7 +171,7 @@
[[package]]
name = "ast-grep-dynamic"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"ast-grep-core",
"ignore",
@@ -183,7 +183,7 @@
[[package]]
name = "ast-grep-language"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"ast-grep-core",
"ignore",
@@ -215,7 +215,7 @@
[[package]]
name = "ast-grep-lsp"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"ast-grep-config",
"ast-grep-core",
@@ -229,7 +229,7 @@
[[package]]
name = "ast-grep-napi"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"ast-grep-config",
"ast-grep-core",
@@ -248,14 +248,16 @@
[[package]]
name = "ast-grep-py"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"anyhow",
"ast-grep-config",
"ast-grep-core",
+ "ast-grep-dynamic",
"ast-grep-language",
"pyo3",
"pythonize",
+ "serde",
]
[[package]]
@@ -314,7 +316,7 @@
[[package]]
name = "benches"
-version = "0.26.0"
+version = "0.26.1"
dependencies = [
"ast-grep-config",
"ast-grep-core",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/Cargo.toml new/ast-grep-0.26.1+0/Cargo.toml
--- old/ast-grep-0.26.0+0/Cargo.toml 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/Cargo.toml 2024-08-10 00:13:30.000000000 +0200
@@ -11,7 +11,7 @@
lto = true
[workspace.package]
-version = "0.26.0"
+version = "0.26.1"
authors = ["Herrington Darkholme <2883231+HerringtonDarkholme(a)users.noreply.github.com>"]
edition = "2021"
license = "MIT"
@@ -22,11 +22,11 @@
readme = "README.md"
[workspace.dependencies]
-ast-grep-core = { path = "crates/core", version = "0.26.0" }
-ast-grep-config = { path = "crates/config", version = "0.26.0" }
-ast-grep-dynamic = { path = "crates/dynamic", version = "0.26.0" }
-ast-grep-language = { path = "crates/language", version = "0.26.0" }
-ast-grep-lsp = { path = "crates/lsp", version = "0.26.0" }
+ast-grep-core = { path = "crates/core", version = "0.26.1" }
+ast-grep-config = { path = "crates/config", version = "0.26.1" }
+ast-grep-dynamic = { path = "crates/dynamic", version = "0.26.1" }
+ast-grep-language = { path = "crates/language", version = "0.26.1" }
+ast-grep-lsp = { path = "crates/lsp", version = "0.26.1" }
bit-set = { version = "0.8.0" }
ignore = { version = "0.4.22" }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/darwin-arm64/package.json new/ast-grep-0.26.1+0/crates/napi/npm/darwin-arm64/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/darwin-arm64/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/darwin-arm64/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-darwin-arm64",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"darwin"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/darwin-x64/package.json new/ast-grep-0.26.1+0/crates/napi/npm/darwin-x64/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/darwin-x64/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/darwin-x64/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-darwin-x64",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"darwin"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/linux-arm64-gnu/package.json new/ast-grep-0.26.1+0/crates/napi/npm/linux-arm64-gnu/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/linux-arm64-gnu/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/linux-arm64-gnu/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-linux-arm64-gnu",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"linux"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/linux-arm64-musl/package.json new/ast-grep-0.26.1+0/crates/napi/npm/linux-arm64-musl/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/linux-arm64-musl/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/linux-arm64-musl/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-linux-arm64-musl",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"linux"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/linux-x64-gnu/package.json new/ast-grep-0.26.1+0/crates/napi/npm/linux-x64-gnu/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/linux-x64-gnu/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/linux-x64-gnu/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-linux-x64-gnu",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"linux"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/linux-x64-musl/package.json new/ast-grep-0.26.1+0/crates/napi/npm/linux-x64-musl/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/linux-x64-musl/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/linux-x64-musl/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-linux-x64-musl",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"linux"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/win32-arm64-msvc/package.json new/ast-grep-0.26.1+0/crates/napi/npm/win32-arm64-msvc/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/win32-arm64-msvc/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/win32-arm64-msvc/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-win32-arm64-msvc",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"win32"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/win32-ia32-msvc/package.json new/ast-grep-0.26.1+0/crates/napi/npm/win32-ia32-msvc/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/win32-ia32-msvc/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/win32-ia32-msvc/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-win32-ia32-msvc",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"win32"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/npm/win32-x64-msvc/package.json new/ast-grep-0.26.1+0/crates/napi/npm/win32-x64-msvc/package.json
--- old/ast-grep-0.26.0+0/crates/napi/npm/win32-x64-msvc/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/npm/win32-x64-msvc/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi-win32-x64-msvc",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"win32"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/napi/package.json new/ast-grep-0.26.1+0/crates/napi/package.json
--- old/ast-grep-0.26.0+0/crates/napi/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/napi/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/napi",
- "version": "0.26.0",
+ "version": "0.26.1",
"description": "Search and Rewrite code at large scale using precise AST pattern",
"homepage": "https://ast-grep.github.io",
"main": "index.js",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/Cargo.toml new/ast-grep-0.26.1+0/crates/pyo3/Cargo.toml
--- old/ast-grep-0.26.0+0/crates/pyo3/Cargo.toml 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/pyo3/Cargo.toml 2024-08-10 00:13:30.000000000 +0200
@@ -19,9 +19,11 @@
ast-grep-core.workspace = true
ast-grep-config.workspace = true
ast-grep-language.workspace = true
+ast-grep-dynamic.workspace = true
anyhow.workspace = true
pyo3 = { version = "0.21.2", optional = true, features = ["anyhow"] }
pythonize = { version = "0.21.1", optional = true }
+serde.workspace = true
# uncomment default features when developing pyo3
[features]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/ast_grep_py/__init__.py new/ast-grep-0.26.1+0/crates/pyo3/ast_grep_py/__init__.py
--- old/ast-grep-0.26.0+0/crates/pyo3/ast_grep_py/__init__.py 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/pyo3/ast_grep_py/__init__.py 2024-08-10 00:13:30.000000000 +0200
@@ -1,7 +1,7 @@
from __future__ import annotations
-from typing import List, TypedDict, Literal, Dict, Union, Mapping
-from .ast_grep_py import SgNode, SgRoot, Pos, Range, Edit
+from typing import List, TypedDict, Literal, Dict, Union, Mapping, Optional
+from .ast_grep_py import SgNode, SgRoot, Pos, Range, Edit, register_dynamic_language
Strictness = Union[Literal["cst"], Literal["smart"], Literal["ast"], Literal["relaxed"], Literal["signature"]]
@@ -55,6 +55,12 @@
utils: Dict[str, Rule]
transform: Dict[str, Mapping]
+class CustomLang(TypedDict, total=False):
+ library_path: str
+ language_symbol: Optional[str]
+ meta_var_char: Optional[str]
+ expando_char: Optional[str]
+
__all__ = [
"Rule",
"Config",
@@ -66,4 +72,5 @@
"Pos",
"Range",
"Edit",
+ "register_dynamic_language",
]
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/ast_grep_py/ast_grep_py.pyi new/ast-grep-0.26.1+0/crates/pyo3/ast_grep_py/ast_grep_py.pyi
--- old/ast-grep-0.26.0+0/crates/pyo3/ast_grep_py/ast_grep_py.pyi 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/pyo3/ast_grep_py/ast_grep_py.pyi 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
-from typing import List, Optional, overload, Unpack
+from typing import List, Optional, overload, Unpack, Dict
-from . import Rule, Config
+from . import Rule, Config, CustomLang
class Pos:
line: int
@@ -65,4 +65,6 @@
# Edit
def replace(self, new_text: str) -> Edit: ...
- def commit_edits(self, edits: List[Edit]) -> str: ...
\ No newline at end of file
+ def commit_edits(self, edits: List[Edit]) -> str: ...
+
+def register_dynamic_language(langs: Dict[str, CustomLang]): ...
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/pyproject.toml new/ast-grep-0.26.1+0/crates/pyo3/pyproject.toml
--- old/ast-grep-0.26.0+0/crates/pyo3/pyproject.toml 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/pyo3/pyproject.toml 2024-08-10 00:13:30.000000000 +0200
@@ -5,7 +5,7 @@
[project]
name = "ast-grep-py"
requires-python = ">=3.8"
-version = "0.26.0"
+version = "0.26.1"
description = "Structural Search and Rewrite code at large scale using precise AST pattern."
authors = [{ name = "Herrington Darkholme", email = "2883231+HerringtonDarkholme(a)users.noreply.github.com" }]
maintainers = [{ name = "Herrington Darkholme", email = "2883231+HerringtonDarkholme(a)users.noreply.github.com" }]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/src/lib.rs new/ast-grep-0.26.1+0/crates/pyo3/src/lib.rs
--- old/ast-grep-0.26.0+0/crates/pyo3/src/lib.rs 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/pyo3/src/lib.rs 2024-08-10 00:13:30.000000000 +0200
@@ -1,13 +1,15 @@
#![cfg(not(test))]
#![cfg(feature = "python")]
+mod py_lang;
mod py_node;
mod range;
mod unicode_position;
+use py_lang::register_dynamic_language;
use py_node::{Edit, SgNode};
use range::{Pos, Range};
use ast_grep_core::{AstGrep, Language, NodeMatch, StrDoc};
-use ast_grep_language::SupportLang;
+use py_lang::PyLang;
use pyo3::prelude::*;
use unicode_position::UnicodePosition;
@@ -20,12 +22,13 @@
m.add_class::<Range>()?;
m.add_class::<Pos>()?;
m.add_class::<Edit>()?;
+ m.add_function(wrap_pyfunction!(register_dynamic_language, m)?)?;
Ok(())
}
#[pyclass]
struct SgRoot {
- inner: AstGrep<StrDoc<SupportLang>>,
+ inner: AstGrep<StrDoc<PyLang>>,
filename: String,
pub(crate) position: UnicodePosition,
}
@@ -35,7 +38,7 @@
#[new]
fn new(src: &str, lang: &str) -> Self {
let position = UnicodePosition::new(src);
- let lang: SupportLang = lang.parse().unwrap();
+ let lang: PyLang = lang.parse().unwrap();
let inner = lang.ast_grep(src);
Self {
inner,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/src/py_lang.rs new/ast-grep-0.26.1+0/crates/pyo3/src/py_lang.rs
--- old/ast-grep-0.26.0+0/crates/pyo3/src/py_lang.rs 1970-01-01 01:00:00.000000000 +0100
+++ new/ast-grep-0.26.1+0/crates/pyo3/src/py_lang.rs 2024-08-10 00:13:30.000000000 +0200
@@ -0,0 +1,125 @@
+use ast_grep_core::language::TSLanguage;
+use ast_grep_dynamic::{DynamicLang, Registration};
+use ast_grep_language::{Language, SupportLang};
+use serde::{Deserialize, Serialize};
+
+use pyo3::prelude::*;
+use pyo3::types::PyDict;
+use pythonize::depythonize_bound;
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::fmt::{Debug, Display, Formatter};
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct CustomLang {
+ library_path: PathBuf,
+ /// the dylib symbol to load ts-language, default is `tree_sitter_{name}`
+ language_symbol: Option<String>,
+ meta_var_char: Option<char>,
+ expando_char: Option<char>,
+ // extensions: Vec<String>,
+}
+
+#[pyfunction]
+pub fn register_dynamic_language(dict: Bound<PyDict>) -> PyResult<()> {
+ let langs = depythonize_bound(dict.into_any())?;
+ let base = std::env::current_dir()?;
+ register(base, langs);
+ Ok(())
+}
+
+fn register(base: PathBuf, langs: HashMap<String, CustomLang>) {
+ let registrations = langs
+ .into_iter()
+ .map(|(name, custom)| to_registration(name, custom, &base))
+ .collect();
+ // TODO, add error handling
+ unsafe { DynamicLang::register(registrations).expect("TODO") }
+}
+
+fn to_registration(name: String, custom_lang: CustomLang, base: &Path) -> Registration {
+ let path = base.join(custom_lang.library_path);
+ let sym = custom_lang
+ .language_symbol
+ .unwrap_or_else(|| format!("tree_sitter_{name}"));
+ Registration {
+ lang_name: name,
+ lib_path: path,
+ symbol: sym,
+ meta_var_char: custom_lang.meta_var_char,
+ expando_char: custom_lang.expando_char,
+ // extensions: custom_lang.extensions,
+ extensions: vec![],
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub enum PyLang {
+ // inlined support lang expando char
+ Builtin(SupportLang),
+ Custom(DynamicLang),
+}
+#[derive(Debug)]
+pub enum PyLangErr {
+ LanguageNotSupported(String),
+}
+
+impl Display for PyLangErr {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
+ use PyLangErr::*;
+ match self {
+ LanguageNotSupported(lang) => write!(f, "{} is not supported!", lang),
+ }
+ }
+}
+
+impl std::error::Error for PyLangErr {}
+
+impl FromStr for PyLang {
+ type Err = PyLangErr;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ if let Ok(b) = SupportLang::from_str(s) {
+ Ok(PyLang::Builtin(b))
+ } else if let Ok(c) = DynamicLang::from_str(s) {
+ Ok(PyLang::Custom(c))
+ } else {
+ Err(PyLangErr::LanguageNotSupported(s.into()))
+ }
+ }
+}
+
+use PyLang::*;
+impl Language for PyLang {
+ fn get_ts_language(&self) -> TSLanguage {
+ match self {
+ Builtin(b) => b.get_ts_language(),
+ Custom(c) => c.get_ts_language(),
+ }
+ }
+
+ fn pre_process_pattern<'q>(&self, query: &'q str) -> Cow<'q, str> {
+ match self {
+ Builtin(b) => b.pre_process_pattern(query),
+ Custom(c) => c.pre_process_pattern(query),
+ }
+ }
+
+ #[inline]
+ fn meta_var_char(&self) -> char {
+ match self {
+ Builtin(b) => b.meta_var_char(),
+ Custom(c) => c.meta_var_char(),
+ }
+ }
+
+ #[inline]
+ fn expando_char(&self) -> char {
+ match self {
+ Builtin(b) => b.expando_char(),
+ Custom(c) => c.expando_char(),
+ }
+ }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/src/py_node.rs new/ast-grep-0.26.1+0/crates/pyo3/src/py_node.rs
--- old/ast-grep-0.26.0+0/crates/pyo3/src/py_node.rs 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/crates/pyo3/src/py_node.rs 2024-08-10 00:13:30.000000000 +0200
@@ -1,9 +1,9 @@
+use crate::py_lang::PyLang;
use crate::range::Range;
use crate::SgRoot;
use ast_grep_config::{DeserializeEnv, RuleCore, SerializableRuleCore};
use ast_grep_core::{NodeMatch, StrDoc};
-use ast_grep_language::SupportLang;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
@@ -16,7 +16,7 @@
#[pyclass(mapping)]
pub struct SgNode {
- pub inner: NodeMatch<'static, StrDoc<SupportLang>>,
+ pub inner: NodeMatch<'static, StrDoc<PyLang>>,
// refcount SgRoot
pub(crate) root: Py<SgRoot>,
}
@@ -328,7 +328,7 @@
&self,
config: Option<Bound<PyDict>>,
kwargs: Option<Bound<PyDict>>,
- ) -> PyResult<RuleCore<SupportLang>> {
+ ) -> PyResult<RuleCore<PyLang>> {
let lang = self.inner.lang();
let config = if let Some(config) = config {
config_from_dict(config)?
@@ -358,10 +358,7 @@
})
}
-fn get_matcher_from_rule(
- lang: &SupportLang,
- dict: Option<Bound<PyDict>>,
-) -> PyResult<RuleCore<SupportLang>> {
+fn get_matcher_from_rule(lang: &PyLang, dict: Option<Bound<PyDict>>) -> PyResult<RuleCore<PyLang>> {
let rule = dict.ok_or_else(|| PyErr::new::<PyValueError, _>("rule must not be empty"))?;
let env = DeserializeEnv::new(*lang);
let config = config_from_rule(rule)?;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/crates/pyo3/tests/test_register_lang.py new/ast-grep-0.26.1+0/crates/pyo3/tests/test_register_lang.py
--- old/ast-grep-0.26.0+0/crates/pyo3/tests/test_register_lang.py 1970-01-01 01:00:00.000000000 +0100
+++ new/ast-grep-0.26.1+0/crates/pyo3/tests/test_register_lang.py 2024-08-10 00:13:30.000000000 +0200
@@ -0,0 +1,35 @@
+from ast_grep_py import SgRoot, register_dynamic_language
+import platform
+
+source = """
+{
+ "test": 123
+}
+""".strip()
+
+# at the moment only test darwin arm64
+def is_arm_mac():
+ return platform.system() == 'Darwin' and platform.processor() == 'arm'
+
+def register_lang():
+ if not is_arm_mac():
+ return
+ register_dynamic_language({
+ "myjson": {
+ "library_path": "../../benches/fixtures/json-mac.so",
+ "language_symbol": "tree_sitter_json",
+ }
+ })
+
+register_lang()
+
+def test_load_json_lang():
+ if not is_arm_mac():
+ return
+ sg = SgRoot(source, "myjson")
+ root = sg.root()
+ node = root.find(pattern="123")
+ assert node
+ assert node.kind() == "number"
+ node = root.find(pattern="456")
+ assert not node
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/package.json new/ast-grep-0.26.1+0/npm/package.json
--- old/ast-grep-0.26.0+0/npm/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli",
- "version": "0.26.0",
+ "version": "0.26.1",
"publishConfig": {
"access": "public"
},
@@ -29,13 +29,13 @@
"postinstall": "node postinstall.js"
},
"optionalDependencies": {
- "@ast-grep/cli-win32-arm64-msvc": "0.26.0",
- "@ast-grep/cli-win32-ia32-msvc": "0.26.0",
- "@ast-grep/cli-win32-x64-msvc": "0.26.0",
- "@ast-grep/cli-darwin-arm64": "0.26.0",
- "@ast-grep/cli-darwin-x64": "0.26.0",
- "@ast-grep/cli-linux-arm64-gnu": "0.26.0",
- "@ast-grep/cli-linux-x64-gnu": "0.26.0"
+ "@ast-grep/cli-win32-arm64-msvc": "0.26.1",
+ "@ast-grep/cli-win32-ia32-msvc": "0.26.1",
+ "@ast-grep/cli-win32-x64-msvc": "0.26.1",
+ "@ast-grep/cli-darwin-arm64": "0.26.1",
+ "@ast-grep/cli-darwin-x64": "0.26.1",
+ "@ast-grep/cli-linux-arm64-gnu": "0.26.1",
+ "@ast-grep/cli-linux-x64-gnu": "0.26.1"
},
"bin": {
"sg": "sg",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/darwin-arm64/package.json new/ast-grep-0.26.1+0/npm/platforms/darwin-arm64/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/darwin-arm64/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/darwin-arm64/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-darwin-arm64",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"darwin"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/darwin-x64/package.json new/ast-grep-0.26.1+0/npm/platforms/darwin-x64/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/darwin-x64/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/darwin-x64/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-darwin-x64",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"darwin"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/linux-arm64-gnu/package.json new/ast-grep-0.26.1+0/npm/platforms/linux-arm64-gnu/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/linux-arm64-gnu/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/linux-arm64-gnu/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-linux-arm64-gnu",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"linux"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/linux-x64-gnu/package.json new/ast-grep-0.26.1+0/npm/platforms/linux-x64-gnu/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/linux-x64-gnu/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/linux-x64-gnu/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-linux-x64-gnu",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"linux"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/win32-arm64-msvc/package.json new/ast-grep-0.26.1+0/npm/platforms/win32-arm64-msvc/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/win32-arm64-msvc/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/win32-arm64-msvc/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-win32-arm64-msvc",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"win32"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/win32-ia32-msvc/package.json new/ast-grep-0.26.1+0/npm/platforms/win32-ia32-msvc/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/win32-ia32-msvc/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/win32-ia32-msvc/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-win32-ia32-msvc",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"win32"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/npm/platforms/win32-x64-msvc/package.json new/ast-grep-0.26.1+0/npm/platforms/win32-x64-msvc/package.json
--- old/ast-grep-0.26.0+0/npm/platforms/win32-x64-msvc/package.json 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/npm/platforms/win32-x64-msvc/package.json 2024-08-10 00:13:30.000000000 +0200
@@ -1,6 +1,6 @@
{
"name": "@ast-grep/cli-win32-x64-msvc",
- "version": "0.26.0",
+ "version": "0.26.1",
"os": [
"win32"
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ast-grep-0.26.0+0/pyproject.toml new/ast-grep-0.26.1+0/pyproject.toml
--- old/ast-grep-0.26.0+0/pyproject.toml 2024-08-08 04:44:39.000000000 +0200
+++ new/ast-grep-0.26.1+0/pyproject.toml 2024-08-10 00:13:30.000000000 +0200
@@ -4,7 +4,7 @@
[project]
name = "ast-grep-cli"
-version = "0.26.0"
+version = "0.26.1"
description = "Structural Search and Rewrite code at large scale using precise AST pattern."
authors = [{ name = "Herrington Darkholme", email = "2883231+HerringtonDarkholme(a)users.noreply.github.com" }]
maintainers = [{ name = "Herrington Darkholme", email = "2883231+HerringtonDarkholme(a)users.noreply.github.com" }]
++++++ vendor.tar.zst ++++++
/work/SRC/openSUSE:Factory/ast-grep/vendor.tar.zst /work/SRC/openSUSE:Factory/.ast-grep.new.7232/vendor.tar.zst differ: char 281831, line 1195
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package erofs-utils for openSUSE:Factory checked in at 2024-08-10 19:08:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/erofs-utils (Old)
and /work/SRC/openSUSE:Factory/.erofs-utils.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "erofs-utils"
Sat Aug 10 19:08:09 2024 rev:13 rq:1193067 version:1.8
Changes:
--------
--- /work/SRC/openSUSE:Factory/erofs-utils/erofs-utils.changes 2023-11-30 22:01:50.990228122 +0100
+++ /work/SRC/openSUSE:Factory/.erofs-utils.new.7232/erofs-utils.changes 2024-08-10 19:13:55.637047961 +0200
@@ -1,0 +2,9 @@
+Fri Aug 9 21:49:47 UTC 2024 - Jan Engelhardt <jengelh(a)inai.de>
+
+- Update to release 1.8
+ * Multi-threaded compression support with the mkfs.erofs utility.
+ * Supporting the Intel IAA hardware accelerator using the QPL
+ driver (for contemporary Xeon Scalable systems).
+ * Initial support for Zstandard (Zstd) compression.
+
+-------------------------------------------------------------------
Old:
----
v1.7.1.tar.gz
New:
----
_scmsync.obsinfo
build.specials.obscpio
v1.8.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ erofs-utils.spec ++++++
--- /var/tmp/diff_new_pack.L0rXW3/_old 2024-08-10 19:13:56.121068062 +0200
+++ /var/tmp/diff_new_pack.L0rXW3/_new 2024-08-10 19:13:56.121068062 +0200
@@ -1,7 +1,7 @@
#
# spec file for package erofs-utils
#
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
Name: erofs-utils
-Version: 1.7.1
+Version: 1.8
Release: 0
Summary: Utilities for the Extendable Read-Only Filesystem (EROFS)
License: GPL-2.0-or-later
@@ -32,6 +32,7 @@
BuildRequires: libuuid-devel
BuildRequires: pkg-config
BuildRequires: xz
+BuildRequires: pkgconfig(liblzma)
BuildRequires: pkgconfig(zlib)
Supplements: filesystem(erofs)
@@ -40,10 +41,10 @@
can create two main types of erofs images, compressed and
uncompressed:
- * For compressed images, it is able to integrate several compression
+* For compressed images, it is able to integrate several compression
algorithms, LZ4 is supported according to the current erofs kernel
implementation.
- * For uncompressed images, it can decide whether the last page of a
+* For uncompressed images, it can decide whether the last page of a
file should be inlined or not properly.
%prep
++++++ _scmsync.obsinfo ++++++
mtime: 1723240479
commit: ccd26f0e9bb248a04646cdfd13da65f41338c74ed1c5b7c64872288278f1c210
url: https://src.opensuse.org/jengelh/erofs-utils
revision: master
++++++ v1.7.1.tar.gz -> v1.8.tar.gz ++++++
++++ 13864 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package forgejo-cli for openSUSE:Factory checked in at 2024-08-10 19:08:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/forgejo-cli (Old)
and /work/SRC/openSUSE:Factory/.forgejo-cli.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "forgejo-cli"
Sat Aug 10 19:08:07 2024 rev:2 rq:1193063 version:0.1.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/forgejo-cli/forgejo-cli.changes 2024-08-08 10:59:09.173481168 +0200
+++ /work/SRC/openSUSE:Factory/.forgejo-cli.new.7232/forgejo-cli.changes 2024-08-10 19:13:54.192987992 +0200
@@ -1,0 +2,6 @@
+Fri Aug 9 21:17:00 UTC 2024 - Richard Rahl <rrahl0(a)opensuse.org>
+
+- update to 0.1.1:
+ * Suggest correct command when OAuth login isn't supported on an instance
+
+-------------------------------------------------------------------
Old:
----
forgejo-cli-0.1.0.obscpio
New:
----
forgejo-cli-0.1.1.obscpio
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ forgejo-cli.spec ++++++
--- /var/tmp/diff_new_pack.yR7Df7/_old 2024-08-10 19:13:55.313034505 +0200
+++ /var/tmp/diff_new_pack.yR7Df7/_new 2024-08-10 19:13:55.313034505 +0200
@@ -17,7 +17,7 @@
Name: forgejo-cli
-Version: 0.1.0
+Version: 0.1.1
Release: 0
Summary: CLI application for interacting with Forgejo
License: Apache-2.0 OR MIT
++++++ _service ++++++
--- /var/tmp/diff_new_pack.yR7Df7/_old 2024-08-10 19:13:55.349036001 +0200
+++ /var/tmp/diff_new_pack.yR7Df7/_new 2024-08-10 19:13:55.353036167 +0200
@@ -2,7 +2,7 @@
<service name="obs_scm" mode="manual">
<param name="url">https://codeberg.org/Cyborus/forgejo-cli.git</param>
<param name="scm">git</param>
- <param name="revision">refs/tags/v0.1.0</param>
+ <param name="revision">refs/tags/v0.1.1</param>
<param name="versionformat">@PARENT_TAG@</param>
<param name="versionrewrite-pattern">v(.*)</param>
</service>
++++++ forgejo-cli-0.1.0.obscpio -> forgejo-cli-0.1.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/forgejo-cli-0.1.0/Cargo.lock new/forgejo-cli-0.1.1/Cargo.lock
--- old/forgejo-cli-0.1.0/Cargo.lock 2024-08-08 03:08:13.000000000 +0200
+++ new/forgejo-cli-0.1.1/Cargo.lock 2024-08-09 20:59:26.000000000 +0200
@@ -542,35 +542,6 @@
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]]
-name = "fj"
-version = "0.1.0"
-dependencies = [
- "auth-git2",
- "base64ct",
- "clap",
- "comrak",
- "crossterm",
- "directories",
- "eyre",
- "forgejo-api",
- "futures",
- "git2",
- "hyper 1.4.1",
- "hyper-util",
- "open",
- "rand",
- "semver",
- "serde",
- "serde_json",
- "sha256",
- "soft_assert",
- "time",
- "tokio",
- "url",
- "uuid",
-]
-
-[[package]]
name = "flate2"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -621,6 +592,35 @@
]
[[package]]
+name = "forgejo-cli"
+version = "0.1.1"
+dependencies = [
+ "auth-git2",
+ "base64ct",
+ "clap",
+ "comrak",
+ "crossterm",
+ "directories",
+ "eyre",
+ "forgejo-api",
+ "futures",
+ "git2",
+ "hyper 1.4.1",
+ "hyper-util",
+ "open",
+ "rand",
+ "semver",
+ "serde",
+ "serde_json",
+ "sha256",
+ "soft_assert",
+ "time",
+ "tokio",
+ "url",
+ "uuid",
+]
+
+[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/forgejo-cli-0.1.0/Cargo.toml new/forgejo-cli-0.1.1/Cargo.toml
--- old/forgejo-cli-0.1.0/Cargo.toml 2024-08-08 03:08:13.000000000 +0200
+++ new/forgejo-cli-0.1.1/Cargo.toml 2024-08-09 20:59:26.000000000 +0200
@@ -1,10 +1,19 @@
[package]
-name = "fj"
-version = "0.1.0"
+name = "forgejo-cli"
+version = "0.1.1"
edition = "2021"
+license = "Apache-2.0 OR MIT"
+repository = "https://codeberg.org/Cyborus/forgejo-cli/"
+description = "CLI tool for Forgejo"
+keywords = ["cli", "forgejo"]
+categories = ["command-line-utilities", "development-tools"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[[bin]]
+name = "fj"
+path = "src/main.rs"
+
[features]
update-check = ["dep:semver"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/forgejo-cli-0.1.0/README.md new/forgejo-cli-0.1.1/README.md
--- old/forgejo-cli-0.1.0/README.md 2024-08-08 03:08:13.000000000 +0200
+++ new/forgejo-cli-0.1.1/README.md 2024-08-09 20:59:26.000000000 +0200
@@ -17,7 +17,7 @@
```
# Latest version
-cargo install --git https://codeberg.org/Cyborus/forgejo-cli.git --tag v0.0.4
+cargo install forgejo-cli
# From `main`
cargo install --git https://codeberg.org/Cyborus/forgejo-cli.git --branch main
```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/forgejo-cli-0.1.0/src/auth.rs new/forgejo-cli-0.1.1/src/auth.rs
--- old/forgejo-cli-0.1.0/src/auth.rs 2024-08-08 03:08:13.000000000 +0200
+++ new/forgejo-cli-0.1.1/src/auth.rs 2024-08-09 20:59:26.000000000 +0200
@@ -45,7 +45,7 @@
println!("{host_domain}{host_path} doesn't support easy login");
println!();
println!("Please visit {applications_url}");
- println!("to create a token, and use it to log in with `fj auth add-token`");
+ println!("to create a token, and use it to log in with `fj auth add-key`");
}
}
AuthCommand::Logout { host } => {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/forgejo-cli-0.1.0/src/repo.rs new/forgejo-cli-0.1.1/src/repo.rs
--- old/forgejo-cli-0.1.0/src/repo.rs 2024-08-08 03:08:13.000000000 +0200
+++ new/forgejo-cli-0.1.1/src/repo.rs 2024-08-09 20:59:26.000000000 +0200
@@ -2,7 +2,7 @@
use clap::Subcommand;
use eyre::{eyre, OptionExt};
-use forgejo_api::structs::CreateRepoOption;
+use forgejo_api::{structs::CreateRepoOption, Forgejo};
use url::Url;
use crate::SpecialRender;
@@ -364,107 +364,34 @@
remote,
push,
} => {
- if remote.is_some() || push {
- let repo = git2::Repository::open(".")?;
-
- let upstream = remote.as_deref().unwrap_or("origin");
- if repo.find_remote(upstream).is_ok() {
- eyre::bail!("A remote named \"{upstream}\" already exists");
- }
- }
let host = RepoInfo::get_current(host_name, None, None)?;
let api = keys.get_api(host.host_url()).await?;
- let repo_spec = CreateRepoOption {
- auto_init: Some(false),
- default_branch: Some("main".into()),
- description,
- gitignores: None,
- issue_labels: None,
- license: None,
- name: repo,
- object_format_name: None,
- private: Some(private),
- readme: Some(String::new()),
- template: Some(false),
- trust_model: Some(forgejo_api::structs::CreateRepoOptionTrustModel::Default),
- };
- let new_repo = api.create_current_user_repo(repo_spec).await?;
- let html_url = new_repo
- .html_url
- .as_ref()
- .ok_or_else(|| eyre::eyre!("new_repo does not have html_url"))?;
- println!("created new repo at {}", html_url);
-
- if remote.is_some() || push {
- let repo = git2::Repository::open(".")?;
-
- let upstream = remote.as_deref().unwrap_or("origin");
- let clone_url = new_repo
- .clone_url
- .as_ref()
- .ok_or_else(|| eyre::eyre!("new_repo does not have clone_url"))?;
- let mut remote = repo.remote(upstream, clone_url.as_str())?;
-
- if push {
- let head = repo.head()?;
- if !head.is_branch() {
- eyre::bail!("HEAD is not on a branch; cannot push to remote");
- }
- let branch_shorthand = head
- .shorthand()
- .ok_or_else(|| eyre!("branch name invalid utf-8"))?
- .to_owned();
- let branch_name = std::str::from_utf8(head.name_bytes())?.to_owned();
-
- let auth = auth_git2::GitAuthenticator::new();
- auth.push(&repo, &mut remote, &[&branch_name])?;
-
- remote.fetch(&[&branch_shorthand], None, None)?;
-
- let mut current_branch = git2::Branch::wrap(head);
- current_branch
- .set_upstream(Some(&format!("{upstream}/{branch_shorthand}")))?;
- }
- }
+ create_repo(&api, repo, description, private, remote, push).await?;
}
RepoCommand::Fork { repo, name, remote } => {
+ fn strip(s: &str) -> &str {
+ let no_scheme = s
+ .strip_prefix("https://")
+ .or_else(|| s.strip_prefix("http://"))
+ .unwrap_or(s);
+ let no_trailing_slash = no_scheme.strip_suffix("/").unwrap_or(no_scheme);
+ no_trailing_slash
+ }
match (repo.host.as_deref(), host_name) {
(Some(a), Some(b)) => {
- fn strip(s: &str) -> &str {
- let no_scheme = s
- .strip_prefix("https://")
- .or_else(|| s.strip_prefix("http://"))
- .unwrap_or(s);
- let no_trailing_slash =
- no_scheme.strip_suffix("/").unwrap_or(no_scheme);
- no_trailing_slash
- }
if strip(a) != strip(b) {
eyre::bail!("conflicting hosts {a} and {b}. please only specify one");
}
}
_ => (),
}
+
let repo_info = RepoInfo::get_current(host_name, Some(&repo), remote.as_deref())?;
let api = keys.get_api(&repo_info.host_url()).await?;
let repo = repo_info
.name()
.ok_or_eyre("couldn't get repo name, please specify")?;
- let opt = forgejo_api::structs::CreateForkOption {
- name,
- organization: None,
- };
- let new_fork = api.create_fork(repo.owner(), repo.name(), opt).await?;
- let fork_full_name = new_fork
- .full_name
- .as_deref()
- .ok_or_eyre("fork does not have name")?;
- println!(
- "Forked {}/{} into {}",
- repo.owner(),
- repo.name(),
- fork_full_name
- );
+ fork_repo(&api, repo, name).await?
}
RepoCommand::View { name, remote } => {
let repo = RepoInfo::get_current(host_name, name.as_ref(), remote.as_deref())?;
@@ -472,143 +399,13 @@
let repo = repo
.name()
.ok_or_eyre("couldn't get repo name, please specify")?;
- let repo = api.repo_get(repo.owner(), repo.name()).await?;
-
- let SpecialRender {
- dash,
- body_prefix,
- dark_grey,
- reset,
- ..
- } = crate::special_render();
-
- println!("{}", repo.full_name.ok_or_eyre("no full name")?);
-
- if let Some(parent) = &repo.parent {
- println!(
- "Fork of {}",
- parent.full_name.as_ref().ok_or_eyre("no full name")?
- );
- }
- if repo.mirror == Some(true) {
- if let Some(original) = &repo.original_url {
- println!("Mirror of {original}")
- }
- }
- let desc = repo.description.as_deref().unwrap_or_default();
- // Don't use body::markdown, this is plain text.
- if !desc.is_empty() {
- if desc.lines().count() > 1 {
- println!();
- }
- for line in desc.lines() {
- println!("{dark_grey}{body_prefix}{reset} {line}");
- }
- }
- println!();
-
- let lang = repo.language.as_deref().unwrap_or_default();
- if !lang.is_empty() {
- println!("Primary language is {lang}");
- }
-
- let stars = repo.stars_count.unwrap_or_default();
- if stars == 1 {
- print!("{stars} star {dash} ");
- } else {
- print!("{stars} stars {dash} ");
- }
-
- let watchers = repo.watchers_count.unwrap_or_default();
- print!("{watchers} watching {dash} ");
-
- let forks = repo.forks_count.unwrap_or_default();
- if forks == 1 {
- print!("{forks} fork");
- } else {
- print!("{forks} forks");
- }
- println!();
-
- let mut first = true;
- if repo.has_issues.unwrap_or_default() && repo.external_tracker.is_none() {
- let issues = repo.open_issues_count.unwrap_or_default();
- if issues == 1 {
- print!("{issues} issue");
- } else {
- print!("{issues} issues");
- }
- first = false;
- }
- if repo.has_pull_requests.unwrap_or_default() {
- if !first {
- print!(" {dash} ");
- }
- let pulls = repo.open_pr_counter.unwrap_or_default();
- if pulls == 1 {
- print!("{pulls} PR");
- } else {
- print!("{pulls} PRs");
- }
- first = false;
- }
- if repo.has_releases.unwrap_or_default() {
- if !first {
- print!(" {dash} ");
- }
- let releases = repo.release_counter.unwrap_or_default();
- if releases == 1 {
- print!("{releases} release");
- } else {
- print!("{releases} releases");
- }
- first = false;
- }
- if !first {
- println!();
- }
- if let Some(external_tracker) = &repo.external_tracker {
- if let Some(tracker_url) = &external_tracker.external_tracker_url {
- println!("Issue tracker is at {tracker_url}");
- }
- }
-
- if let Some(html_url) = &repo.html_url {
- println!();
- println!("View online at {html_url}");
- }
+ view_repo(&api, &repo).await?
}
RepoCommand::Clone { repo, path } => {
let repo = RepoInfo::get_current(host_name, Some(&repo), None)?;
let api = keys.get_api(&repo.host_url()).await?;
let name = repo.name().unwrap();
-
- let repo_data = api.repo_get(name.owner(), name.name()).await?;
- let clone_url = repo_data
- .clone_url
- .as_ref()
- .ok_or_eyre("repo does not have clone url")?;
-
- let repo_name = repo_data
- .name
- .as_deref()
- .ok_or_eyre("repo does not have name")?;
- let repo_full_name = repo_data
- .full_name
- .as_deref()
- .ok_or_eyre("repo does not have full name")?;
-
- let path = path.unwrap_or_else(|| PathBuf::from(format!("./{repo_name}")));
-
- let local_repo = clone_repo(&repo_full_name, &clone_url, &path)?;
-
- if let Some(parent) = repo_data.parent.as_deref() {
- let parent_clone_url = parent
- .clone_url
- .as_ref()
- .ok_or_eyre("parent repo does not have clone url")?;
- local_repo.remote("upstream", parent_clone_url.as_str())?;
- }
+ cmd_clone_repo(&api, &name, path).await?;
}
RepoCommand::Star { repo } => {
let repo = RepoInfo::get_current(host_name, Some(&repo), None)?;
@@ -629,19 +426,7 @@
let repo = RepoInfo::get_current(host_name, Some(&repo), None)?;
let api = keys.get_api(&repo.host_url()).await?;
let name = repo.name().unwrap();
- print!(
- "Are you sure you want to delete {}/{}? (y/N) ",
- name.owner(),
- name.name()
- );
- let user_response = crate::readline("").await?;
- let yes = matches!(user_response.trim(), "y" | "Y" | "yes" | "Yes");
- if yes {
- api.repo_delete(name.owner(), name.name()).await?;
- println!("Deleted {}/{}", name.owner(), name.name());
- } else {
- println!("Did not delete");
- }
+ delete_repo(&api, &name).await?;
}
RepoCommand::Browse { name, remote } => {
let repo = RepoInfo::get_current(host_name, name.as_ref(), remote.as_deref())?;
@@ -660,6 +445,242 @@
}
}
+pub async fn create_repo(
+ api: &Forgejo,
+ repo: String,
+ description: Option<String>,
+ private: bool,
+ remote: Option<String>,
+ push: bool,
+) -> eyre::Result<()> {
+ if remote.is_some() || push {
+ let repo = git2::Repository::open(".")?;
+
+ let upstream = remote.as_deref().unwrap_or("origin");
+ if repo.find_remote(upstream).is_ok() {
+ eyre::bail!("A remote named \"{upstream}\" already exists");
+ }
+ }
+ let repo_spec = CreateRepoOption {
+ auto_init: Some(false),
+ default_branch: Some("main".into()),
+ description,
+ gitignores: None,
+ issue_labels: None,
+ license: None,
+ name: repo,
+ object_format_name: None,
+ private: Some(private),
+ readme: Some(String::new()),
+ template: Some(false),
+ trust_model: Some(forgejo_api::structs::CreateRepoOptionTrustModel::Default),
+ };
+ let new_repo = api.create_current_user_repo(repo_spec).await?;
+ let html_url = new_repo
+ .html_url
+ .as_ref()
+ .ok_or_else(|| eyre::eyre!("new_repo does not have html_url"))?;
+ println!("created new repo at {}", html_url);
+
+ if remote.is_some() || push {
+ let repo = git2::Repository::open(".")?;
+
+ let upstream = remote.as_deref().unwrap_or("origin");
+ let clone_url = new_repo
+ .clone_url
+ .as_ref()
+ .ok_or_else(|| eyre::eyre!("new_repo does not have clone_url"))?;
+ let mut remote = repo.remote(upstream, clone_url.as_str())?;
+
+ if push {
+ let head = repo.head()?;
+ if !head.is_branch() {
+ eyre::bail!("HEAD is not on a branch; cannot push to remote");
+ }
+ let branch_shorthand = head
+ .shorthand()
+ .ok_or_else(|| eyre!("branch name invalid utf-8"))?
+ .to_owned();
+ let branch_name = std::str::from_utf8(head.name_bytes())?.to_owned();
+
+ let auth = auth_git2::GitAuthenticator::new();
+ auth.push(&repo, &mut remote, &[&branch_name])?;
+
+ remote.fetch(&[&branch_shorthand], None, None)?;
+
+ let mut current_branch = git2::Branch::wrap(head);
+ current_branch.set_upstream(Some(&format!("{upstream}/{branch_shorthand}")))?;
+ }
+ }
+
+ Ok(())
+}
+
+async fn fork_repo(api: &Forgejo, repo: &RepoName, name: Option<String>) -> eyre::Result<()> {
+ let opt = forgejo_api::structs::CreateForkOption {
+ name,
+ organization: None,
+ };
+ let new_fork = api.create_fork(repo.owner(), repo.name(), opt).await?;
+ let fork_full_name = new_fork
+ .full_name
+ .as_deref()
+ .ok_or_eyre("fork does not have name")?;
+ println!(
+ "Forked {}/{} into {}",
+ repo.owner(),
+ repo.name(),
+ fork_full_name
+ );
+
+ Ok(())
+}
+
+async fn view_repo(api: &Forgejo, repo: &RepoName) -> eyre::Result<()> {
+ let repo = api.repo_get(repo.owner(), repo.name()).await?;
+
+ let SpecialRender {
+ dash,
+ body_prefix,
+ dark_grey,
+ reset,
+ ..
+ } = crate::special_render();
+
+ println!("{}", repo.full_name.ok_or_eyre("no full name")?);
+
+ if let Some(parent) = &repo.parent {
+ println!(
+ "Fork of {}",
+ parent.full_name.as_ref().ok_or_eyre("no full name")?
+ );
+ }
+ if repo.mirror == Some(true) {
+ if let Some(original) = &repo.original_url {
+ println!("Mirror of {original}")
+ }
+ }
+ let desc = repo.description.as_deref().unwrap_or_default();
+ // Don't use body::markdown, this is plain text.
+ if !desc.is_empty() {
+ if desc.lines().count() > 1 {
+ println!();
+ }
+ for line in desc.lines() {
+ println!("{dark_grey}{body_prefix}{reset} {line}");
+ }
+ }
+ println!();
+
+ let lang = repo.language.as_deref().unwrap_or_default();
+ if !lang.is_empty() {
+ println!("Primary language is {lang}");
+ }
+
+ let stars = repo.stars_count.unwrap_or_default();
+ if stars == 1 {
+ print!("{stars} star {dash} ");
+ } else {
+ print!("{stars} stars {dash} ");
+ }
+
+ let watchers = repo.watchers_count.unwrap_or_default();
+ print!("{watchers} watching {dash} ");
+
+ let forks = repo.forks_count.unwrap_or_default();
+ if forks == 1 {
+ print!("{forks} fork");
+ } else {
+ print!("{forks} forks");
+ }
+ println!();
+
+ let mut first = true;
+ if repo.has_issues.unwrap_or_default() && repo.external_tracker.is_none() {
+ let issues = repo.open_issues_count.unwrap_or_default();
+ if issues == 1 {
+ print!("{issues} issue");
+ } else {
+ print!("{issues} issues");
+ }
+ first = false;
+ }
+ if repo.has_pull_requests.unwrap_or_default() {
+ if !first {
+ print!(" {dash} ");
+ }
+ let pulls = repo.open_pr_counter.unwrap_or_default();
+ if pulls == 1 {
+ print!("{pulls} PR");
+ } else {
+ print!("{pulls} PRs");
+ }
+ first = false;
+ }
+ if repo.has_releases.unwrap_or_default() {
+ if !first {
+ print!(" {dash} ");
+ }
+ let releases = repo.release_counter.unwrap_or_default();
+ if releases == 1 {
+ print!("{releases} release");
+ } else {
+ print!("{releases} releases");
+ }
+ first = false;
+ }
+ if !first {
+ println!();
+ }
+ if let Some(external_tracker) = &repo.external_tracker {
+ if let Some(tracker_url) = &external_tracker.external_tracker_url {
+ println!("Issue tracker is at {tracker_url}");
+ }
+ }
+
+ if let Some(html_url) = &repo.html_url {
+ println!();
+ println!("View online at {html_url}");
+ }
+
+ Ok(())
+}
+
+async fn cmd_clone_repo(
+ api: &Forgejo,
+ name: &RepoName,
+ path: Option<std::path::PathBuf>,
+) -> eyre::Result<()> {
+ let repo_data = api.repo_get(name.owner(), name.name()).await?;
+ let clone_url = repo_data
+ .clone_url
+ .as_ref()
+ .ok_or_eyre("repo does not have clone url")?;
+
+ let repo_name = repo_data
+ .name
+ .as_deref()
+ .ok_or_eyre("repo does not have name")?;
+ let repo_full_name = repo_data
+ .full_name
+ .as_deref()
+ .ok_or_eyre("repo does not have full name")?;
+
+ let path = path.unwrap_or_else(|| PathBuf::from(format!("./{repo_name}")));
+
+ let local_repo = clone_repo(&repo_full_name, &clone_url, &path)?;
+
+ if let Some(parent) = repo_data.parent.as_deref() {
+ let parent_clone_url = parent
+ .clone_url
+ .as_ref()
+ .ok_or_eyre("parent repo does not have clone url")?;
+ local_repo.remote("upstream", parent_clone_url.as_str())?;
+ }
+
+ Ok(())
+}
+
pub fn clone_repo(
repo_name: &str,
url: &url::Url,
@@ -726,3 +747,20 @@
println!("Cloned {} into {}", repo_name, path.display());
Ok(local_repo)
}
+
+async fn delete_repo(api: &Forgejo, name: &RepoName) -> eyre::Result<()> {
+ print!(
+ "Are you sure you want to delete {}/{}? (y/N) ",
+ name.owner(),
+ name.name()
+ );
+ let user_response = crate::readline("").await?;
+ let yes = matches!(user_response.trim(), "y" | "Y" | "yes" | "Yes");
+ if yes {
+ api.repo_delete(name.owner(), name.name()).await?;
+ println!("Deleted {}/{}", name.owner(), name.name());
+ } else {
+ println!("Did not delete");
+ }
+ Ok(())
+}
++++++ forgejo-cli.obsinfo ++++++
--- /var/tmp/diff_new_pack.yR7Df7/_old 2024-08-10 19:13:55.497042147 +0200
+++ /var/tmp/diff_new_pack.yR7Df7/_new 2024-08-10 19:13:55.501042313 +0200
@@ -1,5 +1,5 @@
name: forgejo-cli
-version: 0.1.0
-mtime: 1723079293
-commit: 2b25f0a292a7f4acc542a8248c073e770d633e86
+version: 0.1.1
+mtime: 1723229966
+commit: b3c242d8c5e57959f28fa084619027bc1715bdc0
++++++ vendor.tar.zst ++++++
/work/SRC/openSUSE:Factory/forgejo-cli/vendor.tar.zst /work/SRC/openSUSE:Factory/.forgejo-cli.new.7232/vendor.tar.zst differ: char 698932, line 2890
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package forgejo for openSUSE:Factory checked in at 2024-08-10 19:07:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/forgejo (Old)
and /work/SRC/openSUSE:Factory/.forgejo.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "forgejo"
Sat Aug 10 19:07:58 2024 rev:12 rq:1193061 version:7.0.7
Changes:
--------
--- /work/SRC/openSUSE:Factory/forgejo/forgejo.changes 2024-08-01 22:07:01.662897661 +0200
+++ /work/SRC/openSUSE:Factory/.forgejo.new.7232/forgejo.changes 2024-08-10 19:13:52.268908088 +0200
@@ -1,0 +2,24 @@
+Fri Aug 9 18:13:59 UTC 2024 - Johannes Kastl <opensuse_buildservice(a)ojkastl.de>
+
+- update to 7.0.7:
+ This is a security release. See the documentation for more
+ information on the upgrade procedure.
+ * Security
+ - A change introduced in Forgejo v1.21 allows a Forgejo user
+ with write permission on a repository description to inject a
+ client-side script into the web page viewed by the visitor.
+ This XSS allows for href in anchor elements to be set to a
+ javascript: URI in the repository description, which will
+ execute the specified script upon clicking (and not upon
+ loading). AllowStandardURLs is now called for the repository
+ description policy, which ensures that URIs in anchor
+ elements are mailto:, http:// or https:// and thereby
+ disallowing the javascript: URI.
+ * Bug fixes
+ - PR (backported): disallow javascript: URI in the repository
+ description
+ * Localization
+ - PR (backported): i18n: backport of #4568 #4668 and #4783 to
+ v7
+
+-------------------------------------------------------------------
Old:
----
forgejo-src-7.0.6.tar.gz
forgejo-src-7.0.6.tar.gz.asc
New:
----
forgejo-src-7.0.7.tar.gz
forgejo-src-7.0.7.tar.gz.asc
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ forgejo.spec ++++++
--- /var/tmp/diff_new_pack.o2RajP/_old 2024-08-10 19:13:53.816972377 +0200
+++ /var/tmp/diff_new_pack.o2RajP/_new 2024-08-10 19:13:53.820972543 +0200
@@ -30,7 +30,7 @@
%endif
%endif
Name: forgejo
-Version: 7.0.6
+Version: 7.0.7
Release: 0
Summary: Self-hostable forge
License: MIT
++++++ forgejo-src-7.0.6.tar.gz -> forgejo-src-7.0.7.tar.gz ++++++
/work/SRC/openSUSE:Factory/forgejo/forgejo-src-7.0.6.tar.gz /work/SRC/openSUSE:Factory/.forgejo.new.7232/forgejo-src-7.0.7.tar.gz differ: char 16, line 1
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package trivy-image for openSUSE:Factory checked in at 2024-08-10 19:07:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/trivy-image (Old)
and /work/SRC/openSUSE:Factory/.trivy-image.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "trivy-image"
Sat Aug 10 19:07:56 2024 rev:16 rq:1193017 version:2024
Changes:
--------
--- /work/SRC/openSUSE:Factory/trivy-image/trivy-image.changes 2024-08-09 16:16:57.164663871 +0200
+++ /work/SRC/openSUSE:Factory/.trivy-image.new.7232/trivy-image.changes 2024-08-10 19:13:49.396788814 +0200
@@ -1,0 +2,5 @@
+Thu Aug 8 19:28:10 UTC 2024 - Dirk Mueller <dmueller(a)suse.com>
+
+- add oci.image.ref.name
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ trivy-image.kiwi ++++++
--- /var/tmp/diff_new_pack.ot3XhI/_old 2024-08-10 19:13:50.844848950 +0200
+++ /var/tmp/diff_new_pack.ot3XhI/_new 2024-08-10 19:13:50.860849614 +0200
@@ -39,6 +39,7 @@
<label name="org.opencontainers.image.vendor" value="openSUSE Project"/>
<label name="org.opencontainers.image.source" value="%SOURCEURL%"/>
<label name="org.opencontainers.image.url" value="https://www.opensuse.org"/>
+ <label name="org.opencontainers.image.ref.name" value="%%trivy_version%%-%RELEASE%"/>
<label name="org.opensuse.reference" value="registry.opensuse.org/opensuse/trivy:%%trivy_version%%-%RELEASE%"/>
<label name="org.openbuildservice.disturl" value="%DISTURL%"/>
<label name="org.opensuse.release-stage" value="released"/>
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ugrep for openSUSE:Factory checked in at 2024-08-10 19:07:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ugrep (Old)
and /work/SRC/openSUSE:Factory/.ugrep.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ugrep"
Sat Aug 10 19:07:57 2024 rev:73 rq:1193034 version:6.4.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/ugrep/ugrep.changes 2024-08-09 16:17:18.921572232 +0200
+++ /work/SRC/openSUSE:Factory/.ugrep.new.7232/ugrep.changes 2024-08-10 19:13:51.284867223 +0200
@@ -1,0 +2,7 @@
+Fri Aug 9 17:04:45 UTC 2024 - Andreas Stieger <andreas.stieger(a)gmx.de>
+
+- update to 6.4.1:
+ * fix problem with --fixed-strings and --file FILE when FILE
+ contains an \E
+
+-------------------------------------------------------------------
Old:
----
ugrep-6.4.0.tar.gz
New:
----
ugrep-6.4.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ugrep.spec ++++++
--- /var/tmp/diff_new_pack.WyaufK/_old 2024-08-10 19:13:51.792888320 +0200
+++ /var/tmp/diff_new_pack.WyaufK/_new 2024-08-10 19:13:51.792888320 +0200
@@ -18,7 +18,7 @@
Name: ugrep
-Version: 6.4.0
+Version: 6.4.1
Release: 0
Summary: Universal grep: a feature-rich grep implementation with focus on speed
License: BSD-3-Clause
++++++ ugrep-6.4.0.tar.gz -> ugrep-6.4.1.tar.gz ++++++
/work/SRC/openSUSE:Factory/ugrep/ugrep-6.4.0.tar.gz /work/SRC/openSUSE:Factory/.ugrep.new.7232/ugrep-6.4.1.tar.gz differ: char 31, line 1
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package spack-image for openSUSE:Factory checked in at 2024-08-10 19:07:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/spack-image (Old)
and /work/SRC/openSUSE:Factory/.spack-image.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "spack-image"
Sat Aug 10 19:07:56 2024 rev:19 rq:1193016 version:unknown
Changes:
--------
--- /work/SRC/openSUSE:Factory/spack-image/spack-image.changes 2024-08-09 16:16:56.624641324 +0200
+++ /work/SRC/openSUSE:Factory/.spack-image.new.7232/spack-image.changes 2024-08-10 19:13:47.336703263 +0200
@@ -1,0 +2,5 @@
+Thu Aug 8 19:28:10 UTC 2024 - Dirk Mueller <dmueller(a)suse.com>
+
+- add oci.image.ref.name
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ Dockerfile ++++++
--- /var/tmp/diff_new_pack.SMGmic/_old 2024-08-10 19:13:48.780763232 +0200
+++ /var/tmp/diff_new_pack.SMGmic/_new 2024-08-10 19:13:48.820764893 +0200
@@ -32,6 +32,7 @@
LABEL org.opencontainers.image.created="%BUILDTIME%"
LABEL org.opencontainers.image.vendor="openSUSE Project"
LABEL org.opencontainers.image.source="%SOURCEURL%"
+LABEL org.opencontainers.image.ref.name="0.22-%RELEASE%"
LABEL org.opensuse.reference="registry.opensuse.org/opensuse/bci/spack:0.22-%RELEASE%"
LABEL org.openbuildservice.disturl="%DISTURL%"
LABEL org.opensuse.lifecycle-url="https://en.opensuse.org/Lifetime#openSUSE_BCI"
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package rust-oldstable-image for openSUSE:Factory checked in at 2024-08-10 19:07:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rust-oldstable-image (Old)
and /work/SRC/openSUSE:Factory/.rust-oldstable-image.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rust-oldstable-image"
Sat Aug 10 19:07:55 2024 rev:26 rq:1193015 version:unknown
Changes:
--------
--- /work/SRC/openSUSE:Factory/rust-oldstable-image/rust-oldstable-image.changes 2024-08-09 16:16:55.472593226 +0200
+++ /work/SRC/openSUSE:Factory/.rust-oldstable-image.new.7232/rust-oldstable-image.changes 2024-08-10 19:13:44.672592627 +0200
@@ -1,0 +2,5 @@
+Thu Aug 8 19:28:10 UTC 2024 - Dirk Mueller <dmueller(a)suse.com>
+
+- add oci.image.ref.name
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ Dockerfile ++++++
--- /var/tmp/diff_new_pack.w7ZObg/_old 2024-08-10 19:13:46.672675687 +0200
+++ /var/tmp/diff_new_pack.w7ZObg/_new 2024-08-10 19:13:46.716677514 +0200
@@ -31,6 +31,7 @@
LABEL org.opencontainers.image.created="%BUILDTIME%"
LABEL org.opencontainers.image.vendor="openSUSE Project"
LABEL org.opencontainers.image.source="%SOURCEURL%"
+LABEL org.opencontainers.image.ref.name="1.79-2.%RELEASE%"
LABEL org.opensuse.reference="registry.opensuse.org/opensuse/bci/rust:1.79-2.%RELEASE%"
LABEL org.openbuildservice.disturl="%DISTURL%"
LABEL org.opensuse.lifecycle-url="https://en.opensuse.org/Lifetime#openSUSE_BCI"
1
0