python script to zip & backup directories - can skip temp Visual Studio files



"""
 zip_and_backup_main_dirs.py
 Author: Sean Ryan
 Version: 1.0


 Script to ZIP up a set of directories,
 and then copy the ZIPs to backup locations(s).


 Dependencies:
 - 7zip

 Temp VS files can be skipped.
 ZIP files are uniquely named, using the given backupId.

Usage: zip_and_backup_main_dirs.py {backupId} [options]


The options are:
[-v skip Visual studio temp files]
[-w show Warnings only]


Example: zip_and_backup_main_dirs.py 20110223_1 -v -w
"""
###############################################################


import getopt
import sys
import re
import os
import shutil
import subprocess
from os.path import exists, join


#pathsep ; on windows  , on unix
from os import pathsep


from string import split


###############################################################
# Define some constants:


dirsToBackup = ['E:\\Shared\\scripts',\
'E:\\Shared\\cards',\
'E:\\Sean\\localSource',
'E:\\Sean\\SourceRoot\\root\\BWAC-Mainline-3-1-1-18-new',
'E:\\Sean\\MyDocu~1\\BWAC_Notes' #currently we cannot handle spaces :-(
]


backupDirs = ['W:\\backups',\
'G:\\Development\\Development\\SeanRyan\\backups']


PATH_TO_7ZIP = 'c:\\7-Zip'

###############################################################
# settings:
#LOG_WARNINGS_ONLY - this means, only output if the verbosity is LOG_WARNINGS
LOG_WARNINGS, LOG_WARNINGS_ONLY, LOG_NORMAL, LOG_VERBOSE = range(4)
logVerbosity = LOG_NORMAL


#extensions_excluded = set() - would need to rewrite zip_source_dir.bat


bFilterForVisualStudio = False
backupId = ""


###############################################################
#ask_ok() - prompts the user to continue
def ask_ok(prompt, retries=3, complaint='Yes or no, please!'):
    while True:
        ok = raw_input(prompt)
        ok = ok.lower()
        if ok in ('y', 'ye', 'yes'):
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise IOError('refusenik user')
        print complaint        


###############################################################
#usage() - prints out the usage text, from the top of this file :-)
def usage():
    print __doc__


###############################################################
#main() - main program entry point
def main(argv):
global backupId
global bFilterForVisualStudio
global logVerbosity
try:
opts, args = getopt.getopt(argv, "hvw", ["help", "visualStudio", "warnings"])
except getopt.GetoptError:
usage()
sys.exit(2)
if(len(args) != 1):
usage()
sys.exit(3)
backupId = args[0]
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-v", "--visualStudio"):
bFilterForVisualStudio = True
elif opt in ("-w", "--warnings"):
logVerbosity = LOG_WARNINGS


if __name__ == "__main__":
    main(sys.argv[1:])


###############################################################
#printOut()
#this function prints out, according to user's options for verbosity
def printOut(txt, verb = LOG_NORMAL, bNewLine = True):
global logVerbosity
txt = "> " + txt #prefix to make it easier to grep our output from 7zip's
if(bNewLine):
txt = txt + "\n"
if verb == LOG_WARNINGS_ONLY:
if logVerbosity == LOG_WARNINGS: #special case :-(
sys.stdout.write(txt)
elif(logVerbosity >= verb):
sys.stdout.write(txt)


################################################################
#run the given command line, and check the exit code
def run_exe(scriptToRun, _cwd, logVerbosity, stdOut = None):
#subprocess.check_call([scriptToRun], shell=True, stdout=stdOut)

if(logVerbosity < LOG_VERBOSE):
stdOut = open(os.devnull, 'w') #swallow 7z.exe output

subprocess.check_call([scriptToRun], cwd = _cwd, shell=True, stdout=stdOut)


################################################################
#main algorithm:




def getZipcmd(zipCreated, dirToBackup, bFilterForVisualStudio):
#scriptToRun = PATH_TO_7ZIP + "\\7z.exe a \"" + zipCreated + "\" \"" + dirToBackup + "\" -tzip -mx=3  -r  "
scriptToRun = PATH_TO_7ZIP + "\\7z.exe a " + zipCreated + " " + dirToBackup + " -tzip -mx=3  -r  "

if(bFilterForVisualStudio):
scriptToRun += "-x!*.pdb -x!*.pch -x!*.ncb -x!*.obj -x!*.bsc -x!*.ilk -x!*.il -x!*.tli -x!*.tlh -x!*.idb -x!*.sbr"
return (scriptToRun, PATH_TO_7ZIP)


def getZipFilePath(dirToBackup, backupId):
zipCreated = dirToBackup + "." + backupId + ".zip"
return zipCreated


#to save user time, first check are there any zips that are already present (->error)
for dirToBackup in dirsToBackup:
zipCreated = getZipFilePath(dirToBackup, backupId)
if(os.path.exists(zipCreated)):
raise Exception ("!!! Error - ZIP file already exists - " + zipCreated)


#now create ZIPs:
zipsCreated = list()
for dirToBackup in dirsToBackup:
zipCreated = getZipFilePath(dirToBackup, backupId)


printOut(" ---> zipping dir " + dirToBackup + " -> " + zipCreated + " ...")

if(os.path.exists(zipCreated)):
raise Exception ("!!! Error - ZIP file already exists - " + zipCreated)

(scriptToRun, cwd) = getZipcmd(zipCreated, dirToBackup, bFilterForVisualStudio)
run_exe(scriptToRun, cwd, logVerbosity)


zipsCreated.append(zipCreated)

#backup the ZIPs:
for zipFilePath in zipsCreated:
printOut(" ---> backing up zip file " + zipFilePath + " ...")
for backupDir in backupDirs:
shutil.copy2(zipFilePath, backupDir)


#summary:
printOut("")
printOut("Zips created:")
for zipFilePath in zipsCreated:
printOut(zipFilePath)


printOut("")
printOut("All zips were copied to these backup locations:")
for backupDir in backupDirs:
printOut(backupDir)


#done!

Comments