Skip to content

Commit f7237f0

Browse files
authored
Merge pull request #149 from Kobzol/merge-base-update-origin-master
Fetch newest origin/master before calculating revision base
2 parents 47d736a + 1f17614 commit f7237f0

File tree

1 file changed

+63
-13
lines changed

1 file changed

+63
-13
lines changed

src/git.rs

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const RUST_SRC_URL: &str = "https://github.com/rust-lang/rust";
44
const RUST_SRC_REPO: Option<&str> = option_env!("RUST_SRC_REPO");
55

66
use std::env;
7+
use std::ops::Deref;
78
use std::path::Path;
89

910
use chrono::{TimeZone, Utc};
@@ -25,14 +26,29 @@ impl Commit {
2526
}
2627
}
2728

28-
fn lookup_rev<'rev>(repo: &'rev Repository, rev: &str) -> Result<Git2Commit<'rev>, Error> {
29+
struct RustcRepo {
30+
repository: Repository,
31+
origin_remote: String,
32+
}
33+
34+
impl Deref for RustcRepo {
35+
type Target = Repository;
36+
37+
fn deref(&self) -> &Self::Target {
38+
&self.repository
39+
}
40+
}
41+
42+
fn lookup_rev<'rev>(repo: &'rev RustcRepo, rev: &str) -> Result<Git2Commit<'rev>, Error> {
2943
let revision = repo.revparse_single(rev)?;
3044

3145
// Find the merge-base between the revision and master.
3246
// If revision is a normal commit contained in master, the merge-base will be the commit itself.
3347
// If revision is a tag (e.g. a release version), the merge-base will contain the latest master
3448
// commit contained in that tag.
35-
let master_id = repo.revparse_single("origin/master")?.id();
49+
let master_id = repo
50+
.revparse_single(&format!("{}/master", repo.origin_remote))?
51+
.id();
3652
let revision_id = revision
3753
.as_tag()
3854
.map(|tag| tag.target_id())
@@ -46,36 +62,70 @@ fn lookup_rev<'rev>(repo: &'rev Repository, rev: &str) -> Result<Git2Commit<'rev
4662
bail!("Could not find a commit for revision specifier '{}'", rev)
4763
}
4864

49-
fn get_repo() -> Result<Repository, Error> {
50-
fn open(repo: &Path) -> Result<Repository, Error> {
51-
eprintln!("refreshing repository at {:?}", repo);
65+
fn get_repo() -> Result<RustcRepo, Error> {
66+
fn open(path: &Path) -> Result<(Repository, String), Error> {
67+
eprintln!("opening existing repository at {:?}", path);
68+
let repo = Repository::open(path)?;
69+
70+
let origin_remote = find_origin_remote(&repo)?;
71+
eprintln!("Found origin remote under name `{origin_remote}`");
72+
73+
eprintln!("refreshing repository at {:?}", path);
5274
// This uses the CLI because libgit2 is quite slow to fetch a large repository.
5375
let status = std::process::Command::new("git")
5476
.arg("fetch")
55-
.arg(RUST_SRC_URL)
56-
.current_dir(repo)
77+
.arg(&origin_remote)
78+
.current_dir(path)
5779
.status()
5880
.context(format!(
5981
"expected `git` command-line executable to be installed"
6082
))?;
6183
if !status.success() {
6284
bail!("git fetch failed exit status {}", status);
6385
}
64-
eprintln!("opening existing repository at {:?}", repo);
65-
let repo = Repository::open(repo)?;
66-
Ok(repo)
86+
87+
Ok((repo, origin_remote))
6788
}
6889

6990
let loc = Path::new("rust.git");
70-
match (env::var_os("RUST_SRC_REPO"), RUST_SRC_REPO) {
91+
let (repository, origin_remote) = match (env::var_os("RUST_SRC_REPO"), RUST_SRC_REPO) {
7192
(Some(repo), _) => open(Path::new(&repo)),
7293
(None, _) if loc.exists() => open(loc),
7394
(None, Some(repo)) => open(Path::new(repo)),
7495
_ => {
7596
eprintln!("cloning rust repository");
76-
Ok(RepoBuilder::new().bare(true).clone(RUST_SRC_URL, loc)?)
97+
Ok((
98+
RepoBuilder::new().bare(true).clone(RUST_SRC_URL, loc)?,
99+
"origin".to_string(),
100+
))
77101
}
78-
}
102+
}?;
103+
104+
Ok(RustcRepo {
105+
repository,
106+
origin_remote,
107+
})
108+
}
109+
110+
fn find_origin_remote(repo: &Repository) -> Result<String, Error> {
111+
repo.remotes()?
112+
.iter()
113+
.filter_map(|name| name.and_then(|name| repo.find_remote(name).ok()))
114+
.find(|remote| {
115+
remote
116+
.url()
117+
.map(|url| url.contains(RUST_SRC_URL))
118+
.unwrap_or(false)
119+
})
120+
.and_then(|remote| remote.name().map(|name| name.to_string()))
121+
.ok_or_else(|| {
122+
failure::format_err!(
123+
"rust-lang/rust remote not found. \
124+
Try adding a remote pointing to `{}` in the rust repository at `{}`.",
125+
RUST_SRC_URL,
126+
repo.path().display()
127+
)
128+
})
79129
}
80130

81131
pub(crate) fn get_commit(sha: &str) -> Result<Commit, Error> {

0 commit comments

Comments
 (0)