summaryrefslogtreecommitdiffstats
path: root/Mac/scripts/MkDistr.py
diff options
context:
space:
mode:
authorJack Jansen <jack.jansen@cwi.nl>1995-08-31 13:50:16 (GMT)
committerJack Jansen <jack.jansen@cwi.nl>1995-08-31 13:50:16 (GMT)
commitc9c99f253824deb85461861d1ccfa71fdf1badda (patch)
treececb06d9b12fc1a52d6fb8858cf29bcd719364b7 /Mac/scripts/MkDistr.py
parent7c86b21812babb70be95526d9be3e8e7514375ca (diff)
downloadcpython-c9c99f253824deb85461861d1ccfa71fdf1badda.zip
cpython-c9c99f253824deb85461861d1ccfa71fdf1badda.tar.gz
cpython-c9c99f253824deb85461861d1ccfa71fdf1badda.tar.bz2
Interactively create a distribution from a sourcetree.
Not yet fully tested.
Diffstat (limited to 'Mac/scripts/MkDistr.py')
-rw-r--r--Mac/scripts/MkDistr.py280
1 files changed, 280 insertions, 0 deletions
diff --git a/Mac/scripts/MkDistr.py b/Mac/scripts/MkDistr.py
new file mode 100644
index 0000000..deda71b
--- /dev/null
+++ b/Mac/scripts/MkDistr.py
@@ -0,0 +1,280 @@
+#
+# Interactively decide what to distribute
+#
+# The distribution type is signalled by a letter. The currently
+# defined letters are:
+# p PPC normal distribution
+# P PPC development distribution
+# m 68K normal distribution
+# M 68K development distribution
+#
+# The exclude file signals files to always exclude,
+# The pattern file records are of the form
+# ('pm', '*.c')
+# This excludes all files ending in .c for normal distributions.
+#
+# The include file signals files and directories to include.
+# Records are of the form
+# ('pPmM', 'Lib')
+# This includes the Lib dir in all distributions
+# ('pPmM', 'Tools:bgen:AE:AppleEvents.py', 'Lib:MacToolbox:AppleEvents.py')
+# This includes the specified file, putting it in the given place.
+#
+from MkDistr_ui import *
+import fnmatch
+import regex
+import os
+import sys
+import macfs
+import macostools
+
+SyntaxError='Include/exclude file syntax error'
+
+class Matcher:
+ """Include/exclude database, common code"""
+
+ def __init__(self, type, filename):
+ self.type = type
+ self.filename = filename
+ self.rawdata = []
+ self.parse(filename)
+ self.rawdata.sort()
+ self.rebuild()
+ self.modified = 0
+
+ def parse(self, dbfile):
+ try:
+ fp = open(dbfile)
+ except IOError:
+ return
+ data = fp.readlines()
+ fp.close()
+ for d in data:
+ d = d[:-1]
+ if not d or d[0] == '#': continue
+ pat = self.parseline(d)
+ self.rawdata.append(pat)
+
+ def parseline(self, line):
+ try:
+ data = eval(line)
+ except:
+ raise SyntaxError, line
+ if type(data) <> type(()) or len(data) not in (2,3):
+ raise SyntaxError, line
+ if len(data) == 2:
+ data = data + ('',)
+ return data
+
+ def save(self):
+ fp = open(self.filename, 'w')
+ for d in self.rawdata:
+ fp.write(`d`+'\n')
+ self.modified = 0
+
+ def add(self, value):
+ if len(value) == 2:
+ value = value + ('',)
+ self.rawdata.append(value)
+ self.rebuild1(value)
+ self.modified = 1
+
+ def delete(self, value):
+ key = value
+ for i in range(len(self.rawdata)):
+ if self.rawdata[i][1] == key:
+ del self.rawdata[i]
+ self.unrebuild1(i, key)
+ self.modified = 1
+ return
+ print 'Not found!', key
+
+ def getall(self):
+ return map(lambda x: x[1], self.rawdata)
+
+ def get(self, value):
+ for t, src, dst in self.rawdata:
+ if src == value:
+ return t, src, dst
+ print 'Not found!', value
+
+ def is_modified(self):
+ return self.modified
+
+class IncMatcher(Matcher):
+ """Include filename database and matching engine"""
+
+ def rebuild(self):
+ self.idict = {}
+ self.edict = {}
+ for v in self.rawdata:
+ self.rebuild1(v)
+
+ def rebuild1(self, (tp, src, dst)):
+ if self.type in tp:
+ if dst == '':
+ dst = src
+ self.idict[src] = dst
+ else:
+ self.edict[src] = ''
+
+ def unrebuild1(self, num, src):
+ if self.idict.has_key(src):
+ del self.idict[src]
+ else:
+ del self.edict[src]
+
+ def match(self, patharg):
+ removed = []
+ # First check the include directory
+ path = patharg
+ while 1:
+ if self.idict.has_key(path):
+ # We know of this path (or initial piece of path)
+ dstpath = self.idict[path]
+ # We do want it distributed. Tack on the tail.
+ while removed:
+ dstpath = os.path.join(dstpath, removed[0])
+ removed = removed[1:]
+ # Finally, if the resultant string ends in a separator
+ # tack on our input filename
+ if dstpath[-1] == os.sep:
+ dir, file = os.path.split(path)
+ dstpath = os.path.join(dstpath, path)
+ return dstpath
+ path, lastcomp = os.path.split(path)
+ if not path:
+ break
+ removed[0:0] = [lastcomp]
+ # Next check the exclude directory
+ path = patharg
+ while 1:
+ if self.edict.has_key(path):
+ return ''
+ path, lastcomp = os.path.split(path)
+ if not path:
+ break
+ removed[0:0] = [lastcomp]
+ return None
+
+ def checksourcetree(self):
+ rv = []
+ for name in self.idict.keys():
+ if not os.path.exists(name):
+ rv.append(name)
+ return rv
+
+class ExcMatcher(Matcher):
+ """Exclude pattern database and matching engine"""
+
+ def rebuild(self):
+ self.relist = []
+ for v in self.rawdata:
+ self.rebuild1(v)
+
+ def rebuild1(self, (tp, src, dst)):
+ if self.type in tp:
+ pat = fnmatch.translate(src)
+ self.relist.append(regex.compile(pat))
+ else:
+ self.relist.append(None)
+
+ def unrebuild1(self, num, src):
+ del self.relist[num]
+
+ def match(self, path):
+ comps = os.path.split(path)
+ file = comps[-1]
+ for pat in self.relist:
+ if pat and pat.match(file) == len(file):
+ return 1
+ return 0
+
+
+class Main:
+ """The main program glueing it all together"""
+
+ def __init__(self):
+ InitUI()
+ fss, ok = macfs.GetDirectory('Source directory:')
+ if not ok:
+ sys.exit(0)
+ os.chdir(fss.as_pathname())
+ self.typedist = GetType()
+ print 'TYPE', self.typedist
+ self.inc = IncMatcher(self.typedist, '(MkDistr.include)')
+ self.exc = ExcMatcher(self.typedist, '(MkDistr.exclude)')
+ self.ui = MkDistrUI(self)
+ self.ui.mainloop()
+
+ def check(self):
+ return self.checkdir(':', 1)
+
+ def checkdir(self, path, istop):
+ files = os.listdir(path)
+ rv = []
+ todo = []
+ for f in files:
+ if self.exc.match(f):
+ continue
+ fullname = os.path.join(path, f)
+ if self.inc.match(fullname) == None:
+ if os.path.isdir(fullname):
+ todo.append(fullname)
+ else:
+ rv.append(fullname)
+ for d in todo:
+ if len(rv) > 100:
+ if istop:
+ rv.append('... and more ...')
+ return rv
+ rv = rv + self.checkdir(d, 0)
+ return rv
+
+ def run(self, destprefix):
+ missing = self.inc.checksourcetree()
+ if missing:
+ print '==== Missing source files ===='
+ for i in missing:
+ print i
+ print '==== Fix and retry ===='
+ return
+ if not self.rundir(':', destprefix, 0):
+ return
+ self.rundir(':', destprefix, 1)
+
+ def rundir(self, path, destprefix, doit):
+ files = os.listdir(path)
+ todo = []
+ rv = 1
+ for f in files:
+ if self.exc.match(f):
+ continue
+ fullname = os.path.join(path, f)
+ if os.path.isdir(fullname):
+ todo.append(fullname)
+ else:
+ dest = self.inc.match(fullname)
+ if dest == None:
+ print 'Not yet resolved:', fullname
+ rv = 0
+ if dest:
+ if doit:
+ print 'COPY ', fullname
+ print ' -> ', os.path.join(destprefix, dest)
+ macostools.copy(fullname, os.path.join(destprefix, dest), 1)
+ for d in todo:
+ if not self.rundir(d, destprefix, doit):
+ rv = 0
+ return rv
+
+ def save(self):
+ self.inc.save()
+ self.exc.save()
+
+ def is_modified(self):
+ return self.inc.is_modified() or self.exc.is_modified()
+
+if __name__ == '__main__':
+ Main()
+