Bug: https://bugs.gentoo.org/642632
---
 bin/doins.py                        | 13 ++++++++++---
 pym/portage/tests/bin/test_doins.py |  4 ++--
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/bin/doins.py b/bin/doins.py
index 92e450979..dceffee83 100644
--- a/bin/doins.py
+++ b/bin/doins.py
@@ -107,6 +107,7 @@ def _parse_install_options(
        parser.add_argument('-g', '--group', default=-1, type=_parse_group)
        parser.add_argument('-o', '--owner', default=-1, type=_parse_user)
        parser.add_argument('-m', '--mode', default=0o755, type=_parse_mode)
+       parser.add_argument('-p', '--preserve-timestamps', action='store_true')
        split_options = shlex.split(options)
        namespace, remaining = parser.parse_known_args(split_options)
        # Because parsing '--mode' option is partially supported. If unknown
@@ -168,7 +169,8 @@ class _InsInProcessInstallRunner(object):
                        True on success, otherwise False.
                """
                dest = os.path.join(dest_dir, os.path.basename(source))
-               if not self._is_install_allowed(source, dest):
+               sstat = os.stat(source)
+               if not self._is_install_allowed(source, sstat, dest):
                        return False
 
                # To emulate the `install` command, remove the dest file in
@@ -187,6 +189,11 @@ class _InsInProcessInstallRunner(object):
                                movefile._copyxattr(
                                        source, dest,
                                        exclude=self._xattr_exclude)
+                       if self._parsed_options.preserve_timestamps:
+                               if sys.version_info >= (3, 3):
+                                       os.utime(dest, ns=(sstat.st_mtime_ns, 
sstat.st_mtime_ns))
+                               else:
+                                       os.utime(dest, (sstat.st_mtime, 
sstat.st_mtime))
                except Exception:
                        logging.exception(
                                'Failed to copy file: '
@@ -195,13 +202,14 @@ class _InsInProcessInstallRunner(object):
                        return False
                return True
 
-       def _is_install_allowed(self, source, dest):
+       def _is_install_allowed(self, source, source_stat, dest):
                """Returns if installing source into dest should work.
 
                This is to keep compatibility with the `install` command.
 
                Args:
                        source: path to the source file.
+                       source_stat: stat result for the source file.
                        dest: path to the dest file.
 
                Returns:
@@ -210,7 +218,6 @@ class _InsInProcessInstallRunner(object):
                # To match `install` command, use stat() for source, while
                # lstat() for dest. Raise an exception if stat(source) fails,
                # intentionally.
-               source_stat = os.stat(source)
                try:
                        dest_lstat = os.lstat(dest)
                except OSError as e:
diff --git a/pym/portage/tests/bin/test_doins.py 
b/pym/portage/tests/bin/test_doins.py
index 14d7adfa6..dd40abf6e 100644
--- a/pym/portage/tests/bin/test_doins.py
+++ b/pym/portage/tests/bin/test_doins.py
@@ -38,7 +38,7 @@ class DoIns(setup_env.BinTestCase):
                self.init()
                try:
                        env = setup_env.env
-                       env['INSOPTIONS'] = '-m0644'
+                       env['INSOPTIONS'] = '-pm0644'
                        with open(os.path.join(env['S'], 'test'), 'w'):
                                pass
                        doins('test')
@@ -145,7 +145,7 @@ class DoIns(setup_env.BinTestCase):
                        env = setup_env.env
                        # Use an option which doins.py does not know.
                        # Then, fallback to `install` command is expected.
-                       env['INSOPTIONS'] = '-p'
+                       env['INSOPTIONS'] = '-b'
                        with open(os.path.join(env['S'], 'test'), 'w'):
                                pass
                        doins('test')
-- 
2.13.6


Reply via email to