1 use std
::{path::Path, process::Command}
;
3 /// Finds the remote for rust-lang/rust.
4 /// For example for these remotes it will return `upstream`.
6 /// origin https://github.com/Nilstrieb/rust.git (fetch)
7 /// origin https://github.com/Nilstrieb/rust.git (push)
8 /// upstream https://github.com/rust-lang/rust (fetch)
9 /// upstream https://github.com/rust-lang/rust (push)
11 pub fn get_rust_lang_rust_remote(git_dir
: Option
<&Path
>) -> Result
<String
, String
> {
12 let mut git
= Command
::new("git");
13 if let Some(git_dir
) = git_dir
{
14 git
.current_dir(git_dir
);
16 git
.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
18 let output
= git
.output().map_err(|err
| format
!("{err:?}"))?
;
19 if !output
.status
.success() {
20 return Err("failed to execute git config command".to_owned());
23 let stdout
= String
::from_utf8(output
.stdout
).map_err(|err
| format
!("{err:?}"))?
;
25 let rust_lang_remote
= stdout
27 .find(|remote
| remote
.contains("rust-lang"))
28 .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?
;
31 rust_lang_remote
.split('
.'
).nth(1).ok_or_else(|| "remote name not found".to_owned())?
;
32 Ok(remote_name
.into())
35 pub fn rev_exists(rev
: &str, git_dir
: Option
<&Path
>) -> Result
<bool
, String
> {
36 let mut git
= Command
::new("git");
37 if let Some(git_dir
) = git_dir
{
38 git
.current_dir(git_dir
);
40 git
.args(["rev-parse", rev
]);
41 let output
= git
.output().map_err(|err
| format
!("{err:?}"))?
;
43 match output
.status
.code() {
45 Some(128) => Ok(false),
48 "git didn't exit properly: {}",
49 String
::from_utf8(output
.stderr
).map_err(|err
| format
!("{err:?}"))?
54 "git command exited with status code: {code}: {}",
55 String
::from_utf8(output
.stderr
).map_err(|err
| format
!("{err:?}"))?
61 /// Returns the master branch from which we can take diffs to see changes.
62 /// This will usually be rust-lang/rust master, but sometimes this might not exist.
63 /// This could be because the user is updating their forked master branch using the GitHub UI
64 /// and therefore doesn't need an upstream master branch checked out.
65 /// We will then fall back to origin/master in the hope that at least this exists.
66 pub fn updated_master_branch(git_dir
: Option
<&Path
>) -> Result
<String
, String
> {
67 let upstream_remote
= get_rust_lang_rust_remote(git_dir
)?
;
68 let upstream_master
= format
!("{upstream_remote}/master");
69 if rev_exists(&upstream_master
, git_dir
)?
{
70 return Ok(upstream_master
);
73 // We could implement smarter logic here in the future.
74 Ok("origin/master".into())