commit:     c6d2f47243bcedd4f491db5cbe316c2a261e4da3
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sat Nov  9 19:56:54 2019 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sat Nov  9 20:42:26 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=c6d2f472

FileCopier: native zero-copy and sparse file support

Use native copyfile for zero-copy and sparse file support, and copy
permission bits like shutil.copy.

Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/portage/tests/util/test_file_copier.py |  4 ++++
 lib/portage/util/_async/FileCopier.py      | 16 +++++++++++++---
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/lib/portage/tests/util/test_file_copier.py 
b/lib/portage/tests/util/test_file_copier.py
index 01dfba494..3f1ec6b78 100644
--- a/lib/portage/tests/util/test_file_copier.py
+++ b/lib/portage/tests/util/test_file_copier.py
@@ -4,6 +4,7 @@
 import errno
 import os
 import shutil
+import stat
 import tempfile
 
 from portage.tests import TestCase
@@ -22,8 +23,10 @@ class FileCopierTestCase(TestCase):
                        src_path = os.path.join(tempdir, 'src')
                        dest_path = os.path.join(tempdir, 'dest')
                        content = b'foo'
+                       file_mode = 0o600
                        with open(src_path, 'wb') as f:
                                f.write(content)
+                       os.chmod(src_path, file_mode)
                        copier = FileCopier(src_path=src_path, 
dest_path=dest_path, scheduler=loop)
                        copier.start()
                        loop.run_until_complete(copier.async_wait())
@@ -31,6 +34,7 @@ class FileCopierTestCase(TestCase):
                        copier.future.result()
                        with open(dest_path, 'rb') as f:
                                self.assertEqual(f.read(), content)
+                       self.assertEqual(file_mode, 
stat.S_IMODE(os.stat(dest_path).st_mode))
 
                        # failure due to nonexistent src_path
                        src_path = os.path.join(tempdir, 'does-not-exist')

diff --git a/lib/portage/util/_async/FileCopier.py 
b/lib/portage/util/_async/FileCopier.py
index 3a0be4b63..d9077411d 100644
--- a/lib/portage/util/_async/FileCopier.py
+++ b/lib/portage/util/_async/FileCopier.py
@@ -1,7 +1,11 @@
 # Copyright 2013-2019 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-from portage import shutil
+import os as _os
+
+from portage import _encodings, _unicode_encode
+from portage.util import apply_stat_permissions
+from portage.util.file_copy import copyfile
 from portage.util.futures import asyncio
 from portage.util.futures.executor.fork import ForkExecutor
 from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
@@ -14,6 +18,12 @@ class FileCopier(AsyncTaskFuture):
        __slots__ = ('src_path', 'dest_path')
 
        def _start(self):
-               self.future = 
asyncio.ensure_future(self.scheduler.run_in_executor(ForkExecutor(loop=self.scheduler),
-                       shutil.copy, self.src_path, self.dest_path))
+               self.future = 
asyncio.ensure_future(self.scheduler.run_in_executor(
+                       ForkExecutor(loop=self.scheduler), self._run))
                super(FileCopier, self)._start()
+
+       def _run(self):
+               src_path = _unicode_encode(self.src_path, 
encoding=_encodings['fs'], errors='strict')
+               dest_path = _unicode_encode(self.dest_path, 
encoding=_encodings['fs'], errors='strict')
+               copyfile(src_path, dest_path)
+               apply_stat_permissions(dest_path, _os.stat(src_path))

Reply via email to