summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Cournoyer <maxim.cournoyer@gmail.com>2022-05-06 00:09:29 -0400
committerMaxim Cournoyer <maxim.cournoyer@gmail.com>2022-05-31 14:54:02 -0400
commitdc71b4f1c65c9f3244f96aaf69b9218825361eda (patch)
tree2f2d4ad01e023057f42af396fd96f906269452a2
parentdad15bdb26edbdf7b80519a2e7d0edf4e1efcd5f (diff)
downloadguix-patches-dc71b4f1c65c9f3244f96aaf69b9218825361eda.tar
guix-patches-dc71b4f1c65c9f3244f96aaf69b9218825361eda.tar.gz
gnu: breezy: Update to 3.2.2.
* gnu/packages/patches/breezy-fix-gio.patch: New file. * gnu/local.mk (dist_patch_DATA): Register it. * gnu/packages/version-control.scm (breezy): Update to 3.2.2. [source]{snippet}: Delete pre-generated cythonized C files. {patches}: Apply patch. [tests?]: Disable tests. [phases]{patch-test-shebangs, check}: New phase and override. [native-inputs]: Add nano, python-cython, python-docutils, and python-testrepository. [inputs]: Use new style. Add python-launchpadlib and python-pygobject. [description]: Adjust Bazaar URL.
-rw-r--r--gnu/local.mk1
-rw-r--r--gnu/packages/patches/breezy-fix-gio.patch338
-rw-r--r--gnu/packages/version-control.scm64
3 files changed, 388 insertions, 15 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index b54c1fbefe..513216183d 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -916,6 +916,7 @@ dist_patch_DATA = \
%D%/packages/patches/bloomberg-bde-cmake-module-path.patch \
%D%/packages/patches/bloomberg-bde-tools-fix-install-path.patch \
%D%/packages/patches/bpftrace-disable-bfd-disasm.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/cabal-install-base16-bytestring1.0.patch \
diff --git a/gnu/packages/patches/breezy-fix-gio.patch b/gnu/packages/patches/breezy-fix-gio.patch
new file mode 100644
index 0000000000..f70e761555
--- /dev/null
+++ b/gnu/packages/patches/breezy-fix-gio.patch
@@ -0,0 +1,338 @@
+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 30d15919ab..7351d96600 100644
--- a/gnu/packages/version-control.scm
+++ b/gnu/packages/version-control.scm
@@ -187,29 +187,63 @@ as well as the classic centralized workflow.")
(uri (string-append "https://launchpad.net/brz/"
(version-major+minor version) "/" version
"/+download/breezy-" version ".tar.gz"))
+ (modules '((guix build utils)))
+ ;; Delete pre-generated Cython C files.
+ (snippet '(for-each delete-file (find-files "." "\\pyx.c$")))
(sha256
- (base32 "1md4b6ajawf5h50fqizmjj0g833ihc674dh7fn0mvl4d412nwyhq"))))
+ (base32
+ "1md4b6ajawf5h50fqizmjj0g833ihc674dh7fn0mvl4d412nwyhq"))
+ (patches (search-patches "breezy-fix-gio.patch"))))
(build-system python-build-system)
- ;; TODO: Maybe regenerate C files with Cython?
- (inputs
- `(("gettext" ,gettext-minimal)
- ("python-configobj" ,python-configobj)
- ("python-dulwich" ,python-dulwich)
- ("python-fastbencode" ,python-fastbencode)
- ("python-fastimport" ,python-fastimport)
- ("python-paramiko" ,python-paramiko)
- ("python-patiencediff" ,python-patiencediff)
- ("python-pycryptodome" ,python-pycryptodome)
- ("python-pygpgme" ,python-pygpgme)))
(arguments
- `(#:tests? #f)) ; no tests in release tarball
+ (list
+ #:tests? #f ;FIXME: the test suite hangs
+ #:phases
+ #~(modify-phases %standard-phases
+ (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
+ (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))
(home-page "https://www.breezy-vcs.org/")
(synopsis "Decentralized revision control system")
(description
"Breezy (@command{brz}) is a decentralized revision control system. By
default, Breezy provides support for both the
-@uref{https://www.bazaar-vcs.org, Bazaar} and @uref{https://www.git-scm.com,
-Git} file formats. Breezy is backwards compatible with Bazaar's disk format
+@uref{https://bazaar.canonical.com/, Bazaar} and @uref{https://www.git-scm.com,
+Git} file formats. Breezy is backwabrds compatible with Bazaar's disk format
and protocols. One of the key differences with Bazaar is that Breezy runs on
Python 3.3 and later, rather than on Python 2.")
(license license:gpl2+)))