mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-05 23:42:50 +00:00
git: tolerate unknown git.fetch
remotes if others are available
If `git.fetch` contains remotes that are not available, we currently error even if other remotes are available. For common fork workflows with separate `upstream` and `origin` remotes (for example), this requires a user to either set both remotes in their user config and override single-remote repos or set only one in their user config and override all multi-remote repos to fetch from `upstream` (or both). This change updates fetching to only *warn* about unknown remotes **if** other remotes are available. If none of the configured remotes are available, an error is still raised as before.
This commit is contained in:
parent
92629ded4c
commit
1cdd79071e
@ -61,6 +61,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
* Added `ui.streampager.show-ruler` setting to configure whether the ruler should be
|
* Added `ui.streampager.show-ruler` setting to configure whether the ruler should be
|
||||||
shown when the builtin pager starts up.
|
shown when the builtin pager starts up.
|
||||||
|
|
||||||
|
* `jj git fetch` now warns instead of erroring for unknown `git.fetch` remotes
|
||||||
|
if other remotes are available.
|
||||||
|
|
||||||
### Fixed bugs
|
### Fixed bugs
|
||||||
|
|
||||||
* Fixed crash on change-delete conflict resolution.
|
* Fixed crash on change-delete conflict resolution.
|
||||||
|
@ -98,36 +98,26 @@ pub fn cmd_git_fetch(
|
|||||||
let all_remotes = git::get_all_remote_names(workspace_command.repo().store())?;
|
let all_remotes = git::get_all_remote_names(workspace_command.repo().store())?;
|
||||||
|
|
||||||
let mut matching_remotes = HashSet::new();
|
let mut matching_remotes = HashSet::new();
|
||||||
let mut unmatched_patterns = Vec::new();
|
|
||||||
for pattern in remote_patterns {
|
for pattern in remote_patterns {
|
||||||
let remotes = all_remotes
|
let remotes = all_remotes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|r| pattern.matches(r.as_str()))
|
.filter(|r| pattern.matches(r.as_str()))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
if remotes.is_empty() {
|
if remotes.is_empty() {
|
||||||
unmatched_patterns.push(pattern);
|
writeln!(ui.warning_default(), "No git remotes matching '{pattern}'")?;
|
||||||
} else {
|
} else {
|
||||||
matching_remotes.extend(remotes);
|
matching_remotes.extend(remotes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match &unmatched_patterns[..] {
|
if matching_remotes.is_empty() {
|
||||||
[] => {} // Everything matched, all good
|
return Err(user_error("No git remotes to push"));
|
||||||
[pattern] if pattern.is_exact() => {
|
|
||||||
return Err(user_error(format!("No git remote named '{pattern}'")))
|
|
||||||
}
|
|
||||||
patterns => {
|
|
||||||
return Err(user_error(format!(
|
|
||||||
"No matching git remotes for patterns: {}",
|
|
||||||
patterns.iter().join(", ")
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let remotes = all_remotes
|
let remotes = matching_remotes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|r| matching_remotes.contains(r))
|
|
||||||
.map(|r| r.as_ref())
|
.map(|r| r.as_ref())
|
||||||
|
.sorted()
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
#[cfg(feature = "git2")]
|
#[cfg(feature = "git2")]
|
||||||
|
@ -322,7 +322,8 @@ fn test_git_fetch_with_glob_with_no_matching_remotes(subprocess: bool) {
|
|||||||
insta::allow_duplicates! {
|
insta::allow_duplicates! {
|
||||||
insta::assert_snapshot!(output, @r"
|
insta::assert_snapshot!(output, @r"
|
||||||
------- stderr -------
|
------- stderr -------
|
||||||
Error: No matching git remotes for patterns: rem*
|
Warning: No git remotes matching 'rem*'
|
||||||
|
Error: No git remotes to push
|
||||||
[EOF]
|
[EOF]
|
||||||
[exit status: 1]
|
[exit status: 1]
|
||||||
");
|
");
|
||||||
@ -386,6 +387,28 @@ fn test_git_fetch_multiple_remotes_from_config(subprocess: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]
|
||||||
|
#[test_case(true; "spawn a git subprocess for remote calls")]
|
||||||
|
fn test_git_fetch_no_matching_remote(subprocess: bool) {
|
||||||
|
let test_env = TestEnvironment::default().with_git_subprocess(subprocess);
|
||||||
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
||||||
|
let work_dir = test_env.work_dir("repo");
|
||||||
|
|
||||||
|
let output = work_dir.run_jj(["git", "fetch", "--remote", "rem1"]);
|
||||||
|
insta::allow_duplicates! {
|
||||||
|
insta::assert_snapshot!(output, @r"
|
||||||
|
------- stderr -------
|
||||||
|
Warning: No git remotes matching 'rem1'
|
||||||
|
Error: No git remotes to push
|
||||||
|
[EOF]
|
||||||
|
[exit status: 1]
|
||||||
|
");
|
||||||
|
}
|
||||||
|
insta::allow_duplicates! {
|
||||||
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]
|
#[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]
|
||||||
#[test_case(true; "spawn a git subprocess for remote calls")]
|
#[test_case(true; "spawn a git subprocess for remote calls")]
|
||||||
fn test_git_fetch_nonexistent_remote(subprocess: bool) {
|
fn test_git_fetch_nonexistent_remote(subprocess: bool) {
|
||||||
@ -398,14 +421,16 @@ fn test_git_fetch_nonexistent_remote(subprocess: bool) {
|
|||||||
insta::allow_duplicates! {
|
insta::allow_duplicates! {
|
||||||
insta::assert_snapshot!(output, @r"
|
insta::assert_snapshot!(output, @r"
|
||||||
------- stderr -------
|
------- stderr -------
|
||||||
Error: No git remote named 'rem2'
|
Warning: No git remotes matching 'rem2'
|
||||||
|
bookmark: rem1@rem1 [new] untracked
|
||||||
[EOF]
|
[EOF]
|
||||||
[exit status: 1]
|
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
insta::allow_duplicates! {
|
insta::allow_duplicates! {
|
||||||
// No remote should have been fetched as part of the failing transaction
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
||||||
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
rem1@rem1: ppspxspk 4acd0343 message
|
||||||
|
[EOF]
|
||||||
|
");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,14 +447,16 @@ fn test_git_fetch_nonexistent_remote_from_config(subprocess: bool) {
|
|||||||
insta::allow_duplicates! {
|
insta::allow_duplicates! {
|
||||||
insta::assert_snapshot!(output, @r"
|
insta::assert_snapshot!(output, @r"
|
||||||
------- stderr -------
|
------- stderr -------
|
||||||
Error: No git remote named 'rem2'
|
Warning: No git remotes matching 'rem2'
|
||||||
|
bookmark: rem1@rem1 [new] untracked
|
||||||
[EOF]
|
[EOF]
|
||||||
[exit status: 1]
|
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
// No remote should have been fetched as part of the failing transaction
|
|
||||||
insta::allow_duplicates! {
|
insta::allow_duplicates! {
|
||||||
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
||||||
|
rem1@rem1: ppspxspk 4acd0343 message
|
||||||
|
[EOF]
|
||||||
|
");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user