Skip to content

Commit e5b8282

Browse files
committed
Enforce that base must be a commit ID in patchable.toml
1 parent 3baa3e8 commit e5b8282

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

rust/patchable/src/main.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::{
1111
path::{Path, PathBuf},
1212
};
1313

14-
use git2::Repository;
14+
use git2::{Oid, Repository};
1515
use serde::{Deserialize, Serialize};
1616
use snafu::{OptionExt, ResultExt as _, Snafu};
1717
use tracing_subscriber::{layer::SubscriberExt as _, util::SubscriberInitExt as _};
@@ -30,7 +30,8 @@ struct ProductVersion {
3030
#[derive(Deserialize, Serialize)]
3131
struct ProductVersionConfig {
3232
upstream: String,
33-
base: String,
33+
#[serde(with = "utils::oid_serde")]
34+
base: Oid,
3435
}
3536

3637
struct ProductVersionContext<'a> {
@@ -244,9 +245,12 @@ fn main() -> Result<()> {
244245
.in_scope(|| repo::ensure_bare_repo(&product_repo_root))
245246
.context(OpenProductRepoForCheckoutSnafu)?;
246247

247-
let base_commit =
248-
repo::resolve_commitish_or_fetch(&product_repo, &config.base, &config.upstream)
249-
.context(FetchBaseCommitSnafu)?;
248+
let base_commit = repo::resolve_commitish_or_fetch(
249+
&product_repo,
250+
&config.base.to_string(),
251+
&config.upstream,
252+
)
253+
.context(FetchBaseCommitSnafu)?;
250254
let patched_commit = patch::apply_patches(&product_repo, &ctx.patch_dir(), base_commit)
251255
.context(ApplyPatchesSnafu)?;
252256

@@ -283,14 +287,7 @@ fn main() -> Result<()> {
283287
path: product_worktree_root,
284288
})?;
285289

286-
let base_commit = product_version_repo
287-
.revparse_single(&config.base)
288-
.and_then(|c| c.peel_to_commit())
289-
.context(FindBaseCommitSnafu {
290-
repo: &product_version_repo,
291-
commit: config.base,
292-
})?
293-
.id();
290+
let base_commit = config.base;
294291
let original_leaf_commit = product_version_repo
295292
.head()
296293
.and_then(|c| c.peel_to_commit())
@@ -341,14 +338,17 @@ fn main() -> Result<()> {
341338
.in_scope(|| repo::ensure_bare_repo(&product_repo_root))
342339
.context(OpenProductRepoForCheckoutSnafu)?;
343340

341+
// --base can be a reference, but patchable.toml should always have a resolved commit id,
342+
// so that it cannot be changed under our feet (without us knowing so, anyway...).
344343
tracing::info!(?base, "resolving base commit-ish");
345344
let base_commit = repo::resolve_commitish_or_fetch(&product_repo, &base, &upstream)
346345
.context(FetchBaseCommitSnafu)?;
347346
tracing::info!(?base, base.commit = ?base_commit, "resolved base commit");
348347

348+
tracing::info!("saving configuration");
349349
let config = ProductVersionConfig {
350350
upstream,
351-
base: base.to_string(),
351+
base: base_commit,
352352
};
353353
let config_path = ctx.config_path();
354354
if let Some(config_dir) = config_path.parent() {
@@ -358,7 +358,14 @@ fn main() -> Result<()> {
358358
let config_toml = toml::to_string_pretty(&config).context(SerializeConfigSnafu)?;
359359
File::create_new(&config_path)
360360
.and_then(|mut f| f.write_all(config_toml.as_bytes()))
361-
.context(SaveConfigSnafu { path: config_path })?;
361+
.context(SaveConfigSnafu { path: &config_path })?;
362+
363+
tracing::info!(
364+
config.path = ?config_path,
365+
product = ctx.pv.product,
366+
version = ctx.pv.version,
367+
"created configuration for product version"
368+
);
362369
}
363370
}
364371

rust/patchable/src/utils.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,19 @@ pub fn raw_git_cmd(repo: &Repository) -> std::process::Command {
1414
);
1515
cmd
1616
}
17+
18+
/// Implements (equivalents of) the [`serde`] traits over [`git2::Oid`].
19+
///
20+
/// For use with `#[serde(with = ...)]`.
21+
pub mod oid_serde {
22+
use git2::Oid;
23+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
24+
25+
pub fn serialize<S: Serializer>(value: &Oid, ser: S) -> Result<S::Ok, S::Error> {
26+
value.to_string().serialize(ser)
27+
}
28+
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Oid, D::Error> {
29+
String::deserialize(de)
30+
.and_then(|oid| Oid::from_str(&oid).map_err(<D::Error as serde::de::Error>::custom))
31+
}
32+
}

0 commit comments

Comments
 (0)