2 # Interactively decide what to distribute
5 # The exclude file signals files to always exclude,
6 # The pattern file lines are of the form
8 # This excludes all files ending in .c.
10 # The include file signals files and directories to include.
11 # Records are of the form
12 # ('Tools:bgen:AE:AppleEvents.py', 'Lib:MacToolbox:AppleEvents.py')
13 # This includes the specified file, putting it in the given place, or
14 # ('Tools:bgen:AE:AppleEvents.py', None)
15 # This excludes the specified file.
17 from MkDistr_ui
import *
27 SyntaxError='Include/exclude file syntax error'
30 """Include/exclude database, common code"""
32 def __init__(self
, filename
):
33 self
.filename
= filename
40 def parse(self
, dbfile
):
49 if not d
or d
[0] == '#': continue
50 pat
= self
.parseline(d
)
51 self
.rawdata
.append(pat
)
54 fp
= open(self
.filename
, 'w')
55 self
.savedata(fp
, self
.rawdata
)
61 self
.rawdata
.append(value
)
65 def delete(self
, value
):
67 for i
in range(len(self
.rawdata
)):
68 if self
.rawdata
[i
][0] == key
:
70 self
.unrebuild1(i
, key
)
73 print 'Not found!', key
76 return map(lambda x
: x
[0], self
.rawdata
)
79 for src
, dst
in self
.rawdata
:
82 print 'Not found!', value
84 def is_modified(self
):
87 class IncMatcher(Matcher
):
88 """Include filename database and matching engine"""
93 for v
in self
.rawdata
:
96 def parseline(self
, line
):
100 raise SyntaxError, line
101 if type(data
) <> type(()) or len(data
) not in (1,2):
102 raise SyntaxError, line
107 def savedata(self
, fp
, data
):
108 for d
in self
.rawdata
:
111 def rebuild1(self
, (src
, dst
)):
115 self
.edict
[src
] = None
117 self
.idict
[src
] = dst
119 def unrebuild1(self
, num
, src
):
120 if self
.idict
.has_key(src
):
125 def match(self
, patharg
):
127 # First check the include directory
130 if self
.idict
.has_key(path
):
131 # We know of this path (or initial piece of path)
132 dstpath
= self
.idict
[path
]
133 # We do want it distributed. Tack on the tail.
135 dstpath
= os
.path
.join(dstpath
, removed
[0])
136 removed
= removed
[1:]
137 # Finally, if the resultant string ends in a separator
138 # tack on our input filename
139 if dstpath
[-1] == os
.sep
:
140 dir, file = os
.path
.split(path
)
141 dstpath
= os
.path
.join(dstpath
, file)
143 print 'include', patharg
, dstpath
145 ## path, lastcomp = os.path.split(path)
148 ## removed[0:0] = [lastcomp]
149 ## # Next check the exclude directory
152 if self
.edict
.has_key(path
):
154 print 'exclude', patharg
, path
156 path
, lastcomp
= os
.path
.split(path
)
159 removed
[0:0] = [lastcomp
]
161 print 'nomatch', patharg
164 def checksourcetree(self
):
166 for name
in self
.idict
.keys():
167 if not os
.path
.exists(name
):
171 class ExcMatcher(Matcher
):
172 """Exclude pattern database and matching engine"""
176 for v
in self
.rawdata
:
179 def parseline(self
, data
):
182 def savedata(self
, fp
, data
):
183 for d
in self
.rawdata
:
186 def rebuild1(self
, (src
, dst
)):
187 pat
= fnmatch
.translate(src
)
189 print 'PATTERN', `src`
, 'REGEX', `pat`
190 self
.relist
.append(re
.compile(pat
))
192 def unrebuild1(self
, num
, src
):
195 def match(self
, path
):
196 comps
= os
.path
.split(path
)
198 for pat
in self
.relist
:
199 if pat
and pat
.match(file):
201 print 'excmatch', file, pat
207 """The main program glueing it all together"""
212 if not os
.path
.isdir(':Mac:Distributions'):
213 os
.mkdir(':Mac:Distributions')
214 self
.typedist
= GetType()
215 self
.inc
= IncMatcher(':Mac:Distributions:%s.include'%self
.typedist
)
216 self
.exc
= ExcMatcher(':Mac:Distributions:%s.exclude'%self
.typedist
)
217 self
.ui
= MkDistrUI(self
)
221 return self
.checkdir(':', 1)
223 def checkdir(self
, path
, istop
):
225 print 'checkdir', path
226 files
= os
.listdir(path
)
232 if self
.exc
.match(f
):
234 print 'exclude match', f
236 fullname
= os
.path
.join(path
, f
)
238 print 'checkpath', fullname
239 matchvalue
= self
.inc
.match(fullname
)
240 if matchvalue
== None:
241 if os
.path
.isdir(fullname
):
243 print 'do dir', fullname
244 todo
.append(fullname
)
247 print 'include', fullname
250 print 'badmatch', matchvalue
254 rv
.append('... and more ...')
256 rv
= rv
+ self
.checkdir(d
, 0)
260 missing
= self
.inc
.checksourcetree()
262 print '==== Missing source files ===='
265 print '==== Fix and retry ===='
267 destprefix
= os
.path
.join(sys
.prefix
, ':Mac:Distributions:(vise)')
268 destprefix
= os
.path
.join(destprefix
, '%s Distribution'%self
.typedist
)
269 if not self
.rundir(':', destprefix
, 0):
271 self
.rundir(':', destprefix
, 1)
273 def rundir(self
, path
, destprefix
, doit
):
274 files
= os
.listdir(path
)
278 if self
.exc
.match(f
):
280 fullname
= os
.path
.join(path
, f
)
281 if os
.path
.isdir(fullname
):
282 todo
.append(fullname
)
284 dest
= self
.inc
.match(fullname
)
286 print 'Not yet resolved:', fullname
290 print 'COPY ', fullname
291 print ' -> ', os
.path
.join(destprefix
, dest
)
293 macostools
.copy(fullname
, os
.path
.join(destprefix
, dest
), 1)
295 print '*** Copy failed mysteriously, try again'
296 print '*** cwd', os
.getcwd() #DBG
297 print '*** fsspec', macfs
.FSSpec(fullname
) #DBG
298 # Get rid of open files
303 macostools
.copy(fullname
, os
.path
.join(destprefix
, dest
), 1)
305 if not self
.rundir(d
, destprefix
, doit
):
313 def is_modified(self
):
314 return self
.inc
.is_modified() or self
.exc
.is_modified()
316 if __name__
== '__main__':