*** msilib.py Mon Mar 17 23:41:39 2008 --- msilib_new.py Mon Mar 17 23:41:31 2008 *************** *** 329,367 **** for table in module.tables: add_data(db, table, getattr(module, table)) ! def make_id(str): #str = str.replace(".", "_") # colons are allowed str = str.replace(" ", "_") str = str.replace("-", "_") if str[0] in string.digits: str = "_"+str assert re.match("^[A-Za-z_][A-Za-z0-9_.]*$", str), "FILE"+str return str def gen_uuid(): return str(pythoncom.CreateGuid()) class CAB: ! def __init__(self, name): self.name = name self.file = open(name+".txt", "wt") self.filenames = sets.Set() ! self.index = 0 ! ! def gen_id(self, dir, file): ! logical = _logical = make_id(file) ! pos = 1 ! while logical in self.filenames: ! logical = "%s.%d" % (_logical, pos) ! pos += 1 ! self.filenames.add(logical) ! return logical def append(self, full, file, logical = None): if os.path.isdir(full): return ! if not logical: ! logical = self.gen_id(dir, file) self.index += 1 if full.find(" ")!=-1: print >>self.file, '"%s" %s' % (full, logical) --- 329,368 ---- for table in module.tables: add_data(db, table, getattr(module, table)) ! _global_int = 0 ! def make_id(str, add_num=True): #str = str.replace(".", "_") # colons are allowed str = str.replace(" ", "_") str = str.replace("-", "_") + str = str.replace("+", "_") + str = str.replace("!", "_") if str[0] in string.digits: str = "_"+str assert re.match("^[A-Za-z_][A-Za-z0-9_.]*$", str), "FILE"+str + if len(str) > 65: # MsiFileHash Table has limit of 72 characters. + str = str[-65:] + if add_num: + str = "%s.%d" % (str, _global_int) + _global_int += 1 return str def gen_uuid(): return str(pythoncom.CreateGuid()) class CAB: ! def __init__(self, name, db, start_index=1, diskid=1): self.name = name self.file = open(name+".txt", "wt") self.filenames = sets.Set() ! self.index = start_index-1 ! self.diskid = diskid ! self.db = db def append(self, full, file, logical = None): if os.path.isdir(full): return ! if logical is None: ! logical = make_id(file) self.index += 1 if full.find(" ")!=-1: print >>self.file, '"%s" %s' % (full, logical) *************** *** 369,375 **** print >>self.file, '%s %s' % (full, logical) return self.index, logical ! def commit(self, db): self.file.close() try: os.unlink(self.name+".cab") --- 370,376 ---- print >>self.file, '%s %s' % (full, logical) return self.index, logical ! def commit(self): self.file.close() try: os.unlink(self.name+".cab") *************** *** 394,399 **** --- 395,402 ---- print "WARNING: cabarc.exe not found in registry" cabarc = "cabarc.exe" cmd = r'"%s" -m lzx:21 n %s.cab @%s.txt' % (cabarc, self.name, self.name) + # If there are problems with compression use this. + # cmd = r'"%s" -m mszip n %s.cab @%s.txt' % (cabarc, self.name, self.name) p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for line in p.stdout: *************** *** 405,419 **** if not os.path.exists(self.name+".cab"): raise IOError, "cabarc failed" add_data(db, "Media", ! [(1, self.index, None, "#"+self.name, None, None)]) add_stream(db, self.name, self.name+".cab") os.unlink(self.name+".txt") os.unlink(self.name+".cab") ! db.Commit() - _directories = sets.Set() class Directory: ! def __init__(self, db, cab, basedir, physical, _logical, default, componentflags=None): """Create a new directory in the Directory table. There is a current component at each point in time for the directory, which is either explicitly created through start_component, or implicitly when files are added for the first --- 408,421 ---- if not os.path.exists(self.name+".cab"): raise IOError, "cabarc failed" add_data(db, "Media", ! [(self.diskid, self.index, None, "#"+self.name, None, None)]) add_stream(db, self.name, self.name+".cab") os.unlink(self.name+".txt") os.unlink(self.name+".cab") ! self.db.Commit() class Directory: ! def __init__(self, db, cab, basedir, physical, _logical, default, componentflags=None, add_num=True): """Create a new directory in the Directory table. There is a current component at each point in time for the directory, which is either explicitly created through start_component, or implicitly when files are added for the first *************** *** 422,434 **** None), the path to the physical directory, and a logical directory name. Default specifies the DefaultDir slot in the directory table. componentflags specifies the default flags that new components get.""" ! index = 1 ! _logical = make_id(_logical) ! logical = _logical ! while logical in _directories: ! logical = "%s%d" % (_logical, index) ! index += 1 ! _directories.add(logical) self.db = db self.cab = cab self.basedir = basedir --- 424,430 ---- None), the path to the physical directory, and a logical directory name. Default specifies the DefaultDir slot in the directory table. componentflags specifies the default flags that new components get.""" ! logical = make_id(_logical, add_num=add_num) self.db = db self.cab = cab self.basedir = basedir *************** *** 446,451 **** --- 442,448 ---- self.absolute = physical blogical = None add_data(db, "Directory", [(logical, blogical, default)]) + self._numfiles_wo_commit = 0 def start_component(self, component = None, feature = None, flags = None, keyfile = None, uuid=None): """Add an entry to the Component table, and make this component the current for this *************** *** 465,471 **** if Win64: flags |= 256 if keyfile: ! keyid = self.cab.gen_id(self.absolute, keyfile) self.keyfiles[keyfile] = keyid else: keyid = None --- 462,470 ---- if Win64: flags |= 256 if keyfile: ! ## This does not ensure keyid is unique ! ## The caller needs to make sure keyfiles are not repeated. ! keyid = make_id(keyfile, add_num=False) self.keyfiles[keyfile] = keyid else: keyid = None *************** *** 477,482 **** --- 476,482 ---- [(feature.id, component)]) def make_short(self, file): + file = _replace_bad_chars(file) parts = file.split(".") if len(parts)>1: suffix = parts[-1].upper() *************** *** 514,519 **** --- 514,524 ---- and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" + if self._numfiles_wo_commit > 1000: + self.db.Commit() + self._numfiles_wo_commit = 0 + else: + self._numfiles_wo_commit += 1 if not self.component: self.start_component(self.logical, current_feature) if not src: