Permalink
Browse files

core.actions: imported shutil_g paste function from v1.2.3

The code implements the functionality of cp and mv coreutils in python
and was removed as of v1.4.0 for efficiency and simplicity reasons.
I moved it back in for several reasons:

1. I plan to enhance shutil_g to report on its copying status so I can
display a progress bar

2. With no need for external cp/mv programs, distribution-specific
differences (like broken backup option on MacOS/BSD?) become irrelevant

3. You can still copy in ranger if you accidently delete /bin/cp

4. It gets rid of the occasional bug that the cp process keeps running
when ranger is terminated while copying

The possible downside is reduced efficiency in copying and ranger might
get stuck if the copying function is blocked.  Let's see if it works
out.
  • Loading branch information...
hut committed Aug 15, 2012
1 parent f39d35d commit 19995fd134ac40c940e05e091246e384bbd2e3b1
Showing with 364 additions and 34 deletions.
  1. +36 −34 ranger/core/actions.py
  2. +26 −0 ranger/ext/run_forked.py
  3. +302 −0 ranger/ext/shutil_generatorized.py
View
@@ -22,7 +22,8 @@
SettingsAware
from ranger.core.tab import Tab
from ranger.fsobject import File
-from ranger.core.loader import CommandLoader
+from ranger.core.loader import CommandLoader, Loadable
+from ranger.ext import shutil_generatorized as shutil_g
MACRO_FAIL = "<\x01\x01MACRO_HAS_NO_VALUE\x01\01>"
@@ -1061,53 +1062,54 @@ def _recurse_hardlinked_tree(self, source_path, target_path):
def paste(self, overwrite=False):
"""Paste the selected items into the current directory"""
- copied_files = tuple(self.copy_buffer)
+ copied_files = tuple(self.env.copy)
if not copied_files:
return
- def refresh(_):
- cwd = self.get_directory(original_path)
- cwd.load_content()
-
- cwd = self.thisdir
- original_path = cwd.path
- one_file = copied_files[0]
- if overwrite:
- cp_flags = ['-af', '--']
- mv_flags = ['-f', '--']
- else:
- cp_flags = ['--backup=numbered', '-a', '--']
- mv_flags = ['--backup=numbered', '--']
+ original_path = self.env.cwd.path
+ try:
+ one_file = copied_files[0]
+ except:
+ one_file = None
- if self.do_cut:
- self.copy_buffer.clear()
- self.do_cut = False
+ if self.env.cut:
+ self.env.copy.clear()
+ self.env.cut = False
if len(copied_files) == 1:
descr = "moving: " + one_file.path
else:
descr = "moving files from: " + one_file.dirname
- obj = CommandLoader(args=['mv'] + mv_flags \
- + [f.path for f in copied_files] \
- + [cwd.path], descr=descr)
+ def generate():
+ for f in copied_files:
+ for _ in shutil_g.move(src=f.path,
+ dst=original_path,
+ overwrite=overwrite):
+ yield
+ cwd = self.env.get_directory(original_path)
+ cwd.load_content()
else:
if len(copied_files) == 1:
descr = "copying: " + one_file.path
else:
descr = "copying files from: " + one_file.dirname
- if not overwrite and len(copied_files) == 1 \
- and one_file.dirname == cwd.path:
- # Special case: yypp
- # copying a file onto itself -> create a backup
- obj = CommandLoader(args=['cp', '-f'] + cp_flags \
- + [one_file.path, one_file.path], descr=descr)
- else:
- obj = CommandLoader(args=['cp'] + cp_flags \
- + [f.path for f in copied_files] \
- + [cwd.path], descr=descr)
-
- obj.signal_bind('after', refresh)
- self.loader.add(obj)
+ def generate():
+ for f in self.env.copy:
+ if isdir(f.path):
+ for _ in shutil_g.copytree(src=f.path,
+ dst=join(original_path, f.basename),
+ symlinks=True,
+ overwrite=overwrite):
+ yield
+ else:
+ for _ in shutil_g.copy2(f.path, original_path,
+ symlinks=True,
+ overwrite=overwrite):
+ yield
+ cwd = self.env.get_directory(original_path)
+ cwd.load_content()
+
+ self.loader.add(Loadable(generate(), descr))
def delete(self):
# XXX: warn when deleting mount points/unseen marked files?
View
@@ -0,0 +1,26 @@
+# Copyright (C) 2012 Roman Zimbelmann <romanz@lavabit.com>
+# This software is distributed under the terms of the GNU GPL version 3.
+
+import os
+import subprocess
+
+def Popen_forked(*args, **kwargs):
+ """
+ Forks process and runs Popen with the given args and kwargs.
+
+ If os.fork() is not supported, runs Popen without forking and returns the
+ process object returned by Popen.
+ Otherwise, returns None.
+ """
+ try:
+ pid = os.fork()
+ except:
+ # fall back to not forking if os.fork() is not supported
+ return subprocess.Popen(*args, **kwargs)
+ else:
+ if pid == 0:
+ os.setsid()
+ kwargs['stdin'] = open(os.devnull, 'r')
+ kwargs['stdout'] = kwargs['stderr'] = open(os.devnull, 'w')
+ subprocess.Popen(*args, **kwargs)
+ os._exit(0)
Oops, something went wrong.

0 comments on commit 19995fd

Please sign in to comment.