summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/core/actions.py26
-rw-r--r--ranger/defaults/rc.conf1
2 files changed, 25 insertions, 2 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 8106a89b..4e72de77 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -19,8 +19,8 @@ import re
 import shutil
 import string
 import tempfile
-from os.path import join, isdir, realpath
-from os import link, symlink, getcwd
+from os.path import join, isdir, realpath, exists
+from os import link, symlink, getcwd, listdir, stat
 from inspect import cleandoc
 
 import ranger
@@ -1003,6 +1003,28 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 			except Exception as x:
 				self.notify(x)
 
+	def paste_hardlinked_subtree(self):
+		for f in self.env.copy:
+			try:
+				target_path = join(getcwd(), f.basename)
+				self._recurse_hardlinked_tree(f.path, target_path)
+			except Exception as x:
+				self.notify(x)
+
+	def _recurse_hardlinked_tree(self, source_path, target_path):
+		if isdir(source_path):
+			if not exists(target_path):
+				os.mkdir(target_path, stat(source_path).st_mode)
+			for item in listdir(source_path):
+				self._recurse_hardlinked_tree(
+					join(source_path, item),
+					join(target_path, item))
+		else:
+			if not exists(target_path) \
+			or stat(source_path).st_ino != stat(target_path).st_ino:
+				link(source_path,
+					next_available_filename(target_path))
+
 	def paste(self, overwrite=False):
 		"""Paste the selected items into the current directory"""
 		copied_files = tuple(self.env.copy)
diff --git a/ranger/defaults/rc.conf b/ranger/defaults/rc.conf
index 1ecbc398..77ffa5c3 100644
--- a/ranger/defaults/rc.conf
+++ b/ranger/defaults/rc.conf
@@ -147,6 +147,7 @@ map po paste overwrite=True
 map pl paste_symlink relative=False
 map pL paste_symlink relative=True
 map phl paste_hardlink
+map pht paste_hardlinked_subtree
 
 map dd cut
 map ud uncut