hydrus/include/HydrusPaths.py

313 lines
7.4 KiB
Python

import gc
import HydrusConstants as HC
import HydrusData
import os
import send2trash
import shutil
import subprocess
import sys
import tempfile
import threading
import traceback
def CleanUpTempPath( os_file_handle, temp_path ):
try:
os.close( os_file_handle )
except OSError:
gc.collect()
try:
os.close( os_file_handle )
except OSError:
HydrusData.Print( 'Could not close the temporary file ' + temp_path )
return
try:
os.remove( temp_path )
except OSError:
gc.collect()
try:
os.remove( temp_path )
except OSError:
HydrusData.Print( 'Could not delete the temporary file ' + temp_path )
def ConvertAbsPathToPortablePath( abs_path ):
try: return os.path.relpath( abs_path, HC.BASE_DIR )
except: return abs_path
def ConvertPortablePathToAbsPath( portable_path ):
if os.path.isabs( portable_path ): abs_path = portable_path
else: abs_path = os.path.normpath( os.path.join( HC.BASE_DIR, portable_path ) )
return abs_path
def CopyAndMergeTree( source, dest ):
pauser = HydrusData.BigJobPauser()
if not os.path.exists( dest ):
os.makedirs( dest )
for ( root, dirnames, filenames ) in os.walk( source ):
dest_root = root.replace( source, dest )
for dirname in dirnames:
pauser.Pause()
source_path = os.path.join( root, dirname )
dest_path = os.path.join( dest_root, dirname )
if not os.path.exists( dest_path ):
os.makedirs( dest_path )
shutil.copystat( source_path, dest_path )
for filename in filenames:
pauser.Pause()
source_path = os.path.join( root, filename )
dest_path = os.path.join( dest_root, filename )
shutil.copy2( source_path, dest_path )
def CopyFileLikeToFileLike( f_source, f_dest ):
for block in ReadFileLikeAsBlocks( f_source ): f_dest.write( block )
def DeletePath( path ):
if os.path.exists( path ):
if os.path.isdir( path ):
shutil.rmtree( path )
else:
os.remove( path )
def GetPathSize( path ):
return os.lstat( path )[6]
def GetTempFile(): return tempfile.TemporaryFile()
def GetTempFileQuick(): return tempfile.SpooledTemporaryFile( max_size = 1024 * 1024 * 4 )
def GetTempPath(): return tempfile.mkstemp( prefix = 'hydrus' )
def LaunchDirectory( path ):
def do_it():
if HC.PLATFORM_WINDOWS:
os.startfile( path )
else:
if HC.PLATFORM_OSX: cmd = [ 'open' ]
elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ]
cmd.append( path )
process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() )
process.wait()
process.communicate()
thread = threading.Thread( target = do_it )
thread.daemon = True
thread.start()
def LaunchFile( path ):
def do_it():
if HC.PLATFORM_WINDOWS:
os.startfile( path )
else:
if HC.PLATFORM_OSX: cmd = [ 'open' ]
elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ]
cmd.append( path )
process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() )
process.wait()
process.communicate()
thread = threading.Thread( target = do_it )
thread.daemon = True
thread.start()
def MirrorTree( source, dest ):
pauser = HydrusData.BigJobPauser()
if not os.path.exists( dest ):
os.makedirs( dest )
for ( root, dirnames, filenames ) in os.walk( source ):
dest_root = root.replace( source, dest )
surplus_dest_paths = { os.path.join( dest_root, dest_filename ) for dest_filename in os.listdir( dest_root ) }
for dirname in dirnames:
pauser.Pause()
source_path = os.path.join( root, dirname )
dest_path = os.path.join( dest_root, dirname )
surplus_dest_paths.discard( dest_path )
if not os.path.exists( dest_path ):
os.makedirs( dest_path )
shutil.copystat( source_path, dest_path )
for filename in filenames:
pauser.Pause()
source_path = os.path.join( root, filename )
dest_path = os.path.join( dest_root, filename )
surplus_dest_paths.discard( dest_path )
if not PathsHaveSameSizeAndDate( source_path, dest_path ):
shutil.copy2( source_path, dest_path )
for dest_path in surplus_dest_paths:
pauser.Pause()
DeletePath( dest_path )
def PathsHaveSameSizeAndDate( path1, path2 ):
if os.path.exists( path1 ) and os.path.exists( path2 ):
path1_stat = os.lstat( path1 )
path2_stat = os.lstat( path2 )
same_size = path1_stat[6] == path2_stat[6]
same_modified_time = path1_stat[8] == path2_stat[8]
if same_size and same_modified_time:
return True
return False
def ReadFileLikeAsBlocks( f ):
next_block = f.read( HC.READ_BLOCK_SIZE )
while next_block != '':
yield next_block
next_block = f.read( HC.READ_BLOCK_SIZE )
def RecyclePath( path ):
original_path = path
if HC.PLATFORM_LINUX:
# send2trash for Linux tries to do some Python3 str() stuff in prepping non-str paths for recycling
if not isinstance( path, str ):
try:
path = path.encode( sys.getfilesystemencoding() )
except:
HydrusData.Print( 'Trying to prepare a file for recycling created this error:' )
traceback.print_exc()
return
if os.path.exists( path ):
try:
send2trash.send2trash( path )
except:
HydrusData.Print( 'Trying to recycle a file created this error:' )
traceback.print_exc()
HydrusData.Print( 'It has been fully deleted instead.' )
DeletePath( original_path )