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(regex
.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) == len(file):
201 print 'excmatch', file, pat
207 """The main program glueing it all together"""
211 fss
, ok
= macfs
.GetDirectory('Source directory:')
214 os
.chdir(fss
.as_pathname())
215 if not os
.path
.isdir(':Mac:Distributions'):
216 os
.mkdir(':Mac:Distributions')
218 self
.inc
= IncMatcher(':Mac:Distributions:%s.include'%typedist
)
219 self
.exc
= ExcMatcher(':Mac:Distributions:%s.exclude'%typedist
)
220 self
.ui
= MkDistrUI(self
)
224 return self
.checkdir(':', 1)
226 def checkdir(self
, path
, istop
):
228 print 'checkdir', path
229 files
= os
.listdir(path
)
235 if self
.exc
.match(f
):
237 print 'exclude match', f
239 fullname
= os
.path
.join(path
, f
)
241 print 'checkpath', fullname
242 matchvalue
= self
.inc
.match(fullname
)
243 if matchvalue
== None:
244 if os
.path
.isdir(fullname
):
246 print 'do dir', fullname
247 todo
.append(fullname
)
250 print 'include', fullname
253 print 'badmatch', matchvalue
257 rv
.append('... and more ...')
259 rv
= rv
+ self
.checkdir(d
, 0)
262 def run(self
, destprefix
):
263 missing
= self
.inc
.checksourcetree()
265 print '==== Missing source files ===='
268 print '==== Fix and retry ===='
270 if not self
.rundir(':', destprefix
, 0):
272 self
.rundir(':', destprefix
, 1)
274 def rundir(self
, path
, destprefix
, doit
):
275 files
= os
.listdir(path
)
279 if self
.exc
.match(f
):
281 fullname
= os
.path
.join(path
, f
)
282 if os
.path
.isdir(fullname
):
283 todo
.append(fullname
)
285 dest
= self
.inc
.match(fullname
)
287 print 'Not yet resolved:', fullname
291 print 'COPY ', fullname
292 print ' -> ', os
.path
.join(destprefix
, dest
)
294 macostools
.copy(fullname
, os
.path
.join(destprefix
, dest
), 1)
296 print 'cwd', os
.getcwd() #DBG
297 print 'fsspec', macfs
.FSSpec(fullname
) #DBG
300 if not self
.rundir(d
, destprefix
, doit
):
308 def is_modified(self
):
309 return self
.inc
.is_modified() or self
.exc
.is_modified()
311 if __name__
== '__main__':