From a134d7f88958fda0c64559f8b6fc05b9a8185b2c Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Sat, 30 Dec 2023 19:14:38 -0500 Subject: [PATCH] Remove oemunlockonboot module The module has been split out into another repo [1] so that it can be versioned separately. It now also supports Magisk's automatic update mechanism. Closes: #235 [1] https://github.com/chenxiaolong/OEMUnlockOnBoot Signed-off-by: Andrew Gunnerson --- .github/workflows/modules.yml | 35 ----- Cargo.lock | 60 -------- README.md | 28 +--- modules/common/update-binary | 33 ---- modules/common/updater-script | 1 - modules/oemunlockonboot/Main.java | 83 ---------- modules/oemunlockonboot/module.prop | 6 - modules/oemunlockonboot/service.sh | 20 --- xtask/Cargo.toml | 9 -- xtask/README.md | 13 +- xtask/src/main.rs | 5 +- xtask/src/module.rs | 231 ---------------------------- xtask/src/version.rs | 53 +------ 13 files changed, 5 insertions(+), 572 deletions(-) delete mode 100644 .github/workflows/modules.yml delete mode 100644 modules/common/update-binary delete mode 100644 modules/common/updater-script delete mode 100644 modules/oemunlockonboot/Main.java delete mode 100644 modules/oemunlockonboot/module.prop delete mode 100644 modules/oemunlockonboot/service.sh delete mode 100644 xtask/src/module.rs diff --git a/.github/workflows/modules.yml b/.github/workflows/modules.yml deleted file mode 100644 index 78a2a10..0000000 --- a/.github/workflows/modules.yml +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: Modules -on: - push: - branches: - - master - pull_request: -jobs: - build: - name: Build modules - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v3 - with: - # For git describe - fetch-depth: 0 - - - name: Get version - id: get_version - shell: bash - run: | - echo -n 'version=' >> "${GITHUB_OUTPUT}" - git describe --always \ - | sed -E "s/^v//g;s/([^-]*-g)/r\1/;s/-/./g" \ - >> "${GITHUB_OUTPUT}" - - - name: Build modules - run: cargo xtask modules -a - - - name: Archive artifacts - uses: actions/upload-artifact@v3 - with: - name: avbroot-modules-${{ steps.get_version.outputs.version }} - path: modules/dist/ diff --git a/Cargo.lock b/Cargo.lock index 4b9c612..b4e3b57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -728,12 +728,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "human-sort" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140a09c9305e6d5e557e2ed7cbc68e05765a7d4213975b87cb04920689cc6219" - [[package]] name = "ident_case" version = "1.0.1" @@ -1433,15 +1427,6 @@ dependencies = [ "cipher", ] -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scrypt" version = "0.11.0" @@ -1731,16 +1716,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1759,37 +1734,6 @@ dependencies = [ "rustix", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.48.0" @@ -1961,12 +1905,8 @@ version = "3.0.0" dependencies = [ "anyhow", "clap", - "human-sort", "regex", - "tempfile", "toml_edit", - "walkdir", - "zip", ] [[package]] diff --git a/README.md b/README.md index 5f907d9..8c910b8 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,7 @@ avbroot applies the following patches to the partition images: Repeat: **_ALWAYS leave `OEM unlocking` enabled if rooted._** -* Any operation that causes an improperly-signed boot image to be flashed will result in the device being unbootable and unrecoverable without unlocking the bootloader again (and thus, triggering a data wipe). This includes: - - * Performing a unpatched A/B OTA update while booted into Android via the OS' default updater. This can be blocked via a Magisk/KernelSU module (see: [Blocking A/B OTA Updates](#blocking-ab-ota-updates)). - - * The `Direct install` method for updating Magisk. Magisk updates **must** be done by repatching the OTA, not via the app. +* Any operation that causes an improperly-signed boot image to be flashed will result in the device being unbootable and unrecoverable without unlocking the bootloader again (and thus, triggering a data wipe). This includes the `Direct install` method for updating Magisk. Magisk updates **must** be done by repatching the OTA, not via the app. If the boot image is ever modified, **do not reboot**. [Open an issue](https://github.com/chenxiaolong/avbroot/issues/new) for support and be very clear about what steps were done that lead to the situation. If Android is still running and root access works, it might be possible to recover without wiping and starting over. @@ -184,12 +180,10 @@ If you lose your AVB or OTA signing key, you will no longer be able to sign new Remember: **Do not uncheck `OEM unlocking`!** - **WARNING**: If you are flashing CalyxOS, the setup wizard will [automatically turn off the `OEM unlocking` switch](https://github.com/CalyxOS/platform_packages_apps_SetupWizard/blob/7d2df25cedcbff83ddb608e628f9d97b38259c26/src/org/lineageos/setupwizard/SetupWizardApp.java#L135-L140). Make sure to manually reenable it again from Android's developer settings. Consider using [avbroot's `oemunlockonboot` Magisk module](#oemunlockonboot-enable-oem-unlocking-on-every-boot) to automatically ensure OEM unlocking is enabled on every boot. + **WARNING**: If you are flashing CalyxOS, the setup wizard will [automatically turn off the `OEM unlocking` switch](https://github.com/CalyxOS/platform_packages_apps_SetupWizard/blob/7d2df25cedcbff83ddb608e628f9d97b38259c26/src/org/lineageos/setupwizard/SetupWizardApp.java#L135-L140). Make sure to manually reenable it again from Android's developer settings. Consider using the [`OEMUnlockOnBoot` module](https://github.com/chenxiaolong/OEMUnlockOnBoot) to automatically ensure OEM unlocking is enabled on every boot. 8. That's it! To install future OS, Magisk, or KernelSU updates, see the [next section](#updates). - For extra safety, consider flashing [avbroot's Magisk/KernelSU modules](#avbroot-modules). - ## Updates Updates to Android, Magisk, and KernelSU are all done the same way by patching (or repatching) the OTA. @@ -251,16 +245,6 @@ To safely use Repair Mode: Because the unrooting and rooting are done by flashing OTAs, the device's data will not be wiped. -## avbroot modules - -avbroot's Magisk/KernelSU modules can be downloaded from the [releases page](https://github.com/chenxiaolong/avbroot/releases). - -### `oemunlockonboot`: Enable OEM unlocking on every boot - -To help reduce the risk of OEM unlocking being accidentally disabled (or intentionally disabled as part of some OS' initial setup wizard), this module will attempt to enable the OEM unlocking option on every boot. - -The logs for this module can be found at `/data/local/tmp/avbroot_oem_unlock.log`. - ## Magisk preinit device Magisk versions 25211 and newer require a writable partition for storing custom SELinux rules that need to be accessed during early boot stages. This can only be determined on a real device, so avbroot requires the partition to be explicitly specified via `--magisk-preinit-device `. To find the partition name: @@ -437,14 +421,6 @@ Debug builds work too, but they will run significantly slower (in the sha256 com By default, the executable links to the system's bzip2 and liblzma libraries, which are the only external libraries avbroot depends on. To compile and statically link these two libraries, pass in `--features static`. -To build avbroot's modules from source, run: - -```bash -cargo xtask modules -a -``` - -This requires Java and the Android SDK to be installed. The `ANDROID_HOME` environment variable must be set to the Android SDK path. - ## Verifying digital signatures First, save the public key to a file listing the keys to be trusted. This is the same key listed in [the author's profile](https://github.com/chenxiaolong/). diff --git a/modules/common/update-binary b/modules/common/update-binary deleted file mode 100644 index 28b48e5..0000000 --- a/modules/common/update-binary +++ /dev/null @@ -1,33 +0,0 @@ -#!/sbin/sh - -################# -# Initialization -################# - -umask 022 - -# echo before loading util_functions -ui_print() { echo "$1"; } - -require_new_magisk() { - ui_print "*******************************" - ui_print " Please install Magisk v20.4+! " - ui_print "*******************************" - exit 1 -} - -######################### -# Load util_functions.sh -######################### - -OUTFD=$2 -ZIPFILE=$3 - -mount /data 2>/dev/null - -[ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk -. /data/adb/magisk/util_functions.sh -[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk - -install_module -exit 0 diff --git a/modules/common/updater-script b/modules/common/updater-script deleted file mode 100644 index 11d5c96..0000000 --- a/modules/common/updater-script +++ /dev/null @@ -1 +0,0 @@ -#MAGISK diff --git a/modules/oemunlockonboot/Main.java b/modules/oemunlockonboot/Main.java deleted file mode 100644 index f066ce3..0000000 --- a/modules/oemunlockonboot/Main.java +++ /dev/null @@ -1,83 +0,0 @@ -import android.annotation.SuppressLint; -import android.os.IBinder; -import android.os.IInterface; -import android.os.Process; -import android.system.ErrnoException; - -import java.lang.reflect.Method; - -@SuppressLint({"DiscouragedPrivateApi", "PrivateApi", "SoonBlockedPrivateApi"}) -public class Main { - private static final int GET_SERVICE_ATTEMPTS = 30; - - @SuppressWarnings("SameParameterValue") - private static IInterface getService(Class interfaceClass, String serviceName) throws Exception { - Class serviceManager = Class.forName("android.os.ServiceManager"); - Method getService = serviceManager.getDeclaredMethod("getService", String.class); - - Class stub = Class.forName(interfaceClass.getCanonicalName() + "$Stub"); - Method asInterface = stub.getDeclaredMethod("asInterface", IBinder.class); - - // ServiceManager.waitForService() tries to start the service, which we want to avoid to be - // 100% sure we're not disrupting the boot flow. - for (int attempt = 1; attempt <= GET_SERVICE_ATTEMPTS; ++attempt) { - IBinder iBinder = (IBinder) getService.invoke(null, serviceName); - if (iBinder != null) { - return (IInterface) asInterface.invoke(null, iBinder); - } - - if (attempt < GET_SERVICE_ATTEMPTS) { - Thread.sleep(1000); - } - } - - throw new IllegalStateException( - "Service " + serviceName + " not found after " + GET_SERVICE_ATTEMPTS + " attempts"); - } - - @SuppressWarnings("ConstantConditions") - private static void unlock() throws Exception { - Class iOemLockService = Class.forName("android.service.oemlock.IOemLockService"); - IInterface iFace = getService(iOemLockService, "oem_lock"); - - Method setOemUnlockAllowedByUser = iOemLockService.getDeclaredMethod("setOemUnlockAllowedByUser", boolean.class); - Method isOemUnlockAllowedByUser = iOemLockService.getDeclaredMethod("isOemUnlockAllowedByUser"); - - Boolean unlockAllowed = (Boolean) isOemUnlockAllowedByUser.invoke(iFace); - if (unlockAllowed) { - System.out.println("OEM unlocking already enabled"); - return; - } - - System.out.println("Enabling OEM unlocking"); - setOemUnlockAllowedByUser.invoke(iFace, true); - } - - @SuppressWarnings({"ConstantConditions", "JavaReflectionMemberAccess"}) - private static void switchToSystemUid() throws Exception { - if (Process.myUid() != Process.SYSTEM_UID) { - Method setUid = Process.class.getDeclaredMethod("setUid", int.class); - int errno = (int) setUid.invoke(null, Process.SYSTEM_UID); - - if (errno != 0) { - throw new Exception("Failed to switch to SYSTEM (" + Process.SYSTEM_UID + ") user", - new ErrnoException("setuid", errno)); - } - if (Process.myUid() != Process.SYSTEM_UID) { - throw new IllegalStateException("UID didn't actually change: " + - Process.myUid() + " != " + Process.SYSTEM_UID); - } - } - } - - public static void main(String[] args) { - try { - switchToSystemUid(); - unlock(); - } catch (Exception e) { - System.err.println("Failed to enable OEM unlocking"); - e.printStackTrace(); - System.exit(1); - } - } -} diff --git a/modules/oemunlockonboot/module.prop b/modules/oemunlockonboot/module.prop deleted file mode 100644 index 951c13c..0000000 --- a/modules/oemunlockonboot/module.prop +++ /dev/null @@ -1,6 +0,0 @@ -id=com.chiller3.avbroot.oemunlockonboot -name=oemunlockonboot -version=v3.0.0 -versionCode=196608 -author=chenxiaolong -description=Enable OEM unlocking on every boot diff --git a/modules/oemunlockonboot/service.sh b/modules/oemunlockonboot/service.sh deleted file mode 100644 index 757f832..0000000 --- a/modules/oemunlockonboot/service.sh +++ /dev/null @@ -1,20 +0,0 @@ -exec >/data/local/tmp/avbroot_oem_unlock.log 2>&1 - -mod_dir=${0%/*} - -header() { - echo "----- ${*} -----" -} - -header Environment -echo "Timestamp: $(date)" -echo "Script: ${0}" -echo "UID/GID/Context: $(id)" - -header Enable OEM unlocking -CLASSPATH="${mod_dir}/classes.dex" app_process / Main & -pid=${!} -wait "${pid}" -echo "Exit status: ${?}" -echo "Logcat:" -logcat -d --pid "${pid}" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 37e9d93..64637e3 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -11,14 +11,5 @@ publish = false [dependencies] anyhow = "1.0.75" clap = { version = "4.4.1", features = ["derive"] } -human-sort = "0.2.2" regex = { version = "1.9.4", default-features = false, features = ["perf", "std"] } -tempfile = "3.8.0" toml_edit = "0.21.0" -walkdir = "2.3.3" - -# https://github.com/zip-rs/zip/pull/383 -[dependencies.zip] -git = "https://github.com/chenxiaolong/zip" -rev = "989101f9384b9e94e36e6e9e0f51908fdf98bde6" -default-features = false diff --git a/xtask/README.md b/xtask/README.md index 8c39eea..ee25659 100644 --- a/xtask/README.md +++ b/xtask/README.md @@ -8,7 +8,7 @@ To update the project version, run: cargo xtask set-version -V ``` -This will update the main [`Cargo.toml`](../Cargo.toml) and each module's `module.prop` file. +This will update the main [`Cargo.toml`](../Cargo.toml) file. ## Updating changelog links @@ -19,14 +19,3 @@ Then, run the following command to generate the appropriate link references: ```bash cargo xtask update-changelog ``` - -## Build modules - -To build avbroot's companion modules, run: - -```bash -cargo xtask modules -a -# or -m -m ... -``` - -See the main [`README.md`](../README.md#avbroot-magisk-modules) for more details. diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ede46d5..f0a0509 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -4,13 +4,12 @@ */ mod changelog; -mod module; mod version; use anyhow::Result; use clap::{Parser, Subcommand}; -use crate::{module::ModulesCli, version::SetVersionCli}; +use crate::version::SetVersionCli; const WORKSPACE_DIR: &str = env!("CARGO_WORKSPACE_DIR"); @@ -19,7 +18,6 @@ fn main() -> Result<()> { match cli.command { Command::SetVersion(c) => version::set_version_subcommand(&c), - Command::Modules(c) => module::modules_subcommand(&c), Command::UpdateChangelog => changelog::update_changelog_subcommand(), } } @@ -27,7 +25,6 @@ fn main() -> Result<()> { #[derive(Debug, Subcommand)] pub enum Command { SetVersion(SetVersionCli), - Modules(ModulesCli), /// Update links in CHANGELOG.md. UpdateChangelog, } diff --git a/xtask/src/module.rs b/xtask/src/module.rs deleted file mode 100644 index c9452a8..0000000 --- a/xtask/src/module.rs +++ /dev/null @@ -1,231 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Andrew Gunnerson - * SPDX-License-Identifier: GPL-3.0-only - */ - -use std::{ - collections::HashMap, - env, - ffi::OsStr, - fmt, - fs::{self, File}, - io::{self, BufWriter, Write}, - path::{Path, PathBuf}, - process::Command, -}; - -use anyhow::{anyhow, bail, Result}; -use clap::{Args, Parser, ValueEnum}; -use tempfile::TempDir; -use walkdir::WalkDir; -use zip::{write::FileOptions, ZipWriter}; - -use crate::WORKSPACE_DIR; - -#[cfg(unix)] -const D8: &str = "d8"; -#[cfg(windows)] -const D8: &str = "d8.bat"; - -fn newest_child_by_name(directory: &Path) -> Result { - let mut children = vec![]; - - for entry in fs::read_dir(directory)? { - let entry = entry?; - let path = entry - .path() - .into_os_string() - .into_string() - .map_err(|e| anyhow!("Non-UTF-8 path: {e:?}"))?; - - children.push(path); - } - - children.sort_by(|a, b| human_sort::compare(a, b)); - - children - .pop() - .map(PathBuf::from) - .ok_or_else(|| anyhow!("{directory:?} has no children")) -} - -fn build_dex(writer: &mut dyn Write, sources: &[&Path]) -> Result<()> { - let sdk = env::var_os("ANDROID_HOME") - .map(PathBuf::from) - .ok_or_else(|| anyhow!("ANDROID_HOME must be set to the Android SDK path"))?; - let build_tools = newest_child_by_name(&sdk.join("build-tools"))?; - let platform = newest_child_by_name(&sdk.join("platforms"))?; - let d8 = build_tools.join(D8); - let android_jar = platform.join("android.jar"); - - let temp_dir = TempDir::new()?; - - let mut process = Command::new("javac") - .args(["-source", "1.8"]) - .args(["-target", "1.8"]) - .arg("-cp") - .arg(android_jar) - .arg("-d") - .arg(temp_dir.path()) - .args(sources) - .spawn()?; - let status = process.wait()?; - if !status.success() { - bail!("javac failed with {status}"); - } - - let mut class_files = vec![]; - - for entry in WalkDir::new(temp_dir.path()) { - let entry = entry?; - - if entry.path().extension() == Some(OsStr::new("class")) { - class_files.push(entry.into_path()); - } - } - - let mut process = Command::new(d8) - .arg("--output") - .arg(temp_dir.path()) - .args(class_files) - .spawn()?; - let status = process.wait()?; - if !status.success() { - bail!("d8 failed with {status}"); - } - - let mut reader = File::open(temp_dir.path().join("classes.dex"))?; - io::copy(&mut reader, writer)?; - - Ok(()) -} - -fn parse_props(data: &str) -> Result> { - let mut result = HashMap::new(); - - for line in data.split('\n') { - if line.is_empty() { - continue; - } - - let Some((k, v)) = line.split_once('=') else { - bail!("Malformed line: {line:?}"); - }; - - result.insert(k.trim().to_owned(), v.trim().to_owned()); - } - - Ok(result) -} - -fn start_module( - dist_dir: &Path, - common_dir: &Path, - module_dir: &Path, -) -> Result<(PathBuf, ZipWriter>)> { - let module_prop_raw = fs::read_to_string(module_dir.join("module.prop"))?; - let module_prop = parse_props(&module_prop_raw)?; - - let name = module_prop["name"].as_str(); - let version = module_prop["version"].as_str(); - let version = version.strip_prefix('v').unwrap_or(version); - let zip_path = dist_dir.join(format!("{name}-{version}.zip")); - - let raw_writer = File::create(&zip_path)?; - let mut zip_writer = ZipWriter::new(BufWriter::new(raw_writer)); - - zip_writer.start_file( - "META-INF/com/google/android/update-binary", - FileOptions::default(), - )?; - io::copy( - &mut File::open(common_dir.join("update-binary"))?, - &mut zip_writer, - )?; - - zip_writer.start_file( - "META-INF/com/google/android/updater-script", - FileOptions::default(), - )?; - io::copy( - &mut File::open(common_dir.join("updater-script"))?, - &mut zip_writer, - )?; - - zip_writer.start_file("module.prop", FileOptions::default())?; - zip_writer.write_all(module_prop_raw.as_bytes())?; - - Ok((zip_path, zip_writer)) -} - -pub fn modules_subcommand(cli: &ModulesCli) -> Result<()> { - let modules_dir = Path::new(WORKSPACE_DIR).join("modules"); - let common_dir = modules_dir.join("common"); - let dist_dir = modules_dir.join("dist"); - - fs::create_dir_all(&dist_dir)?; - - let modules = if cli.module.all { - Module::value_variants() - } else { - &cli.module.module - }; - - for module in modules { - let module_dir = modules_dir.join(module.to_string()); - - let (path, mut writer) = start_module(&dist_dir, &common_dir, &module_dir)?; - - match module { - Module::OemUnlockOnBoot => { - writer.start_file("classes.dex", FileOptions::default())?; - build_dex(&mut writer, &[&module_dir.join("Main.java")])?; - - writer.start_file("service.sh", FileOptions::default())?; - let mut reader = File::open(module_dir.join("service.sh"))?; - io::copy(&mut reader, &mut writer)?; - } - } - - writer.finish()?; - - let path = path.canonicalize()?; - println!("Built module: {path:?}"); - } - - Ok(()) -} - -#[derive(Clone, Copy, Debug, ValueEnum)] -#[value(rename_all = "lower")] -enum Module { - OemUnlockOnBoot, -} - -impl fmt::Display for Module { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.to_possible_value() - .expect("no values are skipped") - .get_name() - .fmt(f) - } -} - -#[derive(Debug, Args)] -#[group(required = true, multiple = false)] -pub struct ModuleGroup { - /// Name of module. - #[arg(short, long)] - module: Vec, - - /// Build all modules. - #[arg(short, long, conflicts_with = "module")] - all: bool, -} - -/// Build companion modules. -#[derive(Debug, Parser)] -pub struct ModulesCli { - #[command(flatten)] - module: ModuleGroup, -} diff --git a/xtask/src/version.rs b/xtask/src/version.rs index 9921056..6fa30f7 100644 --- a/xtask/src/version.rs +++ b/xtask/src/version.rs @@ -27,43 +27,6 @@ fn update_cargo_version(version: &str) -> Result<()> { Ok(()) } -fn update_module_version(path: &Path, version: &str) -> Result<()> { - let mut version_code = 0; - - // 8 bits per version component. - for piece in version.split('.') { - let piece: u32 = piece.parse()?; - version_code <<= 8; - version_code |= piece; - } - - let raw_reader = File::open(path)?; - let mut reader = BufReader::new(raw_reader); - let mut result = String::new(); - let mut line = String::new(); - - loop { - line.clear(); - - let n = reader.read_line(&mut line)?; - if n == 0 { - break; - } - - if line.starts_with("version=") { - result.push_str(&format!("version=v{version}\n")); - } else if line.starts_with("versionCode=") { - result.push_str(&format!("versionCode={version_code}\n")); - } else { - result.push_str(&line); - } - } - - fs::write(path, &result)?; - - Ok(()) -} - fn update_changelog_version(version: &str) -> Result<()> { let path = Path::new(WORKSPACE_DIR).join("CHANGELOG.md"); let raw_reader = File::open(&path)?; @@ -109,26 +72,12 @@ fn update_changelog_version(version: &str) -> Result<()> { pub fn set_version_subcommand(cli: &SetVersionCli) -> Result<()> { update_cargo_version(&cli.version)?; - - let modules_dir = Path::new(WORKSPACE_DIR).join("modules"); - - for entry in fs::read_dir(modules_dir)? { - let entry = entry?; - - if entry.file_type()?.is_dir() { - let module_prop = entry.path().join("module.prop"); - if module_prop.exists() { - update_module_version(&module_prop, &cli.version)?; - } - } - } - update_changelog_version(&cli.version)?; Ok(()) } -/// Set the version number in all Cargo.toml files and in the module metadata. +/// Set the version number in all Cargo.toml files. #[derive(Debug, Parser)] pub struct SetVersionCli { /// Version number.