openSUSE Commits
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- 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
- 1 participants
- 383829 discussions
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-aiohttp-socks for openSUSE:Factory checked in at 2025-01-05 15:29:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-aiohttp-socks (Old)
and /work/SRC/openSUSE:Factory/.python-aiohttp-socks.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-aiohttp-socks"
Sun Jan 5 15:29:39 2025 rev:13 rq:1234669 version:0.10.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-aiohttp-socks/python-aiohttp-socks.changes 2024-11-25 23:22:45.213807913 +0100
+++ /work/SRC/openSUSE:Factory/.python-aiohttp-socks.new.1881/python-aiohttp-socks.changes 2025-01-05 15:29:45.982085206 +0100
@@ -1,0 +2,11 @@
+Fri Dec 27 07:02:43 UTC 2024 - Jiri Slaby <jslaby(a)suse.cz>
+
+- Update to 0.10.1
+ * fix ProxyConnector port type hint: str -> int
+ * Update README.md
+ * Refactoring
+ * Make host and port arguments required
+ * Fix compatibility with Python 3.8
+ * minimal typing changes
+
+-------------------------------------------------------------------
Old:
----
aiohttp_socks-0.9.1.tar.gz
New:
----
aiohttp_socks-0.10.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-aiohttp-socks.spec ++++++
--- /var/tmp/diff_new_pack.LNDYlK/_old 2025-01-05 15:29:46.634112026 +0100
+++ /var/tmp/diff_new_pack.LNDYlK/_new 2025-01-05 15:29:46.634112026 +0100
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-aiohttp-socks
-Version: 0.9.1
+Version: 0.10.1
Release: 0
Summary: SOCKS proxy connector for aiohttp
License: Apache-2.0
++++++ aiohttp_socks-0.9.1.tar.gz -> aiohttp_socks-0.10.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aiohttp_socks-0.9.1/PKG-INFO new/aiohttp_socks-0.10.1/PKG-INFO
--- old/aiohttp_socks-0.9.1/PKG-INFO 2024-11-20 14:49:16.908458500 +0100
+++ new/aiohttp_socks-0.10.1/PKG-INFO 2024-12-26 08:06:00.312892000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: aiohttp_socks
-Version: 0.9.1
+Version: 0.10.1
Summary: Proxy connector for aiohttp
Author-email: Roman Snegirev <snegiryev(a)gmail.com>
License: Apache-2.0
@@ -46,7 +46,7 @@
## Requirements
- Python >= 3.8
- aiohttp >= 3.10.0
-- python-socks[asyncio] >= 1.0.1
+- python-socks[asyncio] >= 2.4.3
## Installation
```
@@ -71,7 +71,7 @@
# port=1080,
# username='user',
# password='password',
- # rdns=True
+ # rdns=True # default is True for socks5
# )
### proxy chaining (since ver 0.3.3)
@@ -85,25 +85,6 @@
return await response.text()
```
-#### aiohttp-socks also provides `open_connection` and `create_connection` functions:
-
-```python
-from aiohttp_socks import open_connection
-
-async def fetch():
- reader, writer = await open_connection(
- proxy_url='socks5://user:password@127.0.0.1:1080',
- host='check-host.net',
- port=80
- )
- request = (b"GET /ip HTTP/1.1\r\n"
- b"Host: check-host.net\r\n"
- b"Connection: close\r\n\r\n")
-
- writer.write(request)
- return await reader.read(-1)
-```
-
## Why yet another SOCKS connector for aiohttp
Unlike [aiosocksy](https://github.com/romis2012/aiosocksy), aiohttp_socks has only single point of integration with aiohttp.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aiohttp_socks-0.9.1/README.md new/aiohttp_socks-0.10.1/README.md
--- old/aiohttp_socks-0.9.1/README.md 2024-08-02 07:42:12.000000000 +0200
+++ new/aiohttp_socks-0.10.1/README.md 2024-12-23 11:28:15.000000000 +0100
@@ -14,7 +14,7 @@
## Requirements
- Python >= 3.8
- aiohttp >= 3.10.0
-- python-socks[asyncio] >= 1.0.1
+- python-socks[asyncio] >= 2.4.3
## Installation
```
@@ -39,7 +39,7 @@
# port=1080,
# username='user',
# password='password',
- # rdns=True
+ # rdns=True # default is True for socks5
# )
### proxy chaining (since ver 0.3.3)
@@ -53,25 +53,6 @@
return await response.text()
```
-#### aiohttp-socks also provides `open_connection` and `create_connection` functions:
-
-```python
-from aiohttp_socks import open_connection
-
-async def fetch():
- reader, writer = await open_connection(
- proxy_url='socks5://user:password@127.0.0.1:1080',
- host='check-host.net',
- port=80
- )
- request = (b"GET /ip HTTP/1.1\r\n"
- b"Host: check-host.net\r\n"
- b"Connection: close\r\n\r\n")
-
- writer.write(request)
- return await reader.read(-1)
-```
-
## Why yet another SOCKS connector for aiohttp
Unlike [aiosocksy](https://github.com/romis2012/aiosocksy), aiohttp_socks has only single point of integration with aiohttp.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aiohttp_socks-0.9.1/aiohttp_socks/__init__.py new/aiohttp_socks-0.10.1/aiohttp_socks/__init__.py
--- old/aiohttp_socks-0.9.1/aiohttp_socks/__init__.py 2024-11-20 13:50:52.000000000 +0100
+++ new/aiohttp_socks-0.10.1/aiohttp_socks/__init__.py 2024-12-26 08:03:51.000000000 +0100
@@ -1,5 +1,5 @@
__title__ = 'aiohttp-socks'
-__version__ = '0.9.1'
+__version__ = '0.10.1'
from python_socks import (
ProxyError,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aiohttp_socks-0.9.1/aiohttp_socks/connector.py new/aiohttp_socks-0.10.1/aiohttp_socks/connector.py
--- old/aiohttp_socks-0.9.1/aiohttp_socks/connector.py 2024-07-31 08:28:58.000000000 +0200
+++ new/aiohttp_socks-0.10.1/aiohttp_socks/connector.py 2024-12-26 08:02:39.000000000 +0100
@@ -1,18 +1,22 @@
import asyncio
import socket
-import typing
-from asyncio import BaseTransport, StreamWriter
-from typing import Iterable
+from ssl import SSLContext
+from typing import Any, Iterable, NamedTuple, Optional, List, Tuple
-from aiohttp import TCPConnector, ClientConnectorError
-from aiohttp.abc import AbstractResolver
+from aiohttp import ClientConnectorError, TCPConnector
+from aiohttp.abc import AbstractResolver, ResolveResult
from aiohttp.client_proto import ResponseHandler
from python_socks import ProxyType, parse_proxy_url
from python_socks.async_.asyncio.v2 import Proxy
class NoResolver(AbstractResolver):
- async def resolve(self, host, port=0, family=socket.AF_INET):
+ async def resolve(
+ self,
+ host: str,
+ port: int = 0,
+ family: socket.AddressFamily = socket.AF_INET, # pylint: disable=no-member
+ ) -> List[ResolveResult]:
return [
{
'hostname': host,
@@ -36,23 +40,58 @@
See StreamWriter.__del__ method (was added in Python 3.11.5)
"""
- def __init__(self, loop: asyncio.AbstractEventLoop, writer: StreamWriter):
+ def __init__(self, loop: asyncio.AbstractEventLoop, writer: asyncio.StreamWriter) -> None:
super().__init__(loop)
self._writer = writer
-class ProxyConnector(TCPConnector):
- def __init__(
+class _BaseProxyConnector(TCPConnector):
+ async def _wrap_create_connection(
self,
- proxy_type=ProxyType.SOCKS5,
- host=None,
- port=None,
- username=None,
- password=None,
- rdns=None,
- proxy_ssl=None,
+ *args,
+ addr_infos,
+ req,
+ timeout,
+ client_error=ClientConnectorError,
**kwargs,
- ):
+ ) -> Tuple[asyncio.Transport, ResponseHandler]:
+ try:
+ host: str = addr_infos[0][4][0]
+ port: int = addr_infos[0][4][1]
+ except IndexError as e: # pragma: no cover
+ raise ValueError('Invalid arg: `addr_infos`') from e
+
+ ssl: Optional[SSLContext] = kwargs.get('ssl') # type: ignore
+
+ return await self._connect_via_proxy(
+ host=host,
+ port=port,
+ ssl=ssl,
+ timeout=timeout.sock_connect,
+ )
+
+ async def _connect_via_proxy(
+ self,
+ host: str,
+ port: int,
+ ssl: Optional[SSLContext] = None,
+ timeout: Optional[float] = None,
+ ) -> Tuple[asyncio.Transport, ResponseHandler]:
+ raise NotImplementedError
+
+
+class ProxyConnector(_BaseProxyConnector):
+ def __init__(
+ self,
+ host: str,
+ port: int,
+ proxy_type: ProxyType = ProxyType.SOCKS5,
+ username: Optional[str] = None,
+ password: Optional[str] = None,
+ rdns: Optional[bool] = None,
+ proxy_ssl: Optional[SSLContext] = None,
+ **kwargs: Any,
+ ) -> None:
kwargs['resolver'] = NoResolver()
super().__init__(**kwargs)
@@ -64,7 +103,13 @@
self._rdns = rdns
self._proxy_ssl = proxy_ssl
- async def _connect_via_proxy(self, host, port, ssl=None, timeout=None):
+ async def _connect_via_proxy(
+ self,
+ host: str,
+ port: int,
+ ssl: Optional[SSLContext] = None,
+ timeout: Optional[float] = None,
+ ) -> Tuple[asyncio.Transport, ResponseHandler]:
proxy = Proxy(
proxy_type=self._proxy_type,
host=self._proxy_host,
@@ -82,7 +127,7 @@
timeout=timeout,
)
- transport: BaseTransport = stream.writer.transport
+ transport: asyncio.Transport = stream.writer.transport
protocol: ResponseHandler = _ResponseHandler(
loop=self._loop,
writer=stream.writer,
@@ -93,32 +138,8 @@
return transport, protocol
- async def _wrap_create_connection(
- self,
- *args,
- addr_infos,
- req,
- timeout,
- client_error=ClientConnectorError,
- **kwargs,
- ):
- try:
- host = addr_infos[0][4][0]
- port = addr_infos[0][4][1]
- except IndexError: # pragma: no cover
- raise ValueError('Invalid arg: `addr_infos`')
-
- ssl = kwargs.get('ssl')
-
- return await self._connect_via_proxy(
- host=host,
- port=port,
- ssl=ssl,
- timeout=timeout.sock_connect,
- )
-
@classmethod
- def from_url(cls, url, **kwargs):
+ def from_url(cls, url: str, **kwargs: Any) -> 'ProxyConnector':
proxy_type, host, port, username, password = parse_proxy_url(url)
return cls(
proxy_type=proxy_type,
@@ -130,23 +151,29 @@
)
-class ProxyInfo(typing.NamedTuple):
+class ProxyInfo(NamedTuple):
proxy_type: ProxyType
host: str
port: int
- username: typing.Optional[str] = None
- password: typing.Optional[str] = None
- rdns: typing.Optional[bool] = None
+ username: Optional[str] = None
+ password: Optional[str] = None
+ rdns: Optional[bool] = None
-class ChainProxyConnector(TCPConnector):
+class ChainProxyConnector(_BaseProxyConnector):
def __init__(self, proxy_infos: Iterable[ProxyInfo], **kwargs):
kwargs['resolver'] = NoResolver()
super().__init__(**kwargs)
self._proxy_infos = proxy_infos
- async def _connect_via_proxy(self, host, port, ssl=None, timeout=None):
+ async def _connect_via_proxy(
+ self,
+ host: str,
+ port: int,
+ ssl: Optional[SSLContext] = None,
+ timeout: Optional[float] = None,
+ ) -> Tuple[asyncio.Transport, ResponseHandler]:
forward = None
proxy = None
for info in self._proxy_infos:
@@ -161,6 +188,8 @@
)
forward = proxy
+ assert proxy is not None
+
stream = await proxy.connect(
dest_host=host,
dest_port=port,
@@ -168,7 +197,7 @@
timeout=timeout,
)
- transport: BaseTransport = stream.writer.transport
+ transport: asyncio.Transport = stream.writer.transport
protocol: ResponseHandler = _ResponseHandler(
loop=self._loop,
writer=stream.writer,
@@ -179,32 +208,8 @@
return transport, protocol
- async def _wrap_create_connection(
- self,
- *args,
- addr_infos,
- req,
- timeout,
- client_error=ClientConnectorError,
- **kwargs,
- ):
- try:
- host = addr_infos[0][4][0]
- port = addr_infos[0][4][1]
- except IndexError: # pragma: no cover
- raise ValueError('Invalid arg: `addr_infos`')
-
- ssl = kwargs.get('ssl')
-
- return await self._connect_via_proxy(
- host=host,
- port=port,
- ssl=ssl,
- timeout=timeout.sock_connect,
- )
-
@classmethod
- def from_urls(cls, urls: Iterable[str], **kwargs):
+ def from_urls(cls, urls: Iterable[str], **kwargs: Any) -> 'ChainProxyConnector':
infos = []
for url in urls:
proxy_type, host, port, username, password = parse_proxy_url(url)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aiohttp_socks-0.9.1/aiohttp_socks.egg-info/PKG-INFO new/aiohttp_socks-0.10.1/aiohttp_socks.egg-info/PKG-INFO
--- old/aiohttp_socks-0.9.1/aiohttp_socks.egg-info/PKG-INFO 2024-11-20 14:49:16.000000000 +0100
+++ new/aiohttp_socks-0.10.1/aiohttp_socks.egg-info/PKG-INFO 2024-12-26 08:06:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: aiohttp_socks
-Version: 0.9.1
+Version: 0.10.1
Summary: Proxy connector for aiohttp
Author-email: Roman Snegirev <snegiryev(a)gmail.com>
License: Apache-2.0
@@ -46,7 +46,7 @@
## Requirements
- Python >= 3.8
- aiohttp >= 3.10.0
-- python-socks[asyncio] >= 1.0.1
+- python-socks[asyncio] >= 2.4.3
## Installation
```
@@ -71,7 +71,7 @@
# port=1080,
# username='user',
# password='password',
- # rdns=True
+ # rdns=True # default is True for socks5
# )
### proxy chaining (since ver 0.3.3)
@@ -85,25 +85,6 @@
return await response.text()
```
-#### aiohttp-socks also provides `open_connection` and `create_connection` functions:
-
-```python
-from aiohttp_socks import open_connection
-
-async def fetch():
- reader, writer = await open_connection(
- proxy_url='socks5://user:password@127.0.0.1:1080',
- host='check-host.net',
- port=80
- )
- request = (b"GET /ip HTTP/1.1\r\n"
- b"Host: check-host.net\r\n"
- b"Connection: close\r\n\r\n")
-
- writer.write(request)
- return await reader.read(-1)
-```
-
## Why yet another SOCKS connector for aiohttp
Unlike [aiosocksy](https://github.com/romis2012/aiosocksy), aiohttp_socks has only single point of integration with aiohttp.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aiohttp_socks-0.9.1/aiohttp_socks.egg-info/SOURCES.txt new/aiohttp_socks-0.10.1/aiohttp_socks.egg-info/SOURCES.txt
--- old/aiohttp_socks-0.9.1/aiohttp_socks.egg-info/SOURCES.txt 2024-11-20 14:49:16.000000000 +0100
+++ new/aiohttp_socks-0.10.1/aiohttp_socks.egg-info/SOURCES.txt 2024-12-26 08:06:00.000000000 +0100
@@ -5,6 +5,7 @@
aiohttp_socks/__init__.py
aiohttp_socks/_deprecated.py
aiohttp_socks/connector.py
+aiohttp_socks/py.typed
aiohttp_socks/utils.py
aiohttp_socks.egg-info/PKG-INFO
aiohttp_socks.egg-info/SOURCES.txt
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2025-01-05 15:29:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/crmsh (Old)
and /work/SRC/openSUSE:Factory/.crmsh.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh"
Sun Jan 5 15:29:37 2025 rev:352 rq:1234651 version:5.0.0+20250103.44145ae9
Changes:
--------
--- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2024-12-30 12:52:31.082058412 +0100
+++ /work/SRC/openSUSE:Factory/.crmsh.new.1881/crmsh.changes 2025-01-05 15:29:44.418020874 +0100
@@ -1,0 +2,25 @@
+Fri Jan 03 04:41:48 UTC 2025 - XLiang(a)suse.com
+
+- Update to version 5.0.0+20250103.44145ae9:
+ * Dev: unittests: Adjust unit test for previous commit
+ * Fix: bootstrap: Improve sync_files_to_disk function (bsc#1219537)
+
+-------------------------------------------------------------------
+Thu Jan 02 10:51:14 UTC 2025 - XLiang(a)suse.com
+
+- Update to version 5.0.0+20250102.150f4c85:
+ * Fix: unittest: rename TestPrinter to UnitTestPrinter
+
+-------------------------------------------------------------------
+Thu Jan 02 08:17:29 UTC 2025 - XLiang(a)suse.com
+
+- Update to version 5.0.0+20250102.24021985:
+ * Dev: unittests: Rewrite test_findln_by_timestamp by using fixed date
+
+-------------------------------------------------------------------
+Mon Dec 30 12:48:14 UTC 2024 - XLiang(a)suse.com
+
+- Update to version 5.0.0+20241230.14da5227:
+ * Dev: ra: Drop legacy code to get metadata of the pacemaker daemons
+
+-------------------------------------------------------------------
Old:
----
crmsh-5.0.0+20241230.aae750fc.tar.bz2
New:
----
crmsh-5.0.0+20250103.44145ae9.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.BUVKI6/_old 2025-01-05 15:29:45.006045060 +0100
+++ /var/tmp/diff_new_pack.BUVKI6/_new 2025-01-05 15:29:45.010045225 +0100
@@ -36,7 +36,7 @@
Summary: High Availability cluster command-line interface
License: GPL-2.0-or-later
Group: %{pkg_group}
-Version: 5.0.0+20241230.aae750fc
+Version: 5.0.0+20250103.44145ae9
Release: 0
URL: http://crmsh.github.io
Source0: %{name}-%{version}.tar.bz2
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.BUVKI6/_old 2025-01-05 15:29:45.062047364 +0100
+++ /var/tmp/diff_new_pack.BUVKI6/_new 2025-01-05 15:29:45.066047528 +0100
@@ -9,7 +9,7 @@
</service>
<service name="tar_scm">
<param name="url">https://github.com/ClusterLabs/crmsh.git</param>
- <param name="changesrevision">7ceabf7fa2185cf308c9f65745d4fb18edbf930a</param>
+ <param name="changesrevision">44145ae9a0bfa264864d853696e0e0a49836c8cb</param>
</service>
</servicedata>
(No newline at EOF)
++++++ crmsh-5.0.0+20241230.aae750fc.tar.bz2 -> crmsh-5.0.0+20250103.44145ae9.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20241230.aae750fc/crmsh/bootstrap.py new/crmsh-5.0.0+20250103.44145ae9/crmsh/bootstrap.py
--- old/crmsh-5.0.0+20241230.aae750fc/crmsh/bootstrap.py 2024-12-30 04:06:28.000000000 +0100
+++ new/crmsh-5.0.0+20250103.44145ae9/crmsh/bootstrap.py 2025-01-03 05:09:33.000000000 +0100
@@ -1882,9 +1882,22 @@
"""
Sync file content to disk between cluster nodes
"""
- files_string = ' '.join(filter(lambda f: os.path.isfile(f), FILES_TO_SYNC))
- if files_string:
- utils.cluster_run_cmd("sync {}".format(files_string.strip()))
+ target_files_str = ""
+
+ for f in FILES_TO_SYNC:
+ # check if the file exists on the local node
+ if not os.path.isfile(f):
+ continue
+ try:
+ # check if the file exists on the remote node
+ utils.cluster_run_cmd(f"test -f {f}")
+ except ValueError:
+ continue
+ else:
+ target_files_str += f + " "
+
+ if target_files_str:
+ utils.cluster_run_cmd(f"sync {target_files_str.strip()}")
def detect_mountpoint(seed_host: str) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20241230.aae750fc/crmsh/cibconfig.py new/crmsh-5.0.0+20250103.44145ae9/crmsh/cibconfig.py
--- old/crmsh-5.0.0+20241230.aae750fc/crmsh/cibconfig.py 2024-12-30 04:06:28.000000000 +0100
+++ new/crmsh-5.0.0+20250103.44145ae9/crmsh/cibconfig.py 2025-01-03 05:09:33.000000000 +0100
@@ -24,7 +24,7 @@
from . import crm_gv
from . import ui_utils
from . import userdir
-from .ra import get_ra, get_properties_list, get_pe_meta, get_properties_meta, RAInfo, get_resource_meta_list
+from .ra import get_ra, get_properties_list, get_properties_meta, RAInfo, get_resource_meta_list
from .utils import ext_cmd, safe_open_w, pipe_string, safe_close_w, crm_msec
from .utils import ask, lines2cli, olist
from .utils import page_string, str2tmp, ensure_sudo_readable
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20241230.aae750fc/crmsh/ra.py new/crmsh-5.0.0+20250103.44145ae9/crmsh/ra.py
--- old/crmsh-5.0.0+20241230.aae750fc/crmsh/ra.py 2024-12-30 04:06:28.000000000 +0100
+++ new/crmsh-5.0.0+20250103.44145ae9/crmsh/ra.py 2025-01-03 05:09:33.000000000 +0100
@@ -186,39 +186,19 @@
@utils.memoize
-def get_pe_meta():
- return RAInfo(utils.pacemaker_schedulerd(), "metadata")
-
-
-(a)utils.memoize
-def get_crmd_meta():
- return RAInfo(utils.pacemaker_controld(), "metadata",
- exclude_from_completion=constants.controld_metadata_do_not_complete)
-
-
-(a)utils.memoize
def get_stonithd_meta():
return RAInfo(utils.pacemaker_fenced(), "metadata")
@utils.memoize
-def get_cib_meta():
- return RAInfo(utils.pacemaker_based(), "metadata")
-
-
-(a)utils.memoize
def get_properties_meta():
cluster_option_meta = utils.get_cluster_option_metadata()
if cluster_option_meta:
return RAInfo("cluster_option", None,
exclude_from_completion=constants.controld_metadata_do_not_complete,
meta_string=cluster_option_meta)
- # get_xxx_meta() is a legacy code to get the metadata of the pacemaker daemons,
- # which will be dropped when we fully adopt to crmsh-5.x with pacemaker 3.x.
- meta = copy.deepcopy(get_crmd_meta())
- meta.add_ra_params(get_pe_meta())
- meta.add_ra_params(get_cib_meta())
- return meta
+ else:
+ raise ValueError("No cluster option metadata found")
@utils.memoize
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20241230.aae750fc/test/unittests/test_bootstrap.py new/crmsh-5.0.0+20250103.44145ae9/test/unittests/test_bootstrap.py
--- old/crmsh-5.0.0+20241230.aae750fc/test/unittests/test_bootstrap.py 2024-12-30 04:06:28.000000000 +0100
+++ new/crmsh-5.0.0+20250103.44145ae9/test/unittests/test_bootstrap.py 2025-01-03 05:09:33.000000000 +0100
@@ -1323,7 +1323,11 @@
mock_isfile.side_effect = [True, True]
bootstrap.sync_files_to_disk()
mock_isfile.assert_has_calls([mock.call("file1"), mock.call("file2")])
- mock_cluster_cmd.assert_called_once_with("sync file1 file2")
+ mock_cluster_cmd.assert_has_calls([
+ mock.call("test -f file1"),
+ mock.call("test -f file2"),
+ mock.call("sync file1 file2")
+ ])
@mock.patch('logging.Logger.debug')
@mock.patch('crmsh.sh.ClusterShell.get_stdout_or_raise_error')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20241230.aae750fc/test/unittests/test_report_utils.py new/crmsh-5.0.0+20250103.44145ae9/test/unittests/test_report_utils.py
--- old/crmsh-5.0.0+20241230.aae750fc/test/unittests/test_report_utils.py 2024-12-30 04:06:28.000000000 +0100
+++ new/crmsh-5.0.0+20250103.44145ae9/test/unittests/test_report_utils.py 2025-01-03 05:09:33.000000000 +0100
@@ -1,5 +1,7 @@
+import os
import sys
import datetime
+import tempfile
from crmsh import config
from crmsh import utils as crmutils
from crmsh.report import utils, constants
@@ -807,24 +809,37 @@
self.assertIsNone(result_line)
def test_findln_by_timestamp(self):
- target_time = "Apr 03 13:10"
- this_year = datetime.datetime.now().year
- target_time_stamp = crmutils.parse_to_timestamp(target_time+' '+str(this_year))
- with open('pacemaker.log') as f:
- data = f.read()
- constants.STAMP_TYPE = utils.determin_log_format(data)
- pacemaker_file_path = "pacemaker.log"
- result_line = utils.findln_by_timestamp(data, target_time_stamp, pacemaker_file_path)
- result_line_stamp = utils.get_timestamp(data.split('\n')[result_line-1], pacemaker_file_path)
- assert result_line_stamp > target_time_stamp
- result_pre_line_stamp = utils.get_timestamp(data.split('\n')[result_line-2], pacemaker_file_path)
- assert result_pre_line_stamp < target_time_stamp
-
- target_time = "Apr 03 11:01:19"
- target_time_stamp = crmutils.parse_to_timestamp(target_time+' '+str(this_year))
- result_line = utils.findln_by_timestamp(data, target_time_stamp, pacemaker_file_path)
- result_time = ' '.join(data.split('\n')[result_line-1].split()[:3])
- self.assertEqual(result_time, target_time)
+ data = """2024-04-03T11:01:00Z example-host app-name 1234 ID123 - - This is a log message before the target timestamp (11:01:19).
+2024-04-03T11:01:19Z example-host app-name 1234 ID123 - - This is the log message exactly at the target timestamp (11:01:19).
+2024-04-03T11:01:40Z example-host app-name 1234 ID123 - - This is a log message after the target timestamp (11:01:19).
+2024-04-03T13:09:50Z example-host app-name 1234 ID123 - - This is a log message before the target timestamp (13:10).
+2024-04-03T13:10:00Z example-host app-name 1234 ID123 - - This is the log message exactly at the target timestamp (13:10).
+2024-04-03T13:10:30Z example-host app-name 1234 ID123 - - This is a log message after the target timestamp (13:10)."""
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ temp_file_path = f.name
+ f.write(data.encode())
+ try:
+ target_time = "2024-04-03T13:00:20Z"
+ target_time_stamp = crmutils.parse_to_timestamp(target_time)
+ constants.STAMP_TYPE = utils.determin_log_format(data)
+ result_line = utils.findln_by_timestamp(data, target_time_stamp, temp_file_path)
+ assert result_line == 4
+
+ line_data = data.split('\n')[result_line-1].split()[0]
+ result_line_stamp = crmutils.parse_to_timestamp(line_data)
+ assert result_line_stamp > target_time_stamp
+
+ pre_line_data = data.split('\n')[result_line-2].split()[0]
+ result_pre_line_stamp = crmutils.parse_to_timestamp(pre_line_data)
+ assert result_pre_line_stamp < target_time_stamp
+
+ target_time = "2024-04-03T11:01:19Z"
+ target_time_stamp = crmutils.parse_to_timestamp(target_time)
+ result_line = utils.findln_by_timestamp(data, target_time_stamp, temp_file_path)
+ line_data = data.split('\n')[result_line-1].split()[0]
+ self.assertEqual(line_data, target_time)
+ finally:
+ os.remove(temp_file_path)
@mock.patch('crmsh.utils.parse_to_timestamp')
def test_get_timestamp_from_time_line_not_syslog(self, mock_parse):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20241230.aae750fc/test/unittests/test_scripts.py new/crmsh-5.0.0+20250103.44145ae9/test/unittests/test_scripts.py
--- old/crmsh-5.0.0+20241230.aae750fc/test/unittests/test_scripts.py 2024-12-30 04:06:28.000000000 +0100
+++ new/crmsh-5.0.0+20250103.44145ae9/test/unittests/test_scripts.py 2025-01-03 05:09:33.000000000 +0100
@@ -1,5 +1,3 @@
-from __future__ import print_function
-from __future__ import unicode_literals
# Copyright (C) 2014 Kristoffer Gronlund <kgronlund(a)suse.com>
# See COPYING for license information.
@@ -820,7 +818,7 @@
assert 'primitive bar IPaddr2 ip=192.168.0.15\ngroup g-foo foo bar' == actions[-1]['text'].strip()
-class TestPrinter(object):
+class UnitTestPrinter:
def __init__(self):
import types
self.actions = []
@@ -860,7 +858,7 @@
assert len(actions) == 1
assert actions[0]['name'] == 'call'
assert actions[0]['value'] == '#!/bin/sh\necho "hello world"'
- tp = TestPrinter()
+ tp = UnitTestPrinter()
scripts.run(script_a,
{"foo": "hello world"}, tp)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package openQA for openSUSE:Factory checked in at 2025-01-05 15:29:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
and /work/SRC/openSUSE:Factory/.openQA.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openQA"
Sun Jan 5 15:29:24 2025 rev:657 rq:1234652 version:4.6.1735880672.bb83b72c
Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes 2025-01-02 19:24:08.191183467 +0100
+++ /work/SRC/openSUSE:Factory/.openQA.new.1881/openQA.changes 2025-01-05 15:29:37.853750875 +0100
@@ -1,0 +2,6 @@
+Fri Jan 03 05:13:55 UTC 2025 - okurz(a)suse.com
+
+- Update to version 4.6.1735880672.bb83b72c:
+ * Dependency cron 2025-01-03
+
+-------------------------------------------------------------------
Old:
----
openQA-4.6.1735794217.a28ab50d.obscpio
New:
----
openQA-4.6.1735880672.bb83b72c.obscpio
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.EhGMaW/_old 2025-01-05 15:29:40.997880198 +0100
+++ /var/tmp/diff_new_pack.EhGMaW/_new 2025-01-05 15:29:41.013880856 +0100
@@ -18,7 +18,7 @@
%define short_name openQA-client
Name: %{short_name}-test
-Version: 4.6.1735794217.a28ab50d
+Version: 4.6.1735880672.bb83b72c
Release: 0
Summary: Test package for %{short_name}
License: GPL-2.0-or-later
++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.EhGMaW/_old 2025-01-05 15:29:41.277891715 +0100
+++ /var/tmp/diff_new_pack.EhGMaW/_new 2025-01-05 15:29:41.293892374 +0100
@@ -18,7 +18,7 @@
%define short_name openQA-devel
Name: %{short_name}-test
-Version: 4.6.1735794217.a28ab50d
+Version: 4.6.1735880672.bb83b72c
Release: 0
Summary: Test package for %{short_name}
License: GPL-2.0-or-later
++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.EhGMaW/_old 2025-01-05 15:29:41.585904385 +0100
+++ /var/tmp/diff_new_pack.EhGMaW/_new 2025-01-05 15:29:41.601905043 +0100
@@ -18,7 +18,7 @@
%define short_name openQA
Name: %{short_name}-test
-Version: 4.6.1735794217.a28ab50d
+Version: 4.6.1735880672.bb83b72c
Release: 0
Summary: Test package for openQA
License: GPL-2.0-or-later
++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.EhGMaW/_old 2025-01-05 15:29:41.849915244 +0100
+++ /var/tmp/diff_new_pack.EhGMaW/_new 2025-01-05 15:29:41.861915737 +0100
@@ -18,7 +18,7 @@
%define short_name openQA-worker
Name: %{short_name}-test
-Version: 4.6.1735794217.a28ab50d
+Version: 4.6.1735880672.bb83b72c
Release: 0
Summary: Test package for %{short_name}
License: GPL-2.0-or-later
++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.EhGMaW/_old 2025-01-05 15:29:42.209930052 +0100
+++ /var/tmp/diff_new_pack.EhGMaW/_new 2025-01-05 15:29:42.221930545 +0100
@@ -90,7 +90,7 @@
%define devel_requires %devel_no_selenium_requires chromedriver
Name: openQA
-Version: 4.6.1735794217.a28ab50d
+Version: 4.6.1735880672.bb83b72c
Release: 0
Summary: The openQA web-frontend, scheduler and tools
License: GPL-2.0-or-later
++++++ openQA-4.6.1735794217.a28ab50d.obscpio -> openQA-4.6.1735880672.bb83b72c.obscpio ++++++
/work/SRC/openSUSE:Factory/openQA/openQA-4.6.1735794217.a28ab50d.obscpio /work/SRC/openSUSE:Factory/.openQA.new.1881/openQA-4.6.1735880672.bb83b72c.obscpio differ: char 50, line 1
++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.EhGMaW/_old 2025-01-05 15:29:42.549944037 +0100
+++ /var/tmp/diff_new_pack.EhGMaW/_new 2025-01-05 15:29:42.553944201 +0100
@@ -1,5 +1,5 @@
name: openQA
-version: 4.6.1735794217.a28ab50d
-mtime: 1735794217
-commit: a28ab50de9621173298023b4e1df9e441a61a54f
+version: 4.6.1735880672.bb83b72c
+mtime: 1735880672
+commit: bb83b72c0177ca830e4ad64da21df7b006438666
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package gpu-screen-recorder for openSUSE:Factory checked in at 2025-01-05 15:29:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gpu-screen-recorder (Old)
and /work/SRC/openSUSE:Factory/.gpu-screen-recorder.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gpu-screen-recorder"
Sun Jan 5 15:29:22 2025 rev:13 rq:1234648 version:20250102
Changes:
--------
--- /work/SRC/openSUSE:Factory/gpu-screen-recorder/gpu-screen-recorder.changes 2024-12-09 21:13:09.364943446 +0100
+++ /work/SRC/openSUSE:Factory/.gpu-screen-recorder.new.1881/gpu-screen-recorder.changes 2025-01-05 15:29:33.453569890 +0100
@@ -1,0 +2,8 @@
+Fri Jan 03 04:11:20 UTC 2025 - mantarimay(a)pm.me
+
+- Update to version 20250102:
+ * Better compatibility and performance on some older AMD GPUs
+ * Better handle application audio nodes, fixing possible issue
+ with application audio not working
+
+-------------------------------------------------------------------
Old:
----
gpu-screen-recorder-20241208.tar.zst
New:
----
gpu-screen-recorder-20250102.tar.zst
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ gpu-screen-recorder.spec ++++++
--- /var/tmp/diff_new_pack.mhaMXD/_old 2025-01-05 15:29:35.053635703 +0100
+++ /var/tmp/diff_new_pack.mhaMXD/_new 2025-01-05 15:29:35.061636032 +0100
@@ -1,7 +1,7 @@
#
# spec file for package gpu-screen-recorder
#
-# Copyright (c) 2024 mantarimay
+# Copyright (c) 2025 mantarimay
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%bcond_with test
Name: gpu-screen-recorder
-Version: 20241208
+Version: 20250102
Release: 0
Summary: An extremely fast hardware-accelerated screen recorder
License: GPL-3.0-only
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.mhaMXD/_old 2025-01-05 15:29:35.401650017 +0100
+++ /var/tmp/diff_new_pack.mhaMXD/_new 2025-01-05 15:29:35.449651992 +0100
@@ -1,6 +1,6 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://repo.dec05eba.com/gpu-screen-recorder.git</param>
- <param name="changesrevision">0b9fe9a89783f42d9c3bea1cf9ebf1f4ddf70621</param></service></servicedata>
+ <param name="changesrevision">68a7dc1b7fda0f5963bb2d0a54a0bb0262a28f70</param></service></servicedata>
(No newline at EOF)
++++++ gpu-screen-recorder-20241208.tar.zst -> gpu-screen-recorder-20250102.tar.zst ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/README.md new/gpu-screen-recorder-20250102/README.md
--- old/gpu-screen-recorder-20241208/README.md 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/README.md 2025-01-02 10:42:27.000000000 +0100
@@ -23,9 +23,8 @@
## Note
This software works on X11 and Wayland on AMD, Intel and NVIDIA.
### TEMPORARY ISSUES
-1) screen-direct capture has been temporary disabled as it causes issues with stuttering. This might be a nvfbc bug.
-2) Videos are in variable framerate format. Use MPV to play such videos, otherwise you might experience stuttering in the video if you are using a buggy video player. You can try saving the video into a .mkv file instead as some software may have better support for .mkv files (such as kdenlive). You can use the "-fm cfr" option to to use constant framerate mode.
-3) FLAC audio codec is disabled at the moment because of temporary issues.
+1) Videos are in variable framerate format. Use MPV to play such videos, otherwise you might experience stuttering in the video if you are using a buggy video player. You can try saving the video into a .mkv file instead as some software may have better support for .mkv files (such as kdenlive). You can use the "-fm cfr" option to to use constant framerate mode.
+2) FLAC audio codec is disabled at the moment because of temporary issues.
### AMD/Intel/Wayland root permission
When recording a window or when using the `-w portal` option under AMD/Intel no special user permission is required,
however when recording a monitor (or when using wayland) the program needs root permission (to access KMS).\
@@ -44,7 +43,7 @@
Note that this only works when Xorg server is running as root, and using this option will only give you a performance boost if the game you are recording is bottlenecked by your GPU.\
Note! use at your own risk!
# VRR/G-SYNC
-This should work fine on AMD/Intel X11 or Wayland. On Nvidia X11 G-SYNC only works with the -w screen-direct-force option, but because of bugs in the Nvidia driver this option is not always recommended.
+This should work fine on AMD/Intel X11 or Wayland. On Nvidia X11 G-SYNC only works with the -w screen-direct option, but because of bugs in the Nvidia driver this option is not always recommended.
For example it can cause your computer to freeze when recording certain games.
# Installation
@@ -179,5 +178,5 @@
You can record with desktop portal option (`-w portal`) instead which ignores night light, if you are ok with recording without HDR.
## Kdenlive says that the video is not usable for editing because it has variable frame rate
To fix this you can either record the video in .mkv format or constant frame rate (-fm cfr).
-## Colors look incorrect when recording HDR with hevc_hdr/av1_hdr
-The latest version of KDE Plasma breaks HDR for recording applications. Wayland in general doesn't properly support recording HDR yet. Use desktop portal option (`-w portal`) for now to turn HDR recording into SDR.
\ No newline at end of file
+## Colors look incorrect when recording HDR (with hevc_hdr/av1_hdr) or using an ICC profile
+The latest version of KDE Plasma breaks HDR and ICC profiles for recording applications. Wayland in general doesn't properly support recording HDR yet. Use desktop portal option (`-w portal`) for now to turn HDR recording into SDR and to be able to record with correct colors when using an ICC profile.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/TODO new/gpu-screen-recorder-20250102/TODO
--- old/gpu-screen-recorder-20241208/TODO 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/TODO 2025-01-02 10:42:27.000000000 +0100
@@ -195,3 +195,16 @@
Improve software encoding performance.
Add option to record audio from the recorded window only.
+
+Add option to automatically select best video codec available. Add -k best, -k best_10bit and -k best_hdr.
+
+HDR is broken on kde plasma > 6.2 because of change to how HDR metadata works. See https://github.com/dec05eba/gpu-screen-recorder-issues/issues/60.
+ Use wayland color management protocol when it's available: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/14.
+
+Use different exit codes for different errors. Use one for invalid -w option, another one for invalid -a option for audio devices, etc. This is to make UI error reporting better.
+ Document these exit codes in an exit code .md file, or finally create a manpage where this can be documented.
+
+Ffmpeg fixed black bars in videos on amd when using hevc and when recording at some resolutions, such as 1080p:
+ https://github.com/FFmpeg/FFmpeg/commit/bcfbf2bac8f9eeeedc407b40596f5c7aaa0…
+ https://github.com/FFmpeg/FFmpeg/commit/d0facac679faf45d3356dff2e2cb382580d…
+ Disable gpu screen recorder black bar handling when using hevc on amd when the libavcodec version is the one that comes after those commits.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/kms/client/kms_client.c new/gpu-screen-recorder-20250102/kms/client/kms_client.c
--- old/gpu-screen-recorder-20241208/kms/client/kms_client.c 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/kms/client/kms_client.c 2025-01-02 10:42:27.000000000 +0100
@@ -11,6 +11,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
+#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/capability.h>
@@ -318,17 +319,14 @@
}
fprintf(stderr, "gsr info: gsr_kms_client_init: waiting for server to connect\n");
+ struct pollfd poll_fd = {
+ .fd = self->initial_socket_fd,
+ .events = POLLIN,
+ .revents = 0
+ };
for(;;) {
- struct timeval tv;
- fd_set rfds;
- FD_ZERO(&rfds);
- FD_SET(self->initial_socket_fd, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 100 * 1000; // 100 ms
-
- int select_res = select(1 + self->initial_socket_fd, &rfds, NULL, NULL, &tv);
- if(select_res > 0) {
+ int poll_res = poll(&poll_fd, 1, 100);
+ if(poll_res > 0 && (poll_fd.revents & POLLIN)) {
socklen_t sock_len = 0;
self->initial_client_fd = accept(self->initial_socket_fd, (struct sockaddr*)&remote_addr, &sock_len);
if(self->initial_client_fd == -1) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/kms/server/kms_server.c new/gpu-screen-recorder-20250102/kms/server/kms_server.c
--- old/gpu-screen-recorder-20241208/kms/server/kms_server.c 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/kms/server/kms_server.c 2025-01-02 10:42:27.000000000 +0100
@@ -19,6 +19,7 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_mode.h>
+#include <drm_fourcc.h>
#define MAX_CONNECTORS 32
@@ -362,7 +363,7 @@
response->items[item_index].width = drmfb->width;
response->items[item_index].height = drmfb->height;
response->items[item_index].pixel_format = drmfb->pixel_format;
- response->items[item_index].modifier = drmfb->modifier;
+ response->items[item_index].modifier = drmfb->flags & DRM_MODE_FB_MODIFIERS ? drmfb->modifier : DRM_FORMAT_MOD_INVALID;
response->items[item_index].connector_id = crtc_pair ? crtc_pair->connector_id : 0;
response->items[item_index].is_cursor = property_mask & PLANE_PROPERTY_IS_CURSOR;
if(property_mask & PLANE_PROPERTY_IS_CURSOR) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/meson.build new/gpu-screen-recorder-20250102/meson.build
--- old/gpu-screen-recorder-20241208/meson.build 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/meson.build 2025-01-02 10:42:27.000000000 +0100
@@ -1,4 +1,4 @@
-project('gpu-screen-recorder', ['c', 'cpp'], version : '4.3.4', default_options : ['warning_level=2'])
+project('gpu-screen-recorder', ['c', 'cpp'], version : '5.0.0', default_options : ['warning_level=2'])
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
if get_option('buildtype') == 'debug'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/project.conf new/gpu-screen-recorder-20250102/project.conf
--- old/gpu-screen-recorder-20241208/project.conf 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/project.conf 2025-01-02 10:42:27.000000000 +0100
@@ -1,7 +1,7 @@
[package]
name = "gpu-screen-recorder"
type = "executable"
-version = "4.3.4"
+version = "5.0.0"
platforms = ["posix"]
[config]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/src/damage.c new/gpu-screen-recorder-20250102/src/damage.c
--- old/gpu-screen-recorder-20241208/src/damage.c 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/src/damage.c 2025-01-02 10:42:27.000000000 +0100
@@ -137,7 +137,7 @@
}
memset(&self->monitor, 0, sizeof(self->monitor));
- if(strcmp(monitor_name, "screen") != 0 && strcmp(monitor_name, "screen-direct") != 0 && strcmp(monitor_name, "screen-direct-force") != 0) {
+ if(strcmp(monitor_name, "screen-direct") != 0 && strcmp(monitor_name, "screen-direct-force") != 0) {
if(!get_monitor_by_name(self->egl, GSR_CONNECTION_X11, monitor_name, &self->monitor))
fprintf(stderr, "gsr warning: gsr_damage_set_target_monitor: failed to find monitor: %s\n", monitor_name);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/src/egl.c new/gpu-screen-recorder-20250102/src/egl.c
--- old/gpu-screen-recorder-20241208/src/egl.c 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/src/egl.c 2025-01-02 10:42:27.000000000 +0100
@@ -377,7 +377,7 @@
self->glx_library = dlopen("libGLX.so.0", RTLD_LAZY);
self->gl_library = dlopen("libGL.so.1", RTLD_LAZY);
- if(!self->egl_library) {
+ if(!self->gl_library) {
fprintf(stderr, "gsr error: gsr_egl_load: failed to load libGL.so.1, error: %s\n", dlerror());
goto fail;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/src/main.cpp new/gpu-screen-recorder-20250102/src/main.cpp
--- old/gpu-screen-recorder-20241208/src/main.cpp 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/src/main.cpp 2025-01-02 10:42:27.000000000 +0100
@@ -1080,15 +1080,14 @@
usage_header();
printf("\n");
printf("OPTIONS:\n");
- printf(" -w Window id to record, a display (monitor name), \"screen\", \"screen-direct-force\", \"focused\" or \"portal\".\n");
+ printf(" -w Window id to record, a display (monitor name), \"screen\", \"screen-direct\", \"focused\" or \"portal\".\n");
printf(" If this is \"portal\" then xdg desktop screencast portal with PipeWire will be used. Portal option is only available on Wayland.\n");
printf(" If you select to save the session (token) in the desktop portal capture popup then the session will be saved for the next time you use \"portal\",\n");
printf(" but the session will be ignored unless you run GPU Screen Recorder with the '-restore-portal-session yes' option.\n");
- printf(" If this is \"screen\" or \"screen-direct-force\" then all monitors are recorded on Nvidia X11.\n");
- printf(" On AMD/Intel or wayland \"screen\" will record the first monitor found.\n");
- printf(" \"screen-direct-force\" is not recommended unless you use a VRR (G-SYNC) monitor on Nvidia X11 and you are aware that using this option can cause\n");
- printf(" games to freeze/crash or other issues because of Nvidia driver issues.\n");
- printf(" \"screen-direct-force\" option is only available on Nvidia X11. VRR works without this option on other systems.\n");
+ printf(" If this is \"screen\" then the first monitor found is recorded.\n");
+ printf(" \"screen-direct\" can only be used on Nvidia X11, to allow recording without breaking VRR (G-SYNC). This also records all of your monitors.\n");
+ printf(" Using this \"screen-direct\" option is not recommended unless you use VRR (G-SYNC) as there are Nvidia driver issues that can cause your system or games to freeze/crash.\n");
+ printf(" The \"screen-direct\" option is not needed on AMD, Intel nor Nvidia on Wayland as VRR works properly in those cases.\n");
printf(" Run GPU Screen Recorder with the --list-capture-options option to list valid values for this option.\n");
printf("\n");
printf(" -c Container format for output file, for example mp4, or flv. Only required if no output file is specified or if recording in replay buffer mode.\n");
@@ -2060,7 +2059,7 @@
}
}
-static void list_supported_capture_options(const gsr_window *window, const char *card_path, gsr_gpu_vendor vendor, bool list_monitors) {
+static void list_supported_capture_options(const gsr_window *window, const char *card_path, bool list_monitors) {
const bool wayland = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_WAYLAND;
if(!wayland) {
puts("window");
@@ -2070,14 +2069,9 @@
if(list_monitors) {
capture_options_callback options;
options.window = window;
- if(monitor_capture_use_drm(window, vendor)) {
- const bool is_x11 = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_X11;
- const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM;
- for_each_active_monitor_output(window, card_path, connection_type, output_monitor_info, &options);
- } else {
- puts("screen"); // All monitors in one, only available on Nvidia X11
- for_each_active_monitor_output(window, card_path, GSR_CONNECTION_X11, output_monitor_info, &options);
- }
+ const bool is_x11 = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_X11;
+ const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM;
+ for_each_active_monitor_output(window, card_path, connection_type, output_monitor_info, &options);
}
#ifdef GSR_PORTAL
@@ -2155,7 +2149,7 @@
puts("section=video_codecs");
list_supported_video_codecs(&egl, wayland);
puts("section=capture_options");
- list_supported_capture_options(window, egl.card_path, egl.gpu_info.vendor, list_monitors);
+ list_supported_capture_options(window, egl.card_path, list_monitors);
fflush(stdout);
@@ -2207,6 +2201,7 @@
// |card_path| can be NULL. If not NULL then |vendor| has to be valid
static void list_capture_options_command(const char *card_path, gsr_gpu_vendor vendor) {
+ (void)vendor;
bool wayland = false;
Display *dpy = XOpenDisplay(nullptr);
if (!dpy) {
@@ -2235,7 +2230,7 @@
}
if(card_path) {
- list_supported_capture_options(window, card_path, vendor, true);
+ list_supported_capture_options(window, card_path, true);
} else {
gsr_egl egl;
if(!gsr_egl_load(&egl, window, false)) {
@@ -2252,7 +2247,7 @@
list_monitors = false;
}
}
- list_supported_capture_options(window, egl.card_path, egl.gpu_info.vendor, list_monitors);
+ list_supported_capture_options(window, egl.card_path, list_monitors);
}
fflush(stdout);
@@ -2281,6 +2276,35 @@
}
}
+static void validate_monitor_get_valid(const gsr_egl *egl, std::string &window_str) {
+ const bool is_x11 = gsr_window_get_display_server(egl->window) == GSR_DISPLAY_SERVER_X11;
+ const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM;
+ const bool capture_use_drm = monitor_capture_use_drm(egl->window, egl->gpu_info.vendor);
+
+ if(strcmp(window_str.c_str(), "screen") == 0) {
+ FirstOutputCallback first_output;
+ first_output.output_name = NULL;
+ for_each_active_monitor_output(egl->window, egl->card_path, connection_type, get_first_output, &first_output);
+
+ if(first_output.output_name) {
+ window_str = first_output.output_name;
+ } else {
+ fprintf(stderr, "Error: no usable output found\n");
+ _exit(51);
+ }
+ } else if(capture_use_drm || (strcmp(window_str.c_str(), "screen-direct") != 0 && strcmp(window_str.c_str(), "screen-direct-force") != 0)) {
+ gsr_monitor gmon;
+ if(!get_monitor_by_name(egl, connection_type, window_str.c_str(), &gmon)) {
+ fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str.c_str());
+ fprintf(stderr, " \"screen\"\n");
+ if(!capture_use_drm)
+ fprintf(stderr, " \"screen-direct\"\n");
+ for_each_active_monitor_output(egl->window, egl->card_path, connection_type, monitor_output_callback_print, NULL);
+ _exit(51);
+ }
+ }
+}
+
static gsr_capture* create_capture_impl(std::string &window_str, vec2i output_resolution, bool wayland, gsr_egl *egl, int fps, VideoCodec video_codec, gsr_color_range color_range,
bool record_cursor, bool use_software_video_encoder, bool restore_portal_session, const char *portal_session_token_filepath,
gsr_color_depth color_depth)
@@ -2325,60 +2349,13 @@
_exit(2);
#endif
} else if(contains_non_hex_number(window_str.c_str())) {
- if(monitor_capture_use_drm(egl->window, egl->gpu_info.vendor)) {
- const bool is_x11 = gsr_window_get_display_server(egl->window) == GSR_DISPLAY_SERVER_X11;
- const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM;
-
- if(strcmp(window_str.c_str(), "screen") == 0) {
- FirstOutputCallback first_output;
- first_output.output_name = NULL;
- for_each_active_monitor_output(egl->window, egl->card_path, connection_type, get_first_output, &first_output);
-
- if(first_output.output_name) {
- window_str = first_output.output_name;
- } else {
- fprintf(stderr, "Error: no usable output found\n");
- _exit(1);
- }
- } else {
- gsr_monitor gmon;
- if(!get_monitor_by_name(egl, connection_type, window_str.c_str(), &gmon)) {
- fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str.c_str());
- fprintf(stderr, " \"screen\"\n");
- for_each_active_monitor_output(egl->window, egl->card_path, connection_type, monitor_output_callback_print, NULL);
- _exit(1);
- }
- }
- } else {
- if(strcmp(window_str.c_str(), "screen") != 0 && strcmp(window_str.c_str(), "screen-direct") != 0 && strcmp(window_str.c_str(), "screen-direct-force") != 0) {
- gsr_monitor gmon;
- if(!get_monitor_by_name(egl, GSR_CONNECTION_X11, window_str.c_str(), &gmon)) {
- Display *display = (Display*)gsr_window_get_display(egl->window);
- const int screens_width = XWidthOfScreen(DefaultScreenOfDisplay(display));
- const int screens_height = XWidthOfScreen(DefaultScreenOfDisplay(display));
- fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str.c_str());
- fprintf(stderr, " \"screen\" (%dx%d+%d+%d)\n", screens_width, screens_height, 0, 0);
- fprintf(stderr, " \"screen-direct\" (%dx%d+%d+%d)\n", screens_width, screens_height, 0, 0);
- fprintf(stderr, " \"screen-direct-force\" (%dx%d+%d+%d)\n", screens_width, screens_height, 0, 0);
- for_each_active_monitor_output(egl->window, egl->card_path, GSR_CONNECTION_X11, monitor_output_callback_print, NULL);
- _exit(1);
- }
- }
- }
-
- if(egl->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA && !wayland) {
+ validate_monitor_get_valid(egl, window_str);
+ if(!monitor_capture_use_drm(egl->window, egl->gpu_info.vendor)) {
const char *capture_target = window_str.c_str();
- bool direct_capture = strcmp(window_str.c_str(), "screen-direct") == 0;
+ const bool direct_capture = strcmp(window_str.c_str(), "screen-direct") == 0 || strcmp(window_str.c_str(), "screen-direct-force") == 0;
if(direct_capture) {
capture_target = "screen";
- // TODO: Temporary disable direct capture because push model causes stuttering when it's direct capturing. This might be a nvfbc bug. This does not happen when using a compositor.
- direct_capture = false;
- fprintf(stderr, "Warning: screen-direct has temporary been disabled as it causes stuttering. This is likely a NvFBC bug. Falling back to \"screen\".\n");
- }
-
- if(strcmp(window_str.c_str(), "screen-direct-force") == 0) {
- direct_capture = true;
- capture_target = "screen";
+ fprintf(stderr, "Warning: %s capture option is not recommended unless you use G-SYNC as Nvidia has driver issues that can cause your system or games to freeze/crash.\n", window_str.c_str());
}
gsr_capture_nvfbc_params nvfbc_params;
@@ -2412,7 +2389,7 @@
}
} else {
if(wayland) {
- fprintf(stderr, "Error: GPU Screen Recorder window capture only works in a pure X11 session. Xwayland is not supported. You can record a monitor instead on wayland\n");
+ fprintf(stderr, "Error: GPU Screen Recorder window capture only works in a pure X11 session. Xwayland is not supported. You can record a monitor instead on wayland or use -w portal option which supports window capture if your wayland compositor supports window capture\n");
_exit(2);
}
@@ -2533,7 +2510,7 @@
for(const auto &audio_device_input : audio_devices.audio_inputs) {
fprintf(stderr, " %s (%s)\n", audio_device_input.name.c_str(), audio_device_input.description.c_str());
}
- _exit(2);
+ _exit(50);
}
}
}
@@ -3043,11 +3020,6 @@
_exit(0);
} else if(argc == 4) {
const char *card_path = argv[2];
- if(!try_card_has_valid_plane(card_path)) {
- fprintf(stderr, "Error: \"%s\" is not a valid /dev/dri/cardN card. Make sure that you have at least one monitor connected\n", card_path);
- _exit(1);
- }
-
const char *vendor_str = argv[3];
gsr_gpu_vendor vendor;
if(!gpu_vendor_from_string(vendor_str, &vendor)) {
@@ -3100,17 +3072,17 @@
for(int i = 1; i < argc; i += 2) {
auto it = args.find(argv[i]);
if(it == args.end()) {
- fprintf(stderr, "Invalid argument '%s'\n", argv[i]);
+ fprintf(stderr, "Error: invalid argument '%s'\n", argv[i]);
usage();
}
if(!it->second.values.empty() && !it->second.list) {
- fprintf(stderr, "Expected argument '%s' to only be specified once\n", argv[i]);
+ fprintf(stderr, "Error: expected argument '%s' to only be specified once\n", argv[i]);
usage();
}
if(i + 1 >= argc) {
- fprintf(stderr, "Missing value for argument '%s'\n", argv[i]);
+ fprintf(stderr, "Error: missing value for argument '%s'\n", argv[i]);
usage();
}
@@ -3119,7 +3091,7 @@
for(auto &it : args) {
if(!it.second.optional && !it.second.value()) {
- fprintf(stderr, "Missing argument '%s'\n", it.first.c_str());
+ fprintf(stderr, "Error: missing argument '%s'\n", it.first.c_str());
usage();
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241208/src/pipewire_audio.c new/gpu-screen-recorder-20250102/src/pipewire_audio.c
--- old/gpu-screen-recorder-20241208/src/pipewire_audio.c 2024-12-08 03:15:18.000000000 +0100
+++ new/gpu-screen-recorder-20250102/src/pipewire_audio.c 2025-01-02 10:42:27.000000000 +0100
@@ -370,12 +370,11 @@
}
static struct pw_properties* gsr_pipewire_create_null_audio_sink(const char *name) {
- struct spa_error_location err_loc;
char props_str[512];
snprintf(props_str, sizeof(props_str), "{ factory.name=support.null-audio-sink node.name=\"%s\" media.class=Audio/Sink object.linger=false audio.position=[FL FR] monitor.channel-volumes=true monitor.passthrough=true adjust_time=0 slaves=\"\" }", name);
- struct pw_properties *props = pw_properties_new_string_checked(props_str, strlen(props_str), &err_loc);
+ struct pw_properties *props = pw_properties_new_string(props_str);
if(!props) {
- fprintf(stderr, "gsr error: gsr_pipewire_create_null_audio_sink: failed to create virtual sink properties, error: %d:%d: %s\n", err_loc.line, err_loc.col, err_loc.reason);
+ fprintf(stderr, "gsr error: gsr_pipewire_create_null_audio_sink: failed to create virtual sink properties\n");
return NULL;
}
return props;
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package gpu-screen-recorder-gtk for openSUSE:Factory checked in at 2025-01-05 15:29:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gpu-screen-recorder-gtk (Old)
and /work/SRC/openSUSE:Factory/.gpu-screen-recorder-gtk.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gpu-screen-recorder-gtk"
Sun Jan 5 15:29:21 2025 rev:12 rq:1234647 version:20250102
Changes:
--------
--- /work/SRC/openSUSE:Factory/gpu-screen-recorder-gtk/gpu-screen-recorder-gtk.changes 2024-12-03 20:47:28.647713758 +0100
+++ /work/SRC/openSUSE:Factory/.gpu-screen-recorder-gtk.new.1881/gpu-screen-recorder-gtk.changes 2025-01-05 15:29:32.385525959 +0100
@@ -1,0 +2,16 @@
+Fri Jan 03 04:11:10 UTC 2025 - mantarimay(a)pm.me
+
+- Update to version 20250102:
+ * Fix regression: incorrect window resulting in incorrect game
+ name for video, and background for uncomposited x11
+ * Fix unable to properly add program to system startup on
+ immutable distros
+ * Fix streaming not working in the new UI
+ * Open the running new UI when trying to launch it again instead
+ of showing an error, to allow switching back to the old UI in
+ case of errors
+ * Add a new experimental UI, a ShadowPlay-like fullscreen
+ overlay UI with support for global hotkeys on any Wayland
+ compositor
+
+-------------------------------------------------------------------
Old:
----
gpu-screen-recorder-gtk-20241124.tar.zst
New:
----
gpu-screen-recorder-gtk-20250102.tar.zst
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ gpu-screen-recorder-gtk.spec ++++++
--- /var/tmp/diff_new_pack.MeeYuA/_old 2025-01-05 15:29:33.073554259 +0100
+++ /var/tmp/diff_new_pack.MeeYuA/_new 2025-01-05 15:29:33.077554424 +0100
@@ -1,7 +1,7 @@
#
# spec file for package gpu-screen-recorder-gtk
#
-# Copyright (c) 2024 mantarimay
+# Copyright (c) 2025 mantarimay
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
%bcond_with test
%define appid com.dec05eba.gpu_screen_recorder
Name: gpu-screen-recorder-gtk
-Version: 20241124
+Version: 20250102
Release: 0
Summary: GTK frontend for GPU Screen Recorder
License: GPL-3.0-only
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.MeeYuA/_old 2025-01-05 15:29:33.129556563 +0100
+++ /var/tmp/diff_new_pack.MeeYuA/_new 2025-01-05 15:29:33.137556892 +0100
@@ -1,6 +1,6 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://repo.dec05eba.com/gpu-screen-recorder-gtk.git</param>
- <param name="changesrevision">26adb4d8189ddad7d33a74ba2f356ea97c288fd8</param></service></servicedata>
+ <param name="changesrevision">33071d4c8413b52d628d0253270ce3c5d3743845</param></service></servicedata>
(No newline at EOF)
++++++ gpu-screen-recorder-gtk-20241124.tar.zst -> gpu-screen-recorder-gtk-20250102.tar.zst ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/README.md new/gpu-screen-recorder-gtk-20250102/README.md
--- old/gpu-screen-recorder-gtk-20241124/README.md 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/README.md 2025-01-02 15:36:27.000000000 +0100
@@ -5,9 +5,9 @@
There is a new alternative UI for GPU Screen Recorder in the style of ShadowPlay available here: [GPU Screen Recorder UI](https://git.dec05eba.com/gpu-screen-recorder-ui/).
# Installation
-This program depends on [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/) which needs to be installed first.\
-Run `sudo ./install.sh` or if you are running Arch Linux, then you can find gpu screen recorder gtk on aur under the name gpu-screen-recorder-gtk (`yay -S gpu-screen-recorder-gtk`).\
-You can also install gpu screen recorder (the gtk gui version) from [flathub](https://flathub.org/apps/details/com.dec05eba.gpu_screen_recorder). This flatpak includes gpu-screen-recorder so no need to install that first.
+If you are using an Arch Linux based distro then you can find gpu screen recorder gtk on aur under the name gpu-screen-recorder-gtk (`yay -S gpu-screen-recorder-gtk`).\
+If you are running another distro then you can run `sudo ./install.sh`, but you need to manually install the dependencies, as described below.\
+You can also install gpu screen recorder from [flathub](https://flathub.org/apps/details/com.dec05eba.gpu_screen_recorder). This flatpak includes both this UI and gpu-screen-recorder so no need to install that first.
# Dependencies
GPU Screen Recorder GTK uses meson build system so you need to install `meson` to build GPU Screen Recorder GTK.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/TODO new/gpu-screen-recorder-gtk-20250102/TODO
--- old/gpu-screen-recorder-gtk-20241124/TODO 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/TODO 2025-01-02 15:36:27.000000000 +0100
@@ -69,4 +69,4 @@
Move x11 hotkey code to its own file.
-Add audio devices/app refresh button.
\ No newline at end of file
+Detect gpu screen recorder flatpak update and restart the gsr-ui systemd service to apply the update. Or show a notification when it has been updated and can be restarted to apply update.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/com.dec05eba.gpu_screen_recorder.appdata.xml new/gpu-screen-recorder-gtk-20250102/com.dec05eba.gpu_screen_recorder.appdata.xml
--- old/gpu-screen-recorder-gtk-20241124/com.dec05eba.gpu_screen_recorder.appdata.xml 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/com.dec05eba.gpu_screen_recorder.appdata.xml 2025-01-02 15:36:27.000000000 +0100
@@ -37,6 +37,9 @@
<li>AAC</li>
</ul>
<p>
+ At the moment the program comes with two different UIs. A gtk based one and a new experimental ShadowPlay-like fullscreen overlay UI. The gtk based UI will be removed in the future.
+ </p>
+ <p>
Recording a monitor requires (restricted) root access which means that you have to install GPU Screen Recorder system-wide: "flatpak install --system com.dec05eba.gpu_screen_recorder"
and pkexec needs to be installed on the system and a polkit agent needs to be running.
Note that this only applies to when recording a monitor on AMD/Intel or when recording on Wayland without using the desktop portal option.
@@ -61,25 +64,71 @@
You can find which NVIDIA driver version is running on your system by running "cat /proc/driver/nvidia/version".
</p>
<p>GPU Screen Recorder flatpak can install files in $HOME/.local/share/gpu-screen-recorder. If you want to uninstall GPU Screen Recorder then you will have to remove this directory manually.</p>
+ <p>If you tried out the new UI then a systemd service was added to ~/.local/share/systemd/user/gpu-screen-recorder-ui.service. If you want to uninstall GPU Screen Recorder then you will have to remove this file.</p>
</description>
<launchable type="desktop-id">com.dec05eba.gpu_screen_recorder.desktop</launchable>
<screenshots>
<screenshot type="default">
- <caption>Simple view</caption>
+ <caption>Front page</caption>
+ <image>https://raw.githubusercontent.com/dec05eba/com.dec05eba.gpu_screen_recorder…</image>
+ </screenshot>
+ <screenshot>
+ <caption>Settings page</caption>
+ <image>https://raw.githubusercontent.com/dec05eba/com.dec05eba.gpu_screen_recorder…</image>
+ </screenshot>
+ <screenshot>
+ <caption>Simple view in the old UI</caption>
<image>https://raw.githubusercontent.com/dec05eba/com.dec05eba.gpu_screen_recorder…</image>
</screenshot>
<screenshot>
- <caption>Advanced view</caption>
+ <caption>Advanced view in the old UI</caption>
<image>https://raw.githubusercontent.com/dec05eba/com.dec05eba.gpu_screen_recorder…</image>
</screenshot>
<screenshot>
- <caption>Recording page</caption>
+ <caption>Recording page in the old UI</caption>
<image>https://raw.githubusercontent.com/dec05eba/com.dec05eba.gpu_screen_recorder…</image>
</screenshot>
</screenshots>
<releases>
+ <release version="5.0.4" date="2025-01-01">
+ <description>
+ <ul>
+ <li>Fix regression: incorrect window resulting in incorrect game name for video, and background for uncomposited x11</li>
+ </ul>
+ </description>
+ </release>
+ <release version="5.0.3" date="2024-12-31">
+ <description>
+ <ul>
+ <li>Fix unable to properly add program to system startup on immutable distros</li>
+ </ul>
+ </description>
+ </release>
+ <release version="5.0.2" date="2024-12-31">
+ <description>
+ <ul>
+ <li>Fix streaming not working in the new UI</li>
+ </ul>
+ </description>
+ </release>
+ <release version="5.0.1" date="2024-12-30">
+ <description>
+ <ul>
+ <li>Open the running new UI when trying to launch it again instead of showing an error, to allow switching back to the old UI in case of errors</li>
+ </ul>
+ </description>
+ </release>
+ <release version="5.0.0" date="2024-12-29">
+ <description>
+ <ul>
+ <li>Add a new experimental UI, a ShadowPlay-like fullscreen overlay UI with support for global hotkeys on any Wayland compositor</li>
+ <li>Better compatibility and performance on some older AMD GPUs</li>
+ <li>Better handle application audio nodes, fixing possible issue with application audio not working</li>
+ </ul>
+ </description>
+ </release>
<release version="4.3.3" date="2024-11-22">
<description>
<ul>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/meson.build new/gpu-screen-recorder-gtk-20250102/meson.build
--- old/gpu-screen-recorder-gtk-20241124/meson.build 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/meson.build 2025-01-02 15:36:27.000000000 +0100
@@ -1,4 +1,4 @@
-project('gpu-screen-recorder-gtk', ['c', 'cpp'], version : '4.3.3', default_options : ['warning_level=2'])
+project('gpu-screen-recorder-gtk', ['c', 'cpp'], version : '5.0.0', default_options : ['warning_level=2'])
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
if get_option('buildtype') == 'debug'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/project.conf new/gpu-screen-recorder-gtk-20250102/project.conf
--- old/gpu-screen-recorder-gtk-20241124/project.conf 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/project.conf 2025-01-02 15:36:27.000000000 +0100
@@ -1,7 +1,7 @@
[package]
name = "gpu-screen-recorder-gtk"
type = "executable"
-version = "4.3.3"
+version = "5.0.0"
platforms = ["posix"]
[config]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/src/config.hpp new/gpu-screen-recorder-gtk-20250102/src/config.hpp
--- old/gpu-screen-recorder-gtk-20241124/src/config.hpp 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/src/config.hpp 2025-01-02 15:36:27.000000000 +0100
@@ -48,6 +48,8 @@
bool hevc_amd_bug_warning_shown = false;
bool av1_amd_bug_warning_shown = false;
bool restore_portal_session = true;
+ bool use_new_ui = false;
+ int32_t installed_gsr_global_hotkeys_version = 0;
};
struct YoutubeStreamConfig {
@@ -334,6 +336,8 @@
{"main.hevc_amd_bug_warning_shown", {CONFIG_TYPE_BOOL, &config.main_config.hevc_amd_bug_warning_shown}},
{"main.av1_amd_bug_warning_shown", {CONFIG_TYPE_BOOL, &config.main_config.av1_amd_bug_warning_shown}},
{"main.restore_portal_session", {CONFIG_TYPE_BOOL, &config.main_config.restore_portal_session}},
+ {"main.use_new_ui", {CONFIG_TYPE_BOOL, &config.main_config.use_new_ui}},
+ {"main.installed_gsr_global_hotkeys_version", {CONFIG_TYPE_I32, &config.main_config.installed_gsr_global_hotkeys_version}},
{"streaming.service", {CONFIG_TYPE_STRING, &config.streaming_config.streaming_service}},
{"streaming.youtube.key", {CONFIG_TYPE_STRING, &config.streaming_config.youtube.stream_key}},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-gtk-20241124/src/main.cpp new/gpu-screen-recorder-gtk-20250102/src/main.cpp
--- old/gpu-screen-recorder-gtk-20241124/src/main.cpp 2024-11-24 22:52:36.000000000 +0100
+++ new/gpu-screen-recorder-gtk-20250102/src/main.cpp 2025-01-02 15:36:27.000000000 +0100
@@ -20,6 +20,8 @@
#include <vector>
#include <libayatana-appindicator/app-indicator.h>
+#define GSR_CURRENT_GLOBAL_HOTKEYS_CODE_VERSION 1
+
#ifndef GSR_VERSION
#define GSR_VERSION "unknown"
#endif
@@ -151,6 +153,7 @@
static bool streaming = false;
static pid_t gpu_screen_recorder_process = -1;
static int prev_exit_status = -1;
+static bool config_empty = false;
static Config config;
static std::string record_file_current_filename;
static bool nvfbc_installed = false;
@@ -241,7 +244,6 @@
struct SupportedCaptureOptions {
bool window = false;
bool focused = false;
- bool screen = false;
bool portal = false;
std::vector<GsrMonitor> monitors;
};
@@ -1033,6 +1035,7 @@
return GDK_FILTER_CONTINUE;
Window target_win = ev->xbutton.subwindow;
+ // TODO: Fix, this is incorrect when trying to record steam window. For steam window
Window new_window = window_get_target_window_child(_select_window_userdata->display, target_win);
if(new_window)
target_win = new_window;
@@ -1396,13 +1399,13 @@
if(flatpak && !flatpak_is_installed_as_system()) {
if(gsr_info.system_info.display_server == DisplayServer::WAYLAND) {
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "GPU Screen Recorder needs to be installed system-wide to record your monitor on Wayland when not using the portal option. To install GPU Screen recorder system-wide, you can run this command:\n"
+ "GPU Screen Recorder needs to be installed system-wide to record your monitor on Wayland when not using the portal option. You can run this command to install GPU Screen recorder system-wide:\n"
"flatpak install --system com.dec05eba.gpu_screen_recorder\n");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
} else {
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "GPU Screen Recorder needs to be installed system-wide to record your monitor on AMD/Intel when not using the portal option. To install GPU Screen recorder system-wide, you can run this command:\n"
+ "GPU Screen Recorder needs to be installed system-wide to record your monitor on AMD/Intel when not using the portal option. You can run this command to install GPU Screen recorder system-wide:\n"
"flatpak install --system com.dec05eba.gpu_screen_recorder\n"
"Alternatively, record a single window which doesn't have this restriction.");
gtk_dialog_run(GTK_DIALOG(dialog));
@@ -2595,8 +2598,6 @@
_gsr_info->supported_capture_options.window = true;
else if(line == "focused")
_gsr_info->supported_capture_options.focused = true;
- else if(line == "screen")
- _gsr_info->supported_capture_options.screen = true;
else if(line == "portal")
_gsr_info->supported_capture_options.portal = true;
else
@@ -2706,6 +2707,112 @@
g_free(id);
}
+static void launch_gsr_ui(bool show_ui) {
+ const char *args[] = { "gsr-ui", show_ui ? "launch-show" : "launch-hide", nullptr };
+ execvp(args[0], (char* const*)args);
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "gsr-ui (gpu-screen-recorder-ui) isn't installed. Please install it first.");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
+
+static gboolean on_click_switch_to_new_ui(GtkButton*, gpointer) {
+ if(!dpy) {
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "The new UI only works on X11 or through XWayland on Wayland. Native Wayland is not supported because Wayland is missing features required by this software.\n"
+ "Install X11 on your system to use the new UI.");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return true;
+ }
+
+ if(!is_pkexec_installed()) {
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "pkexec needs to be installed to switch to the new UI");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return true;
+ }
+
+ if(!flatpak_is_installed_as_system()) {
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "GPU Screen Recorder needs to be installed system-wide to use the new UI. You can run this command to install GPU Screen recorder system-wide:\n"
+ "flatpak install --system com.dec05eba.gpu_screen_recorder\n");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return true;
+ }
+
+ GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ "You are about to try out the new UI, which is a ShadowPlay-like fullscreen UI. It runs in the background and you have to show/hide it by pressing Alt+Z.\n"
+ "This new UI is still experimental and you may experience issues depending on your system. You can switch back to the old UI at any time by opening the UI and clicking on the settings button and clicking on the \"Go back to the old UI\" button.\n"
+ "Note that at the moment it assumes you are using a keyboard with qwerty layout. If you are using another keyboard layout then instead of pressing Alt+Z you have to press the key that has been switched the with Z key.\n"
+ "\n"
+ "This new UI comes with new features, such as being able to automatically launch it on system startup by enabling it in settings, and hotkey support on any Wayland compositor.\n"
+ "\n"
+ "If you are using an NVIDIA GPU then you may experience issue with recording/replay if a suspend happens while recording/using replay. This is an NVIDIA driver issue and it also happens in the old UI.\n"
+ "See this for a workaround: <a href=\"https://wiki.archlinux.org/title/NVIDIA/Tips_and_tricks#Preserve_video_memo…">Arch Wiki - Preserve video memory after suspend</a>.\n"
+ "\n"
+ "Are you sure you want to switch to the new UI?");
+ gint response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ switch(response) {
+ case GTK_RESPONSE_YES:
+ break;
+ case GTK_RESPONSE_NO:
+ default:
+ return true;
+ }
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ "The new UI needs root privileges to finish setup to make global hotkeys and recording work on any system. The new UI will also be added to system startup.\n"
+ "\n"
+ "Are you sure you want to continue?");
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ switch(response) {
+ case GTK_RESPONSE_YES:
+ break;
+ case GTK_RESPONSE_NO:
+ default:
+ return true;
+ }
+
+ const int exit_code = system("flatpak-spawn --host -- /var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/kms-server-proxy setup-gsr-ui");
+ if(exit_code != 0) {
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "Failed to setup the new UI. You either cancelled the installation or you don't have pkexec installed and a polkit agent running.");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return true;
+ }
+
+ config.main_config.use_new_ui = true;
+ config.main_config.installed_gsr_global_hotkeys_version = GSR_CURRENT_GLOBAL_HOTKEYS_CODE_VERSION;
+ save_configs();
+
+ bool service_install_successful = (system(
+ "data_home=$(flatpak-spawn --host -- /bin/sh -c 'echo \"${XDG_DATA_HOME:-$HOME/.local/share}\"') && "
+ "flatpak-spawn --host -- install -Dm644 /var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/share/gpu-screen-recorder/gpu-screen-recorder-ui.service \"$data_home/systemd/user/gpu-screen-recorder-ui.service\"") == 0);
+ service_install_successful &= (system("flatpak-spawn --host -- systemctl --user daemon-reload") == 0);
+ service_install_successful &= (system("flatpak-spawn --host -- systemctl enable --now --user gpu-screen-recorder-ui") == 0);
+ if(!service_install_successful) {
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
+ "Failed to add GPU Screen Recorder to system startup. If you want the new UI to start on system startup then you need to add this command to system startup:\n"
+ "flatpak run com.dec05eba.gpu_screen_recorder gsr-ui");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ }
+
+ if(!service_install_successful)
+ launch_gsr_ui(true);
+
+ g_application_quit(G_APPLICATION(select_window_userdata.app));
+ return true;
+}
+
static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *app) {
GtkGrid *main_grid = GTK_GRID(gtk_grid_new());
gtk_stack_add_named(stack, GTK_WIDGET(main_grid), "common-settings");
@@ -2723,7 +2830,9 @@
int notifications_area_row = 0;
GtkGrid *simple_advanced_grid = GTK_GRID(gtk_grid_new());
- gtk_grid_attach(main_grid, GTK_WIDGET(simple_advanced_grid), 0, main_grid_row++, 2, 1);
+ gtk_grid_set_column_spacing(simple_advanced_grid, 10);
+ gtk_grid_attach(main_grid, GTK_WIDGET(simple_advanced_grid), 0, main_grid_row++, flatpak ? 3 : 2, 1);
+
gtk_grid_attach(simple_advanced_grid, gtk_label_new("View: "), 0, 0, 1, 1);
view_combo_box = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
g_signal_connect(view_combo_box, "scroll-event", G_CALLBACK(scroll_event_ignore), NULL);
@@ -2734,6 +2843,12 @@
gtk_combo_box_set_active(GTK_COMBO_BOX(view_combo_box), 0);
g_signal_connect(view_combo_box, "changed", G_CALLBACK(view_combo_box_change_callback), view_combo_box);
+ if(flatpak) {
+ GtkButton *switch_to_new_ui_button = GTK_BUTTON(gtk_button_new_with_label("Try out the new UI"));
+ gtk_grid_attach(simple_advanced_grid, GTK_WIDGET(switch_to_new_ui_button), 2, 0, 1, 1);
+ g_signal_connect(switch_to_new_ui_button, "clicked", G_CALLBACK(on_click_switch_to_new_ui), nullptr);
+ }
+
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
gtk_scrolled_window_set_min_content_width(scrolled_window, 100);
gtk_scrolled_window_set_min_content_height(scrolled_window, 100);
@@ -2796,12 +2911,6 @@
const bool allow_screen_capture = is_monitor_capture_drm() || nvfbc_installed;
if(allow_screen_capture) {
- if(gsr_info.supported_capture_options.screen) {
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, "All monitors", -1);
- gtk_list_store_set(store, &iter, 1, "screen", -1);
- }
-
for(const auto &monitor : gsr_info.supported_capture_options.monitors) {
std::string label = "Monitor ";
label += monitor.name;
@@ -2852,7 +2961,9 @@
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(record_area_selection_menu), renderer, "text", 0, NULL);
gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(record_area_selection_menu), renderer, record_area_set_sensitive, NULL, NULL);
- if(allow_screen_capture || gsr_info.supported_capture_options.portal)
+ if(allow_screen_capture && !gsr_info.supported_capture_options.portal && gsr_info.supported_capture_options.monitors.empty())
+ gtk_combo_box_set_active(record_area_selection_menu, 0);
+ else if(allow_screen_capture || gsr_info.supported_capture_options.portal)
gtk_combo_box_set_active(record_area_selection_menu, 2);
else
gtk_combo_box_set_active(record_area_selection_menu, 0);
@@ -3061,42 +3172,44 @@
gtk_list_store_set(store, &iter, 1, "hevc", -1);
gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.av1 ? "AV1 (Smallest file size, worst software compatibility)" : "AV1 (Not available on your system)", -1);
- gtk_list_store_set(store, &iter, 1, "av1", -1);
-
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.vp8 ? "VP8" : "VP8 (Not available on your system)", -1);
- gtk_list_store_set(store, &iter, 1, "vp8", -1);
-
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.vp9 ? "VP9" : "VP9 (Not available on your system)", -1);
- gtk_list_store_set(store, &iter, 1, "vp9", -1);
+ gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.hevc ? "HEVC (10 bit, reduces banding)" : "HEVC (10 bit, not available on your system)", -1);
+ gtk_list_store_set(store, &iter, 1, "hevc_10bit", -1);
if(gsr_info.system_info.display_server == DisplayServer::WAYLAND) {
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.hevc ? "HEVC (HDR)" : "HEVC (HDR, not available on your system)", -1);
gtk_list_store_set(store, &iter, 1, "hevc_hdr", -1);
-
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.av1 ? "AV1 (HDR)" : "AV1 (HDR, not available on your system)", -1);
- gtk_list_store_set(store, &iter, 1, "av1_hdr", -1);
} else {
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, "HEVC (HDR, not available on X11)", -1);
gtk_list_store_set(store, &iter, 1, "hevc_hdr", -1);
+ }
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.av1 ? "AV1 (Smallest file size, worst software compatibility)" : "AV1 (Not available on your system)", -1);
+ gtk_list_store_set(store, &iter, 1, "av1", -1);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.av1 ? "AV1 (10 bit, reduces banding)" : "AV1 (10 bit, not available on your system)", -1);
+ gtk_list_store_set(store, &iter, 1, "av1_10bit", -1);
+
+ if(gsr_info.system_info.display_server == DisplayServer::WAYLAND) {
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.av1 ? "AV1 (HDR)" : "AV1 (HDR, not available on your system)", -1);
+ gtk_list_store_set(store, &iter, 1, "av1_hdr", -1);
+ } else {
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, "AV1 (HDR, not available on X11)", -1);
gtk_list_store_set(store, &iter, 1, "av1_hdr", -1);
}
gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.hevc ? "HEVC (10 bit, reduces banding)" : "HEVC (10 bit, not available on your system)", -1);
- gtk_list_store_set(store, &iter, 1, "hevc_10bit", -1);
+ gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.vp8 ? "VP8" : "VP8 (Not available on your system)", -1);
+ gtk_list_store_set(store, &iter, 1, "vp8", -1);
gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.av1 ? "AV1 (10 bit, reduces banding)" : "AV1 (10 bit, not available on your system)", -1);
- gtk_list_store_set(store, &iter, 1, "av1_10bit", -1);
+ gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.vp9 ? "VP9" : "VP9 (Not available on your system)", -1);
+ gtk_list_store_set(store, &iter, 1, "vp9", -1);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, gsr_info.supported_video_codecs.h264_software ? "H264 Software Encoder (Slow, not recommeded)" : "H264 Software Encoder (Not available on your system)", -1);
@@ -3903,16 +4016,11 @@
}
static void load_config() {
- bool config_empty = false;
- config = read_config(config_empty);
-
std::string first_monitor;
if(gsr_info.system_info.display_server != DisplayServer::WAYLAND && strcmp(config.main_config.record_area_option.c_str(), "window") == 0) {
//
} else if(gsr_info.system_info.display_server != DisplayServer::WAYLAND && strcmp(config.main_config.record_area_option.c_str(), "focused") == 0) {
//
- } else if(gsr_info.system_info.display_server != DisplayServer::WAYLAND && gsr_info.gpu_info.vendor == GpuVendor::NVIDIA && strcmp(config.main_config.record_area_option.c_str(), "screen") == 0) {
- //
} else if(config.main_config.record_area_option == "portal" && gsr_info.supported_capture_options.portal && gsr_info.system_info.display_server == DisplayServer::WAYLAND) {
//
} else {
@@ -4195,7 +4303,7 @@
if(gsr_info.system_info.display_server == DisplayServer::X11 && !dpy) {
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "Failed to connect to X11 server");
+ "Failed to connect to the X11 server");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_application_quit(G_APPLICATION(app));
@@ -4236,7 +4344,7 @@
#else
const char *icon_path = "/usr/share/icons";
#endif
- gtk_icon_theme_set_search_path(icon_theme, &icon_path, 1);
+ gtk_icon_theme_prepend_search_path(icon_theme, icon_path);
const char *icon_name = "com.dec05eba.gpu_screen_recorder";
if(!gtk_icon_theme_has_icon(icon_theme, icon_name))
@@ -4320,15 +4428,124 @@
}
}
+static bool kms_server_proxy_setup_gsr_ui(const char *msg) {
+ GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", msg);
+ const gint response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ switch(response) {
+ case GTK_RESPONSE_YES:
+ break;
+ case GTK_RESPONSE_NO:
+ default: {
+ config.main_config.use_new_ui = false;
+ save_config(config);
+ return false;
+ }
+ }
+
+ const int exit_code = system("flatpak-spawn --host -- /var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/kms-server-proxy setup-gsr-ui");
+ if(exit_code != 0) {
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Failed to setup the new UI. You either cancelled the installation or you don't have pkexec installed and a polkit agent running.");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ config.main_config.use_new_ui = false;
+ save_configs();
+ return false;
+ }
+
+ config.main_config.use_new_ui = true;
+ config.main_config.installed_gsr_global_hotkeys_version = GSR_CURRENT_GLOBAL_HOTKEYS_CODE_VERSION;
+ save_config(config);
+ return true;
+}
+
+static bool is_gsr_global_hotkeys_installed() {
+ const char *user_homepath = getenv("HOME");
+ if(!user_homepath)
+ user_homepath = "/tmp";
+
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/.local/share/gpu-screen-recorder/gsr-global-hotkeys", user_homepath);
+ return access(path, F_OK) == 0;
+}
+
+static bool is_kms_server_proxy_installed() {
+ const char *user_homepath = getenv("HOME");
+ if(!user_homepath)
+ user_homepath = "/tmp";
+
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/.local/share/gpu-screen-recorder/kms-server-proxy-1", user_homepath);
+ return access(path, F_OK) == 0;
+}
+
+static void startup_new_ui(bool launched_by_daemon) {
+ if(!dpy) {
+ if(launched_by_daemon) {
+ fprintf(stderr, "Error: failed to connect to the X11 server, assuming no graphical session has started yet\n");
+ exit(1);
+ } else {
+ GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "Failed to connect to the X11 server while trying to start the new GPU Screen Recorder UI. Please install X11 on your system to use the new UI");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ config.main_config.use_new_ui = false;
+ save_config(config);
+ return;
+ }
+ }
+
+ if(config.main_config.installed_gsr_global_hotkeys_version != GSR_CURRENT_GLOBAL_HOTKEYS_CODE_VERSION) {
+ if(!kms_server_proxy_setup_gsr_ui(
+ "An update is available. The new GPU Screen Recorder UI needs root privileges to finish update to make global hotkeys and recording work on any system.\n"
+ "\n"
+ "Are you sure you want to continue?"))
+ {
+ return;
+ }
+ } else if(!is_gsr_global_hotkeys_installed() || !is_kms_server_proxy_installed()) {
+ if(!kms_server_proxy_setup_gsr_ui(
+ "Required files are missing to launch the new GPU Screen Recorder UI. These files will be installed again.\n"
+ "\n"
+ "Are you sure you want to continue?"))
+ {
+ return;
+ }
+ }
+
+ launch_gsr_ui(!launched_by_daemon);
+ exit(0);
+}
+
int main(int argc, char **argv) {
setlocale(LC_ALL, "C");
+ const bool use_old_ui_opt = argc == 2 && strcmp(argv[1], "use-old-ui") == 0;
+ const bool launched_by_daemon_opt = argc == 2 && strcmp(argv[1], "gsr-ui") == 0;
+ argc = 1;
+
if(geteuid() == 0) {
fprintf(stderr, "Error: don't run gpu-screen-recorder-gtk as the root user\n");
return 1;
}
dpy = XOpenDisplay(NULL);
+
+ config_empty = false;
+ config = read_config(config_empty);
+
+ if(use_old_ui_opt) {
+ system("flatpak-spawn --host -- systemctl disable --user gpu-screen-recorder-ui");
+ config.main_config.use_new_ui = false;
+ save_config(config);
+ }
+
+ if(config.main_config.use_new_ui)
+ startup_new_ui(launched_by_daemon_opt);
+
gsr_info_exit_status = get_gpu_screen_recorder_info(&gsr_info);
if(gsr_info_exit_status == GsrInfoExitStatus::OK) {
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ripcalc for openSUSE:Factory checked in at 2025-01-05 15:29:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ripcalc (Old)
and /work/SRC/openSUSE:Factory/.ripcalc.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ripcalc"
Sun Jan 5 15:29:19 2025 rev:2 rq:1234641 version:0.1.13
Changes:
--------
--- /work/SRC/openSUSE:Factory/ripcalc/ripcalc.changes 2024-08-02 17:27:40.262130058 +0200
+++ /work/SRC/openSUSE:Factory/.ripcalc.new.1881/ripcalc.changes 2025-01-05 15:29:30.145433822 +0100
@@ -1,0 +2,8 @@
+Thu Jan 2 20:08:16 UTC 2025 - Andreas Stieger <andreas.stieger(a)gmx.de>
+
+- Update to version 0.1.13
+ * don't require input to be one IP per line
+ * show subnets within network in format
+ * limit how much an encapsulating network can grow with --group
+
+-------------------------------------------------------------------
Old:
----
ripcalc-0.1.12.obscpio
New:
----
ripcalc-0.1.13.obscpio
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ripcalc.spec ++++++
--- /var/tmp/diff_new_pack.3eVwlQ/_old 2025-01-05 15:29:31.045470841 +0100
+++ /var/tmp/diff_new_pack.3eVwlQ/_new 2025-01-05 15:29:31.045470841 +0100
@@ -1,7 +1,7 @@
#
# spec file for package ripcalc
#
-# Copyright (c) 2024 Andreas Stieger <Andreas.Stieger(a)gmx.de>
+# Copyright (c) 2025 Andreas Stieger <Andreas.Stieger(a)gmx.de>
#
# 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: ripcalc
-Version: 0.1.12
+Version: 0.1.13
Release: 0
Summary: Tool for network addresses
License: GPL-3.0-or-later
@@ -35,6 +35,9 @@
%prep
%autosetup -p1 -a1
+%if 0%{?suse_version} < 1600
+find Cargo.lock vendor/ -type f -name Cargo.lock -exec sed -Ei 's/^version = 4$/version = 3/g' {} \;
+%endif
%build
%{cargo_build}
++++++ _service ++++++
--- /var/tmp/diff_new_pack.3eVwlQ/_old 2025-01-05 15:29:31.081472322 +0100
+++ /var/tmp/diff_new_pack.3eVwlQ/_new 2025-01-05 15:29:31.085472486 +0100
@@ -5,7 +5,7 @@
<param name="changesgenerate">enable</param>
<param name="filename">ripcalc</param>
<param name="versionformat">@PARENT_TAG@</param>
- <param name="revision">v0.1.12</param>
+ <param name="revision">v0.1.13</param>
<param name="versionrewrite-pattern">v(.*)</param>
<param name="versionrewrite-replacement">\1</param>
</service>
@@ -20,8 +20,5 @@
<param name="compression">zst</param>
<param name="update">true</param>
</service>
- <service name="cargo_audit" mode="manual">
- <param name="srcdir">projectname</param>
- </service>
</services>
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.3eVwlQ/_old 2025-01-05 15:29:31.105473309 +0100
+++ /var/tmp/diff_new_pack.3eVwlQ/_new 2025-01-05 15:29:31.109473474 +0100
@@ -1,7 +1,8 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://gitlab.com/edneville/ripcalc.git</param>
- <param name="changesrevision">5aca7acaf7fc5e6d53eb737e620fe418cf76bfdb</param>
+ <param name="changesrevision">d1e29a5ea08ffcb525d423dcbe51e26436d5f851</param>
</service>
</servicedata>
+(No newline at EOF)
++++++ ripcalc-0.1.12.obscpio -> ripcalc-0.1.13.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/Cargo.lock new/ripcalc-0.1.13/Cargo.lock
--- old/ripcalc-0.1.12/Cargo.lock 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/Cargo.lock 2025-01-01 19:06:50.000000000 +0100
@@ -116,7 +116,7 @@
[[package]]
name = "ripcalc"
-version = "0.1.12"
+version = "0.1.13"
dependencies = [
"csv",
"getopts",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/Cargo.toml new/ripcalc-0.1.13/Cargo.toml
--- old/ripcalc-0.1.12/Cargo.toml 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/Cargo.toml 2025-01-01 19:06:50.000000000 +0100
@@ -1,7 +1,7 @@
[package]
name = "ripcalc"
description = "ripcalc, format and lookup IP addresses"
-version = "0.1.12"
+version = "0.1.13"
authors = ["ed neville <ed(a)s5h.net>"]
edition = "2018"
license = "GPL-3.0-or-later"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/Makefile new/ripcalc-0.1.13/Makefile
--- old/ripcalc-0.1.12/Makefile 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/Makefile 2025-01-01 19:06:50.000000000 +0100
@@ -49,6 +49,11 @@
printf "127.0.0.1/8\n" | $(RELEASE) | grep "IP is: 127.0.0.1/8" | wc -l | tr -d '[:blank:]' | grep -Fx 1
printf " 127.0.0.1/8 \n " | $(RELEASE) | grep "IP is: 127.0.0.1/8" | wc -l | tr -d '[:blank:]' | grep -Fx 1
$(RELEASE) --base 10 -6 55835323703435061617372717077650323870 | grep "IP is: 2a01:7e00::f03c:92ff:fe35:b99e/64" | wc -l | tr -d '[:blank:]' | grep -Fx 1
+ printf '10.0.1.0 10.0.255.0' | $(RELEASE) -e --format cidr | grep "10.0.0.0/16" | wc -l | tr -d '[:blank:]' | grep -Fx 1
+ printf '10.0.1.0 10.0.255.0\n10.2.0.0 10.2.2.2\n10.3.0.0\n10.10.10.10\n' | $(RELEASE) --format cidr | wc -l | tr -d '[:blank:]' | grep -Fx 6
+ printf '2a0a:1100:1002::/48' | $(RELEASE) --networks 64 | tr -d '[:blank:]' | grep -Fx "Networks(64):65536"
+ printf '2a0a:1100:1002::/48' | $(RELEASE) --networks 64 --format '%D:%N' | grep -Fx '64:65536'
+ for i in 1 2 3 4; do for j in 1 2 3 4; do echo 192.$$i.$$j.1; done; done | $(RELEASE) --group 16 --format short --encapsulating | wc -l | tr -d '[:blank:]' | grep -Fx 4
install: all
command -v please && please install -m 0755 -s $(RELEASE) /usr/local/bin || sudo install -m 0755 -s $(RELEASE) /usr/local/bin
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/README.md new/ripcalc-0.1.13/README.md
--- old/ripcalc-0.1.12/README.md 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/README.md 2025-01-01 19:06:50.000000000 +0100
@@ -11,6 +11,12 @@
&& please install -m 0755 -s target/release/ripcalc /usr/local/bin
```
+or
+
+```
+please snap install ripcalc
+```
+
# usage
Ripcalc allows networks to be provided by argument
@@ -85,7 +91,9 @@
| %r | Network reservation information (if available) |
| %d | Matching device interface by IP |
| %m | Matching media link interface by network |
-| %k | RBL-style format |
+| %k | RBL/reverse DNS-style format |
+| %D | Network size (--networks) |
+| %N | Number of subnets (--networks) |
| %% | % |
| \n | Line break |
| \t | Tab character |
@@ -188,6 +196,12 @@
please ip route add blackhole `ripcalc -e 192.168.56.10 192.168.57.1 192.168.44.47`
```
+Networks can be grouped, in a scenario where you have a list of unwanted traffic, you can turn this into a list of small networks to block, supposing you don't want to block anything that covers more than a /19:
+
+```
+cat bad_traffic | ripcalc --encapsulating --group 19 --format cidr
+```
+
# help
```
@@ -199,19 +213,22 @@
-c, --csv PATH csv reference file
-d, --divide CIDR divide network into chunks
--noexpand do not expand networks in list
- -e, --encapsulating
+ -e, --encapsulating
display encapsulating network from arguments or lookup
list
-f, --format STRING format output
'cidr' expands to %a/%c\n
'short' expands to %a\n
See manual for more options
+ --group CIDR maximum network group size for encapsulation
-h, --help display help
-i, --field FIELD csv field
-l, --list list all addresses in network
--outside display when extremities are outside network
--inside display when extremities are inside network
-m, --mask CIDR cidr mask
+ -n, --networks CIDR instead of hosts, display number of subnets of this
+ size
-r, --reverse (none, inputs, sources or both) v4 octets, v6 hex
-s, --file PATH lookup addresses from, - for stdin
-v, --version print version
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/changelog.md new/ripcalc-0.1.13/changelog.md
--- old/ripcalc-0.1.12/changelog.md 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/changelog.md 2025-01-01 19:06:50.000000000 +0100
@@ -1,3 +1,9 @@
+0.1.13
+
+ * don't require input to be one IP per line
+ * show subnets within network in format, suggested by andy(a)bitfolk.com
+ * limit how much an encapsulating network can grow with --group
+
0.1.12
* now builds on macos #1, thanks @sander_maijers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/ripcalc.1 new/ripcalc-0.1.13/ripcalc.1
--- old/ripcalc-0.1.12/ripcalc.1 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/ripcalc.1 2025-01-01 19:06:50.000000000 +0100
@@ -15,7 +15,7 @@
. ftr VB CB
. ftr VBI CBI
.\}
-.TH "ripcalc" "1" "11 July 2024" "ripcalc 0.1.12" "User Manual"
+.TH "ripcalc" "1" "01 January 2025" "ripcalc 0.1.13" "User Manual"
.hy
.SH NAME
.PP
@@ -40,7 +40,7 @@
.PP
\f[B]ripcalc -s/--file [-] 127.0.0.1\f[R]
.PP
-\f[B]ripcalc -e/--encapsulating [-s/--file name]\f[R]
+\f[B]ripcalc -e/--encapsulating [-s/--file name] [--group CIDR]\f[R]
.PP
\f[B]ripcalc -s/--file name [--inside/--outside] 127.0.0.1\f[R]
.PP
@@ -48,6 +48,8 @@
.PP
\f[B]ripcalc -d/--divide [CIDR] 127.0.0.1/24\f[R]
.PP
+\f[B]ripcalc \[en]networks [CIDR] 127.0.0.1/24\f[R]
+.PP
\f[B]ripcalc -h/--help\f[R]
.SH DESCRIPTION
.PP
@@ -76,11 +78,16 @@
or both can be treated as back-to-front.
.PP
\f[B]ripcalc\f[R] can return a list of subnets when a network is
-provided along with the \f[B]divide\f[R] argument and a subnet CIDR
+provided along with the \f[V]--divide\f[R] argument and a subnet CIDR
mask.
.PP
When \f[V]--encapsulating\f[R] is used the containing network will be
-returned.
+returned, use with \f[V]--group\f[R] to limit the range that an
+encapsulating network can grow.
+.PP
+The number (\f[B]%D\f[R]) of subnets can be printed when using the
+\f[V]--group\f[R] argument with the \f[B]%N\f[R] formatters.
+The argument should be the CIDR mask, see below for example.
.SH CSV
.PP
Network matches can be returned from a \f[B]CSV\f[R].
@@ -233,7 +240,17 @@
T{
%k
T}@T{
-RBL-style format
+RBL/reverse DNS-style format
+T}
+T{
+%D
+T}@T{
+Network size (--networks)
+T}
+T{
+%N
+T}@T{
+Number of subnets (--networks)
T}
T{
%%
@@ -263,10 +280,64 @@
--format \[aq]%{name}\[aq]
\f[R]
.fi
-.SS inside/outside
+.SH inside/outside
.PP
When \f[V]--inside\f[R] or \f[V]--outside\f[R] are given addresses that
match \f[V]--file\f[R] are printed.
If no matches are found \f[V]ripcalc\f[R] will exit non-zero.
+.SH subnets
+.PP
+For large networks it can be useful to see the number of subnets, to see
+the number of /29 subnets within a /24 network, the command would look
+like this:
+.IP
+.nf
+\f[C]
+ripcalc --networks 29 192.168.230.0/24
+ IP is: 192.168.230.0/24
+ Broadcast is: 192.168.230.255
+ Network is: 192.168.230.0
+ Subnet is: 255.255.255.0
+ Wildcard is: 0.0.0.255
+ Networks (29): 32
+\f[R]
+.fi
+.PP
+Or for a IPv6 /48 network that you want to subnet into /64, you can see
+there are 65536 subnets:
+.IP
+.nf
+\f[C]
+ ripcalc --networks 64 2001:db8:1::/48
+ IP is: 2001:db8:1::/48
+ Expanded: 2001:0db8:0001:0000:0000:0000:0000:0000
+ Network is: 2001:0db8:0001:0000:0000:0000:0000:0000
+Last host address: 2001:0db8:0001:ffff:ffff:ffff:ffff:ffff
+ Subnet is: ffff:ffff:ffff:0000:0000:0000:0000:0000
+ Networks (64): 65536
+\f[R]
+.fi
+.SH encapsulating
+.PP
+Suppose a large flood of requests are from a network pattern, to
+preserve service you may want to block the whole network that
+encapsulates a list:
+.IP
+.nf
+\f[C]
+please ip route add blackhole \[ga]ripcalc -e 192.168.56.10 192.168.57.1 192.168.44.47\[ga]
+\f[R]
+.fi
+.PP
+Networks can be grouped, in a scenario where you have a list of unwanted
+traffic, you can turn this into a list of small networks to block,
+supposing you don\[cq]t want to block anything that covers more than a
+/19:
+.IP
+.nf
+\f[C]
+cat bad_traffic | ripcalc --encapsulating --group 19 --format cidr
+\f[R]
+.fi
.SH AUTHORS
Ed Neville (ed-ripcalc\[at]s5h.net)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/ripcalc.md new/ripcalc-0.1.13/ripcalc.md
--- old/ripcalc-0.1.12/ripcalc.md 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/ripcalc.md 2025-01-01 19:06:50.000000000 +0100
@@ -2,9 +2,9 @@
title: ripcalc
section: 1
header: User Manual
-footer: ripcalc 0.1.12
+footer: ripcalc 0.1.13
author: Ed Neville (ed-ripcalc(a)s5h.net)
-date: 11 July 2024
+date: 01 January 2025
---
# NAME
@@ -31,7 +31,7 @@
**ripcalc -s/--file [-] 127.0.0.1**
-**ripcalc -e/--encapsulating [-s/--file name]**
+**ripcalc -e/--encapsulating [-s/--file name] [--group CIDR]**
**ripcalc -s/--file name [--inside/--outside] 127.0.0.1**
@@ -39,6 +39,8 @@
**ripcalc -d/--divide [CIDR] 127.0.0.1/24**
+**ripcalc --networks [CIDR] 127.0.0.1/24**
+
**ripcalc -h/--help**
@@ -56,9 +58,11 @@
When `--reverse` is used the `inputs`, `sources` or both can be treated as back-to-front.
-**ripcalc** can return a list of subnets when a network is provided along with the **divide** argument and a subnet CIDR mask.
+**ripcalc** can return a list of subnets when a network is provided along with the `--divide` argument and a subnet CIDR mask.
+
+When `--encapsulating` is used the containing network will be returned, use with `--group` to limit the range that an encapsulating network can grow.
-When `--encapsulating` is used the containing network will be returned.
+The number (**%D**) of subnets can be printed when using the `--group` argument with the **%N** formatters. The argument should be the CIDR mask, see below for example.
# CSV
@@ -117,7 +121,9 @@
| %r | Network reservation information (if available) |
| %d | Matching device interface by IP |
| %m | Matching media link interface by network |
-| %k | RBL-style format |
+| %k | RBL/reverse DNS-style format |
+| %D | Network size (--networks) |
+| %N | Number of subnets (--networks) |
| %% | % |
| \n | Line break |
| \t | Tab character |
@@ -128,8 +134,39 @@
--format '%{name}'
-## inside/outside
+# inside/outside
When `--inside` or `--outside` are given addresses that match `--file` are printed. If no matches are found `ripcalc` will exit non-zero.
+# subnets
+
+For large networks it can be useful to see the number of subnets, to see the number of /29 subnets within a /24 network, the command would look like this:
+
+ ripcalc --networks 29 192.168.230.0/24
+ IP is: 192.168.230.0/24
+ Broadcast is: 192.168.230.255
+ Network is: 192.168.230.0
+ Subnet is: 255.255.255.0
+ Wildcard is: 0.0.0.255
+ Networks (29): 32
+
+Or for a IPv6 /48 network that you want to subnet into /64, you can see there are 65536 subnets:
+
+ ripcalc --networks 64 2001:db8:1::/48
+ IP is: 2001:db8:1::/48
+ Expanded: 2001:0db8:0001:0000:0000:0000:0000:0000
+ Network is: 2001:0db8:0001:0000:0000:0000:0000:0000
+ Last host address: 2001:0db8:0001:ffff:ffff:ffff:ffff:ffff
+ Subnet is: ffff:ffff:ffff:0000:0000:0000:0000:0000
+ Networks (64): 65536
+
+# encapsulating
+
+Suppose a large flood of requests are from a network pattern, to preserve service you may want to block the whole network that encapsulates a list:
+
+ please ip route add blackhole `ripcalc -e 192.168.56.10 192.168.57.1 192.168.44.47`
+
+Networks can be grouped, in a scenario where you have a list of unwanted traffic, you can turn this into a list of small networks to block, supposing you don't want to block anything that covers more than a /19:
+
+ cat bad_traffic | ripcalc --encapsulating --group 19 --format cidr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/src/lib.rs new/ripcalc-0.1.13/src/lib.rs
--- old/ripcalc-0.1.12/src/lib.rs 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/src/lib.rs 2025-01-01 19:06:50.000000000 +0100
@@ -6,6 +6,7 @@
use nix::sys::stat::SFlag;
use std::collections::HashMap;
use std::fmt;
+use std::io::BufRead;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
use std::net::ToSocketAddrs;
@@ -417,7 +418,7 @@
for key in networks.keys().skip(1) {
let mut key = key.clone();
match (&ip.address, &key.address) {
- (Addr::V4(_), Addr::V4(_)) => {
+ (Addr::V4(_), Addr::V4(_)) | (Addr::V6(_), Addr::V6(_)) => {
if key.cidr < ip.cidr {
ip.cidr = key.cidr;
}
@@ -431,19 +432,57 @@
}
ip = network(&ip);
}
- (Addr::V6(_), Addr::V6(_)) => {
- if key.cidr < ip.cidr {
- ip.cidr = key.cidr;
+ (_, _) => {
+ return None;
+ }
+ }
+ }
+
+ Some(ip)
+}
+
+pub fn smallest_group_network_limited(networks: &HashMap<Ip, bool>, cidr: u32) -> Option<Vec<Ip>> {
+ if networks.is_empty() {
+ return None;
+ }
+
+ let mut net_list: HashMap<Ip, Ip> = HashMap::new();
+
+ for key in networks.keys() {
+ let mut bucket_ip = key.clone();
+ bucket_ip.cidr = cidr;
+
+ let mut key_copy = key.clone();
+
+ // don't add a entry with a bigger network than cidr
+ if key_copy.cidr < cidr {
+ key_copy.cidr = cidr;
+ }
+
+ let bucket = network(&bucket_ip);
+
+ if !net_list.contains_key(&bucket) {
+ net_list.insert(bucket.clone(), key_copy.clone());
+ }
+
+ let ip = net_list.get_mut(&bucket).unwrap();
+
+ match (&ip.address, &key.address) {
+ (Addr::V4(_), Addr::V4(_)) | (Addr::V6(_), Addr::V6(_)) => {
+ // println!("ip.cidr {}, key_copy.cidr {}", ip.cidr, key_copy.cidr);
+ if key_copy.cidr < ip.cidr {
+ // println!("key less than ip: ip.cidr {}, key_copy.cidr {}", ip.cidr, key_copy.cidr);
+ ip.cidr = key_copy.cidr;
}
- key.cidr = ip.cidr;
- while network(&key) != network(&ip) {
+ key_copy.cidr = ip.cidr;
+ while network(&key_copy) != network(ip) && ip.cidr > cidr {
if ip.cidr == 0 {
return None;
}
ip.cidr -= 1;
- key.cidr = ip.cidr;
+ key_copy.cidr = ip.cidr;
}
- ip = network(&ip);
+ *ip = network(ip);
}
(_, _) => {
return None;
@@ -451,7 +490,7 @@
}
}
- Some(ip)
+ Some(net_list.values().cloned().collect())
}
impl fmt::Display for Ip {
@@ -1046,6 +1085,7 @@
ip: &Ip,
formatted: String,
rows: &Option<HashMap<Ip, NetRow>>,
+ subnet_size: Option<u32>,
) -> Option<String> {
let ip = &mut ip.clone();
let mut reformatted = formatted;
@@ -1200,6 +1240,20 @@
'%' => {
out_str.push('%');
}
+ 'D' => {
+ if let Some(s) = subnet_size {
+ out_str.push_str(&s.to_string());
+ } else {
+ out_str.push('D');
+ };
+ }
+ 'N' => {
+ if let Some(s) = subnet_size {
+ out_str.push_str(&subnets_in_network(s, ip).to_string());
+ } else {
+ out_str.push('N');
+ };
+ }
_ => {
out_str.push(k);
}
@@ -1265,3 +1319,46 @@
false
}
+
+pub fn find_ips<'a>(
+ reader: &'a mut Box<dyn BufRead>,
+ input_base: Option<i32>,
+ reverse: &'a Reverse,
+) -> impl 'a + std::iter::Iterator<Item = Vec<Ip>> {
+ std::iter::from_fn(move || {
+ if let Some(line) = reader.lines().next().into_iter().by_ref().next() {
+ let line: String = line.as_ref().unwrap().trim().to_string();
+ let mut v = vec![];
+
+ for part in line.split(' ') {
+ let p = part.trim();
+ if p.is_empty() {
+ continue;
+ }
+
+ let ip = match parse_address_mask(
+ p,
+ Some(32),
+ Some(128),
+ input_base,
+ matches!(reverse, Reverse::Both | Reverse::Input),
+ ) {
+ Some(x) => x,
+ None => {
+ eprintln!("Could not parse {}", p);
+ continue;
+ }
+ };
+
+ v.push(ip);
+ }
+ return Some(v);
+ }
+ None
+ })
+}
+
+pub fn subnets_in_network(networks: u32, ip: &Ip) -> u128 {
+ let base: u128 = 2;
+ base.pow(networks - ip.cidr)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/src/main.rs new/ripcalc-0.1.13/src/main.rs
--- old/ripcalc-0.1.12/src/main.rs 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/src/main.rs 2025-01-01 19:06:50.000000000 +0100
@@ -12,13 +12,46 @@
rows: &Option<HashMap<Ip, NetRow>>,
used: Option<&HashMap<Addr, bool>>,
) {
+ let mut networks: Option<u32> = None;
+
+ if matches.opt_present("networks") {
+ let nets = matches.opt_str("networks").unwrap().trim().parse().unwrap();
+
+ if nets < ip.cidr && !(matches.opt_present("encapsulating") && matches.opt_present("group"))
+ {
+ eprintln!("{} is bigger than the network mask {}", nets, ip.cidr);
+ std::process::exit(1);
+ }
+
+ match ip.address {
+ Addr::V4(_) => {
+ if nets > 32 {
+ eprintln!("{} is too big", nets);
+ std::process::exit(1);
+ }
+ }
+ Addr::V6(_) => {
+ if nets > 128 {
+ eprintln!("{} is too big", nets);
+ std::process::exit(1);
+ }
+ }
+ }
+ networks = Some(nets);
+ }
+
let mut formatted = if matches.opt_present("f") {
matches.opt_str("f").unwrap()
} else {
+ let mut network_size = "Network size: %t".to_string();
let width = 25;
+ if matches.opt_present("networks") {
+ network_size = format!("Networks ({}): %N", networks.as_ref().unwrap()).to_string();
+ }
match ip.address {
- Addr::V4(_) => format!("{ip:>width$}/{cidr}\n{broadcast:>width$}\n{network:>width$}\n{subnet:>width$}\n{wildcard:>width$}\n{network_size:>width$}\n", ip="IP is: %a", cidr="%c", broadcast="Broadcast is: %b", network="Network is: %n", subnet="Subnet is: %s", wildcard="Wildcard is: %w", network_size="Network size: %t", width=width),
- Addr::V6(_) => format!("{ip:>widthn$}/{cidr}\n{expanded:>width$}\n{network:>width$}\n{last_host_address:>width$}\n{subnet:>width$}\n{network_size:>widthn$}\n", ip="IP is: %a", cidr="%c", expanded="Expanded: %xa", network="Network is: %xn", last_host_address="Last host address: %xb", subnet="Subnet is: %xs", network_size="Network size: %t", width=width, widthn=width-1),
+
+ Addr::V4(_) => format!("{ip:>width$}/{cidr}\n{broadcast:>width$}\n{network:>width$}\n{subnet:>width$}\n{wildcard:>width$}\n{network_size:>width$}\n", ip="IP is: %a", cidr="%c", broadcast="Broadcast is: %b", network="Network is: %n", subnet="Subnet is: %s", wildcard="Wildcard is: %w", network_size=network_size, width=width),
+ Addr::V6(_) => format!("{ip:>widthn$}/{cidr}\n{expanded:>width$}\n{network:>width$}\n{last_host_address:>width$}\n{subnet:>width$}\n{network_size:>widthn$}\n", ip="IP is: %a", cidr="%c", expanded="Expanded: %xa", network="Network is: %xn", last_host_address="Last host address: %xb", subnet="Subnet is: %xs", network_size=network_size, width=width, widthn=width-1),
}
};
@@ -40,7 +73,7 @@
};
for ip_copy in addresses(ip, used, Some(divide)) {
- if let Some(m) = format_details(&ip_copy, formatted.to_string(), rows) {
+ if let Some(m) = format_details(&ip_copy, formatted.to_string(), rows, networks) {
print!("{}", m);
}
}
@@ -49,21 +82,21 @@
if matches.opt_present("list") {
if matches.opt_present("noexpand") {
- if let Some(m) = format_details(ip, formatted, rows) {
+ if let Some(m) = format_details(ip, formatted, rows, networks) {
print!("{}", m);
}
return;
}
for ip_copy in addresses(ip, used, None) {
- if let Some(m) = format_details(&ip_copy, formatted.to_string(), rows) {
+ if let Some(m) = format_details(&ip_copy, formatted.to_string(), rows, networks) {
print!("{}", m);
}
}
return;
}
- if let Some(m) = format_details(ip, formatted, rows) {
+ if let Some(m) = format_details(ip, formatted, rows, networks) {
print!("{}", m);
}
}
@@ -189,7 +222,7 @@
rows: &Option<HashMap<Ip, NetRow>>,
inside: Option<bool>,
) {
- let reader: Box<dyn BufRead> = if path == "-" {
+ let mut reader: Box<dyn BufRead> = if path == "-" {
Box::new(BufReader::new(std::io::stdin()))
} else {
let path = std::path::Path::new(&path);
@@ -203,24 +236,10 @@
Box::new(BufReader::new(File::open(path).unwrap()))
};
- let mut used: HashMap<Addr, bool> = HashMap::new();
if matches.opt_present("available") {
- for line in reader.lines() {
- let line: String = line.as_ref().unwrap().trim().to_string();
- let ip = match parse_address_mask(
- line.as_ref(),
- Some(32),
- Some(128),
- input_base,
- matches!(reverse, Reverse::Both | Reverse::Input),
- ) {
- Some(x) => x,
- None => {
- eprintln!("Could not parse {}", line);
- continue;
- }
- };
- for ip in addresses(&ip, None, None) {
+ let mut used: HashMap<Addr, bool> = HashMap::new();
+ for a in find_ips(&mut reader, input_base, reverse) {
+ for ip in a {
used.insert(ip.address, true);
}
}
@@ -233,31 +252,36 @@
if matches.opt_present("encapsulating") {
let mut used: HashMap<Ip, bool> = HashMap::new();
- for line in reader.lines() {
- let line: String = line.as_ref().unwrap().trim().to_string();
- let ip = match parse_address_mask(
- line.as_ref(),
- Some(32),
- Some(128),
- input_base,
- matches!(reverse, Reverse::Both | Reverse::Input),
- ) {
- Some(x) => x,
- None => {
- eprintln!("Could not parse {}", line);
- continue;
- }
- };
- used.insert(ip, true);
+ for a in find_ips(&mut reader, input_base, reverse) {
+ for i in a {
+ used.insert(i, true);
+ }
}
- match smallest_group_network(&used) {
- Some(x) => {
- print_details(&x, matches, rows, None);
+ if matches.opt_present("group") {
+ let network_size: u32 = matches.opt_str("group").unwrap().trim().parse().unwrap();
+
+ match smallest_group_network_limited(&used, network_size) {
+ Some(mut x) => {
+ x.sort_by(|a, b| a.partial_cmp(b).unwrap());
+ for y in x {
+ print_details(&y, matches, rows, None);
+ }
+ }
+ None => {
+ eprintln!("Could not find an encapsulating network, sorry");
+ std::process::exit(1);
+ }
}
- None => {
- eprintln!("Could not find an encapsulating network, sorry");
- std::process::exit(1);
+ } else {
+ match smallest_group_network(&used) {
+ Some(x) => {
+ print_details(&x, matches, rows, None);
+ }
+ None => {
+ eprintln!("Could not find an encapsulating network, sorry");
+ std::process::exit(1);
+ }
}
}
@@ -266,51 +290,41 @@
let mut found_match = false;
- for line in reader.lines() {
- let line: String = line.as_ref().unwrap().trim().to_string();
- let ip = parse_address_mask(
- &line,
- Some(32),
- Some(128),
- input_base,
- matches!(reverse, Reverse::Both | Reverse::Source),
- );
- if ip.is_none() {
- continue;
- }
+ for a in find_ips(&mut reader, input_base, reverse) {
+ for ip in a {
+ match inside {
+ Some(true) => {
+ let mut found = false;
+ for arg in ip_args {
+ if within(arg, &ip) {
+ found = true;
+ break;
+ }
+ }
- match inside {
- Some(true) => {
- let mut found = false;
- for arg in ip_args {
- if within(arg, ip.as_ref().unwrap()) {
- found = true;
- break;
+ if found {
+ found_match = true;
+ print_details(&ip, matches, rows, None);
}
}
+ Some(false) => {
+ let mut found = false;
- if found {
- found_match = true;
- print_details(&ip.unwrap(), matches, rows, None);
- }
- }
- Some(false) => {
- let mut found = false;
-
- for arg in ip_args {
- if within(arg, ip.as_ref().unwrap()) {
- found = true;
- break;
+ for arg in ip_args {
+ if within(arg, &ip) {
+ found = true;
+ break;
+ }
}
- }
- if !found {
- found_match = true;
- print_details(&ip.unwrap(), matches, rows, None);
+ if !found {
+ found_match = true;
+ print_details(&ip, matches, rows, None);
+ }
+ }
+ None => {
+ print_details(&ip, matches, rows, None);
}
- }
- None => {
- print_details(&ip.unwrap(), matches, rows, None);
}
}
}
@@ -363,6 +377,12 @@
);
opts.optopt("f", "format", "format output\n'cidr' expands to %a/%c\\n\n'short' expands to %a\\n\nSee manual for more options", "STRING");
+ opts.optopt(
+ "",
+ "group",
+ "maximum network group size for encapsulation",
+ "CIDR",
+ );
opts.optflag("h", "help", "display help");
opts.optopt("i", "field", "csv field", "FIELD");
@@ -374,6 +394,12 @@
);
opts.optflag("", "inside", "display when extremities are inside network");
opts.optopt("m", "mask", "cidr mask", "CIDR");
+ opts.optopt(
+ "n",
+ "networks",
+ "instead of hosts, display number of subnets of this size",
+ "CIDR",
+ );
opts.optopt(
"r",
@@ -416,6 +442,26 @@
inside = Some(false);
}
+ if matches.opt_present("group") {
+ let _: u32 = match matches.opt_str("group").unwrap().trim().parse() {
+ Ok(x) => x,
+ Err(x) => {
+ eprintln!("Cannot convert {} to number", x);
+ std::process::exit(1);
+ }
+ };
+ }
+
+ if matches.opt_present("networks") {
+ let _: u32 = match matches.opt_str("networks").unwrap().trim().parse() {
+ Ok(x) => x,
+ Err(x) => {
+ eprintln!("Cannot convert {} to number", x);
+ std::process::exit(1);
+ }
+ };
+ }
+
if matches.opt_present("reverse") {
match matches.opt_str("reverse").unwrap().as_str() {
"inputs" => {
@@ -556,13 +602,29 @@
}
if matches.opt_present("encapsulating") {
- match smallest_group_network(&used) {
- Some(x) => {
- print_details(&x, &matches, &rows, None);
+ if matches.opt_present("networks") {
+ let network_size: u32 = matches.opt_str("networks").unwrap().trim().parse().unwrap();
+
+ match smallest_group_network_limited(&used, network_size) {
+ Some(x) => {
+ for y in x {
+ print_details(&y, &matches, &rows, None);
+ }
+ }
+ None => {
+ eprintln!("Could not find an encapsulating network, sorry");
+ std::process::exit(1);
+ }
}
- None => {
- eprintln!("Could not find an encapsulating network, sorry");
- std::process::exit(1);
+ } else {
+ match smallest_group_network(&used) {
+ Some(x) => {
+ print_details(&x, &matches, &rows, None);
+ }
+ None => {
+ eprintln!("Could not find an encapsulating network, sorry");
+ std::process::exit(1);
+ }
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ripcalc-0.1.12/tests/funcs.rs new/ripcalc-0.1.13/tests/funcs.rs
--- old/ripcalc-0.1.12/tests/funcs.rs 2024-07-11 22:35:02.000000000 +0200
+++ new/ripcalc-0.1.13/tests/funcs.rs 2025-01-01 19:06:50.000000000 +0100
@@ -277,7 +277,7 @@
cidr: 30,
};
- let f = format_details(&net, "%a".to_string(), &None);
+ let f = format_details(&net, "%a".to_string(), &None, None);
assert_eq!(f, Some("192.168.0.0".to_string()));
}
@@ -291,6 +291,7 @@
},
"%".to_string(),
&None,
+ None,
);
assert_eq!(f, Some("%".to_string()));
@@ -302,6 +303,7 @@
},
"%%".to_string(),
&None,
+ None,
);
assert_eq!(f, Some("%".to_string()));
@@ -313,6 +315,7 @@
},
"%%%".to_string(),
&None,
+ None,
);
assert_eq!(f, Some("%%".to_string()));
@@ -324,6 +327,7 @@
},
"%%%%".to_string(),
&None,
+ None,
);
assert_eq!(f, Some("%%".to_string()));
@@ -336,7 +340,7 @@
cidr: 64,
};
- let f = format_details(&net, "select * from IP6 where (ip >= %ln and ip <= %lb) and active = 1;\nupdate IP6 set active = 0 where (ip >= %ln and ip <= %lb) and active = 1;".to_string(), &None);
+ let f = format_details(&net, "select * from IP6 where (ip >= %ln and ip <= %lb) and active = 1;\nupdate IP6 set active = 0 where (ip >= %ln and ip <= %lb) and active = 1;".to_string(), &None, None);
assert_eq!(f, Some("select * from IP6 where (ip >= 42540724579414763292693624807812497408 and ip <= 42540724579414763311140368881522049023) and active = 1;
update IP6 set active = 0 where (ip >= 42540724579414763292693624807812497408 and ip <= 42540724579414763311140368881522049023) and active = 1;".to_string()));
@@ -349,7 +353,7 @@
cidr: 64,
};
- let f = format_details(&net, "%%b".to_string(), &None);
+ let f = format_details(&net, "%%b".to_string(), &None, None);
assert_eq!(f, Some("%b".to_string()));
}
@@ -361,7 +365,7 @@
cidr: 64,
};
- let f = format_details(&net, "%lb".to_string(), &None);
+ let f = format_details(&net, "%lb".to_string(), &None, None);
assert_eq!(
f,
@@ -376,7 +380,7 @@
cidr: 64,
};
- let f = format_details(&net, "%lb\n\n\n%%".to_string(), &None);
+ let f = format_details(&net, "%lb\n\n\n%%".to_string(), &None, None);
assert_eq!(
f,
@@ -391,16 +395,16 @@
cidr: 64,
};
- let f = format_details(&net, "\n".to_string(), &None);
+ let f = format_details(&net, "\n".to_string(), &None, None);
assert_eq!(f, Some("\n".to_string()));
- let f = format_details(&net, "\\".to_string(), &None);
+ let f = format_details(&net, "\\".to_string(), &None, None);
assert_eq!(f, Some('\\'.to_string()));
- let f = format_details(&net, "\\i".to_string(), &None);
+ let f = format_details(&net, "\\i".to_string(), &None, None);
assert_eq!(f, Some("i".to_string()));
- let f = format_details(&net, "\\t".to_string(), &None);
+ let f = format_details(&net, "\\t".to_string(), &None, None);
assert_eq!(f, Some("\t".to_string()));
}
@@ -626,9 +630,9 @@
cidr: 30,
};
- let f = format_details(&net, "%La".to_string(), &None);
+ let f = format_details(&net, "%La".to_string(), &None, None);
assert_eq!(f, Some("-1819047474".to_string()));
- let f = format_details(&net, "%la".to_string(), &None);
+ let f = format_details(&net, "%la".to_string(), &None, None);
assert_eq!(f, Some("2475919822".to_string()));
let net = Ip {
@@ -636,9 +640,9 @@
cidr: 30,
};
- let f = format_details(&net, "%La".to_string(), &None);
+ let f = format_details(&net, "%La".to_string(), &None, None);
assert_eq!(f, Some("-5192296858534827628530496329154561".to_string()));
- let f = format_details(&net, "%la".to_string(), &None);
+ let f = format_details(&net, "%la".to_string(), &None, None);
assert_eq!(
f,
Some("340277174624079928635746076935439056895".to_string())
@@ -806,4 +810,148 @@
let v: Vec<Ip> = i.collect();
assert_eq!(v.len(), 65536);
}
+
+ #[test]
+ fn test_networks_sizing_v6() {
+ let net = Ip {
+ address: Addr::V6(Ipv6Addr::from_str("::1").unwrap()),
+ cidr: 48,
+ };
+
+ assert_eq!(subnets_in_network(64, &net), 65536);
+ assert_eq!(subnets_in_network(48, &net), 1);
+ assert_eq!(subnets_in_network(49, &net), 2);
+ }
+
+ #[test]
+ fn test_networks_sizing_v4() {
+ let net = Ip {
+ address: Addr::V4(Ipv4Addr::from_str("127.0.0.1").unwrap()),
+ cidr: 16,
+ };
+
+ assert_eq!(subnets_in_network(24, &net), 256);
+ assert_eq!(subnets_in_network(25, &net), 512);
+ assert_eq!(subnets_in_network(26, &net), 1024);
+ assert_eq!(subnets_in_network(27, &net), 2048);
+ assert_eq!(subnets_in_network(28, &net), 4096);
+ }
+
+ #[test]
+ fn test_smallest_network_limited() {
+ let empty: HashMap<Ip, bool> = HashMap::new();
+ assert_eq!(smallest_group_network_limited(&empty, 32), None);
+ }
+
+ #[test]
+ fn test_smallest_network_limited_22_24() {
+ let mut net_list: HashMap<Ip, bool> = HashMap::new();
+ for i in 0..4 {
+ for j in 0..4 {
+ net_list.insert(
+ Ip {
+ address: Addr::V4(
+ Ipv4Addr::from_str(&format!("192.168.{i}.{j}")).expect("bad ipv4"),
+ ),
+ cidr: 24,
+ },
+ true,
+ );
+ }
+ }
+
+ let mut resp = smallest_group_network_limited(&net_list, 22).unwrap();
+ resp.sort_by(|a, b| a.partial_cmp(b).unwrap());
+ assert_eq!(
+ resp,
+ [Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.168.0.0")).expect("bad ipv4")),
+ cidr: 22
+ }]
+ );
+ }
+
+ #[test]
+ fn test_smallest_network_limited_22_8() {
+ let mut net_list: HashMap<Ip, bool> = HashMap::new();
+ for i in 0..4 {
+ for j in 0..4 {
+ net_list.insert(
+ Ip {
+ address: Addr::V4(
+ Ipv4Addr::from_str(&format!("192.{i}.{j}.0")).expect("bad ipv4"),
+ ),
+ cidr: 8,
+ },
+ true,
+ );
+ }
+ }
+
+ let mut resp = smallest_group_network_limited(&net_list, 22).unwrap();
+ resp.sort_by(|a, b| a.partial_cmp(b).unwrap());
+ assert_eq!(
+ resp,
+ [
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.0.0")).expect("bad ipv4")),
+ cidr: 22
+ },
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.1.0.0")).expect("bad ipv4")),
+ cidr: 22
+ },
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.2.0.0")).expect("bad ipv4")),
+ cidr: 22
+ },
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.3.0.0")).expect("bad ipv4")),
+ cidr: 22
+ },
+ ]
+ );
+ }
+
+ #[test]
+ fn test_smallest_network_limited_24_8() {
+ let mut net_list: HashMap<Ip, bool> = HashMap::new();
+ for i in 0..4 {
+ for j in 0..4 {
+ net_list.insert(
+ Ip {
+ address: Addr::V4(
+ Ipv4Addr::from_str(&format!("192.0.{i}.{j}")).expect("bad ipv4"),
+ ),
+ cidr: 8,
+ },
+ true,
+ );
+ }
+ }
+
+ let mut resp = smallest_group_network_limited(&net_list, 24).unwrap();
+ resp.sort_by(|a, b| a.partial_cmp(b).unwrap());
+ assert_eq!(
+ resp,
+ [
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.0.0")).expect("bad ipv4")),
+ cidr: 24
+ },
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.1.0")).expect("bad ipv4")),
+ cidr: 24
+ },
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.2.0")).expect("bad ipv4")),
+ cidr: 24
+ },
+ Ip {
+ address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.3.0")).expect("bad ipv4")),
+ cidr: 24
+ },
+ ]
+ );
+ }
}
++++++ ripcalc.obsinfo ++++++
--- /var/tmp/diff_new_pack.3eVwlQ/_old 2025-01-05 15:29:31.229478410 +0100
+++ /var/tmp/diff_new_pack.3eVwlQ/_new 2025-01-05 15:29:31.233478574 +0100
@@ -1,5 +1,5 @@
name: ripcalc
-version: 0.1.12
-mtime: 1720730102
-commit: 5aca7acaf7fc5e6d53eb737e620fe418cf76bfdb
+version: 0.1.13
+mtime: 1735754810
+commit: d1e29a5ea08ffcb525d423dcbe51e26436d5f851
++++++ vendor.tar.zst ++++++
++++ 995733 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ghc-time-compat for openSUSE:Factory checked in at 2025-01-05 15:29:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-time-compat (Old)
and /work/SRC/openSUSE:Factory/.ghc-time-compat.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-time-compat"
Sun Jan 5 15:29:18 2025 rev:19 rq:1234638 version:1.9.8
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-time-compat/ghc-time-compat.changes 2024-07-22 17:17:53.673016706 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-time-compat.new.1881/ghc-time-compat.changes 2025-01-05 15:29:29.129392030 +0100
@@ -1,0 +2,7 @@
+Thu Dec 26 13:31:38 UTC 2024 - Peter Simons <psimons(a)suse.com>
+
+- Update time-compat to version 1.9.8.
+ Upstream has not updated the file "CHANGELOG.md" since the last
+ release.
+
+-------------------------------------------------------------------
Old:
----
time-compat-1.9.7.tar.gz
time-compat.cabal
New:
----
time-compat-1.9.8.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-time-compat.spec ++++++
--- /var/tmp/diff_new_pack.I301fW/_old 2025-01-05 15:29:29.773418520 +0100
+++ /var/tmp/diff_new_pack.I301fW/_new 2025-01-05 15:29:29.777418684 +0100
@@ -20,13 +20,12 @@
%global pkgver %{pkg_name}-%{version}
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 1.9.7
+Version: 1.9.8
Release: 0
Summary: Compatibility package for time
License: BSD-3-Clause
URL: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/2.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-base-devel
BuildRequires: ghc-base-orphans-devel
@@ -37,6 +36,8 @@
BuildRequires: ghc-hashable-devel
BuildRequires: ghc-hashable-prof
BuildRequires: ghc-rpm-macros
+BuildRequires: ghc-template-haskell-devel
+BuildRequires: ghc-template-haskell-prof
BuildRequires: ghc-time-devel
BuildRequires: ghc-time-prof
ExcludeArch: %{ix86}
@@ -45,6 +46,8 @@
BuildRequires: ghc-HUnit-prof
BuildRequires: ghc-QuickCheck-devel
BuildRequires: ghc-QuickCheck-prof
+BuildRequires: ghc-random-devel
+BuildRequires: ghc-random-prof
BuildRequires: ghc-tagged-devel
BuildRequires: ghc-tagged-prof
BuildRequires: ghc-tasty-devel
@@ -94,7 +97,6 @@
%prep
%autosetup -n %{pkg_name}-%{version}
-cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
++++++ time-compat-1.9.7.tar.gz -> time-compat-1.9.8.tar.gz ++++++
++++ 6007 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ghc-scientific for openSUSE:Factory checked in at 2025-01-05 15:29:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-scientific (Old)
and /work/SRC/openSUSE:Factory/.ghc-scientific.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-scientific"
Sun Jan 5 15:29:17 2025 rev:34 rq:1234637 version:0.3.8.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-scientific/ghc-scientific.changes 2024-07-22 17:17:35.928308012 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-scientific.new.1881/ghc-scientific.changes 2025-01-05 15:29:28.237355340 +0100
@@ -1,0 +2,6 @@
+Thu Dec 26 13:50:23 UTC 2024 - Peter Simons <psimons(a)suse.com>
+
+- Update scientific to version 0.3.8.0 revision 2.
+ Upstream has revised the Cabal build instructions on Hackage.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-scientific.spec ++++++
--- /var/tmp/diff_new_pack.mwbP1B/_old 2025-01-05 15:29:28.869381336 +0100
+++ /var/tmp/diff_new_pack.mwbP1B/_new 2025-01-05 15:29:28.873381500 +0100
@@ -26,7 +26,7 @@
License: BSD-3-Clause
URL: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal…
+Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/2.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-base-devel
BuildRequires: ghc-base-prof
++++++ scientific.cabal ++++++
--- /var/tmp/diff_new_pack.mwbP1B/_old 2025-01-05 15:29:28.921383474 +0100
+++ /var/tmp/diff_new_pack.mwbP1B/_new 2025-01-05 15:29:28.925383639 +0100
@@ -1,6 +1,6 @@
name: scientific
version: 0.3.8.0
-x-revision: 1
+x-revision: 2
synopsis: Numbers represented using scientific notation
description:
"Data.Scientific" provides the number type 'Scientific'. Scientific numbers are
@@ -50,13 +50,14 @@
|| ==9.0.2
|| ==9.2.8
|| ==9.4.8
- || ==9.6.5
- || ==9.8.2
+ || ==9.6.6
+ || ==9.8.4
|| ==9.10.1
+ || ==9.12.1
source-repository head
type: git
- location: git://github.com/basvandijk/scientific.git
+ location: https://github.com/basvandijk/scientific.git
flag integer-simple
description: Use the integer-simple package instead of integer-gmp
@@ -79,7 +80,7 @@
ghc-options: -Wall
build-depends:
- base >=4.5 && <4.21
+ base >=4.5 && <4.22
, binary >=0.8.6.0 && <0.9
, bytestring >=0.10.8.2 && <0.13
, containers >=0.6.0.1 && <0.8
@@ -87,7 +88,7 @@
, hashable >=1.4.4.0 && <1.6
, integer-logarithms >=1.0.3.1 && <1.1
, primitive >=0.9.0.0 && <0.10
- , template-haskell >=2.14.0.0 && <2.23
+ , template-haskell >=2.14.0.0 && <2.24
, text >=1.2.3.0 && <1.3 || >=2.0 && <2.2
if impl(ghc >=9.0)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ghc-skylighting-core for openSUSE:Factory checked in at 2025-01-05 15:29:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-skylighting-core (Old)
and /work/SRC/openSUSE:Factory/.ghc-skylighting-core.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-skylighting-core"
Sun Jan 5 15:29:16 2025 rev:43 rq:1233974 version:0.14.5
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-skylighting-core/ghc-skylighting-core.changes 2024-12-20 23:11:47.619374662 +0100
+++ /work/SRC/openSUSE:Factory/.ghc-skylighting-core.new.1881/ghc-skylighting-core.changes 2025-01-05 15:29:27.249314700 +0100
@@ -1,0 +2,13 @@
+Mon Dec 23 06:56:27 UTC 2024 - Peter Simons <psimons(a)suse.com>
+
+- Update skylighting-core to version 0.14.5.
+ ## 0.14.5
+
+ * Update xml syntax definitions for bash, cmake, commonlisp, isocpp,
+ javascript-react, julia, latex, lua, markdown, modelines, nix, orgmode,
+ php, python, rhtml, ruby, swift, xml, yaml, zig, zsh. Add odin (required
+ by orgmode).
+
+ * Update JSON syntax definition from upstream. (#203)
+
+-------------------------------------------------------------------
Old:
----
skylighting-core-0.14.4.tar.gz
New:
----
skylighting-core-0.14.5.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-skylighting-core.spec ++++++
--- /var/tmp/diff_new_pack.xbwoxx/_old 2025-01-05 15:29:27.881340696 +0100
+++ /var/tmp/diff_new_pack.xbwoxx/_new 2025-01-05 15:29:27.885340861 +0100
@@ -20,7 +20,7 @@
%global pkgver %{pkg_name}-%{version}
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.14.4
+Version: 0.14.5
Release: 0
Summary: Syntax highlighting library
License: BSD-3-Clause
++++++ skylighting-core-0.14.4.tar.gz -> skylighting-core-0.14.5.tar.gz ++++++
++++ 6005 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package ghc-pandoc-lua-engine for openSUSE:Factory checked in at 2025-01-05 15:29:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-pandoc-lua-engine (Old)
and /work/SRC/openSUSE:Factory/.ghc-pandoc-lua-engine.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-pandoc-lua-engine"
Sun Jan 5 15:29:14 2025 rev:12 rq:1233972 version:0.4.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-pandoc-lua-engine/ghc-pandoc-lua-engine.changes 2024-12-20 23:11:30.094652131 +0100
+++ /work/SRC/openSUSE:Factory/.ghc-pandoc-lua-engine.new.1881/ghc-pandoc-lua-engine.changes 2025-01-05 15:29:24.197189162 +0100
@@ -1,0 +2,6 @@
+Mon Dec 23 19:46:55 UTC 2024 - Peter Simons <psimons(a)suse.com>
+
+- Update pandoc-lua-engine to version 0.4.1.
+ Upstream does not provide a change log file.
+
+-------------------------------------------------------------------
Old:
----
pandoc-lua-engine-0.4.tar.gz
New:
----
pandoc-lua-engine-0.4.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-pandoc-lua-engine.spec ++++++
--- /var/tmp/diff_new_pack.bbqxtE/_old 2025-01-05 15:29:25.165228979 +0100
+++ /var/tmp/diff_new_pack.bbqxtE/_new 2025-01-05 15:29:25.165228979 +0100
@@ -20,7 +20,7 @@
%global pkgver %{pkg_name}-%{version}
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.4
+Version: 0.4.1
Release: 0
Summary: Lua engine to power custom pandoc conversions
License: GPL-2.0-or-later
++++++ pandoc-lua-engine-0.4.tar.gz -> pandoc-lua-engine-0.4.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pandoc-lua-engine-0.4/pandoc-lua-engine.cabal new/pandoc-lua-engine-0.4.1/pandoc-lua-engine.cabal
--- old/pandoc-lua-engine-0.4/pandoc-lua-engine.cabal 2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.4.1/pandoc-lua-engine.cabal 2001-09-09 03:46:40.000000000 +0200
@@ -1,6 +1,6 @@
cabal-version: 2.4
name: pandoc-lua-engine
-version: 0.4
+version: 0.4.1
build-type: Simple
license: GPL-2.0-or-later
license-file: COPYING.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pandoc-lua-engine-0.4/src/Text/Pandoc/Lua/Module/Pandoc.hs new/pandoc-lua-engine-0.4.1/src/Text/Pandoc/Lua/Module/Pandoc.hs
--- old/pandoc-lua-engine-0.4/src/Text/Pandoc/Lua/Module/Pandoc.hs 2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.4.1/src/Text/Pandoc/Lua/Module/Pandoc.hs 2001-09-09 03:46:40.000000000 +0200
@@ -146,6 +146,7 @@
otherConstructors :: [DocumentedFunction PandocError]
otherConstructors =
[ mkAttr
+ , mkCaption
, mkCell
, mkAttributeList
, mkCitation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pandoc-lua-engine-0.4/src/Text/Pandoc/Lua/Module/Utils.hs new/pandoc-lua-engine-0.4.1/src/Text/Pandoc/Lua/Module/Utils.hs
--- old/pandoc-lua-engine-0.4/src/Text/Pandoc/Lua/Module/Utils.hs 2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.4.1/src/Text/Pandoc/Lua/Module/Utils.hs 2001-09-09 03:46:40.000000000 +0200
@@ -316,7 +316,11 @@
[ (fmap Shared.stringify . peekPandoc)
, (fmap Shared.stringify . peekInline)
, (fmap Shared.stringify . peekBlock)
+ , (fmap Shared.stringify . peekCaption)
+ , (fmap Shared.stringify . peekCell)
, (fmap Shared.stringify . peekCitation)
+ , (fmap Shared.stringify . peekTableHead)
+ , (fmap Shared.stringify . peekTableFoot)
, (fmap stringifyMetaValue . peekMetaValue)
, (fmap (const "") . peekAttr)
, (fmap (const "") . peekListAttributes)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pandoc-lua-engine-0.4/test/lua/module/pandoc-utils.lua new/pandoc-lua-engine-0.4.1/test/lua/module/pandoc-utils.lua
--- old/pandoc-lua-engine-0.4/test/lua/module/pandoc-utils.lua 2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.4.1/test/lua/module/pandoc-utils.lua 2001-09-09 03:46:40.000000000 +0200
@@ -223,6 +223,22 @@
local inlines = pandoc.Inlines{pandoc.Str 'a', pandoc.Subscript('b')}
assert.are_equal('ab', utils.stringify(inlines))
end),
+ test('Caption', function ()
+ local capt = pandoc.Caption(pandoc.Para{pandoc.Str 'a', pandoc.Emph('b')})
+ assert.are_equal('ab', utils.stringify(capt))
+ end),
+ test('Cell', function ()
+ local cell = pandoc.Cell(pandoc.Para{pandoc.Str 'a', pandoc.Emph('b')})
+ assert.are_equal('ab', utils.stringify(cell))
+ end),
+ test('TableFoot', function ()
+ local tf = pandoc.TableFoot{pandoc.Row{pandoc.Cell{pandoc.Plain "x y"}}}
+ assert.are_equal('x y', utils.stringify(tf))
+ end),
+ test('TableHead', function ()
+ local th = pandoc.TableHead{pandoc.Row{pandoc.Cell{pandoc.Plain "head1"}}}
+ assert.are_equal('head1', utils.stringify(th))
+ end),
test('Meta', function ()
local meta = pandoc.Meta{
a = pandoc.Inlines 'funny and ',
1
0