aboutsummaryrefslogtreecommitdiff
path: root/tools/cleantree.py
blob: b5971d480ce2bc4cc29b35adaa4350e5f5b307f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/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])

################################################################################

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 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
  NotWorkRe=re.compile("'\.' is not a working copy")
  while 1:
    line=StdOut.readline()
    if not line:
      break
    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:-1])
      if g_Options.SkipUtil:
        if Item[:5]=='util'+os.sep:
          continue
        if Item[:6]=='tools'+os.sep:
          continue
      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

################################################################################
if not g_Args:
  g_Args=["."]

for Dir in g_Args:
  os.chdir(Dir)
  CleanTree(Dir, g_Options.NoVerbose)