mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-09 17:32:50 +00:00
git: simply call fetch() with one or more branch name filters
This commit is contained in:
parent
560b63544a
commit
a6ac9b46e7
@ -100,7 +100,7 @@ pub struct GitFetchArgs {
|
|||||||
///
|
///
|
||||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||||
/// expand `*` as a glob. The other wildcard characters aren't supported.
|
/// expand `*` as a glob. The other wildcard characters aren't supported.
|
||||||
#[arg(long, value_parser = parse_string_pattern)]
|
#[arg(long, default_value = "glob:*", value_parser = parse_string_pattern)]
|
||||||
branch: Vec<StringPattern>,
|
branch: Vec<StringPattern>,
|
||||||
/// The remote to fetch from (only named remotes are supported, can be
|
/// The remote to fetch from (only named remotes are supported, can be
|
||||||
/// repeated)
|
/// repeated)
|
||||||
@ -319,7 +319,7 @@ fn cmd_git_fetch(
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&git_repo,
|
&git_repo,
|
||||||
&remote,
|
&remote,
|
||||||
(!args.branch.is_empty()).then_some(&args.branch),
|
&args.branch,
|
||||||
cb,
|
cb,
|
||||||
&command.settings().git_settings(),
|
&command.settings().git_settings(),
|
||||||
)
|
)
|
||||||
@ -535,7 +535,7 @@ fn do_git_clone(
|
|||||||
fetch_tx.mut_repo(),
|
fetch_tx.mut_repo(),
|
||||||
&git_repo,
|
&git_repo,
|
||||||
remote_name,
|
remote_name,
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
cb,
|
cb,
|
||||||
&command.settings().git_settings(),
|
&command.settings().git_settings(),
|
||||||
)
|
)
|
||||||
|
@ -1001,16 +1001,10 @@ pub fn fetch(
|
|||||||
mut_repo: &mut MutableRepo,
|
mut_repo: &mut MutableRepo,
|
||||||
git_repo: &git2::Repository,
|
git_repo: &git2::Repository,
|
||||||
remote_name: &str,
|
remote_name: &str,
|
||||||
branch_names: Option<&[StringPattern]>,
|
branch_names: &[StringPattern],
|
||||||
callbacks: RemoteCallbacks<'_>,
|
callbacks: RemoteCallbacks<'_>,
|
||||||
git_settings: &GitSettings,
|
git_settings: &GitSettings,
|
||||||
) -> Result<GitFetchStats, GitFetchError> {
|
) -> Result<GitFetchStats, GitFetchError> {
|
||||||
let branch_name_filter = |branch: &str| {
|
|
||||||
branch_names.map_or(true, |patterns| {
|
|
||||||
patterns.iter().any(|pattern| pattern.matches(branch))
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
// Perform a `git fetch` on the local git repo, updating the remote-tracking
|
// Perform a `git fetch` on the local git repo, updating the remote-tracking
|
||||||
// branches in the git repo.
|
// branches in the git repo.
|
||||||
let mut remote = git_repo.find_remote(remote_name).map_err(|err| {
|
let mut remote = git_repo.find_remote(remote_name).map_err(|err| {
|
||||||
@ -1026,27 +1020,28 @@ pub fn fetch(
|
|||||||
fetch_options.proxy_options(proxy_options);
|
fetch_options.proxy_options(proxy_options);
|
||||||
let callbacks = callbacks.into_git();
|
let callbacks = callbacks.into_git();
|
||||||
fetch_options.remote_callbacks(callbacks);
|
fetch_options.remote_callbacks(callbacks);
|
||||||
let refspecs = {
|
// At this point, we are only updating Git's remote tracking branches, not the
|
||||||
// If no globs have been given, import all branches
|
// local branches.
|
||||||
let globs = if let Some(patterns) = branch_names {
|
let refspecs: Vec<_> = branch_names
|
||||||
patterns
|
.iter()
|
||||||
.iter()
|
.map(|pattern| {
|
||||||
.map(|pattern| pattern.to_glob())
|
pattern
|
||||||
.collect::<Option<Vec<_>>>()
|
.to_glob()
|
||||||
.ok_or(GitFetchError::InvalidBranchPattern)?
|
.filter(|glob| !glob.contains(INVALID_REFSPEC_CHARS))
|
||||||
} else {
|
.map(|glob| format!("+refs/heads/{glob}:refs/remotes/{remote_name}/{glob}"))
|
||||||
vec!["*".into()]
|
})
|
||||||
|
.collect::<Option<_>>()
|
||||||
|
.ok_or(GitFetchError::InvalidBranchPattern)?;
|
||||||
|
if refspecs.is_empty() {
|
||||||
|
// Don't fall back to the base refspecs.
|
||||||
|
let stats = GitFetchStats {
|
||||||
|
default_branch: None,
|
||||||
|
import_stats: GitImportStats {
|
||||||
|
abandoned_commits: vec![],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if globs.iter().any(|g| g.contains(INVALID_REFSPEC_CHARS)) {
|
return Ok(stats);
|
||||||
return Err(GitFetchError::InvalidBranchPattern);
|
}
|
||||||
}
|
|
||||||
// At this point, we are only updating Git's remote tracking branches, not the
|
|
||||||
// local branches.
|
|
||||||
globs
|
|
||||||
.iter()
|
|
||||||
.map(|glob| format!("+refs/heads/{glob}:refs/remotes/{remote_name}/{glob}"))
|
|
||||||
.collect_vec()
|
|
||||||
};
|
|
||||||
tracing::debug!("remote.download");
|
tracing::debug!("remote.download");
|
||||||
remote.download(&refspecs, Some(&mut fetch_options))?;
|
remote.download(&refspecs, Some(&mut fetch_options))?;
|
||||||
tracing::debug!("remote.prune");
|
tracing::debug!("remote.prune");
|
||||||
@ -1075,7 +1070,7 @@ pub fn fetch(
|
|||||||
tracing::debug!("import_refs");
|
tracing::debug!("import_refs");
|
||||||
let import_stats = import_some_refs(mut_repo, git_repo, git_settings, |ref_name| {
|
let import_stats = import_some_refs(mut_repo, git_repo, git_settings, |ref_name| {
|
||||||
to_remote_branch(ref_name, remote_name)
|
to_remote_branch(ref_name, remote_name)
|
||||||
.map(branch_name_filter)
|
.map(|branch| branch_names.iter().any(|pattern| pattern.matches(branch)))
|
||||||
.unwrap_or_else(|| matches!(ref_name, RefName::Tag(_)))
|
.unwrap_or_else(|| matches!(ref_name, RefName::Tag(_)))
|
||||||
})?;
|
})?;
|
||||||
let stats = GitFetchStats {
|
let stats = GitFetchStats {
|
||||||
|
@ -35,6 +35,7 @@ use jj_lib::op_store::{BranchTarget, RefTarget, RemoteRef, RemoteRefState};
|
|||||||
use jj_lib::refs::BranchPushUpdate;
|
use jj_lib::refs::BranchPushUpdate;
|
||||||
use jj_lib::repo::{MutableRepo, ReadonlyRepo, Repo};
|
use jj_lib::repo::{MutableRepo, ReadonlyRepo, Repo};
|
||||||
use jj_lib::settings::{GitSettings, UserSettings};
|
use jj_lib::settings::{GitSettings, UserSettings};
|
||||||
|
use jj_lib::str_util::StringPattern;
|
||||||
use jj_lib::workspace::Workspace;
|
use jj_lib::workspace::Workspace;
|
||||||
use maplit::{btreemap, hashset};
|
use maplit::{btreemap, hashset};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
@ -1964,7 +1965,7 @@ fn test_fetch_empty_repo() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -1989,7 +1990,7 @@ fn test_fetch_initial_commit() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2038,7 +2039,7 @@ fn test_fetch_success() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2063,7 +2064,7 @@ fn test_fetch_success() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2119,7 +2120,7 @@ fn test_fetch_prune_deleted_ref() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2138,7 +2139,7 @@ fn test_fetch_prune_deleted_ref() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2160,7 +2161,7 @@ fn test_fetch_no_default_branch() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2183,7 +2184,7 @@ fn test_fetch_no_default_branch() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"origin",
|
"origin",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
)
|
)
|
||||||
@ -2192,6 +2193,37 @@ fn test_fetch_no_default_branch() {
|
|||||||
assert_eq!(stats.default_branch, None);
|
assert_eq!(stats.default_branch, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fetch_empty_refspecs() {
|
||||||
|
let test_data = GitRepoData::create();
|
||||||
|
let git_settings = GitSettings::default();
|
||||||
|
empty_git_commit(&test_data.origin_repo, "refs/heads/main", &[]);
|
||||||
|
|
||||||
|
// Base refspecs shouldn't be respected
|
||||||
|
let mut tx = test_data
|
||||||
|
.repo
|
||||||
|
.start_transaction(&test_data.settings, "test");
|
||||||
|
git::fetch(
|
||||||
|
tx.mut_repo(),
|
||||||
|
&test_data.git_repo,
|
||||||
|
"origin",
|
||||||
|
&[],
|
||||||
|
git::RemoteCallbacks::default(),
|
||||||
|
&git_settings,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(tx
|
||||||
|
.mut_repo()
|
||||||
|
.get_remote_branch("main", "origin")
|
||||||
|
.is_absent());
|
||||||
|
// No remote refs should have been fetched
|
||||||
|
git::import_refs(tx.mut_repo(), &test_data.git_repo, &git_settings).unwrap();
|
||||||
|
assert!(tx
|
||||||
|
.mut_repo()
|
||||||
|
.get_remote_branch("main", "origin")
|
||||||
|
.is_absent());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fetch_no_such_remote() {
|
fn test_fetch_no_such_remote() {
|
||||||
let test_data = GitRepoData::create();
|
let test_data = GitRepoData::create();
|
||||||
@ -2203,7 +2235,7 @@ fn test_fetch_no_such_remote() {
|
|||||||
tx.mut_repo(),
|
tx.mut_repo(),
|
||||||
&test_data.git_repo,
|
&test_data.git_repo,
|
||||||
"invalid-remote",
|
"invalid-remote",
|
||||||
None,
|
&[StringPattern::everything()],
|
||||||
git::RemoteCallbacks::default(),
|
git::RemoteCallbacks::default(),
|
||||||
&git_settings,
|
&git_settings,
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user