def __init__(self): super(BootstrapArgParser, self).__init__( description="Bootstrap a variant config, based on an existing base " "config, or based on another variant config") requiredOpts = self.add_argument_group("Required args") requiredOpts.add_argument( '-b', '--base', required=True, action="store", help="base config code to use, in the format A.B") requiredOpts.add_argument( '-v', '--variant', required=True, action="store", help="variant config code to use, in the format A.B.C") #requiredOpts.add_argument('-v', '--vendor', required = True, action = "store") #requiredOpts.add_argument('-m', '--model', required = True, action = "store") optionalOpts = self.add_argument_group("Optional args") optionalOpts.add_argument( '--learn-settings', action="store_true", help= "Learn settings from a connected device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "--learn-props", action="store_true", help= "Learn update.property from a connected device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "--learn-partitions", action="store_true", help= "Learn information about partitions on device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "--learn-imgs", action="store_true", help= "Pull recovery and boot img from the device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "-f", "--force", required=False, action="store_true", help="Overwrite an existing variant bootstrap directory if exists") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR self.configTreeParser = ConfigTreeParser( DotIdentifierResolver([self.deviceDir, self.baseDir]))
def __init__(self): super(BootstrapArgParser, self).__init__(description = "Bootstrap a variant config, based on an existing base " "config, or based on another variant config") requiredOpts = self.add_argument_group("Required args") requiredOpts.add_argument('-b', '--base', required = True, action = "store", help="base config code to use, in the format A.B") requiredOpts.add_argument('-v', '--variant', required = True, action = "store", help="variant config code to use, in the format A.B.C") #requiredOpts.add_argument('-v', '--vendor', required = True, action = "store") #requiredOpts.add_argument('-m', '--model', required = True, action = "store") optionalOpts = self.add_argument_group("Optional args") optionalOpts.add_argument('--learn-settings', action="store_true", help="Learn settings from a connected device, and set in the bootstrapped config file" ) optionalOpts.add_argument("--learn-props", action = "store_true", help="Learn update.property from a connected device, and set in the bootstrapped config file") optionalOpts.add_argument("--learn-partitions", action = "store_true", help="Learn information about partitions on device, and set in the bootstrapped config file") optionalOpts.add_argument("--learn-imgs", action = "store_true", help="Pull recovery and boot img from the device, and set in the bootstrapped config file") optionalOpts.add_argument("-f", "--force", required = False, action = "store_true", help="Overwrite an existing variant bootstrap directory if exists") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR self.configTreeParser = ConfigTreeParser(DotIdentifierResolver([self.deviceDir, self.baseDir]))
def __init__(self, description="Make mode cmd"): super(MakeArgParser, self).__init__(description=description) targetOpts = self.add_mutually_exclusive_group(required=True) targetOpts.add_argument( '-v', '--variant', action="store", help="variant config code to use, in the format A.B.C") targetOpts.add_argument( '-c', '--config', action='store', help= "Explicit path to config to use instead of passing variant code, requires --output" ) optionalOpts = self.add_argument_group("Optional opts") optionalOpts.add_argument("-o", "--output", action="store", help="Override default output path") optionalOpts.add_argument("-k", "--keep-work", action="store_true", help="Don't delete work dir when finished") optionalOpts.add_argument( '--learn-settings', action="store_true", help= "Learn settings from a connected device, and use in generated update package" ) self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR identifierResolver = DotIdentifierResolver( [self.deviceDir, self.baseDir]) self.configTreeParser = ConfigTreeParser(identifierResolver)
def __init__(self, description = "Make mode cmd"): super(MakeArgParser, self).__init__(description = description) targetOpts = self.add_mutually_exclusive_group(required = True) targetOpts.add_argument('-v', '--variant',action = "store", help="variant config code to use, in the format A.B.C") targetOpts.add_argument('-c', '--config', action= 'store', help = "Explicit path to config to use instead of passing variant code, requires --output") optionalOpts = self.add_argument_group("Optional opts") optionalOpts.add_argument("-o", "--output", action="store", help = "Override default output path") optionalOpts.add_argument("-k", "--keep-work", action="store_true", help="Don't delete work dir when finished") optionalOpts.add_argument('--learn-settings', action="store_true", help= "Learn settings from a connected device, and use in generated update package") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR identifierResolver = DotIdentifierResolver([self.deviceDir, self.baseDir]) self.configTreeParser = ConfigTreeParser(identifierResolver)
class BootstrapArgParser(InceptionArgParser): def __init__(self): super(BootstrapArgParser, self).__init__( description="Bootstrap a variant config, based on an existing base " "config, or based on another variant config") requiredOpts = self.add_argument_group("Required args") requiredOpts.add_argument( '-b', '--base', required=True, action="store", help="base config code to use, in the format A.B") requiredOpts.add_argument( '-v', '--variant', required=True, action="store", help="variant config code to use, in the format A.B.C") #requiredOpts.add_argument('-v', '--vendor', required = True, action = "store") #requiredOpts.add_argument('-m', '--model', required = True, action = "store") optionalOpts = self.add_argument_group("Optional args") optionalOpts.add_argument( '--learn-settings', action="store_true", help= "Learn settings from a connected device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "--learn-props", action="store_true", help= "Learn update.property from a connected device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "--learn-partitions", action="store_true", help= "Learn information about partitions on device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "--learn-imgs", action="store_true", help= "Pull recovery and boot img from the device, and set in the bootstrapped config file" ) optionalOpts.add_argument( "-f", "--force", required=False, action="store_true", help="Overwrite an existing variant bootstrap directory if exists") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR self.configTreeParser = ConfigTreeParser( DotIdentifierResolver([self.deviceDir, self.baseDir])) def process(self): super(BootstrapArgParser, self).process() self.createDir(self.deviceDir) self.config = self.configTreeParser.parseJSON(self.args["base"]) if self.config.get("__config__") is None: sys.stderr.write( "You are using an outdated config tree. Please run 'incept sync -v VARIANT_CODE' or set __config__ (see https://goo.gl/aFWPby)\n" ) sys.exit(1) self.configDir = self.config.getSource(getDir=True) baseCodePath = "/".join(self.args["base"].split(".")[:2]) self.variantDir = os.path.join(self.deviceDir, baseCodePath, self.args["variant"]) logger.info("Writing new config") self.newConfig = self.createNewConfig( self.args["base"] + "." + self.args["variant"], self.args["variant"], self.config) self.setupDirPaths() self.createDirs() #self.unpackimg(bootImg, self.bootDir, self.config["tools"]["unpackbootimg"], "boot") unpackerKey, unpacker = self.config.getHostBinary("unpackbootimg") bootImg = self.config.getProperty("boot.img", None) if bootImg and self.config.get("boot.__make__", False): if type(bootImg.getValue()) is str: logger.info("Unpacking boot img") self.unpackimg( bootImg.getConfig().resolveRelativePath( bootImg.getValue()), self.bootDir, unpacker, "boot") recoveryImg = self.config.getProperty("recovery.img", None) if recoveryImg and self.config.get("recovery.__make__", False): if type(recoveryImg.getValue()) is str: logger.info("Unpacking recovery img") self.unpackimg( recoveryImg.getConfig().resolveRelativePath( recoveryImg.getValue()), self.recoveryDir, unpacker, "recovery") if any((self.args["learn_settings"], self.args["learn_partitions"], self.args["learn_props"], self.args["learn_imgs"])): syncer = ConfigSyncer(self.newConfig) if self.args["learn_settings"]: logger.info("pulling settings") syncer.applyDiff(syncer.pullAndDiff()) if self.args["learn_partitions"]: logger.info("pulling partitions info") syncer.syncPartitions(True) if self.args["learn_props"]: logger.info("pulling props") syncer.syncProps(True) if self.args["learn_imgs"]: imgsDir = os.path.join(self.variantDir, "imgs") os.makedirs(imgsDir) if self.newConfig.getMountConfig("recovery.dev"): logger.info("pulling recovery.img") syncer.syncImg( "recovery.img", self.newConfig.getMountConfig("recovery.dev"), imgsDir, self.variantDir) else: logger.warn( "__config__.target.mount.recovery.dev not set, not syncing recovery.img" ) if self.newConfig.getMountConfig("boot.dev"): logger.info("pulling boot.img") syncer.syncImg("boot.img", self.newConfig.getMountConfig("boot.dev"), imgsDir, self.variantDir) else: logger.warn( "__config__.target.mount.boot.dev not set, not syncing boot.img" ) configPath = self.writeNewConfig(self.args["variant"]) logger.info("Created %s" % configPath) return True def createNewConfig(self, identifier, name, baseConfig): return ConfigV2.new(identifier, name, baseConfig) def writeNewConfig(self, name): out = os.path.join(self.variantDir, "%s.json" % name) newConfigFile = open(out, "w") newConfigFile.write(self.newConfig.dumpContextData()) newConfigFile.close() return out def createDir(self, d): if not os.path.exists(d): logger.info("Creating: %s" % d) os.makedirs(d) else: logger.info("Exists: %s" % d) def setupDirPaths(self): self.imgDir = os.path.join(self.variantDir, "img") self.bootDir = os.path.join(self.imgDir, "boot") self.recoveryDir = os.path.join(self.imgDir, "recovery") self.fsDir = os.path.join(self.variantDir, InceptionConstants.FS_DIR) def createDirs(self): # self.createDir(self.variantDir) if os.path.exists(self.variantDir): if self.args["force"]: shutil.rmtree(self.variantDir) else: raise InceptionArgParserException("%s exists!!" % self.variantDir) self.createDir(self.variantDir) self.createDir(self.fsDir) def getAbsolutePathOf(self, f): return os.path.dirname(os.path.realpath(__file__)) + "/" + f def getConfigPath(self, configName): return os.path.join(self.configDir, configName + ".config") def unpackimg(self, img, out, unpacker, imgType): bootImgGenerator = imgtools.unpackimg(unpacker, img, out) self.newConfig.set("%s.img.cmdline" % imgType, bootImgGenerator.getKernelCmdLine(quote=False)) self.newConfig.set("%s.img.base" % imgType, bootImgGenerator.getBaseAddr()) self.newConfig.set("%s.img.ramdisk_offset" % imgType, bootImgGenerator.getRamdiskOffset()) self.newConfig.set("%s.img.second_offset" % imgType, bootImgGenerator.getSecondOffset()) self.newConfig.set("%s.img.tags_offset" % imgType, bootImgGenerator.getTagsOffset()) self.newConfig.set("%s.img.pagesize" % imgType, bootImgGenerator.getPageSize()) self.newConfig.set("%s.img.second_size" % imgType, bootImgGenerator.getSecondSize()) self.newConfig.set("%s.img.dt_size" % imgType, bootImgGenerator.getDeviceTreeSize()) self.newConfig.set( "%s.img.kernel" % imgType, os.path.relpath(bootImgGenerator.getKernel(), self.variantDir)) self.newConfig.set( "%s.img.ramdisk" % imgType, os.path.relpath(bootImgGenerator.getRamdisk(), self.variantDir)) self.newConfig.set( "%s.img.dt" % imgType, os.path.relpath(bootImgGenerator.getDeviceTree(), self.variantDir)) fstab = Fstab.parseFstab( os.path.join(out, bootImgGenerator.getRamdisk(), "etc", "recovery.fstab")) processParts = ("boot", "system", "recovery", "cache") for p in processParts: fstabPart = fstab.getByMountPoint("/" + p) key = "__config__.target.mount.%s." % p if self.newConfig.get(key + "dev") != fstabPart.getDevice(): self.newConfig.set(key + "dev", fstabPart.getDevice()) if self.newConfig.get(key + "mount") != fstabPart.getMountPoint(): self.newConfig.set(key + "mount", fstabPart.getMountPoint()) if self.newConfig.get(key + "fs") != fstabPart.getType(): self.newConfig.set(key + "fs", fstabPart.getType())
class BootstrapArgParser(InceptionArgParser): def __init__(self): super(BootstrapArgParser, self).__init__(description = "Bootstrap a variant config, based on an existing base " "config, or based on another variant config") requiredOpts = self.add_argument_group("Required args") requiredOpts.add_argument('-b', '--base', required = True, action = "store", help="base config code to use, in the format A.B") requiredOpts.add_argument('-v', '--variant', required = True, action = "store", help="variant config code to use, in the format A.B.C") #requiredOpts.add_argument('-v', '--vendor', required = True, action = "store") #requiredOpts.add_argument('-m', '--model', required = True, action = "store") optionalOpts = self.add_argument_group("Optional args") optionalOpts.add_argument('--learn-settings', action="store_true", help="Learn settings from a connected device, and set in the bootstrapped config file" ) optionalOpts.add_argument("--learn-props", action = "store_true", help="Learn update.property from a connected device, and set in the bootstrapped config file") optionalOpts.add_argument("--learn-partitions", action = "store_true", help="Learn information about partitions on device, and set in the bootstrapped config file") optionalOpts.add_argument("--learn-imgs", action = "store_true", help="Pull recovery and boot img from the device, and set in the bootstrapped config file") optionalOpts.add_argument("-f", "--force", required = False, action = "store_true", help="Overwrite an existing variant bootstrap directory if exists") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR self.configTreeParser = ConfigTreeParser(DotIdentifierResolver([self.deviceDir, self.baseDir])) def process(self): super(BootstrapArgParser, self).process() self.createDir(self.deviceDir) self.config = self.configTreeParser.parseJSON(self.args["base"]) self.configDir = self.config.getSource(getDir=True) baseCodePath= "/".join(self.args["base"].split(".")[:2]) self.variantDir = os.path.join(self.deviceDir, baseCodePath, self.args["variant"]) logger.info("Writing new config") self.newConfig = self.createNewConfig(self.args["base"] + "." + self.args["variant"], self.args["variant"], self.config) self.setupDirPaths() self.createDirs() #self.unpackimg(bootImg, self.bootDir, self.config["tools"]["unpackbootimg"], "boot") unpackerProperty = self.config.getProperty("common.tools.unpackbootimg.bin") unpacker = unpackerProperty.getConfig().resolveRelativePath(unpackerProperty.getValue()) bootImg = self.config.getProperty("boot.img", None) if bootImg and self.config.get("boot.__make__", False): if type(bootImg.getValue()) is str: logger.info("Unpacking boot img") self.unpackimg(bootImg.getConfig().resolveRelativePath(bootImg.getValue()), self.bootDir, unpacker, "boot") recoveryImg = self.config.getProperty("recovery.img", None) if recoveryImg and self.config.get("recovery.__make__", False): if type(recoveryImg.getValue()) is str: logger.info("Unpacking recovery img") self.unpackimg(recoveryImg.getConfig().resolveRelativePath(recoveryImg.getValue()), self.recoveryDir, unpacker, "recovery") if any((self.args["learn_settings"], self.args["learn_partitions"], self.args["learn_props"], self.args["learn_imgs"])): syncer = ConfigSyncer(self.newConfig) if self.args["learn_settings"]: logger.info("pulling settings") syncer.applyDiff(syncer.pullAndDiff()) if self.args["learn_partitions"]: logger.info("pulling partitions info") syncer.syncPartitions(True) if self.args["learn_props"]: logger.info("pulling props") syncer.syncProps(True) if self.args["learn_imgs"]: imgsDir = os.path.join(self.variantDir, "imgs") os.makedirs(imgsDir) if self.newConfig.get("recovery.dev"): logger.info("pulling recovery.img") syncer.syncImg("recovery.img", self.newConfig.get("recovery.dev"), imgsDir, self.variantDir) else: logger.warn("recovery.dev not set, not syncing recovery.img") if self.newConfig.get("boot.dev"): logger.info("pulling boot.img") syncer.syncImg("boot.img", self.newConfig.get("boot.dev"), imgsDir, self.variantDir) else: logger.warn("boot.dev not set, not syncing boot.img") self.writeNewConfig(self.args["variant"]) self.writeCmdLog(os.path.join(self.variantDir, "bootstrap.commands.log")) return True def createNewConfig(self, identifier, name, baseConfig): return Config.new(identifier, name, baseConfig) def writeNewConfig(self, name): newConfigFile = open(os.path.join(self.variantDir, "%s.json" % name), "w") newConfigFile.write(self.newConfig.dumpContextData()) newConfigFile.close() def createDir(self, d): if not os.path.exists(d): logger.info("Creating: %s" % d) os.makedirs(d) else: logger.info("Exists: %s" % d) def setupDirPaths(self): self.imgDir = os.path.join(self.variantDir, "img") self.bootDir = os.path.join(self.imgDir, "boot") self.recoveryDir = os.path.join(self.imgDir, "recovery") self.fsDir = os.path.join(self.variantDir, InceptionConstants.FS_DIR) def createDirs(self): # self.createDir(self.variantDir) if os.path.exists(self.variantDir): if self.args["force"]: shutil.rmtree(self.variantDir) else: raise InceptionArgParserException("%s exists!!" % self.variantDir) self.createDir(self.variantDir) self.createDir(self.fsDir) def getAbsolutePathOf(self, f): return os.path.dirname(os.path.realpath(__file__)) + "/" + f def getConfigPath(self, configName): return os.path.join(self.configDir, configName + ".config") def unpackimg(self, img, out, unpacker, imgType): if not os.path.isfile(img): raise ValueError("Coudn't find %s to unpack" % img) filename = img.split('/')[-1] ramdisk = "%s/%s-ramdisk" % (out, filename) kernel = "%s/%s-zImage" % (out, filename) dt = "%s/%s-dt" % (out, filename) ramdiskDir = os.path.join(out, "ramdisk") ramdiskExtracted = ramdiskDir + "/" + filename + "-ramdisk" os.makedirs(out) unpackResult = self.execCmd(unpacker, "-i", img, "-o", out, failMessage = "Failed to unpack %s to %s" % (img, out)) try: self.execCmd("gunzip", ramdisk + ".gz") except InceptionExecCmdFailedException as e: self.execCmd("mv", ramdisk + ".gz", ramdisk + ".xz") self.execCmd("unxz", ramdisk + ".xz") self.createDir(ramdiskDir) self.execCmd("mv", ramdisk, ramdiskDir) f = open(ramdiskExtracted) try: self.execCmd("cpio", "-i", cwd = ramdiskDir, stdin = f) finally: f.close() os.remove(ramdiskExtracted) #process unpacker output resultList = unpackResult.split('\n') for l in resultList: try: dissect = l.split(' ') key = dissect[0] value = " ".join(dissect[1:]) or None except ValueError: key = l.split(' ') value = None if key == "BOARD_KERNEL_CMDLINE": self.newConfig.set("%s.img.cmdline" % imgType, value) elif key == "BOARD_KERNEL_BASE": self.newConfig.set("%s.img.base" % imgType, "0x" + value) elif key == "BOARD_RAMDISK_OFFSET": self.newConfig.set("%s.img.ramdisk_offset" % imgType, "0x" + value) elif key == "BOARD_SECOND_OFFSET": self.newConfig.set("%s.img.second_offset" % imgType, "0x" + value) elif key == "BOARD_TAGS_OFFSET": self.newConfig.set("%s.img.tags_offset" % imgType, "0x" + value) elif key == "BOARD_PAGE_SIZE": self.newConfig.set("%s.img.pagesize" % imgType, int(value)) elif key == "BOARD_SECOND_SIZE": self.newConfig.set("%s.img.second_size" % imgType, int(value)) elif key == "BOARD_DT_SIZE": self.newConfig.set("%s.img.dt_size" % imgType, int(value)) self.newConfig.set("%s.img.kernel" % imgType, os.path.relpath(kernel, self.variantDir)) self.newConfig.set("%s.img.ramdisk" % imgType, os.path.relpath(ramdiskDir, self.variantDir)) self.newConfig.set("%s.img.dt" % imgType, os.path.relpath(dt, self.variantDir))
class MakeArgParser(InceptionArgParser): def __init__(self, description="Make mode cmd"): super(MakeArgParser, self).__init__(description=description) targetOpts = self.add_mutually_exclusive_group(required=True) targetOpts.add_argument( '-v', '--variant', action="store", help="variant config code to use, in the format A.B.C") targetOpts.add_argument( '-c', '--config', action='store', help= "Explicit path to config to use instead of passing variant code, requires --output" ) optionalOpts = self.add_argument_group("Optional opts") optionalOpts.add_argument("-o", "--output", action="store", help="Override default output path") optionalOpts.add_argument("-k", "--keep-work", action="store_true", help="Don't delete work dir when finished") optionalOpts.add_argument( '--learn-settings', action="store_true", help= "Learn settings from a connected device, and use in generated update package" ) self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR identifierResolver = DotIdentifierResolver( [self.deviceDir, self.baseDir]) self.configTreeParser = ConfigTreeParser(identifierResolver) def process(self): super(MakeArgParser, self).process() code = self.args["variant"] outDir = self.args["output"] if code: self.config = self.configTreeParser.parseJSON(code) try: a, b, c = code.split('.') except ValueError as e: raise InceptionArgParserException( "Code must me in the format vendor.model.variant") self.setWorkDir(os.path.join(InceptionConstants.WORK_DIR, a, b, c)) else: configPath = self.args["config"] if not outDir: print("Must set --output when using --config") sys.exit(1) self.config = self.configTreeParser.parseJSONFile(configPath) self.setWorkDir(tempfile.mkdtemp()) if self.config.get("__abstract__", False, directOnly=True): print("Won't make abstract config %s" % code) sys.exit(1) if self.config.get("__config__") is None: sys.stderr.write( "You are using an outdated config tree. Please run 'incept sync -v VARIANT_CODE' or set __config__ (see https://goo.gl/aFWPby)\n" ) sys.exit(1) if outDir: self.config.setOutPath(outDir) else: outDir = self.config.getOutPath() self.workDir = self.getWorkDir() self.configDir = os.path.dirname(self.config.getSource()) logger.info("Cleaning work dir " + self.workDir) if os.path.exists(self.workDir): shutil.rmtree(self.workDir) os.makedirs(self.workDir) if self.args["learn_settings"]: syncer = ConfigSyncer(self.config) syncer.applyDiff(syncer.pullAndDiff()) self.config.make(self.workDir) self.writeUsedConfig() if not self.args["keep_work"]: logger.info("Cleaning up work dir") shutil.rmtree(self.getWorkDir()) return True def writeUsedConfig(self): f = open(os.path.join(self.config.getOutPath(), "config.json"), "w") f.write(self.config.dumpFullData()) f.close()
def __init__(self, description="Make mode cmd"): super(MakeArgParser, self).__init__(description=description) self.makeables = [ "package", "boot", "cache", "recovery", "dnx", "update", "installer", "odin", "extras" ] targetOpts = self.add_mutually_exclusive_group(required=True) targetOpts.add_argument( '-v', '--variant', action="store", help="variant config code to use, in the format A.B.C") targetOpts.add_argument( '-c', '--config', action='store', help= "Explicit path to config to use instead of passing variant code, requires --output" ) optionalOpts = self.add_argument_group("Optional opts") optionalOpts.add_argument("-o", "--output", action="store", help="Override default output path") optionalOpts.add_argument( "-d", "--keep-dirs", action="store_true", help= "Keep output hierarchy when default output path is overriden. Default is True, requires -o" ) optionalOpts.add_argument("-w", "--keep-work", action="store_true", help="Don't delete work dir when finished") optionalOpts.add_argument( "-O", "--keep-output", action="store_true", help= "Don't clear output dir before make, will replace files with existing names." ) optionalOpts.add_argument( '--learn-settings', action="store_true", help= "Learn settings from a connected device, and use in generated update package" ) configQueryOpts = self.add_argument_group("Config query options") configQueryOpts.add_argument("--config-list-keys", action="store_true", help="List available signing keys") makeOpts = self.add_argument_group("General Make opts") for makeable in self.makeables: formattedMakeableName = makeable[0].upper() + makeable[1:] makeOpts.add_argument("--only-%s" % makeable, action="store_true", help="Make only %s " % formattedMakeableName) makeableGp = self.add_argument_group("%s Maker Opts" % formattedMakeableName) flagGp = makeableGp.add_mutually_exclusive_group(required=False) flagGp.add_argument("--%s" % makeable, dest=makeable, action="store_true", help="Make %s, overrides config" % makeable, default=None) flagGp.add_argument("--no-%s" % makeable, dest=makeable, action="store_false", help="Don't make %s, overrides config " % makeable, default=None) if makeable == "recovery": makeableGp.add_argument("--recovery-sign", action="store", metavar="keys_name", help="Recovery signing keys name") makeableGp.add_argument("--recovery-no-sign", action="store_true") makeableGp.add_argument("--recovery-img", action="store") elif makeable == "update": makeableGp.add_argument( "--update-no-reboot", action="store_true", help="Don't reboot after update script executes") makeableGp.add_argument("--update-sign", action="store", metavar="keys_name", help="Update signing keys name") makeableGp.add_argument("--update-apps", action="store_true", help="Make apps") makeableGp.add_argument("--update-no-apps", action="store_true", help="Don't make apps") makeableGp.add_argument("--update-settings", action="store_true", help="Make settings") makeableGp.add_argument("--update-no-settings", action="store_true", help="Don't make Settings") makeableGp.add_argument("--update-network", action="store_true", help="Make network") makeableGp.add_argument("--update-no-network", action="store_true", help="Don't make network") makeableGp.add_argument("--update-databases", action="store_true", help="Make databases") makeableGp.add_argument("--update-no-databases", action="store_true", help="Don't make databases") makeableGp.add_argument("--update-adb", action="store_true", help="Make adb") makeableGp.add_argument("--update-no-adb", action="store_true", help="Don't make adb") makeableGp.add_argument("--update-property", action="store_true", help="Make property") makeableGp.add_argument("--update-no-property", action="store_true", help="Don't make property") makeableGp.add_argument("--update-busybox", action="store_true", help="Make busybox") makeableGp.add_argument("--update-no-busybox", action="store_true", help="Don't make busybox") makeableGp.add_argument("--update-restore_stock_recovery", action="store_true", help="Restore stock recovery") makeableGp.add_argument("--update-no-restore_stock_recovery", action="store_true", help="Don't restore stock recovery") makeableGp.add_argument( "--update-root", metavar="method_name", action="store", help="Root the device with the specified root method") makeableGp.add_argument("--update-no-root", action="store_true", help="Don't root the device") makeableGp.add_argument("--update-no-sign", action="store_true") makeableGp.add_argument("--update-no-wipe", action="store_true") makeableGp.add_argument("--update-wipe", action="store_true") makeableGp.add_argument("--update-verbose", action="store_true") makeableGp.add_argument("--update-no-verbose", action="store_true") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR identifierResolver = DotIdentifierResolver( [self.deviceDir, self.baseDir]) self.configTreeParser = ConfigTreeParser(identifierResolver)
class MakeArgParser(InceptionArgParser): def __init__(self, description="Make mode cmd"): super(MakeArgParser, self).__init__(description=description) self.makeables = [ "package", "boot", "cache", "recovery", "dnx", "update", "installer", "odin", "extras" ] targetOpts = self.add_mutually_exclusive_group(required=True) targetOpts.add_argument( '-v', '--variant', action="store", help="variant config code to use, in the format A.B.C") targetOpts.add_argument( '-c', '--config', action='store', help= "Explicit path to config to use instead of passing variant code, requires --output" ) optionalOpts = self.add_argument_group("Optional opts") optionalOpts.add_argument("-o", "--output", action="store", help="Override default output path") optionalOpts.add_argument( "-d", "--keep-dirs", action="store_true", help= "Keep output hierarchy when default output path is overriden. Default is True, requires -o" ) optionalOpts.add_argument("-w", "--keep-work", action="store_true", help="Don't delete work dir when finished") optionalOpts.add_argument( "-O", "--keep-output", action="store_true", help= "Don't clear output dir before make, will replace files with existing names." ) optionalOpts.add_argument( '--learn-settings', action="store_true", help= "Learn settings from a connected device, and use in generated update package" ) configQueryOpts = self.add_argument_group("Config query options") configQueryOpts.add_argument("--config-list-keys", action="store_true", help="List available signing keys") makeOpts = self.add_argument_group("General Make opts") for makeable in self.makeables: formattedMakeableName = makeable[0].upper() + makeable[1:] makeOpts.add_argument("--only-%s" % makeable, action="store_true", help="Make only %s " % formattedMakeableName) makeableGp = self.add_argument_group("%s Maker Opts" % formattedMakeableName) flagGp = makeableGp.add_mutually_exclusive_group(required=False) flagGp.add_argument("--%s" % makeable, dest=makeable, action="store_true", help="Make %s, overrides config" % makeable, default=None) flagGp.add_argument("--no-%s" % makeable, dest=makeable, action="store_false", help="Don't make %s, overrides config " % makeable, default=None) if makeable == "recovery": makeableGp.add_argument("--recovery-sign", action="store", metavar="keys_name", help="Recovery signing keys name") makeableGp.add_argument("--recovery-no-sign", action="store_true") makeableGp.add_argument("--recovery-img", action="store") elif makeable == "update": makeableGp.add_argument( "--update-no-reboot", action="store_true", help="Don't reboot after update script executes") makeableGp.add_argument("--update-sign", action="store", metavar="keys_name", help="Update signing keys name") makeableGp.add_argument("--update-apps", action="store_true", help="Make apps") makeableGp.add_argument("--update-no-apps", action="store_true", help="Don't make apps") makeableGp.add_argument("--update-settings", action="store_true", help="Make settings") makeableGp.add_argument("--update-no-settings", action="store_true", help="Don't make Settings") makeableGp.add_argument("--update-network", action="store_true", help="Make network") makeableGp.add_argument("--update-no-network", action="store_true", help="Don't make network") makeableGp.add_argument("--update-databases", action="store_true", help="Make databases") makeableGp.add_argument("--update-no-databases", action="store_true", help="Don't make databases") makeableGp.add_argument("--update-adb", action="store_true", help="Make adb") makeableGp.add_argument("--update-no-adb", action="store_true", help="Don't make adb") makeableGp.add_argument("--update-property", action="store_true", help="Make property") makeableGp.add_argument("--update-no-property", action="store_true", help="Don't make property") makeableGp.add_argument("--update-busybox", action="store_true", help="Make busybox") makeableGp.add_argument("--update-no-busybox", action="store_true", help="Don't make busybox") makeableGp.add_argument("--update-restore_stock_recovery", action="store_true", help="Restore stock recovery") makeableGp.add_argument("--update-no-restore_stock_recovery", action="store_true", help="Don't restore stock recovery") makeableGp.add_argument( "--update-root", metavar="method_name", action="store", help="Root the device with the specified root method") makeableGp.add_argument("--update-no-root", action="store_true", help="Don't root the device") makeableGp.add_argument("--update-no-sign", action="store_true") makeableGp.add_argument("--update-no-wipe", action="store_true") makeableGp.add_argument("--update-wipe", action="store_true") makeableGp.add_argument("--update-verbose", action="store_true") makeableGp.add_argument("--update-no-verbose", action="store_true") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR identifierResolver = DotIdentifierResolver( [self.deviceDir, self.baseDir]) self.configTreeParser = ConfigTreeParser(identifierResolver) def process(self): super(MakeArgParser, self).process() code = self.args["variant"] outDir = self.args["output"] if code: self.config = self.configTreeParser.parseJSON(code) try: a, b, c = code.split('.') except ValueError as e: raise InceptionArgParserException( "Code must me in the format vendor.model.variant") self.setWorkDir(os.path.join(InceptionConstants.WORK_DIR, a, b, c)) else: configPath = self.args["config"] if not outDir: print("Must set --output when using --config") sys.exit(1) self.config = self.configTreeParser.parseJSONFile(configPath) self.setWorkDir(tempfile.mkdtemp()) if self.config.get("__abstract__", False, directOnly=True): print("Won't make abstract config %s" % code) sys.exit(1) if self.config.get("__config__") is None: sys.stderr.write( "You are using an outdated config tree. Please run 'incept sync -v VARIANT_CODE' or set __config__ (see https://goo.gl/aFWPby)\n" ) sys.exit(1) makeOnly = [] for makeable in self.makeables: if self.args["only_%s" % makeable]: makeOnly.append(makeable) for makeable in self.makeables: if len(makeOnly): self.config.set("%s.__make__" % makeable, makeable in makeOnly) elif self.args[makeable] is not None: self.config.set("%s.__make__" % makeable, self.args[makeable]) if self.args["recovery_no_sign"]: self.config.set("recovery.keys", None) elif self.args["recovery_sign"] is not None: self.config.set("recovery.keys", self.args["recovery_sign"]) if self.args["recovery_img"]: self.config.set("recovery.img", self.args["recovery_img"]) if self.args["update_no_sign"]: self.config.set("update.keys", None) elif self.args["update_sign"] is not None: self.config.set("update.keys", self.args["update_sign"]) updateMakeables = ("apps", "settings", "databases", "property", "adb", "network", "busybox", "root", "restore_stock_recovery") for updateMakeable in updateMakeables: if self.args["update_%s" % updateMakeable]: if updateMakeable == "restore_stock_recovery": self.config.set("update.%s" % updateMakeable, True) elif updateMakeable == "root": self.config.set("update.root_method", self.args["update_%s" % updateMakeable]) else: self.config.set("update.%s.__make__" % updateMakeable, True) elif self.args["update_no_%s" % updateMakeable]: if updateMakeable == "restore_stock_recovery": self.config.set("update.%s" % updateMakeable, False) elif updateMakeable == "root": self.config.set("update.%s", None) else: self.config.set("update.%s.__make__" % updateMakeable, False) if self.args["update_no_reboot"]: self.config.set("update.script.wait", 60 * 5) if self.args["update_no_wipe"]: self.config.set("update.script.format_data", False) elif self.args["update_wipe"]: self.config.set("update.script.format_data", True) if self.args["update_no_verbose"]: self.config.set("update.script.verbose", False) elif self.args["update_verbose"]: self.config.set("update.script.verbose", True) if outDir: self.config.setOutPath(outDir, self.args["keep_dirs"]) else: outDir = self.config.getOutPath() if not self.handleConfigQueryArrgs(self.args, self.config): self.workDir = self.getWorkDir() self.configDir = os.path.dirname(self.config.getSource()) logger.info("Cleaning work dir " + self.workDir) if os.path.exists(self.workDir): shutil.rmtree(self.workDir) os.makedirs(self.workDir) if self.args["learn_settings"]: syncer = ConfigSyncer(self.config) syncer.applyDiff(syncer.pullAndDiff()) self.config.make(self.workDir, not self.args["keep_output"]) if not self.args["keep_work"]: logger.info("Cleaning up work dir") shutil.rmtree(self.getWorkDir()) return True def handleConfigQueryArrgs(self, args, config): if args["config_list_keys"]: keys = config.get("__config__.host.keys", {}).keys() for i in range(0, len(keys)): print("%s- %s" % (i + 1, keys[i])) return True return False
class MakeArgParser(InceptionArgParser): def __init__(self, description = "Make mode cmd"): super(MakeArgParser, self).__init__(description = description) targetOpts = self.add_mutually_exclusive_group(required = True) targetOpts.add_argument('-v', '--variant',action = "store", help="variant config code to use, in the format A.B.C") targetOpts.add_argument('-c', '--config', action= 'store', help = "Explicit path to config to use instead of passing variant code, requires --output") optionalOpts = self.add_argument_group("Optional opts") optionalOpts.add_argument("-o", "--output", action="store", help = "Override default output path") optionalOpts.add_argument("-k", "--keep-work", action="store_true", help="Don't delete work dir when finished") optionalOpts.add_argument('--learn-settings', action="store_true", help= "Learn settings from a connected device, and use in generated update package") self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR identifierResolver = DotIdentifierResolver([self.deviceDir, self.baseDir]) self.configTreeParser = ConfigTreeParser(identifierResolver) def process(self): super(MakeArgParser, self).process() code = self.args["variant"] outDir = self.args["output"] if code: self.config = self.configTreeParser.parseJSON(code) try: a, b, c= code.split('.') except ValueError as e: raise InceptionArgParserException( "Code must me in the format vendor.model.variant" ) self.setWorkDir(os.path.join(InceptionConstants.WORK_DIR, a, b, c) ) else: configPath = self.args["config"] if not outDir: print("Must set --output when using --config") sys.exit(1) self.config = self.configTreeParser.parseJSONFile(configPath) self.setWorkDir(tempfile.mkdtemp()) if self.config.get("__abstract__", False, directOnly=True): print("Won't make abstract config %s" % code) sys.exit(1) if outDir: self.config.setOutPath(outDir) else: outDir = self.config.getOutPath() self.workDir = self.getWorkDir() self.configDir = os.path.dirname(self.config.getSource()) logger.info("Cleaning work dir " + self.workDir) if os.path.exists(self.workDir): shutil.rmtree(self.workDir) os.makedirs(self.workDir) if self.args["learn_settings"]: syncer = ConfigSyncer(self.config) syncer.applyDiff(syncer.pullAndDiff()) self.config.make(self.workDir) self.writeUsedConfig() if not self.args["keep_work"]: logger.info("Cleaning up work dir") shutil.rmtree(self.getWorkDir()) return True def writeUsedConfig(self): f = open(os.path.join(self.config.getOutPath(), "config.json"), "w") f.write(self.config.dumpFullData()) f.close()
class BootstrapArgParser(InceptionArgParser): def __init__(self): super(BootstrapArgParser, self).__init__( description="Bootstrap a variant config, based on an existing base " "config, or based on another variant config" ) requiredOpts = self.add_argument_group("Required args") requiredOpts.add_argument( "-b", "--base", required=True, action="store", help="base config code to use, in the format A.B" ) requiredOpts.add_argument( "-v", "--variant", required=True, action="store", help="variant config code to use, in the format A.B.C" ) # requiredOpts.add_argument('-v', '--vendor', required = True, action = "store") # requiredOpts.add_argument('-m', '--model', required = True, action = "store") optionalOpts = self.add_argument_group("Optional args") optionalOpts.add_argument( "--learn-settings", action="store_true", help="Learn settings from a connected device, and set in the bootstrapped config file", ) optionalOpts.add_argument( "--learn-props", action="store_true", help="Learn update.property from a connected device, and set in the bootstrapped config file", ) optionalOpts.add_argument( "--learn-partitions", action="store_true", help="Learn information about partitions on device, and set in the bootstrapped config file", ) optionalOpts.add_argument( "--learn-imgs", action="store_true", help="Pull recovery and boot img from the device, and set in the bootstrapped config file", ) optionalOpts.add_argument( "-f", "--force", required=False, action="store_true", help="Overwrite an existing variant bootstrap directory if exists", ) self.deviceDir = InceptionConstants.VARIANTS_DIR self.baseDir = InceptionConstants.BASE_DIR self.configTreeParser = ConfigTreeParser(DotIdentifierResolver([self.deviceDir, self.baseDir])) def process(self): super(BootstrapArgParser, self).process() self.createDir(self.deviceDir) self.config = self.configTreeParser.parseJSON(self.args["base"]) if self.config.get("__config__") is None: sys.stderr.write( "You are using an outdated config tree. Please run 'incept sync -v VARIANT_CODE' or set __config__ (see https://goo.gl/aFWPby)\n" ) sys.exit(1) self.configDir = self.config.getSource(getDir=True) baseCodePath = "/".join(self.args["base"].split(".")[:2]) self.variantDir = os.path.join(self.deviceDir, baseCodePath, self.args["variant"]) logger.info("Writing new config") self.newConfig = self.createNewConfig( self.args["base"] + "." + self.args["variant"], self.args["variant"], self.config ) self.setupDirPaths() self.createDirs() # self.unpackimg(bootImg, self.bootDir, self.config["tools"]["unpackbootimg"], "boot") unpackerKey, unpacker = self.config.getHostBinary("unpackbootimg") bootImg = self.config.getProperty("boot.img", None) if bootImg and self.config.get("boot.__make__", False): if type(bootImg.getValue()) is str: logger.info("Unpacking boot img") self.unpackimg( bootImg.getConfig().resolveRelativePath(bootImg.getValue()), self.bootDir, unpacker, "boot" ) recoveryImg = self.config.getProperty("recovery.img", None) if recoveryImg and self.config.get("recovery.__make__", False): if type(recoveryImg.getValue()) is str: logger.info("Unpacking recovery img") self.unpackimg( recoveryImg.getConfig().resolveRelativePath(recoveryImg.getValue()), self.recoveryDir, unpacker, "recovery", ) if any( ( self.args["learn_settings"], self.args["learn_partitions"], self.args["learn_props"], self.args["learn_imgs"], ) ): syncer = ConfigSyncer(self.newConfig) if self.args["learn_settings"]: logger.info("pulling settings") syncer.applyDiff(syncer.pullAndDiff()) if self.args["learn_partitions"]: logger.info("pulling partitions info") syncer.syncPartitions(True) if self.args["learn_props"]: logger.info("pulling props") syncer.syncProps(True) if self.args["learn_imgs"]: imgsDir = os.path.join(self.variantDir, "imgs") os.makedirs(imgsDir) if self.newConfig.getMountConfig("recovery.dev"): logger.info("pulling recovery.img") syncer.syncImg( "recovery.img", self.newConfig.getMountConfig("recovery.dev"), imgsDir, self.variantDir ) else: logger.warn("__config__.target.mount.recovery.dev not set, not syncing recovery.img") if self.newConfig.getMountConfig("boot.dev"): logger.info("pulling boot.img") syncer.syncImg("boot.img", self.newConfig.getMountConfig("boot.dev"), imgsDir, self.variantDir) else: logger.warn("__config__.target.mount.boot.dev not set, not syncing boot.img") configPath = self.writeNewConfig(self.args["variant"]) logger.info("Created %s" % configPath) return True def createNewConfig(self, identifier, name, baseConfig): return ConfigV2.new(identifier, name, baseConfig) def writeNewConfig(self, name): out = os.path.join(self.variantDir, "%s.json" % name) newConfigFile = open(out, "w") newConfigFile.write(self.newConfig.dumpContextData()) newConfigFile.close() return out def createDir(self, d): if not os.path.exists(d): logger.info("Creating: %s" % d) os.makedirs(d) else: logger.info("Exists: %s" % d) def setupDirPaths(self): self.imgDir = os.path.join(self.variantDir, "img") self.bootDir = os.path.join(self.imgDir, "boot") self.recoveryDir = os.path.join(self.imgDir, "recovery") self.fsDir = os.path.join(self.variantDir, InceptionConstants.FS_DIR) def createDirs(self): # self.createDir(self.variantDir) if os.path.exists(self.variantDir): if self.args["force"]: shutil.rmtree(self.variantDir) else: raise InceptionArgParserException("%s exists!!" % self.variantDir) self.createDir(self.variantDir) self.createDir(self.fsDir) def getAbsolutePathOf(self, f): return os.path.dirname(os.path.realpath(__file__)) + "/" + f def getConfigPath(self, configName): return os.path.join(self.configDir, configName + ".config") def unpackimg(self, img, out, unpacker, imgType): bootImgGenerator = imgtools.unpackimg(unpacker, img, out) self.newConfig.set("%s.img.cmdline" % imgType, bootImgGenerator.getKernelCmdLine(quote=False)) self.newConfig.set("%s.img.base" % imgType, bootImgGenerator.getBaseAddr()) self.newConfig.set("%s.img.ramdisk_offset" % imgType, bootImgGenerator.getRamdiskOffset()) self.newConfig.set("%s.img.second_offset" % imgType, bootImgGenerator.getSecondOffset()) self.newConfig.set("%s.img.tags_offset" % imgType, bootImgGenerator.getTagsOffset()) self.newConfig.set("%s.img.pagesize" % imgType, bootImgGenerator.getPageSize()) self.newConfig.set("%s.img.second_size" % imgType, bootImgGenerator.getSecondSize()) self.newConfig.set("%s.img.dt_size" % imgType, bootImgGenerator.getDeviceTreeSize()) self.newConfig.set("%s.img.kernel" % imgType, os.path.relpath(bootImgGenerator.getKernel(), self.variantDir)) self.newConfig.set("%s.img.ramdisk" % imgType, os.path.relpath(bootImgGenerator.getRamdisk(), self.variantDir)) self.newConfig.set("%s.img.dt" % imgType, os.path.relpath(bootImgGenerator.getDeviceTree(), self.variantDir)) fstab = Fstab.parseFstab(os.path.join(out, bootImgGenerator.getRamdisk(), "etc", "recovery.fstab")) processParts = ("boot", "system", "recovery", "cache") for p in processParts: fstabPart = fstab.getByMountPoint("/" + p) key = "__config__.target.mount.%s." % p if self.newConfig.get(key + "dev") != fstabPart.getDevice(): self.newConfig.set(key + "dev", fstabPart.getDevice()) if self.newConfig.get(key + "mount") != fstabPart.getMountPoint(): self.newConfig.set(key + "mount", fstabPart.getMountPoint()) if self.newConfig.get(key + "fs") != fstabPart.getType(): self.newConfig.set(key + "fs", fstabPart.getType())