| e8555c89 Andy McCall |
1 |
|
| 2 |
|
| 3 |
from optparse import OptionParser |
| 4 |
from os import walk |
| 5 |
from os.path import ( |
| 6 |
basename, dirname, isfile, join as joinpath, relpath, split as splitpath |
| 7 |
) |
| 8 |
from uuid import uuid4 |
| 9 |
|
| 10 |
indentSize = 2 |
| 11 |
|
| 12 |
excludedDirectories = ['.svn', 'CVS'] |
| 13 |
excludedFiles = ['node.mk'] |
| 14 |
|
| 15 |
|
| 16 |
def isParentDir(child, parent): |
| 17 |
return '..' not in relpath(child, parent) |
| 18 |
|
| 19 |
def makeFileId(guid): |
| 20 |
return 'file_' + guid |
| 21 |
|
| 22 |
def makeDirectoryId(guid): |
| 23 |
return 'directory_' + guid |
| 24 |
|
| 25 |
def makeComponentId(guid): |
| 26 |
return 'component_' + guid |
| 27 |
|
| 28 |
def newGuid(): |
| 29 |
return str(uuid4()).replace('-', '') |
| 30 |
|
| 31 |
def walkPath(sourcePath): |
| 32 |
if isfile(sourcePath): |
| 33 |
yield dirname(sourcePath), [], [ basename(sourcePath) ] |
| 34 |
else: |
| 35 |
for dirpath, dirnames, filenames in walk(sourcePath): |
| 36 |
yield dirpath, dirnames, filenames |
| 37 |
|
| 38 |
class WixFragment(object): |
| 39 |
|
| 40 |
def __init__(self, fileGenerator, componentGroup, directoryRef, virtualDir, |
| 41 |
excludedFile, win64): |
| 42 |
self.fileGenerator = fileGenerator |
| 43 |
self.componentGroup = componentGroup |
| 44 |
self.directoryRef = directoryRef |
| 45 |
self.virtualDir = virtualDir |
| 46 |
self.indentLevel = 0 |
| 47 |
self.win64 = 'yes' if win64 else 'no' |
| 48 |
|
| 49 |
if excludedFile: |
| 50 |
|
| 51 |
excludedFiles.append(excludedFile) |
| 52 |
|
| 53 |
def incrementIndent(self): |
| 54 |
self.indentLevel += indentSize |
| 55 |
|
| 56 |
def decrementIndent(self): |
| 57 |
self.indentLevel -= indentSize |
| 58 |
|
| 59 |
def indent(self, line): |
| 60 |
return ' ' * self.indentLevel + line |
| 61 |
|
| 62 |
def startElement(self, elementName, **args): |
| 63 |
line = self.indent( |
| 64 |
'<%s %s>' % ( |
| 65 |
elementName, |
| 66 |
' '.join('%s="%s"' % item for item in args.items()) |
| 67 |
) |
| 68 |
) |
| 69 |
self.incrementIndent() |
| 70 |
return line |
| 71 |
|
| 72 |
def endElement(self, elementName): |
| 73 |
self.decrementIndent() |
| 74 |
return self.indent('</%s>' % elementName) |
| 75 |
|
| 76 |
def yieldFragment(self): |
| 77 |
|
| 78 |
components = [] |
| 79 |
|
| 80 |
|
| 81 |
stack = [] |
| 82 |
|
| 83 |
|
| 84 |
virtualstack = [] |
| 85 |
|
| 86 |
yield self.indent( |
| 87 |
'<?xml version="1.0" encoding="utf-8"?>' |
| 88 |
) |
| 89 |
yield self.startElement( |
| 90 |
'Wix', xmlns = 'http://schemas.microsoft.com/wix/2006/wi' |
| 91 |
) |
| 92 |
yield self.startElement('Fragment') |
| 93 |
yield self.startElement('DirectoryRef', Id = self.directoryRef) |
| 94 |
|
| 95 |
|
| 96 |
if self.virtualDir: |
| 97 |
head = self.virtualDir |
| 98 |
while head: |
| 99 |
joinedPath = head |
| 100 |
head, tail_ = splitpath(head) |
| 101 |
virtualstack.insert(0, joinedPath) |
| 102 |
for path in virtualstack: |
| 103 |
componentId = 'directory_' + str(uuid4()).replace('-', '_') |
| 104 |
yield self.startElement( |
| 105 |
'Directory', Id = componentId, Name = basename(path) |
| 106 |
) |
| 107 |
|
| 108 |
|
| 109 |
firstDir = True |
| 110 |
for dirpath, dirnames, filenames in self.fileGenerator: |
| 111 |
|
| 112 |
|
| 113 |
for exclusion in excludedDirectories: |
| 114 |
if exclusion in dirnames: |
| 115 |
dirnames.remove(exclusion) |
| 116 |
|
| 117 |
if firstDir: |
| 118 |
firstDir = False |
| 119 |
else: |
| 120 |
|
| 121 |
while stack: |
| 122 |
popped = stack.pop() |
| 123 |
if isParentDir(dirpath, popped): |
| 124 |
stack.append(popped) |
| 125 |
break |
| 126 |
else: |
| 127 |
yield self.endElement('Directory') |
| 128 |
|
| 129 |
|
| 130 |
stack.append(dirpath) |
| 131 |
yield self.startElement( |
| 132 |
'Directory', Id = makeDirectoryId(newGuid()), |
| 133 |
Name = basename(dirpath) |
| 134 |
) |
| 135 |
|
| 136 |
|
| 137 |
for exclusion in excludedFiles: |
| 138 |
if exclusion in filenames: |
| 139 |
filenames.remove(exclusion) |
| 140 |
|
| 141 |
|
| 142 |
for filename in filenames: |
| 143 |
guid = newGuid() |
| 144 |
componentId = makeComponentId(guid) |
| 145 |
sourcePath = joinpath(dirpath, filename) |
| 146 |
|
| 147 |
yield self.startElement( |
| 148 |
'Component', Id = componentId, Guid = guid, |
| 149 |
DiskId = '1', Win64 = self.win64 |
| 150 |
) |
| 151 |
yield self.startElement( |
| 152 |
'File', Id = makeFileId(guid), Name = filename, |
| 153 |
Source = sourcePath |
| 154 |
) |
| 155 |
yield self.endElement('File') |
| 156 |
|
| 157 |
yield self.endElement('Component') |
| 158 |
components.append(componentId) |
| 159 |
|
| 160 |
|
| 161 |
while stack: |
| 162 |
popped = stack.pop() |
| 163 |
yield self.endElement('Directory') |
| 164 |
|
| 165 |
|
| 166 |
while virtualstack: |
| 167 |
popped = virtualstack.pop() |
| 168 |
yield self.endElement('Directory') |
| 169 |
|
| 170 |
yield self.endElement('DirectoryRef') |
| 171 |
yield self.endElement('Fragment') |
| 172 |
|
| 173 |
|
| 174 |
yield self.startElement('Fragment') |
| 175 |
yield self.startElement('ComponentGroup', Id = self.componentGroup) |
| 176 |
for component in components: |
| 177 |
yield self.startElement('ComponentRef', Id = component) |
| 178 |
yield self.endElement('ComponentRef') |
| 179 |
yield self.endElement('ComponentGroup') |
| 180 |
yield self.endElement('Fragment') |
| 181 |
|
| 182 |
yield self.endElement('Wix') |
| 183 |
|
| 184 |
def generateWixFragment( |
| 185 |
sourcePath, componentGroup, directoryRef, virtualDir, excludedFile, win64 |
| 186 |
): |
| 187 |
fileGenerator = walkPath(sourcePath) |
| 188 |
wf = WixFragment( |
| 189 |
fileGenerator, componentGroup, directoryRef, virtualDir, excludedFile, |
| 190 |
win64 |
| 191 |
) |
| 192 |
return wf.yieldFragment() |
| 193 |
|
| 194 |
def run(): |
| 195 |
parser = OptionParser() |
| 196 |
parser.add_option( |
| 197 |
'-c', '--componentGroup', type = 'string', dest = 'componentGroup' |
| 198 |
) |
| 199 |
parser.add_option( |
| 200 |
'-r', '--directoryRef', type = 'string', dest = 'directoryRef' |
| 201 |
) |
| 202 |
parser.add_option( |
| 203 |
'-s', '--sourcePath', type = 'string', dest = 'sourcePath' |
| 204 |
) |
| 205 |
parser.add_option( |
| 206 |
'-v', '--virtualDir', type = 'string', dest = 'virtualDir' |
| 207 |
) |
| 208 |
parser.add_option( |
| 209 |
'-x', '--excludedFile', type = 'string', dest = 'excludedFile' |
| 210 |
) |
| 211 |
parser.add_option( |
| 212 |
'-w', '--win64', type = 'string', dest = 'win64' |
| 213 |
) |
| 214 |
options, args_ = parser.parse_args() |
| 215 |
|
| 216 |
for line in generateWixFragment( |
| 217 |
options.sourcePath, options.componentGroup, options.directoryRef, |
| 218 |
options.virtualDir, options.excludedFile, options.win64 |
| 219 |
): |
| 220 |
print(line) |
| 221 |
|
| 222 |
if __name__ == '__main__': |
| 223 |
run() |