From 8e5094497ccb187d712bb3dfcddb87c6be5698f7 Mon Sep 17 00:00:00 2001 From: Dariqq Date: Sun, 26 Jan 2025 12:27:10 +0000 Subject: gnu: breezy: Update to 3.3.9. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit breezy now depends on a rust compiler and crates so we need to switch to cargo-build-system to set up rust and then readd all the python phases. * gnu/packages/version-control.scm (breezy): Update to 3.3.9. [build-system]: switch to cargo-build-system [#:phases]: Convert back to python-build-system Add a phase to install the bash-completion file. Run the testsuite again. [native-inputs]: Remove python-docutils, python-testrepository Add gettext-minimal, python-wrapper, python-setuptools, python-setuptools-rust, python-setuptools-gettext, python-tomli, python wheel. Add python testtools and python packaging for tests. [inputs]: Remove gettext-minimal, python-pygobject. Add python-merge3, python-pygithub, python-pyyaml, python-tzlocal, python-urllib3 Replace python-pycrptodome and python-pygpgme with python-gpg * gnu/packages/patches/breezy-fix-gio.patch: Remove patch * gnu/local.mk : Deregister it. Change-Id: I69d6c4491442a9ba93a748137fb2ad810a423abd Signed-off-by: Ludovic Courtès --- gnu/local.mk | 1 - gnu/packages/patches/breezy-fix-gio.patch | 338 ------------------------------ gnu/packages/version-control.scm | 122 ++++++++--- 3 files changed, 89 insertions(+), 372 deletions(-) delete mode 100644 gnu/packages/patches/breezy-fix-gio.patch (limited to 'gnu') diff --git a/gnu/local.mk b/gnu/local.mk index dc0502c139..c8a29bf98b 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1060,7 +1060,6 @@ dist_patch_DATA = \ %D%/packages/patches/bloomberg-bde-tools-fix-install-path.patch \ %D%/packages/patches/boolector-find-googletest.patch \ %D%/packages/patches/boost-fix-duplicate-definitions-bug.patch \ - %D%/packages/patches/breezy-fix-gio.patch \ %D%/packages/patches/byobu-writable-status.patch \ %D%/packages/patches/bubblewrap-fix-locale-in-tests.patch \ %D%/packages/patches/busybox-add-missing-sha-NI-guard.patch \ diff --git a/gnu/packages/patches/breezy-fix-gio.patch b/gnu/packages/patches/breezy-fix-gio.patch deleted file mode 100644 index f70e761555..0000000000 --- a/gnu/packages/patches/breezy-fix-gio.patch +++ /dev/null @@ -1,338 +0,0 @@ -This patch combines https://code.launchpad.net/~jelmer/brz/enable-gio/+merge/419150 -and https://bazaar.launchpad.net/~jelmer/brz/fix-gio/revision/7570. - -=== modified file 'breezy/transport/gio_transport.py' ---- a/breezy/transport/gio_transport.py 2022-04-09 12:17:41 +0000 -+++ b/breezy/transport/gio_transport.py 2022-04-09 12:33:51 +0000 -@@ -52,11 +52,7 @@ - from ..tests.test_server import TestServer - - try: -- import glib --except ImportError as e: -- raise errors.DependencyNotPresent('glib', e) --try: -- import gio -+ from gi.repository import Gio as gio - except ImportError as e: - raise errors.DependencyNotPresent('gio', e) - - -@@ -57,6 +57,9 @@ - raise errors.DependencyNotPresent('gio', e) - - -+from gi.repository.GLib import GError -+ -+ - class GioLocalURLServer(TestServer): - """A pretend server for local transports, using file:// urls. - -@@ -81,7 +84,7 @@ - def __init__(self, transport, relpath): - FileStream.__init__(self, transport, relpath) - self.gio_file = transport._get_GIO(relpath) -- self.stream = self.gio_file.create() -+ self.stream = self.gio_file.create(0, None) - - def _close(self): - self.stream.close() -@@ -90,7 +93,7 @@ - try: - # Using pump_string_file seems to make things crash - osutils.pumpfile(BytesIO(bytes), self.stream) -- except gio.Error as e: -+ except GError as e: - # self.transport._translate_gio_error(e,self.relpath) - raise errors.BzrError(str(e)) - -@@ -98,12 +101,12 @@ - class GioStatResult(object): - - def __init__(self, f): -- info = f.query_info('standard::size,standard::type') -+ info = f.query_info('standard::size,standard::type', 0, None) - self.st_size = info.get_size() - type = info.get_file_type() -- if (type == gio.FILE_TYPE_REGULAR): -+ if type == gio.FileType.REGULAR: - self.st_mode = stat.S_IFREG -- elif type == gio.FILE_TYPE_DIRECTORY: -+ elif type == gio.FileType.DIRECTORY: - self.st_mode = stat.S_IFDIR - - -@@ -122,7 +125,7 @@ - user, netloc = netloc.rsplit('@', 1) - # Seems it is not possible to list supported backends for GIO - # so a hardcoded list it is then. -- gio_backends = ['dav', 'file', 'ftp', 'obex', 'sftp', 'ssh', 'smb'] -+ gio_backends = ['dav', 'file', 'ftp', 'obex', 'sftp', 'ssh', 'smb', 'http'] - if scheme not in gio_backends: - raise urlutils.InvalidURL(base, - extra="GIO support is only available for " + -@@ -138,13 +141,10 @@ - _from_transport=_from_transport) - - def _relpath_to_url(self, relpath): -- full_url = urlutils.join(self.url, relpath) -- if isinstance(full_url, str): -- raise urlutils.InvalidURL(full_url) -- return full_url -+ return urlutils.join(self.url, relpath) - - def _get_GIO(self, relpath): -- """Return the ftplib.GIO instance for this object.""" -+ """Return the GIO instance for this object.""" - # Ensures that a connection is established - connection = self._get_connection() - if connection is None: -@@ -152,7 +152,7 @@ - connection, credentials = self._create_connection() - self._set_connection(connection, credentials) - fileurl = self._relpath_to_url(relpath) -- file = gio.File(fileurl) -+ file = gio.File.new_for_uri(fileurl) - return file - - def _auth_cb(self, op, message, default_user, default_domain, flags): -@@ -197,7 +197,7 @@ - try: - obj.mount_enclosing_volume_finish(res) - self.loop.quit() -- except gio.Error as e: -+ except GError as e: - self.loop.quit() - raise errors.BzrError( - "Failed to mount the given location: " + str(e)) -@@ -209,12 +209,12 @@ - user, password = credentials - - try: -- connection = gio.File(self.url) -+ connection = gio.File.new_for_uri(self.url) - mount = None - try: - mount = connection.find_enclosing_mount() -- except gio.Error as e: -- if (e.code == gio.ERROR_NOT_MOUNTED): -+ except GError as e: -+ if e.code == gio.IOErrorEnum.NOT_MOUNTED: - self.loop = glib.MainLoop() - ui.ui_factory.show_message('Mounting %s using GIO' % - self.url) -@@ -227,7 +227,7 @@ - m = connection.mount_enclosing_volume(op, - self._mount_done_cb) - self.loop.run() -- except gio.Error as e: -+ except GError as e: - raise errors.TransportError(msg="Error setting up connection:" - " %s" % str(e), orig_error=e) - return connection, (user, password) -@@ -257,8 +257,8 @@ - if stat.S_ISREG(st.st_mode) or stat.S_ISDIR(st.st_mode): - return True - return False -- except gio.Error as e: -- if e.code == gio.ERROR_NOT_FOUND: -+ except GError as e: -+ if e.code == gio.IOErrorEnum.NOT_FOUND: - return False - else: - self._translate_gio_error(e, relpath) -@@ -281,10 +281,10 @@ - buf = fin.read() - fin.close() - return BytesIO(buf) -- except gio.Error as e: -+ except GError as e: - # If we get a not mounted here it might mean - # that a bad path has been entered (or that mount failed) -- if (e.code == gio.ERROR_NOT_MOUNTED): -+ if e.code == gio.IOErrorEnum.NOT_MOUNTED: - raise errors.PathError(relpath, - extra='Failed to get file, make sure the path is correct. ' - + str(e)) -@@ -307,19 +307,19 @@ - closed = True - try: - f = self._get_GIO(tmppath) -- fout = f.create() -+ fout = f.create(0, None) - closed = False - length = self._pump(fp, fout) - fout.close() - closed = True - self.stat(tmppath) - dest = self._get_GIO(relpath) -- f.move(dest, flags=gio.FILE_COPY_OVERWRITE) -+ f.move(dest, flags=gio.FileCopyFlags.OVERWRITE) - f = None - if mode is not None: - self._setmode(relpath, mode) - return length -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath) - finally: - if not closed and fout is not None: -@@ -335,7 +335,7 @@ - f = self._get_GIO(relpath) - f.make_directory() - self._setmode(relpath, mode) -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath) - - def open_write_stream(self, relpath, mode=None): -@@ -369,14 +369,11 @@ - f.delete() - else: - raise errors.NotADirectory(relpath) -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath) - except errors.NotADirectory as e: - # just pass it forward - raise e -- except Exception as e: -- mutter('failed to rmdir %s: %s' % (relpath, e)) -- raise errors.PathError(relpath) - - def append_file(self, relpath, file, mode=None): - """Append the text in the file-like object into the final -@@ -392,7 +389,7 @@ - result = 0 - fo = self._get_GIO(tmppath) - fi = self._get_GIO(relpath) -- fout = fo.create() -+ fout = fo.create(0, None) - try: - info = GioStatResult(fi) - result = info.st_size -@@ -400,11 +397,11 @@ - self._pump(fin, fout) - fin.close() - # This separate except is to catch and ignore the -- # gio.ERROR_NOT_FOUND for the already existing file. -+ # gio.IOErrorEnum.NOT_FOUND for the already existing file. - # It is valid to open a non-existing file for append. - # This is caused by the broken gio append_to... -- except gio.Error as e: -- if e.code != gio.ERROR_NOT_FOUND: -+ except GError as e: -+ if e.code != gio.IOErrorEnum.NOT_FOUND: - self._translate_gio_error(e, relpath) - length = self._pump(file, fout) - fout.close() -@@ -413,9 +410,11 @@ - raise errors.BzrError("Failed to append size after " - "(%d) is not original (%d) + written (%d) total (%d)" % - (info.st_size, result, length, result + length)) -- fo.move(fi, flags=gio.FILE_COPY_OVERWRITE) -+ fo.move( -+ fi, flags=gio.FileCopyFlags.OVERWRITE, cancellable=None, -+ progress_callback=None) - return result -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath) - - def _setmode(self, relpath, mode): -@@ -429,8 +428,8 @@ - try: - f = self._get_GIO(relpath) - f.set_attribute_uint32(gio.FILE_ATTRIBUTE_UNIX_MODE, mode) -- except gio.Error as e: -- if e.code == gio.ERROR_NOT_SUPPORTED: -+ except GError as e: -+ if e.code == gio.IOErrorEnum.NOT_SUPPORTED: - # Command probably not available on this server - mutter("GIO Could not set permissions to %s on %s. %s", - oct(mode), self._remote_path(relpath), str(e)) -@@ -444,8 +443,8 @@ - mutter("GIO move (rename): %s => %s", rel_from, rel_to) - f = self._get_GIO(rel_from) - t = self._get_GIO(rel_to) -- f.move(t) -- except gio.Error as e: -+ f.move(t, flags=0, cancellable=None, progress_callback=None) -+ except GError as e: - self._translate_gio_error(e, rel_from) - - def move(self, rel_from, rel_to): -@@ -455,8 +454,8 @@ - mutter("GIO move: %s => %s", rel_from, rel_to) - f = self._get_GIO(rel_from) - t = self._get_GIO(rel_to) -- f.move(t, flags=gio.FILE_COPY_OVERWRITE) -- except gio.Error as e: -+ f.move(t, flags=gio.FileCopyFlags.OVERWRITE) -+ except GError as e: - self._translate_gio_error(e, relfrom) - - def delete(self, relpath): -@@ -466,7 +465,7 @@ - mutter("GIO delete: %s", relpath) - f = self._get_GIO(relpath) - f.delete() -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath) - - def external_url(self): -@@ -489,11 +488,11 @@ - try: - entries = [] - f = self._get_GIO(relpath) -- children = f.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_NAME) -+ children = f.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_NAME, 0, None) - for child in children: - entries.append(urlutils.escape(child.get_name())) - return entries -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath) - - def iter_files_recursive(self): -@@ -519,7 +518,7 @@ - mutter("GIO stat: %s", relpath) - f = self._get_GIO(relpath) - return GioStatResult(f) -- except gio.Error as e: -+ except GError as e: - self._translate_gio_error(e, relpath, extra='error w/ stat') - - def lock_read(self, relpath): -@@ -556,21 +555,21 @@ - mutter("GIO Error: %s %s" % (str(err), path)) - if extra is None: - extra = str(err) -- if err.code == gio.ERROR_NOT_FOUND: -+ if err.code == gio.IOErrorEnum.NOT_FOUND: - raise errors.NoSuchFile(path, extra=extra) -- elif err.code == gio.ERROR_EXISTS: -+ elif err.code == gio.IOErrorEnum.EXISTS: - raise errors.FileExists(path, extra=extra) -- elif err.code == gio.ERROR_NOT_DIRECTORY: -+ elif err.code == gio.IOErrorEnum.NOT_DIRECTORY: - raise errors.NotADirectory(path, extra=extra) -- elif err.code == gio.ERROR_NOT_EMPTY: -+ elif err.code == gio.IOErrorEnum.NOT_EMPTY: - raise errors.DirectoryNotEmpty(path, extra=extra) -- elif err.code == gio.ERROR_BUSY: -+ elif err.code == gio.IOErrorEnum.BUSY: - raise errors.ResourceBusy(path, extra=extra) -- elif err.code == gio.ERROR_PERMISSION_DENIED: -+ elif err.code == gio.IOErrorEnum.PERMISSION_DENIED: - raise errors.PermissionDenied(path, extra=extra) -- elif err.code == gio.ERROR_HOST_NOT_FOUND: -+ elif err.code == gio.IOErrorEnum.HOST_NOT_FOUND: - raise errors.PathError(path, extra=extra) -- elif err.code == gio.ERROR_IS_DIRECTORY: -+ elif err.code == gio.IOErrorEnum.IS_DIRECTORY: - raise errors.PathError(path, extra=extra) - else: - mutter('unable to understand error for path: %s: %s', path, err) - diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scm index e67d8f7838..9ecb5cf98a 100644 --- a/gnu/packages/version-control.scm +++ b/gnu/packages/version-control.scm @@ -63,6 +63,7 @@ ;;; Copyright © 2024 Herman Rimm ;;; Copyright © 2024 Sharlatan Hellseher ;;; Copyright © 2025 Artyom V. Poptsov +;;; Copyright © 2025 Dariqq ;;; ;;; This file is part of GNU Guix. ;;; @@ -184,7 +185,7 @@ (define-module (gnu packages version-control) (define-public breezy (package (name "breezy") - (version "3.2.2") + (version "3.3.9") (source (origin (method url-fetch) @@ -196,51 +197,106 @@ (define-public breezy (snippet '(for-each delete-file (find-files "." "\\pyx.c$"))) (sha256 (base32 - "1md4b6ajawf5h50fqizmjj0g833ihc674dh7fn0mvl4d412nwyhq")) - (patches (search-patches "breezy-fix-gio.patch")))) - (build-system python-build-system) + "1n6mqd1iy50537kb4lsr52289yyr1agmkxpchxlhb9682zr8nn62")))) + (build-system cargo-build-system) (arguments (list - #:tests? #f ;FIXME: the test suite hangs + #:cargo-inputs (list rust-lazy-static-1 + rust-pyo3-0.22 + rust-regex-1) + #:install-source? #f + #:modules + '((guix build cargo-build-system) + ((guix build python-build-system) #:prefix py:) + (guix build utils)) + #:imported-modules + `(,@%cargo-build-system-modules + ,@%python-build-system-modules) #:phases #~(modify-phases %standard-phases + (add-after 'unpack 'ensure-no-mtimes-pre-1980 + (assoc-ref py:%standard-phases 'ensure-no-mtimes-pre-1980)) + (add-after 'ensure-no-mtimes-pre-1980 'enable-bytecode-determinism + (assoc-ref py:%standard-phases 'enable-bytecode-determinism)) + (add-after 'enable-bytecode-determinism 'ensure-no-cythonized-files + (assoc-ref py:%standard-phases 'ensure-no-cythonized-files)) (add-after 'unpack 'patch-test-shebangs (lambda _ (substitute* (append (find-files "breezy/bzr/tests") (find-files "breezy/tests")) (("#!/bin/sh") (format #f "#!~a" (which "sh")))))) - (replace 'check + (add-before 'build 'adjust-for-python-3.10 + (lambda _ + (substitute* '("breezy/doc_generate/__init__.py" + "breezy/tests/test_selftest.py") + ;; AttributeError: module 'datetime' has no attribute 'UTC' + ;; This only works for python >= 3.11 + (("datetime.UTC") "datetime.timezone.utc")))) + (replace 'build + (assoc-ref py:%standard-phases 'build)) + (delete 'check) ;moved after the install phase + (replace 'install + (assoc-ref py:%standard-phases 'install)) + (add-after 'install 'add-install-to-pythonpath + (assoc-ref py:%standard-phases 'add-install-to-pythonpath)) + (add-after 'add-install-to-pythonpath 'add-install-to-path + (assoc-ref py:%standard-phases 'add-install-to-path)) + (add-after 'add-install-to-path 'install-completion + (lambda* (#:key outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (bash (string-append out "/share/bash-completion" + "/completions"))) + (install-file "contrib/bash/brz" bash)))) + (add-after 'add-install-to-path 'wrap + (assoc-ref py:%standard-phases 'wrap)) + (add-after 'wrap 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? - ;; The test_read_bundle tests fails with "TypeError: a - ;; bytes-like object is required, not '_ResultTuple'" (see: - ;; https://bugs.launchpad.net/brz/+bug/1968415/comments/4). - (substitute* "breezy/bzr/tests/__init__.py" - (("'test_read_bundle'," all) - (string-append "# " all))) (setenv "BZR_EDITOR" "nano") - (setenv "HOME" "/tmp") - (invoke "testr" "init") - (invoke "testr" "run"))))))) - (native-inputs - (list nano ;for tests - python-cython - python-docutils - python-subunit - python-testrepository)) - (inputs - (list gettext-minimal - python-configobj - python-dulwich - python-fastbencode - python-fastimport - python-launchpadlib - python-paramiko - python-patiencediff - python-pycryptodome - python-pygobject - python-pygpgme)) + (invoke "brz" "selftest" "--verbose" "--parallel=fork" + ;; This test hangs + "-x" "breezy.tests.blackbox.test_serve" + ;; No GnuPG key results for pattern: bazaar@example.com + "-x" "breezy.tests.test_gpg" + ;; compgen: command not found + "-x" "bash_completion" + ;; No such file or directory: '/etc/mtab' + "-x" "breezy.tests.blackbox.test_diff.TestExternalDiff.test_external_diff" + ;; Value "/etc/ssl/certs/ca-certificates.crt" is not valid for "ssl.ca_certs" + "-x" "breezy.tests.test_https_urllib.CaCertsConfigTests.test_default_exists" + ;; Unknown Failure + "-x" "breezy.tests.test_plugins.TestLoadPluginAt.test_compiled_loaded" + "-x" "breezy.tests.test_plugins.TestPlugins.test_plugin_get_path_pyc_only" + "-x" "breezy.tests.test_selftest.TestActuallyStartBzrSubprocess.test_start_and_stop_bzr_subprocess_send_signal")))) + (add-before 'strip 'rename-pth-file + (assoc-ref py:%standard-phases 'rename-pth-file))))) + (native-inputs (list gettext-minimal + python-wrapper + python-cython + python-setuptools + python-setuptools-gettext + python-setuptools-rust + python-tomli + python-wheel + ;; tests + nano + python-testtools + python-packaging + python-subunit)) + (inputs (list python-configobj + python-dulwich + python-fastbencode + python-fastimport + python-launchpadlib + python-merge3 + python-paramiko + python-gpg + python-patiencediff + python-pygithub + python-pyyaml + python-tzlocal + python-urllib3)) (home-page "https://www.breezy-vcs.org/") (synopsis "Decentralized revision control system") (description -- cgit v1.2.3