Mini Shell
# -*- coding: utf-8 -*-
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
import glob
import os
import shutil
import stat
class CopyDirectory:
def __init__(self, source, destination, pattern="*", directorypattern="*", overwriteolder=0,
copyfile=shutil.copyfile, copy_file_mode=False, rewrite_plugin_conf=False):
"""
ATTENTION: values other than '*' for parameter 'directorypattern' are not supported
"""
self.sourcedirectory = source
self.destinationdirectory = destination
self.pattern = pattern
self.directorypattern = directorypattern
self.overwriteolder = overwriteolder
self.directorylist = []
self.filelist = []
self.copyfile = copyfile
self.copy_file_mode = copy_file_mode # specify if permissions for files (files only, not directories) should be copied
self.rewrite_plugin_conf = rewrite_plugin_conf
def process(self):
print("Gathering file list for {}".format(self.destinationdirectory))
self.walk()
print("Building directory tree and copying files")
self.go()
def walk(self):
'''
Gather the list of directories and files to copy
'''
for dir, subdirs, files in os.walk(self.sourcedirectory):
self._copydir(self, dir, subdirs + files)
def go(self):
'''
Perform the primary function of copying a directory
given an already constructed directory and file list
(generally created by walk)
'''
for directory in self.directorylist:
# following is built in to this class
self.copydirectory(directory)
print("Copy/update files...")
for source, destination in self.filelist:
# following is an argument to the constructor
try:
filepath = os.path.dirname(destination)
if not os.path.exists(filepath):
os.makedirs(filepath)
self.copyfile(source, destination)
if self.copy_file_mode:
shutil.copymode(source, destination)
except Exception as e:
print("Warning! Can not update fle: {}".format(destination))
print(e)
def _copydir(self, arg, directory, files):
'''
Perform copying for a particular directory
'''
# print directory
# collect files, use files if we have '*' pattern
workingfiles = self._files(directory, files)
# filter subdirectories, modifies files in-place
self._subdirectories(directory, files)
destinationdirectory = self._directorysetup(directory)
# should provide option for not overwriting files
# possibly with date checks etc.
# For extra marks, just collect this information
# and return a list of copies to be made,
# so the user can review before copying.
# Do the copying
# print workingfiles
for file in workingfiles:
source = os.path.join(directory, file)
destination = os.path.join(destinationdirectory, file)
if source.endswith('plugin.conf') and os.path.exists(destination) and \
not self.rewrite_plugin_conf:
continue
if self.overwriteolder and os.path.exists(destination):
if os.stat(source)[stat.ST_MTIME] > os.stat(destination)[stat.ST_MTIME]:
# we don't care if it's older, or it is older (hopefully)
self.filelist.append((source, destination))
else:
print("skip %s (source not newer)" % (source))
else:
self.filelist.append((source, destination))
def _subdirectories(self, directory, default):
'''
Filters the list of subdirectories which will be copied
'''
# following modifies which directories are copied
# does so by modifying file list in place (see os.path.walk)
# Note: this does not work because os.path.walk is removed in python 3
if self.directorypattern != "*":
# default[:] = glob.glob(os.path.join(directory, self.directorypattern))
raise Exception('Filtering of directories not supported')
def _files(self, directory, default):
'''
create the filtered list of files
'''
def dirfilter(values, directory=directory):
result = []
for value in values:
if not os.path.isdir(os.path.join(directory, value)):
result.append(value)
return result
# following is for local processing
if self.pattern != "*":
return dirfilter(glob.glob(os.path.join(directory, self.pattern)))
else:
return dirfilter(default)
def _directorysetup(self, directory):
'''
Ensure that the destination directory is available
build it if it is not
'''
# print "setup directory", directory
# should make this manipulation more robust
# currently assumes all sorts of things :(
prefix = os.path.commonprefix((self.sourcedirectory, directory))
extendeddirectory = directory[len(prefix):]
# get rid of preceding /, so won't be interpreted as root
if extendeddirectory and extendeddirectory[0] == os.sep:
extendeddirectory = extendeddirectory[1:]
destinationdirectory = os.path.join(self.destinationdirectory, extendeddirectory)
# print " destinationdirectory", destinationdirectory
self.directorylist.append(destinationdirectory)
return destinationdirectory
def copydirectory(self, directory):
'''
Called after tree building,
creates needed directories
'''
# create directory if not already there
# if not os.path.exists( directory ):
try:
os.mkdir(directory)
print("made directory", directory)
except os.error:
pass
Zerion Mini Shell 1.0