Skip to content

Commit d408ac1

Browse files
niwismicprog
authored andcommitted
git-checkout: Support branchless commits
When creating a database from a git repository, bender currently fetches all branches and tags from the remote before checking out the specified reference. However, it is possible that a commit does not belong to a branch or a tag. For instance, GitHub creates PR merge commits and stores their references in `refs/pull`. To checkout such a branchless commit, it must first be fetched explicitly. Therefore, when creating the database, explicitly fetch the specified reference in addition to all branches and tags (those are still needed e.g. for `bender update`). An open corner case is when `Bender.lock` is updated with a branchless commit hash after creating the database, but the manifest is not. This will skip fetching altogether and the database might not contain the desired branchless commit. A possible solution would be to track the modification time of `Bender.lock`; see `manifest_mtime`. However, since this is not the intended use of bender and, in a similar form, already possible today, I chose not to address this for now. Context: The pulp-action [integrate](https://github.com/pulp-platform/pulp-actions/tree/main/integrate) currently does not work for `pull_request` events, since the run's context (the PR merge commit) is not accessible by the dependent's CI due to the issue addressed by this PR. (see https://github.com/pulp-platform/cva6/actions/runs/10512893871/job/29127223222) Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
1 parent a6b1c8b commit d408ac1

2 files changed

Lines changed: 25 additions & 3 deletions

File tree

src/git.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,13 @@ impl<'git, 'ctx> Git<'ctx> {
154154
.map(|_| ())
155155
}
156156

157+
/// Fetch the specified ref of a remote.
158+
pub async fn fetch_ref(self, remote: &str, reference: &str) -> Result<()> {
159+
self.spawn_with(|c| c.arg("fetch").arg(remote).arg(reference))
160+
.await
161+
.map(|_| ())
162+
}
163+
157164
/// Stage all local changes.
158165
pub async fn add_all(self) -> Result<()> {
159166
self.spawn_with(|c| c.arg("add").arg("--all"))

src/sess.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
460460
}
461461
DependencySource::Path(_) => Ok(DependencyVersions::Path),
462462
DependencySource::Git(ref url) => {
463-
let db = self.git_database(&dep.name, url, force_fetch).await?;
463+
let db = self.git_database(&dep.name, url, force_fetch, None).await?;
464464
self.git_versions_func(db)
465465
.await
466466
.map(DependencyVersions::Git)
@@ -477,6 +477,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
477477
name: &str,
478478
url: &str,
479479
force_fetch: bool,
480+
fetch_ref: Option<&str>,
480481
) -> Result<Git<'ctx>> {
481482
// TODO: Make the assembled future shared and keep it in a lookup table.
482483
// Then use that table to return the future if it already exists.
@@ -533,6 +534,13 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
533534
.and_then(|_| git.spawn_with(|c| c.arg("init").arg("--bare")))
534535
.and_then(|_| git.spawn_with(|c| c.arg("remote").arg("add").arg("origin").arg(url)))
535536
.and_then(|_| git.fetch("origin"))
537+
.and_then(|_| async {
538+
if let Some(reference) = fetch_ref {
539+
git.fetch_ref("origin", reference).await
540+
} else {
541+
Ok(())
542+
}
543+
})
536544
.await
537545
.map_err(move |cause| {
538546
if url3.contains("git@") {
@@ -559,6 +567,13 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
559567
Ok(())
560568
})
561569
.and_then(|_| git.fetch("origin"))
570+
.and_then(|_| async {
571+
if let Some(reference) = fetch_ref {
572+
git.fetch_ref("origin", reference).await
573+
} else {
574+
Ok(())
575+
}
576+
})
562577
.await
563578
.map_err(move |cause| {
564579
if url3.contains("git@") {
@@ -841,7 +856,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
841856
// branches or tags for shallow clones.
842857
let tag_name_0 = format!("bender-tmp-{}", revision);
843858
let tag_name_1 = tag_name_0.clone();
844-
let git = self.git_database(name, url, false).await?;
859+
let git = self.git_database(name, url, false, Some(revision)).await?;
845860
git.spawn_with(move |c| c.arg("tag").arg(tag_name_0).arg(revision).arg("--force"))
846861
.map_err(move |cause| {
847862
warnln!("Please ensure the commits are available on the remote or run bender update");
@@ -1041,7 +1056,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
10411056
(DepSrc::Git(url), DepVer::Git(rev)) => {
10421057
let dep_name = self.sess.intern_string(dep.name.as_str());
10431058
// TODO MICHAERO: May need proper chaining using and_then
1044-
let db = self.git_database(&dep.name, url, false).await?;
1059+
let db = self.git_database(&dep.name, url, false, None).await?;
10451060
let entries = db.list_files(rev, Some("Bender.yml")).await?;
10461061
let data = match entries.into_iter().next() {
10471062
None => Ok(None),

0 commit comments

Comments
 (0)