339 lines
13 KiB
Diff
339 lines
13 KiB
Diff
|
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)
|
||
|
|