Skip to content

Commit

Permalink
Don't fail on invalid release tag.
Browse files Browse the repository at this point in the history
Reintroduce `get_dev_suffix`.
  • Loading branch information
Serock3 committed May 13, 2024
1 parent e452385 commit e218bf4
Showing 1 changed file with 32 additions and 39 deletions.
71 changes: 32 additions & 39 deletions mullvad-version/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ impl Target {
}

fn main() {
let product_version = compute_product_version(Target::current_target());
let android_product_version = compute_product_version(Target::Android);
let product_version = get_product_version(Target::current_target());
let android_product_version = get_product_version(Target::Android);

let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
fs::write(out_dir.join("product-version.txt"), product_version).unwrap();
Expand All @@ -47,64 +47,61 @@ fn main() {
/// Computes the Mullvad product version using the latest release on the given platform and the git
/// hash pointed to by `HEAD`. Also triggers a rebuild of this crate when the information becomes
/// outdated.
fn compute_product_version(target: Target) -> String {
fn get_product_version(target: Target) -> String {
let version_file_path = match target {
Target::Android => ANDROID_VERSION_FILE_PATH,
Target::Desktop => DESKTOP_VERSION_FILE_PATH,
};
println!("cargo:rerun-if-changed={version_file_path}");
let product_version = fs::read_to_string(version_file_path)

let release_version = fs::read_to_string(version_file_path)
.unwrap_or_else(|_| panic!("Failed to read {version_file_path}"))
.trim()
.to_owned();

// Compute the expected tag name for the release named `product_version`
let release_tag = match target {
Target::Android => format!("android/{product_version}"),
Target::Desktop => product_version.to_owned(),
Target::Android => format!("android/{release_version}"),
Target::Desktop => release_version.to_owned(),
};

format!("{release_version}{}", get_suffix(&release_tag))
}

/// Returns the suffix for the current build. If the build is done on a git tag named
/// `product_version`, the suffix is empty. Otherwise, `-dev-$hash` is appended to the
/// release version, or `-dev-unknown` when a git hash cannot be found.
fn get_suffix(release_tag: &str) -> String {
if !valid_git_repo() {
return "-dev-unknown".to_owned();
};
// Rerun this build script on changes to the git ref that affects the build version.
// NOTE: This must be kept up to date with the behavior of `git_rev_parse_commit_hash`.
// If an error is returned, we are not in a repository and a proper release version cannot be
// built.
if let Err(()) = rerun_if_git_ref_changed(&release_tag) {
return format!("{release_tag}-dev-local");
};

// Get the git commit hashes for the latest release and current HEAD
let head_commit_hash = git_rev_parse_commit_hash("HEAD");
let product_version_commit_hash = git_rev_parse_commit_hash(&release_tag);
rerun_if_git_ref_changed(release_tag);
let head_commit_hash =
git_rev_parse_commit_hash("HEAD").expect("Failed to run `git rev-parse HEAD^{{commit}}`");
let product_version_commit_hash = git_rev_parse_commit_hash(release_tag);

// If we are currently building the release tag, there is no dev suffix
if head_commit_hash == product_version_commit_hash {
product_version
if Some(&head_commit_hash) == product_version_commit_hash.as_ref() {
String::new()
} else {
format!(
"{release_tag}-dev-{}",
&head_commit_hash[..GIT_HASH_DEV_SUFFIX_LEN]
)
format!("-dev-{}", &head_commit_hash[..GIT_HASH_DEV_SUFFIX_LEN])
}
}

fn valid_git_repo() -> bool {
matches!(Command::new("git").arg("status").status(), Ok(status) if status.success())
}

/// Trigger rebuild of `mullvad-version` on changing branch (`.git/HEAD`), on changes to the ref of
/// the current branch (`.git/refs/heads/$current_branch`) and on changes to the ref of the current
/// release tag (`.git/refs/tags/$current_release_tag`).
///
/// Returns an error if not in a git repository, or the git binary is not in `PATH`.
fn rerun_if_git_ref_changed(release_tag: &str) -> Result<(), ()> {
fn rerun_if_git_ref_changed(release_tag: &str) {
let git_dir = Path::new("..").join(".git");

if !git_dir.exists() {
return Err(());
}

// Check that `git` can be executed
match Command::new("git").arg("--version").status() {
Ok(status) if status.success() => {}
_ => return Err(()),
};

// The `.git/HEAD` file contains the position of the current head. If in 'detached HEAD' state,
// this will be the ref of the current commit. If on a branch it will just point to it, e.g.
// `ref: refs/heads/main`. Tracking changes to this file will tell us if we change branch, or
Expand Down Expand Up @@ -150,21 +147,17 @@ fn rerun_if_git_ref_changed(release_tag: &str) -> Result<(), ()> {
// track this file, however, as any changes to the current branch, 'detached HEAD' state
// or tags will update the corresponding `.git/refs` file we are tracking, even if it had
// previously been pruned.

Ok(())
}

/// Returns the commit hash for the commit that `git_ref` is pointing to.
fn git_rev_parse_commit_hash(git_ref: &str) -> String {
fn git_rev_parse_commit_hash(git_ref: &str) -> Option<String> {
let output = Command::new("git")
.arg("rev-parse")
.arg(format!("{git_ref}^{{commit}}"))
.output()
.expect("Failed to run `git rev-parse`");
let stdout = String::from_utf8(output.stdout).unwrap();
if !output.status.success() {
let stderr = String::from_utf8(output.stderr).unwrap();
panic!("Command `git rev-parse` failed:\nstdout: {stdout}\nstderr: {stderr}");
return None;
}
stdout.trim().to_owned()
Some(String::from_utf8(output.stdout).unwrap().trim().to_owned())
}

0 comments on commit e218bf4

Please sign in to comment.