diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c6b531548..15c49d64b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -20,12 +20,12 @@ android { applicationId = "com.topjohnwu.magisk" vectorDrawables.useSupportLibrary = true multiDexEnabled = true - versionName = Config["appVersion"] - versionCode = Config["appVersionCode"]?.toInt() - buildConfigField("int", "LATEST_MAGISK", Config["versionCode"] ?: "Integer.MAX_VALUE") + versionName = Config.appVersion + versionCode = Config.appVersionCode + buildConfigField("int", "LATEST_MAGISK", Config.magiskVersionCode.toString()) javaCompileOptions.annotationProcessorOptions.arguments( - mapOf("room.incremental" to "true") + mapOf("room.incremental" to "true") ) } diff --git a/build.py b/build.py index 6bbae2e1d..da9ae912d 100755 --- a/build.py +++ b/build.py @@ -116,6 +116,10 @@ def system(cmd): return subprocess.run(cmd, shell=True, stdout=STDOUT) +def cmd_out(cmd): + return subprocess.check_output(cmd).strip().decode('utf-8') + + def xz(data): return lzma.compress(data, preset=9, check=lzma.CHECK_NONE) @@ -129,37 +133,39 @@ def parse_props(file): prop = line.split('=') if len(prop) != 2: continue - props[prop[0].strip(' \t\r\n')] = prop[1].strip(' \t\r\n') + value = prop[1].strip(' \t\r\n') + if len(value) == 0: + continue + props[prop[0].strip(' \t\r\n')] = value return props def load_config(args): - # Load prop file - if not op.exists(args.config): - error(f'Please make sure {args.config} exists') + commit_hash = cmd_out(['git', 'rev-parse', '--short=8', 'refs/heads/master']) + commit_count = cmd_out(['git', 'rev-list', '--count', 'refs/heads/master']) # Some default values + config['version'] = commit_hash + config['versionCode'] = 2147483647 + config['appVersion'] = commit_hash + config['appVersionCode'] = commit_count config['outdir'] = 'out' config['prettyName'] = 'false' config['keyStore'] = 'release-key.jks' - config.update(parse_props(args.config)) + # Load prop file + if op.exists(args.config): + config.update(parse_props(args.config)) # Sanitize configs config['prettyName'] = config['prettyName'].lower() == 'true' - if 'version' not in config or 'versionCode' not in config: - error('Config error: "version" and "versionCode" is required') - try: config['versionCode'] = int(config['versionCode']) except ValueError: error('Config error: "versionCode" is required to be an integer') - if args.release and not op.exists(config['keyStore']): - error(f'Config error: assign "keyStore" to a java keystore') - mkdir_p(config['outdir']) global STDOUT STDOUT = None if args.verbose else subprocess.DEVNULL @@ -295,10 +301,15 @@ def build_binary(args): header('* Building binaries: ' + ' '.join(args.target)) - config_stat = os.stat(args.config) + update_flags = True flags = op.join('native', 'jni', 'include', 'flags.hpp') - if config_stat.st_mtime_ns > os.stat(flags).st_mtime_ns: - os.utime(flags, ns=(config_stat.st_atime_ns, config_stat.st_mtime_ns)) + + if op.exists(args.config): + config_stat = os.stat(args.config) + update_flags = config_stat.st_mtime_ns > os.stat(flags).st_mtime_ns + + if update_flags: + os.utime(flags) # Basic flags global base_flags @@ -567,7 +578,7 @@ parser.add_argument('-r', '--release', action='store_true', parser.add_argument('-v', '--verbose', action='store_true', help='verbose output') parser.add_argument('-c', '--config', default='config.prop', - help='override config file (default: config.prop)') + help='set config file (default: config.prop)') subparsers = parser.add_subparsers(title='actions') all_parser = subparsers.add_parser( diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 60da16e4f..4b90bc638 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -13,3 +13,7 @@ gradlePlugin { } } } + +dependencies { + implementation("org.eclipse.jgit:org.eclipse.jgit:5.10.0.202012080955-r") +} diff --git a/buildSrc/src/main/java/BuildSource.kt b/buildSrc/src/main/java/BuildSource.kt index 58c8d84e4..30841ef11 100644 --- a/buildSrc/src/main/java/BuildSource.kt +++ b/buildSrc/src/main/java/BuildSource.kt @@ -1,5 +1,6 @@ -import org.gradle.api.GradleException +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.internal.storage.file.FileRepository import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.provideDelegate @@ -7,19 +8,33 @@ import java.io.File import java.util.* private val props = Properties() +private lateinit var commitHash: String +private var commitCount = 0 object Config { - operator fun get(key: String) = props[key] as? String - fun contains(key: String) = props.containsKey(key) + operator fun get(key: String) : String? { + val v = props[key] as? String ?: return null + return if (v.isBlank()) null else v + } + fun contains(key: String) = get(key) != null + + val appVersion: String get() = get("appVersion") ?: commitHash + val appVersionCode: Int get() = get("appVersionCode")?.toInt() ?: commitCount + val magiskVersionCode: Int get() = get("versionCode")?.toInt() ?: Int.MAX_VALUE } class MagiskPlugin : Plugin { override fun apply(project: Project) { val configPath: String? by project - val file = configPath?.let { File(it) } ?: project.file("config.prop") - if (!file.exists()) - throw GradleException("Please setup config.prop") + val config = configPath?.let { File(it) } ?: project.file("config.prop") + if (config.exists()) + config.inputStream().use { props.load(it) } - file.inputStream().use { props.load(it) } + if (!Config.contains("appVersion") || !Config.contains("appVersionCode")) { + val repo = FileRepository(project.rootProject.file(".git")) + val refId = repo.refDatabase.exactRef("refs/heads/master").objectId + commitHash = repo.newObjectReader().abbreviate(refId, 8).name() + commitCount = Git(repo).log().add(refId).call().count() + } } } diff --git a/config.prop.sample b/config.prop.sample index 261e3f750..d8ff85686 100644 --- a/config.prop.sample +++ b/config.prop.sample @@ -1,3 +1,8 @@ +########################################################## +# All variables in config.prop are optional +# Removing or leaving them blank will keep default values +########################################################## + # The version name and version code of Magisk version= versionCode= @@ -6,16 +11,28 @@ versionCode= appVersion= appVersionCode= -outdir=out +# Output path +outdir= -# Whether use pretty names for zips, e.g. Magisk-v${version}.zip, Magisk-uninstaller-${date}.zip -# The default output names are magisk-${release/debug/uninstaller}.zip -prettyName=false +################################################################ +# Whether to use pretty names for zips +# e.g. Magisk-v${version}.zip, Magisk-uninstaller-${date}.zip +# Default names are magisk-${release/debug/uninstaller}.zip +################################################################ -# Only used when building with release flag -# These passwords are used along with keyStore to sign APKs and zips -# keyPass is the pwd for the specified keyAlias -keyStore=release-key.jks +# The value is either true or false +prettyName= + +##################################################### +# Signing configs for signing zips and APKs +# These 4 variables has to be either all set or not +##################################################### + +# Path to keystore file +keyStore= +# Keystore password keyStorePass= +# The desired key alias in the keystore keyAlias= +# Password of specified key alias keyPass=