diff options
Diffstat (limited to 'synchronise.py')
-rw-r--r-- | synchronise.py | 473 |
1 files changed, 238 insertions, 235 deletions
diff --git a/synchronise.py b/synchronise.py index 66d6ad581..8951f1e85 100644 --- a/synchronise.py +++ b/synchronise.py @@ -1,235 +1,238 @@ -import os,sys,shutil,re,stat
-
-from optparse import OptionParser
-
-usage = "usage: %prog [options] <SrcDir> <DestDir>"
-parser = OptionParser(usage=usage)
-parser.add_option("-n", "--donothing", action='store_true', dest="DoNothing", default=False, help="Do not copy the files.")
-parser.add_option("", "--extension", action='store', dest="Extension", default=None, help="Copy only files with this extension.")
-parser.add_option("-y", "--ask", action='store_true', dest="Ask", default=False, help="Ask confirmation to copy.")
-parser.add_option("-a", "--ask-file", action='append', dest="FilesToConfirm", default=[], help="Ask confirmation to copy for this speicific file (only useful if -y is not used).")
-parser.add_option("-d", "--delete-file_re", dest="FilesToDeleteRe", default="", help="Regular expression of files to delete.")
-parser.add_option("-s", "--no-skip-svn", dest="NoSkipSvn", action='store_true', default=False, help="Do not Skip .svn directories.")
-parser.add_option("-g", "--no-skip-git", dest="NoSkipGit", action='store_true', default=False, help="Do not Skip .git directories.")
-parser.add_option("-e", "--del-exist-only-dest", dest="DelExistOnlyDest", action='store_true', default=False, help="Delete files that exist only in the destination directory.")
-parser.add_option( "" , "--skip-dir", dest="SkipDirs", action='append', default=[], help="Adds a directory name to skip.")
-parser.add_option( "" , "--skip-file", dest="SkipFiles", action='append', default=[], help="Adds a file name to skip.")
-
-(g_Options, g_Args) = parser.parse_args()
-
-if g_Options.FilesToDeleteRe:
- try:
- g_FilesToDelete=re.compile(g_Options.FilesToDeleteRe,re.I)
- except:
- print 'Wrong regular expression:',g_Options.FilesToDeleteRe
- sys.exit(1)
-else:
- g_FilesToDelete=None
-
-if len(g_Args)!=2:
- parser.error("Wrong number of arguments: "+repr(g_Args))
- sys.exit(1)
-
-g_FilesToConfirm={}
-for File in g_Options.FilesToConfirm:
- g_FilesToConfirm[File]=1
-
-g_DirsToSkip={}
-for Dir in g_Options.SkipDirs:
- g_DirsToSkip[Dir]=1
-
-g_FilesToSkip={}
-for File in g_Options.SkipFiles:
- g_FilesToSkip[File]=1
-
-g_Ask=g_Options.Ask
-g_DoNothing=g_Options.DoNothing
-g_NoSkipSvn=g_Options.NoSkipSvn
-g_NoSkipGit=g_Options.NoSkipGit
-
-g_WriteMask=stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH
-
-g_SrcDir=os.path.realpath(g_Args[0])
-g_DestDir=os.path.realpath(g_Args[1])
-
-if g_Options.Extension:
- g_Extre=re.compile('.*\.%s$'%g_Options.Extension,re.I)
-else:
- g_Extre=None
-
-###############################################################################
-g_LenSrcDir=len(g_SrcDir)
-if g_SrcDir[-1]!=os.path.sep:
- g_LenSrcDir+=1
-
-def SkipDir(SrcDir,File):
- Ret = g_DirsToSkip.has_key(File)
- SrcDir=SrcDir[g_LenSrcDir:]
-
- while not Ret and SrcDir:
- SrcDir,Part=os.path.split(SrcDir)
- File=os.path.join(Part,File)
- Ret = g_DirsToSkip.has_key(File)
- return Ret
-
-###############################################################################
-def DeleteFiles(SrcFile,DestFile):
- print 'Deleting %s'%(SrcFile)
- os.remove(SrcFile)
- print 'Deleting %s'%(DestFile)
- try:
- os.remove(DestFile)
- except:
- print DestFile,'does not exist'
-
-###############################################################################
-#characters=['|','/','-','\\']
-#chariter=iter(characters)
-#def PrintBusy():
-# global characters
-# global chariter
-#
-# try:
-# char=chariter.next()
-# except StopIteration:
-# chariter=iter(characters)
-# char=chariter.next()
-#
-# sys.stdout.write(char)
-# sys.stdout.write(chr(8))
-count=0
-def PrintBusy():
- global count
- count+=1
- item=str(count)
- sys.stdout.write(item)
- sys.stdout.write(chr(8)*len(item))
-###############################################################################
-
-if not os.path.isdir(g_DestDir):
- print g_DestDir,"is not a directory"
- sys.exit(1)
-
-def FileDiff(SrcFile,DestFile):
- try:
- Src=open(SrcFile,'rb')
- Dest=open(DestFile,'rb')
- while 1:
- SrcLine=Src.read(4096)
- DestLine=Dest.read(4096)
- if SrcLine!=DestLine:
- return 1
- if not SrcLine:
- return 0
- except Exception,Object:
- #print "Exception occured"
- #print Object
- return 1
-
-g_Dot=0
-def SynchroniseDir(SrcDir,DestDir):
- global g_Dot
- SrcFiles=os.listdir(SrcDir)
- if g_Options.DelExistOnlyDest:
- DstFiles=os.listdir(DestDir)
- for File in DstFiles:
- DestFile=os.path.join(DestDir,File)
- try:
- Index=SrcFiles.index(File)
- except ValueError:
- if os.path.isdir(DestFile):
- if not g_NoSkipSvn and File=='.svn':
- continue # Skip svn administration dirs
- if not g_NoSkipGit and File=='.git':
- continue # Skip svn administration dirs
- if SkipDir(SrcDir,File):
- continue
- print 'Deleting directory',DestFile
- shutil.rmtree(DestFile)
- else:
- if g_FilesToSkip.has_key(File):
- continue
- print 'Deleting file',DestFile
- os.remove(DestFile)
-
- for File in SrcFiles:
- SrcFile=os.path.join(SrcDir,File)
- DestFile=os.path.join(DestDir,File)
- if os.path.isdir(SrcFile):
- if not g_NoSkipSvn and File=='.svn':
- continue # Skip svn administration dirs
- if not g_NoSkipGit and File=='.git':
- continue # Skip svn administration dirs
- if SkipDir(SrcDir,File):
- continue
- if not os.path.isdir(DestFile):
- if g_Dot:
- sys.stdout.write('\n')
- g_Dot=0
- if not g_DoNothing:
- if g_Ask:
- sys.stdout.write("Create directory %s? (y/n)"%DestFile)
- if sys.stdin.read(1)=='y':
- print "Creating dir",DestFile
- os.mkdir(DestFile)
- sys.stdin.read(1)
- else:
- print "Creating dir",DestFile
- os.mkdir(DestFile)
- else:
- print "Creating dir",DestFile
- SynchroniseDir(SrcFile,DestFile)
- else:
- if g_Extre and not g_Extre.search(File):
- continue
- if g_FilesToSkip.has_key(File):
- continue
- if g_FilesToDelete:
- if g_FilesToDelete.search(File):
- if g_Dot:
- sys.stdout.write('\n')
- g_Dot=0
- DeleteFiles(SrcFile,DestFile)
- continue
- if FileDiff(SrcFile,DestFile):
- #if os.system('fc /b "%s" "%s" >& nul'%(SrcFile,DestFile)):
- if g_Dot:
- sys.stdout.write('\n')
- g_Dot=0
- if not g_DoNothing:
- if g_Ask or g_FilesToConfirm.has_key(File):
- sys.stdout.write("Copy/Merge %s to %s? (y/n/m/d)"%(SrcFile,DestFile))
- R=sys.stdin.read(1)
- if R=='y':
- print '%s -> %s'%(SrcFile,DestFile)
- shutil.copyfile(SrcFile,DestFile)
- elif R=='m':
- print '%s -> %s'%(SrcFile,DestFile)
- os.system('fcg "%s" "%s"'%(SrcFile,DestFile))
- elif R=='d':
- DeleteFiles(SrcFile,DestFile)
- sys.stdin.read(1)
- else:
- print '%s -> %s'%(SrcFile,DestFile)
- # check if the file is read-only
- try:
- Mode=os.stat(DestFile).st_mode
- except OSError:
- Mode=g_WriteMask
- if not g_WriteMask&Mode:
- ReadOnly=True
- os.chmod(DestFile,Mode|g_WriteMask)
- else:
- ReadOnly=False
- shutil.copyfile(SrcFile,DestFile)
- if ReadOnly:
- os.chmod(DestFile,Mode & (~g_WriteMask) )
-
- else:
- print '%s -> %s'%(SrcFile,DestFile)
- else:
- PrintBusy()
- g_Dot=1
-
-SynchroniseDir(g_SrcDir,g_DestDir)
-sys.stdout.write("\n")
+#!/usr/bin/python +import os,sys,shutil,re,stat + +from optparse import OptionParser + +sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + +usage = "usage: %prog [options] <SrcDir> <DestDir>" +parser = OptionParser(usage=usage) +parser.add_option("-n", "--donothing", action='store_true', dest="DoNothing", default=False, help="Do not copy the files.") +parser.add_option("", "--extension", action='store', dest="Extension", default=None, help="Copy only files with this extension.") +parser.add_option("-y", "--ask", action='store_true', dest="Ask", default=False, help="Ask confirmation to copy.") +parser.add_option("-a", "--ask-file", action='append', dest="FilesToConfirm", default=[], help="Ask confirmation to copy for this speicific file (only useful if -y is not used).") +parser.add_option("-d", "--delete-file_re", dest="FilesToDeleteRe", default="", help="Regular expression of files to delete.") +parser.add_option("-s", "--no-skip-svn", dest="NoSkipSvn", action='store_true', default=False, help="Do not Skip .svn directories.") +parser.add_option("-g", "--no-skip-git", dest="NoSkipGit", action='store_true', default=False, help="Do not Skip .git directories.") +parser.add_option("-e", "--del-exist-only-dest", dest="DelExistOnlyDest", action='store_true', default=False, help="Delete files that exist only in the destination directory.") +parser.add_option( "" , "--skip-dir", dest="SkipDirs", action='append', default=[], help="Adds a directory name to skip.") +parser.add_option( "" , "--skip-file", dest="SkipFiles", action='append', default=[], help="Adds a file name to skip.") + +(g_Options, g_Args) = parser.parse_args() + +if g_Options.FilesToDeleteRe: + try: + g_FilesToDelete=re.compile(g_Options.FilesToDeleteRe,re.I) + except: + print 'Wrong regular expression:',g_Options.FilesToDeleteRe + sys.exit(1) +else: + g_FilesToDelete=None + +if len(g_Args)!=2: + parser.error("Wrong number of arguments: "+repr(g_Args)) + sys.exit(1) + +g_FilesToConfirm={} +for File in g_Options.FilesToConfirm: + g_FilesToConfirm[File]=1 + +g_DirsToSkip={} +for Dir in g_Options.SkipDirs: + g_DirsToSkip[Dir]=1 + +g_FilesToSkip={} +for File in g_Options.SkipFiles: + g_FilesToSkip[File]=1 + +g_Ask=g_Options.Ask +g_DoNothing=g_Options.DoNothing +g_NoSkipSvn=g_Options.NoSkipSvn +g_NoSkipGit=g_Options.NoSkipGit + +g_WriteMask=stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH + +g_SrcDir=os.path.realpath(g_Args[0]) +g_DestDir=os.path.realpath(g_Args[1]) + +if g_Options.Extension: + g_Extre=re.compile('.*\.%s$'%g_Options.Extension,re.I) +else: + g_Extre=None + +############################################################################### +g_LenSrcDir=len(g_SrcDir) +if g_SrcDir[-1]!=os.path.sep: + g_LenSrcDir+=1 + +def SkipDir(SrcDir,File): + Ret = g_DirsToSkip.has_key(File) + SrcDir=SrcDir[g_LenSrcDir:] + + while not Ret and SrcDir: + SrcDir,Part=os.path.split(SrcDir) + File=os.path.join(Part,File) + Ret = g_DirsToSkip.has_key(File) + return Ret + +############################################################################### +def DeleteFiles(SrcFile,DestFile): + print 'Deleting %s'%(SrcFile) + os.remove(SrcFile) + print 'Deleting %s'%(DestFile) + try: + os.remove(DestFile) + except: + print DestFile,'does not exist' + +############################################################################### +#characters=['|','/','-','\\'] +#chariter=iter(characters) +#def PrintBusy(): +# global characters +# global chariter +# +# try: +# char=chariter.next() +# except StopIteration: +# chariter=iter(characters) +# char=chariter.next() +# +# sys.stdout.write(char) +# sys.stdout.write(chr(8)) +count=0 +def PrintBusy(): + global count + count+=1 + item=str(count) + sys.stdout.write(item) + sys.stdout.write(chr(8)*len(item)) +############################################################################### + +if not os.path.isdir(g_DestDir): + print g_DestDir,"is not a directory" + sys.exit(1) + +def FileDiff(SrcFile,DestFile): + try: + Src=open(SrcFile,'rb') + Dest=open(DestFile,'rb') + while 1: + SrcLine=Src.read(4096) + DestLine=Dest.read(4096) + if SrcLine!=DestLine: + return 1 + if not SrcLine: + return 0 + except Exception,Object: + #print "Exception occured" + #print Object + return 1 + +g_Dot=0 +def SynchroniseDir(SrcDir,DestDir): + global g_Dot + SrcFiles=os.listdir(SrcDir) + if g_Options.DelExistOnlyDest: + DstFiles=os.listdir(DestDir) + for File in DstFiles: + DestFile=os.path.join(DestDir,File) + try: + Index=SrcFiles.index(File) + except ValueError: + if os.path.isdir(DestFile): + if not g_NoSkipSvn and File=='.svn': + continue # Skip svn administration dirs + if not g_NoSkipGit and File=='.git': + continue # Skip svn administration dirs + if SkipDir(SrcDir,File): + continue + print 'Deleting directory',DestFile + shutil.rmtree(DestFile) + else: + if g_FilesToSkip.has_key(File): + continue + print 'Deleting file',DestFile + os.remove(DestFile) + + for File in SrcFiles: + SrcFile=os.path.join(SrcDir,File) + DestFile=os.path.join(DestDir,File) + if os.path.isdir(SrcFile): + if not g_NoSkipSvn and File=='.svn': + continue # Skip svn administration dirs + if not g_NoSkipGit and File=='.git': + continue # Skip svn administration dirs + if SkipDir(SrcDir,File): + continue + if not os.path.isdir(DestFile): + if g_Dot: + sys.stdout.write('\n') + g_Dot=0 + if not g_DoNothing: + if g_Ask: + sys.stdout.write("Create directory %s? (y/n)"%DestFile) + if sys.stdin.read(1)=='y': + print "Creating dir",DestFile + os.mkdir(DestFile) + sys.stdin.read(1) + else: + print "Creating dir",DestFile + os.mkdir(DestFile) + else: + print "Creating dir",DestFile + SynchroniseDir(SrcFile,DestFile) + else: + if g_Extre and not g_Extre.search(File): + continue + if g_FilesToSkip.has_key(File): + continue + if g_FilesToDelete: + if g_FilesToDelete.search(File): + if g_Dot: + sys.stdout.write('\n') + g_Dot=0 + DeleteFiles(SrcFile,DestFile) + continue + if FileDiff(SrcFile,DestFile): + #if os.system('fc /b "%s" "%s" >& nul'%(SrcFile,DestFile)): + if g_Dot: + sys.stdout.write('\n') + g_Dot=0 + if not g_DoNothing: + if g_Ask or g_FilesToConfirm.has_key(File): + sys.stdout.write("Copy/Merge %s to %s? (y/n/m/d)"%(SrcFile,DestFile)) + R=sys.stdin.read(1) + if R=='y': + print '%s -> %s'%(SrcFile,DestFile) + shutil.copyfile(SrcFile,DestFile) + elif R=='m': + print '%s -> %s'%(SrcFile,DestFile) + os.system('fcg "%s" "%s"'%(SrcFile,DestFile)) + elif R=='d': + DeleteFiles(SrcFile,DestFile) + sys.stdin.read(1) + else: + print '%s -> %s'%(SrcFile,DestFile) + # check if the file is read-only + try: + Mode=os.stat(DestFile).st_mode + except OSError: + Mode=g_WriteMask + if not g_WriteMask&Mode: + ReadOnly=True + os.chmod(DestFile,Mode|g_WriteMask) + else: + ReadOnly=False + shutil.copyfile(SrcFile,DestFile) + if ReadOnly: + os.chmod(DestFile,Mode & (~g_WriteMask) ) + + else: + print '%s -> %s'%(SrcFile,DestFile) + else: + PrintBusy() + g_Dot=1 + +SynchroniseDir(g_SrcDir,g_DestDir) +sys.stdout.write("\n") |