#!/usr/bin/python """ Reads AUS data from various file formats. """ import os from aus import Release, Update, Patch """ Parses and imports AUS2-style "snippet" configuration files. """ class Aus2Snippet: """ AUS2 defines three different types of versioned configuration types: * directory schema ** e.g. 2/Firefox/2.0/Darwin_Universal-gcc3/2006081703/en-US/ * file "snippet" schema * URL schema """ def run(self, incoming_dir): AUS2_DIR_SCHEMA_2_LENGTH = 7 # e.g. '2', 'Sunbird', 'trunk', 'Linux_x86-gcc3', '2007092904', 'en-US' AUS2_DIR_SCHEMA_3_LENGTH = 8 # e.g. '3', 'Firefox', '2.0.0.12', 'Linux_x86-gcc3', '2007092904', 'en-US', 'release' os.chdir(incoming_dir) # Directories must contain both the partial.txt and complete.txt files. # These files may be empty. for root, dirs, files in os.walk("."): if "complete.txt" in files and "partial.txt" in files: release_dir = root.split("/")[1:] schema = int(release_dir[0]) if schema == 2: if len(release_dir) != AUS2_DIR_SCHEMA_2_LENGTH: assert("Invalid AUS directory: "+str(release_dir)) elif schema == 3: if len(release_dir) != AUS2_DIR_SCHEMA_3_LENGTH: assert("Invalid AUS directory: "+str(release_dir)) else: assert("Unknown aus2 file schema, must be 2 or 3: "+schema) product = release_dir[1] # e.g. "Firefox" version = release_dir[2] # e.g. "2.0.0.13" buildTarget = release_dir[3] # e.g. "Darwin_Universal-gcc3" buildId = release_dir[4] # e.g. "2007032620" locale = release_dir[5] # e.g. "en-US" channel = "nightly" if schema == 3: channel = release_dir[6] # e.g. "release" # There may be missing update info, or no info at all ("null update"). # Therefore, generate a null update here, and put information into it as we find it. update = Update(type="minor") release = Release(product, version, buildTarget, buildId, locale, channel, update) for file in ["complete.txt", "partial.txt"]: patchContents = [] fh = open(os.path.join(root, file)) for line in fh: patchContents.append(line.strip()) fh.close() if len(patchContents) == 0: # explicit null update continue elif len(patchContents) < 7: print "Invalid patch, expecting at least 8 lines but got "+str(len(patchContents))+": "+os.path.join(root,f) continue patchInfo = {} patchInfo["updateType"] = "minor" # check for AUS2 version 1 file format if (patchContents[0].find('=') != -1): # AUS2 version 1 file format (key=value pairs, line number not significant) for line in patchContents: (key, value) = line.split('=', 1) patchInfo[key] = value else: # AUS2 version 0 file format found (line number is significant) patchInfo["type"] = patchContents[0] patchInfo["url"] = patchContents[1] patchInfo["hashFunction"] = patchContents[2] patchInfo["hashValue"] = patchContents[3] patchInfo["size"] = patchContents[4] patchInfo["build"] = patchContents[5] patchInfo["appv"] = patchContents[6] patchInfo["extv"] = patchContents[7] # license and details URLs are optional fields if len(patchContents) >= 9: patchInfo["detailsUrl"] = patchContents[8] if len(patchContents) >= 10: patchInfo["licenseUrl"] = patchContents[9] if patchInfo["updateType"] != "major" and patchInfo["updateType"] != "minor": assert("Unknown update type: "+patchInfo["updateType"]) if patchInfo["type"] == "complete" and file != "complete.txt": assert("Mismatched type in file and filename: "+os.path.join(root,file)) elif patchInfo["type"] == "partial" and file != "partial.txt": assert("Mismatched type in file and filename: "+os.path.join(root,file)) elif patchInfo["type"] != "partial" and patchInfo["type"] != "complete": assert("Unknown patch type: "+patchInfo["type"]) patch = Patch(patchInfo["type"], patchInfo["url"], patchInfo["hashFunction"], patchInfo["hashValue"], patchInfo["size"], patchInfo["build"]) update.setType(patchInfo["updateType"]) update.setVersion(version) update.setAppVersion(patchInfo["appv"]) update.setExtensionVersion(patchInfo["extv"]) if patchInfo.has_key("detailsUrl"): update.setDetailsUrl(patchInfo["detailsUrl"]) if patchInfo.has_key("licenseUrl"): update.setLicenseUrl(patchInfo["licenseUrl"]) if patchInfo["type"] == "complete": update.setCompletePatch(patch) elif patchInfo["type"] == "partial": update.setPartialPatch(patch) yield (release)