aboutsummaryrefslogtreecommitdiff
path: root/tools/cleantree.py
blob: e873723dfb9fa47b26a2fe97fcefcfda8da08aa4 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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)