Beispiel #1
0
    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
Beispiel #2
0
    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 make(self, workDir, outDir):
        recoveryImg = self.getMakeProperty("img")

        with self.newTmpWorkDir() as recoveryExtractDir:
            with self.newTmpWorkDir() as recoveryRamdiskDir:
                workRamdiskDir = os.path.join(recoveryRamdiskDir, "ramdisk")
                if type(recoveryImg.getValue()) is str:
                    _, unpacker = self.getHostBinary("unpackbootimg")
                    bootImgGenerator = imgtools.unpackimg(
                        unpacker, recoveryImg.resolveAsRelativePath(), recoveryExtractDir
                    )
                    shutil.copytree(
                        os.path.join(recoveryExtractDir, bootImgGenerator.getRamdisk()), workRamdiskDir, symlinks=True
                    )

                    imgType = "recovery"
                    self.setValue("recovery.img", {})
                    self.setValue("%s.img.cmdline" % imgType, bootImgGenerator.getKernelCmdLine(quote=False))
                    self.setValue("%s.img.base" % imgType, bootImgGenerator.getBaseAddr())
                    self.setValue("%s.img.ramdisk_offset" % imgType, bootImgGenerator.getRamdiskOffset())
                    self.setValue("%s.img.second_offset" % imgType, bootImgGenerator.getSecondOffset())
                    self.setValue("%s.img.tags_offset" % imgType, bootImgGenerator.getTagsOffset())
                    self.setValue("%s.img.pagesize" % imgType, bootImgGenerator.getPageSize())
                    self.setValue("%s.img.second_size" % imgType, bootImgGenerator.getSecondSize())
                    self.setValue("%s.img.dt_size" % imgType, bootImgGenerator.getDeviceTreeSize())
                    self.setValue("%s.img.kernel" % imgType, bootImgGenerator.getKernel())
                    self.setValue("%s.img.dt" % imgType, bootImgGenerator.getDeviceTree())
                else:
                    shutil.copytree(
                        self.getMakeProperty("img.ramdisk").resolveAsRelativePath(), workRamdiskDir, symlinks=True
                    )

                self.setValue("recovery.img.ramdisk", workRamdiskDir)
                if self.getMakeValue("inject_keys", True):
                    if not self.injectKeys(workRamdiskDir):
                        logger.warning("key already exists in %s, not injecting" % self.__class__.PATH_KEYS)
                    else:
                        logger.debug("injected key in %s" % self.__class__.PATH_KEYS)

                self.injectBusyBox(workRamdiskDir)

                fstabPath = os.path.join(workRamdiskDir, "etc", "fstab")
                fstab = Fstab.parseFstab(os.path.join(workRamdiskDir, "etc", "recovery.fstab"))

                diffMounts = ConfigSyncer.diffMounts(self.getConfig(), fstab)
                for k, v in diffMounts.items():
                    self.getConfig().setRecursive(k, v)

                if not os.path.exists(fstabPath):
                    self.injectFstab(fstab, workRamdiskDir)

                result = super(RecoveryImageMaker, self).make(workDir, outDir)
                self.setValue("recovery.img", recoveryImg.getValue())
                return result
    def make(self, workDir, outDir):
        recoveryImg = self.getMakeProperty("img")

        with self.newTmpWorkDir() as recoveryExtractDir:
            with self.newTmpWorkDir() as recoveryRamdiskDir:
                workRamdiskDir = os.path.join(recoveryRamdiskDir, "ramdisk")
                if type(recoveryImg.getValue()) is str:
                    _, unpacker = self.getHostBinary("unpackbootimg")
                    bootImgGenerator = imgtools.unpackimg(unpacker, recoveryImg.resolveAsRelativePath(), recoveryExtractDir)
                    shutil.copytree(os.path.join(recoveryExtractDir, bootImgGenerator.getRamdisk()), workRamdiskDir, symlinks=True)

                    imgType = "recovery"
                    self.setValue("recovery.img", {})
                    self.setValue("%s.img.cmdline" % imgType, bootImgGenerator.getKernelCmdLine(quote=False))
                    self.setValue("%s.img.base" % imgType, bootImgGenerator.getBaseAddr())
                    self.setValue("%s.img.ramdisk_offset" % imgType, bootImgGenerator.getRamdiskOffset())
                    self.setValue("%s.img.second_offset" % imgType, bootImgGenerator.getSecondOffset())
                    self.setValue("%s.img.tags_offset" % imgType, bootImgGenerator.getTagsOffset())
                    self.setValue("%s.img.pagesize" % imgType, bootImgGenerator.getPageSize())
                    self.setValue("%s.img.second_size" % imgType, bootImgGenerator.getSecondSize())
                    self.setValue("%s.img.dt_size" % imgType, bootImgGenerator.getDeviceTreeSize())
                    self.setValue("%s.img.kernel" % imgType, bootImgGenerator.getKernel())
                    self.setValue("%s.img.dt" % imgType, bootImgGenerator.getDeviceTree())
                else:
                    shutil.copytree(self.getMakeProperty("img.ramdisk").resolveAsRelativePath(), workRamdiskDir, symlinks=True)

                self.setValue("recovery.img.ramdisk", workRamdiskDir)
                if self.getMakeValue("inject_keys", True):
                    if not self.injectKeys(workRamdiskDir):
                        logger.warning("key already exists in %s, not injecting" % self.__class__.PATH_KEYS)
                    else:
                        logger.debug("injected key in %s" % self.__class__.PATH_KEYS)

                self.injectBusyBox(workRamdiskDir)


                fstabPath = os.path.join(workRamdiskDir, "etc", "fstab")
                fstab = Fstab.parseFstab(os.path.join(workRamdiskDir, "etc", "recovery.fstab"))

                diffMounts = ConfigSyncer.diffMounts(self.getConfig(), fstab)
                for k, v in diffMounts.items():
                    self.getConfig().setRecursive(k, v)

                if not os.path.exists(fstabPath):
                    self.injectFstab(fstab, workRamdiskDir)

                result = super(RecoveryImageMaker, self).make(workDir, outDir)
                self.setValue("recovery.img", recoveryImg.getValue())
                return result
Beispiel #5
0
    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
Beispiel #6
0
 def learnPartitions(self):
     syncer = ConfigSyncer(self.config)
     return syncer.syncPartitions()
Beispiel #7
0
 def learnSettings(self):
     syncer = ConfigSyncer(self.config)
     diff = syncer.pullAndDiff()
     return diff
Beispiel #8
0
 def learnProps(self):
     syncer = ConfigSyncer(self.config)
     return syncer.syncProps()
Beispiel #9
0
 def learnPartitions(self):
     syncer = ConfigSyncer(self.config)
     return syncer.syncPartitions()
Beispiel #10
0
 def learnSettings(self):
     syncer = ConfigSyncer(self.config)
     diff = syncer.pullAndDiff()
     return diff
Beispiel #11
0
 def learnProps(self):
     syncer = ConfigSyncer(self.config)
     return syncer.syncProps()
Beispiel #12
0
    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
Beispiel #13
0
    def make(self, workDir, outDir):
        recoveryImg = self.getMakeProperty("img")
        preprocessed = self.getMakeValue("preprocessed", False)

        with self.newTmpWorkDir() as recoveryExtractDir:
            with self.newTmpWorkDir() as recoveryRamdiskDir:
                workRamdiskDir = os.path.join(recoveryRamdiskDir, "ramdisk")
                if type(recoveryImg.getValue()) is str:
                    if preprocessed:
                        return super(RecoveryImageMaker,
                                     self).make(workDir, outDir)

                    unpackerName = self.getMakeValue("unpacker",
                                                     "unpackbootimg")
                    assert unpackerName in ("unpackbootimg", "unmkbootimg")
                    _, unpacker = self.getHostBinary(unpackerName)
                    bootImgGenerator = imgtools.unpackimg(
                        unpacker,
                        recoveryImg.resolveAsRelativePath(),
                        recoveryExtractDir,
                        mode=imgtools.MODE_UNMKBOOTIMG if unpackerName
                        == "unmkbootimg" else imgtools.MODE_UNPACKBOOTIMG)
                    shutil.copytree(os.path.join(
                        recoveryExtractDir, bootImgGenerator.getRamdisk()),
                                    workRamdiskDir,
                                    symlinks=True)

                    imgType = "recovery"
                    self.setValue("recovery.img", {})
                    self.setValue(
                        "%s.img.cmdline" % imgType,
                        bootImgGenerator.getKernelCmdLine(quote=False))
                    self.setValue("%s.img.base" % imgType,
                                  bootImgGenerator.getBaseAddr())
                    self.setValue("%s.img.ramdisk_offset" % imgType,
                                  bootImgGenerator.getRamdiskOffset())
                    self.setValue("%s.img.second_offset" % imgType,
                                  bootImgGenerator.getSecondOffset())
                    self.setValue("%s.img.tags_offset" % imgType,
                                  bootImgGenerator.getTagsOffset())
                    self.setValue("%s.img.pagesize" % imgType,
                                  bootImgGenerator.getPageSize())
                    self.setValue("%s.img.second_size" % imgType,
                                  bootImgGenerator.getSecondSize())
                    self.setValue("%s.img.dt_size" % imgType,
                                  bootImgGenerator.getDeviceTreeSize())
                    self.setValue("%s.img.kernel" % imgType,
                                  bootImgGenerator.getKernel())
                    self.setValue("%s.img.dt" % imgType,
                                  bootImgGenerator.getDeviceTree())
                    self.setValue("%s.img.kernel_offset" % imgType,
                                  bootImgGenerator.getKernelOffset())
                else:
                    shutil.copytree(self.getMakeProperty(
                        "img.ramdisk").resolveAsRelativePath(),
                                    workRamdiskDir,
                                    symlinks=True)

                self.setValue("recovery.img.ramdisk", workRamdiskDir)
                if not preprocessed:
                    if self.getMakeValue("inject_keys", True):
                        if not self.injectKeys(workRamdiskDir):
                            logger.warning(
                                "key already exists in %s, not injecting" %
                                self.__class__.PATH_KEYS)
                        else:
                            logger.debug("injected key in %s" %
                                         self.__class__.PATH_KEYS)

                    self.injectBusyBox(workRamdiskDir)
                    self.readProps(workRamdiskDir)
                    self.overrideDmVerityHash(workRamdiskDir)

                    fstabPath = os.path.join(workRamdiskDir, "etc", "fstab")
                    fstab = None

                    for fstabname in RecoveryImageMaker.FSTABS:
                        fstabpathcheck = os.path.join(workRamdiskDir, "etc",
                                                      fstabname)
                        if os.path.exists(fstabpathcheck):
                            fstab = Fstab.parseFstab(fstabpathcheck)
                            break

                    if fstab is None:
                        raise ValueError("Couldn't parse any of /etc/{%s}" %
                                         (",".join(RecoveryImageMaker.FSTABS)))

                    diffMounts = ConfigSyncer.diffMounts(
                        self.getConfig(), fstab)
                    for k, v in diffMounts.items():
                        self.getConfig().setRecursive(k, v)

                    if not os.path.exists(fstabPath) and self.getMakeValue(
                            "inject_fstab", True):
                        self.injectFstab(fstab, workRamdiskDir)

                    result = super(RecoveryImageMaker,
                                   self).make(workDir, outDir)
                    self.setValue("recovery.img", recoveryImg.getValue())
                return result
Beispiel #14
0
    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
Beispiel #15
0
    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