~swag/armagetronad/0.2.9-sty+ct+ap-fork

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#!/usr/bin/python
# sorts resources by their included name and version information
# usage: call from the directory containing the resources or
# call
# sortresources.py <path_to_seach_and_sort>
# use sortresources.py -h to get command line option help

from xml import sax
from xml.sax import handler
import string
import os.path
import os
import sys
import StringIO

# parse a resource xml file and fill in data property data strucure
def parseResource(filename, data):
    # document parser class
    class docHandler(handler.ContentHandler):
        def __init__(self,data):
            self.data = data

            # fill in defaults
            data.type = "unknown"
            data.name = ""
            data.version = "1.0"
            data.author = "Anonymous"
            data.category = ""

        def startElement(self,name,attr):
            # just parse the <map> tag and fill data
            if name in("Resource","Map"):
                # set type from tag name it is not already set
                try: oldtype = self.data.type
                except: self.data.type = name.lower()       

                # read values from file    
                if "name" in attr.getNames():
                    self.data.name     = attr.getValue("name")
                else:
                    return #invalid element
                if "author" in attr.getNames():
                    self.data.author   = attr.getValue("author")
                else:
                    return #invalid element

                if "type" in attr.getNames():
                    self.data.type     = attr.getValue("type")
                if "version" in attr.getNames():
                    self.data.version  = attr.getValue("version")
                if "category" in attr.getNames():
                    self.data.category = attr.getValue("category")
                    
    # rudimentary entity resolver
    class entityResolver:
          # initialize, storing a path and a data object
          def __init__(self,path,data):
              self.path = path
              self.data = data

          # return a stream for a given external entity
          def resolveEntity(self,pubid,sysid):
              path = self.path

              # extract data type: the base name of the DTD
              self.data.type = string.split(sysid,"-")[0]

              # look in current and parent directories for dtds
              while len(path) > 0:
                  fullfile = os.path.join(path, sysid)
                  try:    return open( fullfile )
                  except: pass
                  # go to "parent" directory
                  path = os.path.split(path)[0]

              # fallback: return empty stream, result: no dtd checking is done.
              # Not horribly bad in this context
              print "warning, could not find requested entity", sysid
              return StringIO.StringIO("")

    # parse: create parser...
    parser = sax.make_parser()
    # set it's content handler to extract the category data we want...
    parser.setContentHandler( docHandler(data) )
    # give it a dummy entity resolver that tries to find external entites in a
    # half-assed way...
    parser.setEntityResolver( entityResolver(os.path.split(filename)[0], data) )
    # and go!
    parser.parse( open(filename) )
    
    # exception rule for the moment: Translate type = map to type = aamap.
    try: 
         if data.type == "map":
            data.type = "aamap"
    except: pass

# take the parsed data and trandsform it into a filename
def getName(data):
    return os.path.join(data.author, data.category, data.name) + "-" + data.version + "." + data.type + ".xml"

# determine the canonical name of a xml resource
def getCanonicalPath(path):
    # trivial data class
    class Data:
        pass

    # parse xml file and return name
    data = Data()
    parseResource(path, data)
    return getName(data)

# scan for all XML files in the directory and rename them according to the rules
def scanDir(sourceDir, destinationDir, function):
    def visitor( arg, dirname, names ):
        for file in names:
            if len(file) > 4 and file[-4:] == ".xml":
                path = os.path.join(dirname,file)
                newPath = getCanonicalPath(path)
                # call the passed function
                function(path, os.path.join(destinationDir, newPath), newPath)
        
    os.path.walk(sourceDir, visitor, visitor )

# move file oldFile to newFile
def Move(oldFile, newFile, canonicalPath ):
    if oldFile == newFile:
        return False

    Print( oldFile, newFile, canonicalPath )

    # generate target directory
    dir = os.path.split(newFile)[0]
    if not os.path.exists(dir):
        os.makedirs(dir)

    # move file
    os.rename(oldFile, newFile)
    return True

# dummy replacement: just print
def Print(oldFile, newFile, canonicalPath ):
    if oldFile == newFile:
        return False

    if doPrint:
        print "renaming", oldFile, "->", newFile

# move file oldFile to newFile, setting apache rewrite rules to keep the file
# fetchable from its old position
def Redirect(oldFile, newFile, canonicalPath ):
    # move the file
    if Move( oldFile, newFile, canonicalPath ):
        # determine full path
        fullCanonicalPath = "/resource/" + canonicalPath

        # file was really moved, see what directory it came from
        oldPath = os.path.split( oldFile )

        # determine filename of the .htaccess file
        htaccessPath = os.path.join( oldPath[0], ".htaccess" )

        # determine whether we need to add the RewriteEngine On line:
        needEngine = True
        try:
            # open .htaccess file in the old directory for reading
            accessFile = open(htaccessPath)
            for line in accessFile:
                splitLineLower = string.split(line.lower())
                splitLine      = string.split(line)
                if splitLineLower[0] == "rewriteengine":
                    # rewriting is already mentioned; we don't have to enable it laster.
                    needEngine = False

                # see if there already is a rewrite rule for our file
                if splitLineLower[0] == "rewriterule" and splitLine[1] == oldPath[1]:
                    if splitLine[2] == fullCanonicalPath:
                        # nothing to do
                        return
                    else:
                        print "Warning: There already is a different RewriteRule for", oldFile, "in place."
        except: pass

        # open .htaccess file for appended writing
        accessFile = open(htaccessPath, "a")
        
        # enable rewriting
        if needEngine:
            accessFile.write("RewriteEngine On\n")

        # add rewrite rule
        accessFile.write( "RewriteRule " + oldPath[1] + " " + fullCanonicalPath + "\n");

# print usage message and exit.
def Options( ret ):
    print
    print "Usage: sortresources.py [OPTIONS] <source directory> <destination directory>"
    print "       Omitting the destination directory makes it equal to the source."
    print "       Omitting both directories makes them the current working directory."
    print "Options: -r add apache rewrite rules"
    print "         -n don't do anything, just print what would be done"
    print "         -v print non-warning status messages"
    print "         -h print this message"
    print
    sys.exit( ret )
    
if __name__ == "__main__":
    destinationDirectory = "."
    sourceDirectory = "."
    function  = Move

    global doPrint
    doPrint = False

    # parse arguments
    for arg in sys.argv[1:]:
        # parse options
        if arg[0] == "-":
            if len(arg) > 1:
                if arg[1] == "h":
                    Options( 0 )
                    continue
                if arg[1] == "n":
                    function = Print
                    doPrint = True
                    continue
                if arg[1] == "r":
                    function = Redirect
                    continue
                if arg[1] == "v":
                    doPrint = True
                    continue
                print "\nUnknown option:", arg
                Options(-1)
            else:
                Options(-1)
        else:
            # non-dashed argument gives the target and destination directory
            if "." == destinationDirectory:
                sourceDirectory = arg
            destinationDirectory = arg
    
    # print sourceDirectory, destinationDirectory

    # do the work
    scanDir(sourceDirectory, destinationDirectory, function)