diff options
Diffstat (limited to 'tools/cleantree.py')
| -rw-r--r-- | tools/cleantree.py | 152 | 
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)
 | 
