about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authortoonn <toonn@toonn.io>2020-06-29 18:48:44 +0200
committertoonn <toonn@toonn.io>2020-06-29 19:09:19 +0200
commit114ce4d88fe751c0fc3ba66b823f4bf32b17df32 (patch)
treeea4c591a7e06500fcf42c9462a78085d07806ddd
parente2619d96f23b28a100266e8b9fe4fee7df59ed01 (diff)
downloadranger-114ce4d88fe751c0fc3ba66b823f4bf32b17df32.tar.gz
Include mtime in hash rather than comparing
Comparing the mtimes of a file and a cached preview or including the
mtime in the preview's hash are almost equivalent except this way we
don't need to find out the preview's mtime.

We include the device identifier and the inode in the hash, this makes
sure duplicate filenames don't cause erroneous hits in the cache.
-rw-r--r--ranger/core/actions.py19
1 files changed, 12 insertions, 7 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 9b64f63a..245ff818 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -35,9 +35,10 @@ from ranger.container.file import File
 from ranger.core.loader import CommandLoader, CopyLoader
 from ranger.container.settings import ALLOWED_SETTINGS, ALLOWED_VALUES
 
-
 MACRO_FAIL = "<\x01\x01MACRO_HAS_NO_VALUE\x01\01>"
 
+PY3 = version_info[0] >= 3
+
 LOG = getLogger(__name__)
 
 
@@ -1050,10 +1051,15 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
 
     @staticmethod
     def sha1_encode(path):
-        if version_info[0] < 3:
-            return os.path.join(ranger.args.cachedir, sha1(path).hexdigest()) + '.jpg'
-        return os.path.join(ranger.args.cachedir,
-                            sha1(path.encode('utf-8', 'backslashreplace')).hexdigest()) + '.jpg'
+        stat_ = stat(path)
+        if PY3:
+            path = path.encode('utf-8', 'backslashreplace')
+        sha = sha1(path)
+        sha.update(stat_.st_dev)
+        sha.update(stat_.st_ino)
+        sha.update(stat_.st_mtime)
+        hashpath = os.path.join(ranger.args.cachedir, sha.hexdigest())
+        return '{0}.jpg'.format(hashpath)
 
     def get_preview(self, fobj, width, height):  # pylint: disable=too-many-return-statements
         pager = self.ui.get_pager()
@@ -1123,8 +1129,7 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
             os.makedirs(ranger.args.cachedir)
         cacheimg = os.path.join(ranger.args.cachedir, self.sha1_encode(path))
         if self.settings.preview_images and \
-                os.path.isfile(cacheimg) and \
-                os.path.getmtime(cacheimg) >= os.path.getmtime(path):
+                os.path.isfile(cacheimg):
             data['foundpreview'] = True
             data['imagepreview'] = True
             pager.set_image(cacheimg)