aboutsummaryrefslogtreecommitdiff
path: root/tools/cleantree.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/cleantree.py')
-rw-r--r--tools/cleantree.py152
1 files changed, 152 insertions, 0 deletions
diff --git a/tools/cleantree.py b/tools/cleantree.py
new file mode 100644
index 000000000..e873723df
--- /dev/null
+++ b/tools/cleantree.py
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+__doc__="""%prog [options] [<directory>]
+
+Removes all unversioned files from a subversion working copy directory
+<directory>.
+When <directory> is not specified the current directory is used.
+<directory can also be a white space seperated list of directories.
+"""
+import os,sys,re,subprocess
+from optparse import OptionParser
+
+parser = OptionParser(__doc__)
+parser.add_option("-r", "--recursive", action='store_true', dest="Recursive", default=False, help="Also clean subdirectories.")
+parser.add_option("-s", "--skiputil", action='store_true', dest="SkipUtil", default=False, help="Skip util and tools directory.")
+parser.add_option("-v", "--noverbose", action='store_true', dest="NoVerbose", default=False, help="No output.")
+
+(g_Options, g_Args) = parser.parse_args()
+
+if g_Args:
+ for i in range(len(g_Args)):
+ g_Args[i]=os.path.abspath(g_Args[i])
+ if not os.path.isdir(g_Args[i]):
+ parser.error("%s is not a valid directory"%g_Args[i])
+
+NotWorkRe=re.compile("'\.' is not a working copy")
+
+################################################################################
+
+def Print (Message,NoVerbose=None,Append='\n'):
+ if NoVerbose!=1:
+ Message+=Append
+ sys.stdout.write(Message)
+
+################################################################################
+class RunCommandException(Exception):
+ def __init__(this,CommandLine,Output=None):
+ this.CommandLine=CommandLine
+ this.Output=Output
+ def __str__(this):
+ Ret="\n!!! RunCommand exception:\n-> Commandline:\n"
+ Ret+=this.CommandLine
+ if this.Output:
+ Ret+="\n-> Output:\n"
+ Ret+=this.Output
+ else:
+ Ret+="\n-> Command not found"
+ Ret+="\n"
+ return Ret
+################################################################################
+PIPE=subprocess.PIPE
+STDOUT=subprocess.STDOUT
+
+def RunCommand(Command):
+ try:
+ if sys.platform=='linux2':
+ Process=subprocess.Popen(Command, stdin=PIPE, stdout=PIPE, stderr=STDOUT, shell=True)
+ else:
+ CREATE_NO_WINDOW=0x8000000
+ Process=subprocess.Popen(Command, stdin=PIPE, stdout=PIPE, stderr=STDOUT, creationflags=CREATE_NO_WINDOW, shell=True)
+ import msvcrt
+ msvcrt.setmode(Process.stdout.fileno(), os.O_TEXT) # Threat output as ascii noy binary
+ except:
+ raise RunCommandException(Command)
+ return Process
+
+################################################################################
+def DelTreeNoJunctions(Dir):
+ try:
+ os.rmdir(Dir)
+ # empty dir or it was a junction, so we can return immediately
+ return
+ except:
+ pass
+
+ for root, dirs, files in os.walk(Dir, topdown=True):
+ for name in files:
+ os.remove(os.path.join(root,name))
+ for dir in dirs:
+ # first try just to remove the directory. This is to be sure that when it is a symbolic link
+ # just the link is removed and not the complete contents where it points to
+ try:
+ os.rmdir(os.path.join(root,dir))
+ del dirs[dir] # do not walk this directory
+ except:
+ pass # go further in the directory tree
+ # Now delete the empty directories left over from the previous walk
+ for root, dirs, files in os.walk(Dir, topdown=False):
+ for dir in dirs:
+ os.rmdir(os.path.join(root,dir))
+ os.rmdir(Dir)
+
+################################################################################
+def ProcessSvnLine(line,NoVerbose=None):
+ if line:
+ if NotWorkRe.search(line):
+ Print(NotWorkRe.sub("'%s' is not a working copy directory. Not cleaning this directory."%(re.sub(r"\\",r"\\\\",Dir)),line))
+ sys.exit(1)
+ if line[0]=='?' or line[0]=='I':
+ Item=re.sub("^\s+","",line[2:])
+ if g_Options.SkipUtil:
+ if Item[:5]=='util'+os.sep:
+ return
+ if Item[:6]=='tools'+os.sep:
+ return
+ if os.path.isdir(Item):
+ Print('Deleting directory %s'%(os.path.abspath(Item)),NoVerbose)
+ try:
+ DelTreeNoJunctions(Item)
+ except:
+ print "Error deleting directory %s. Contains read-only files?"%Item
+ else:
+ Print('Deleting file %s'%(os.path.abspath(Item)),NoVerbose)
+ try:
+ os.remove(Item)
+ except Exception,Details:
+ print "Error deleting file %s. Is read-only? "%Item
+ print Details
+################################################################################
+def CleanTree(Dir, NoVerbose=None):
+ Print("Cleaning '"+Dir+"'")
+ if g_Options.Recursive:
+ Command='svn st --no-ignore'
+ else:
+ Command='svn st -N --no-ignore'
+ Process=RunCommand(Command)
+ StdOut=Process.stdout
+ all_data=""
+ while 1:
+ done = Process.poll()
+ if done == None or done == 0:
+ line=StdOut.readline()
+ all_data+=line
+ line=line.rstrip()
+ ProcessSvnLine(line,NoVerbose)
+ if done == 0:
+ data=StdOut.read()
+ all_data+=data
+ for line in data.splitlines():
+ ProcessSvnLine(line,NoVerbose)
+ break
+ elif done != None:
+ #error!
+ print "error running svn command:", Command
+ print all_data, StdOut.read()
+ sys.exit(1)
+################################################################################
+if not g_Args:
+ g_Args=["."]
+
+for Dir in g_Args:
+ os.chdir(Dir)
+ CleanTree(Dir, g_Options.NoVerbose)