ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: list new remote branches during git fetch

This commit is contained in:
Vladimir Petrzhikovskii 2024-02-13 23:17:05 +01:00 committed by Vladimir
parent a1b16c5583
commit 06d67f02d8
10 changed files with 251 additions and 37 deletions

View file

@ -51,6 +51,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* When creating a new workspace, the sparse patterns are now copied over from
the current workspace.
* `jj git fetch` now automatically prints new remote branches and tags by default.
### Fixed bugs
* On Windows, symlinks in the repo are now materialized as regular files in the

View file

@ -953,7 +953,7 @@ impl WorkspaceCommandHelper {
return Ok(());
}
print_git_import_stats(ui, &stats)?;
print_git_import_stats(ui, tx.repo(), &stats, false)?;
let mut tx = tx.into_inner();
// Rebase here to show slightly different status message.
let num_rebased = tx.mut_repo().rebase_descendants(&self.settings)?;

View file

@ -447,7 +447,7 @@ fn init_git_refs(
if !tx.mut_repo().has_changes() {
return Ok(repo);
}
print_git_import_stats(ui, &stats)?;
print_git_import_stats(ui, tx.repo(), &stats, false)?;
if colocated {
// If git.auto-local-branch = true, local branches could be created for
// the imported remote branches.
@ -537,7 +537,7 @@ fn cmd_git_fetch(
GitFetchError::InternalGitError(err) => map_git_error(err),
_ => user_error(err),
})?;
print_git_import_stats(ui, &stats.import_stats)?;
print_git_import_stats(ui, tx.repo(), &stats.import_stats, true)?;
}
tx.finish(
ui,
@ -751,7 +751,7 @@ fn do_git_clone(
unreachable!("we didn't provide any globs")
}
})?;
print_git_import_stats(ui, &stats.import_stats)?;
print_git_import_stats(ui, fetch_tx.repo(), &stats.import_stats, true)?;
fetch_tx.finish(ui, "fetch from git remote into empty repo")?;
Ok((workspace_command, stats))
}
@ -1190,7 +1190,7 @@ fn cmd_git_import(
// That's why cmd_git_export() doesn't export the HEAD ref.
git::import_head(tx.mut_repo())?;
let stats = git::import_refs(tx.mut_repo(), &command.settings().git_settings())?;
print_git_import_stats(ui, &stats)?;
print_git_import_stats(ui, tx.repo(), &stats, true)?;
tx.finish(ui, "import git refs")?;
Ok(())
}

View file

@ -21,13 +21,17 @@ use std::sync::Mutex;
use std::time::Instant;
use std::{error, iter};
use jj_lib::git::{self, FailedRefExport, FailedRefExportReason, GitImportStats};
use itertools::Itertools;
use jj_lib::git::{self, FailedRefExport, FailedRefExportReason, GitImportStats, RefName};
use jj_lib::git_backend::GitBackend;
use jj_lib::repo::{ReadonlyRepo, Repo as _};
use jj_lib::op_store::{RefTarget, RemoteRef};
use jj_lib::repo::{ReadonlyRepo, Repo};
use jj_lib::store::Store;
use jj_lib::workspace::Workspace;
use unicode_width::UnicodeWidthStr;
use crate::cli_util::{user_error, CommandError};
use crate::formatter::Formatter;
use crate::progress::Progress;
use crate::ui::Ui;
@ -172,7 +176,37 @@ pub fn with_remote_git_callbacks<T>(
f(callbacks)
}
pub fn print_git_import_stats(ui: &mut Ui, stats: &GitImportStats) -> Result<(), CommandError> {
pub fn print_git_import_stats(
ui: &mut Ui,
repo: &dyn Repo,
stats: &GitImportStats,
show_ref_stats: bool,
) -> Result<(), CommandError> {
if show_ref_stats {
let refs_stats = stats
.changed_remote_refs
.iter()
.map(|(ref_name, (remote_ref, ref_target))| {
RefStatus::new(ref_name, remote_ref, ref_target, repo)
})
.collect_vec();
let has_both_ref_kinds = refs_stats
.iter()
.any(|x| matches!(x.ref_kind, RefKind::Branch))
&& refs_stats
.iter()
.any(|x| matches!(x.ref_kind, RefKind::Tag));
let max_width = refs_stats.iter().map(|x| x.ref_name.width()).max();
if let Some(max_width) = max_width {
let mut stderr = ui.stderr_formatter();
for status in refs_stats {
status.output(max_width, has_both_ref_kinds, &mut *stderr)?;
}
}
}
if !stats.abandoned_commits.is_empty() {
writeln!(
ui.stderr(),
@ -180,9 +214,105 @@ pub fn print_git_import_stats(ui: &mut Ui, stats: &GitImportStats) -> Result<(),
stats.abandoned_commits.len()
)?;
}
Ok(())
}
struct RefStatus {
ref_kind: RefKind,
ref_name: String,
tracking_status: TrackingStatus,
import_status: ImportStatus,
}
impl RefStatus {
fn new(
ref_name: &RefName,
remote_ref: &RemoteRef,
ref_target: &RefTarget,
repo: &dyn Repo,
) -> Self {
let (ref_name, ref_kind, tracking_status) = match ref_name {
RefName::RemoteBranch { branch, remote } => (
format!("{branch}@{remote}"),
RefKind::Branch,
if repo.view().get_remote_branch(branch, remote).is_tracking() {
TrackingStatus::Tracked
} else {
TrackingStatus::Untracked
},
),
RefName::Tag(tag) => (tag.clone(), RefKind::Tag, TrackingStatus::NotApplicable),
RefName::LocalBranch(branch) => {
(branch.clone(), RefKind::Branch, TrackingStatus::Tracked)
}
};
let import_status = match (remote_ref.target.is_absent(), ref_target.is_absent()) {
(true, false) => ImportStatus::New,
(false, true) => ImportStatus::Deleted,
_ => ImportStatus::Updated,
};
Self {
ref_name,
tracking_status,
import_status,
ref_kind,
}
}
fn output(
&self,
max_ref_name_width: usize,
has_both_ref_kinds: bool,
out: &mut dyn Formatter,
) -> std::io::Result<()> {
let tracking_status = match self.tracking_status {
TrackingStatus::Tracked => "tracked",
TrackingStatus::Untracked => "untracked",
TrackingStatus::NotApplicable => "",
};
let import_status = match self.import_status {
ImportStatus::New => "new",
ImportStatus::Deleted => "deleted",
ImportStatus::Updated => "updated",
};
let ref_name_display_width = self.ref_name.width();
let pad_width = max_ref_name_width.saturating_sub(ref_name_display_width);
let padded_ref_name = format!("{}{:>pad_width$}", self.ref_name, "", pad_width = pad_width);
let ref_kind = match self.ref_kind {
RefKind::Branch => "branch: ",
RefKind::Tag if !has_both_ref_kinds => "tag: ",
RefKind::Tag => "tag: ",
};
write!(out, "{ref_kind}")?;
write!(out.labeled("branch"), "{padded_ref_name}")?;
writeln!(out, " [{import_status}] {tracking_status}")
}
}
enum RefKind {
Branch,
Tag,
}
enum TrackingStatus {
Tracked,
Untracked,
NotApplicable, // for tags
}
enum ImportStatus {
New,
Deleted,
Updated,
}
pub fn print_failed_git_export(
ui: &Ui,
failed_branches: &[FailedRefExport],

View file

@ -536,7 +536,9 @@ fn test_branch_forget_fetched_branch() {
// We can fetch feature1 again.
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
feature1: mzyxwzks 9f01a0e0 message
@origin: mzyxwzks 9f01a0e0 message
@ -548,7 +550,9 @@ fn test_branch_forget_fetched_branch() {
// Fetch works even without the export-import
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
feature1: mzyxwzks 9f01a0e0 message
@origin: mzyxwzks 9f01a0e0 message
@ -574,7 +578,9 @@ fn test_branch_forget_fetched_branch() {
// Fetching a moved branch does not create a conflict
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
feature1: ooosovrs 38aefb17 (empty) another message
@origin: ooosovrs 38aefb17 (empty) another message
@ -687,7 +693,12 @@ fn test_branch_track_untrack() {
);
test_env.add_config("git.auto-local-branch = false");
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [new] untracked
branch: feature2@origin [new] untracked
branch: main@origin [new] untracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
feature1@origin: sptzoqmo 7b33f629 commit 1
feature2@origin: sptzoqmo 7b33f629 commit 1
@ -759,7 +770,12 @@ fn test_branch_track_untrack() {
],
);
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [updated] untracked
branch: feature2@origin [updated] untracked
branch: main@origin [updated] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
feature1: sptzoqmo 7b33f629 commit 1
feature1@origin: mmqqkyyt 40dabdaf commit 2
@ -791,6 +807,10 @@ fn test_branch_track_untrack() {
test_env.add_config("git.auto-local-branch = true");
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [updated] untracked
branch: feature2@origin [updated] untracked
branch: feature3@origin [new] tracked
branch: main@origin [updated] tracked
Abandoned 1 commits that are no longer reachable.
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
@ -847,7 +867,11 @@ fn test_branch_track_untrack_patterns() {
// Fetch new commit without auto tracking
test_env.add_config("git.auto-local-branch = false");
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: feature1@origin [new] untracked
branch: feature2@origin [new] untracked
"###);
// Track local branch
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);

View file

@ -63,6 +63,7 @@ fn test_git_clone() {
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Fetching into new repo in "$TEST_ENV/clone"
branch: main@origin [new] tracked
Working copy now at: uuqppmxq 1f0b881a (empty) (no description set)
Parent commit : mzyxwzks 9f01a0e0 main | message
Added 1 files, modified 0 files, removed 0 files
@ -173,6 +174,7 @@ fn test_git_clone_colocate() {
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Fetching into new repo in "$TEST_ENV/clone"
branch: main@origin [new] tracked
Working copy now at: uuqppmxq 1f0b881a (empty) (no description set)
Parent commit : mzyxwzks 9f01a0e0 main | message
Added 1 files, modified 0 files, removed 0 files
@ -328,6 +330,8 @@ fn test_git_clone_remote_default_branch() {
test_env.jj_cmd_ok(test_env.env_root(), &["git", "clone", "source", "clone1"]);
insta::assert_snapshot!(stderr, @r###"
Fetching into new repo in "$TEST_ENV/clone1"
branch: feature1@origin [new] tracked
branch: main@origin [new] tracked
Working copy now at: sqpuoqvx cad212e1 (empty) (no description set)
Parent commit : mzyxwzks 9f01a0e0 feature1 main | message
Added 1 files, modified 0 files, removed 0 files
@ -346,6 +350,8 @@ fn test_git_clone_remote_default_branch() {
test_env.jj_cmd_ok(test_env.env_root(), &["git", "clone", "source", "clone2"]);
insta::assert_snapshot!(stderr, @r###"
Fetching into new repo in "$TEST_ENV/clone2"
branch: feature1@origin [new] untracked
branch: main@origin [new] untracked
Working copy now at: pmmvwywv fa729b1e (empty) (no description set)
Parent commit : mzyxwzks 9f01a0e0 feature1@origin main | message
Added 1 files, modified 0 files, removed 0 files

View file

@ -507,6 +507,8 @@ fn test_git_colocated_fetch_deleted_or_moved_branch() {
let (stdout, stderr) = test_env.jj_cmd_ok(&clone_path, &["git", "fetch"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
branch: B_to_delete@origin [deleted] untracked
branch: C_to_move@origin [updated] tracked
Abandoned 2 commits that are no longer reachable.
"###);
// "original C" and "B_to_delete" are abandoned, as the corresponding branches

View file

@ -111,7 +111,7 @@ fn test_git_fetch_single_remote() {
.jj_cmd(&repo_path, &["git", "fetch"])
.assert()
.success()
.stderr("Fetching from the only existing remote: rem1\n");
.stderr("Fetching from the only existing remote: rem1\nbranch: rem1@rem1 [new] tracked\n");
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
rem1: qxosxrvv 6a211027 message
@rem1: qxosxrvv 6a211027 message
@ -237,6 +237,7 @@ fn test_git_fetch_nonexistent_remote() {
&["git", "fetch", "--remote", "rem1", "--remote", "rem2"],
);
insta::assert_snapshot!(stderr, @r###"
branch: rem1@rem1 [new] untracked
Error: No git remote named 'rem2'
"###);
// No remote should have been fetched as part of the failing transaction
@ -253,6 +254,7 @@ fn test_git_fetch_nonexistent_remote_from_config() {
let stderr = &test_env.jj_cmd_failure(&repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stderr, @r###"
branch: rem1@rem1 [new] untracked
Error: No git remote named 'rem2'
"###);
// No remote should have been fetched as part of the failing transaction
@ -461,7 +463,12 @@ fn test_git_fetch_all() {
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @"");
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [new] tracked
branch: a2@origin [new] tracked
branch: b@origin [new] tracked
branch: trunk1@origin [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
a1: nknoxmzm 359a9a02 descr_for_a1
@origin: nknoxmzm 359a9a02 descr_for_a1
@ -529,6 +536,10 @@ fn test_git_fetch_all() {
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [updated] tracked
branch: a2@origin [updated] tracked
branch: b@origin [updated] tracked
branch: trunk2@origin [new] tracked
Abandoned 2 commits that are no longer reachable.
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
@ -616,7 +627,9 @@ fn test_git_fetch_some_of_many_branches() {
let (stdout, stderr) =
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "b"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: b@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
c7d4bdcbc215 descr_for_b b
ff36dc55760e descr_for_trunk1
@ -635,7 +648,10 @@ fn test_git_fetch_some_of_many_branches() {
&["git", "fetch", "--branch", "glob:a*"],
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [new] tracked
branch: a2@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
decaa3966c83 descr_for_a2 a2
359a9a02457d descr_for_a1 a1
@ -704,6 +720,8 @@ fn test_git_fetch_some_of_many_branches() {
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [updated] tracked
branch: b@origin [updated] tracked
Abandoned 1 commits that are no longer reachable.
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
@ -741,6 +759,7 @@ fn test_git_fetch_some_of_many_branches() {
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a2@origin [updated] tracked
Abandoned 1 commits that are no longer reachable.
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
@ -808,7 +827,10 @@ fn test_git_fetch_undo() {
&["git", "fetch", "--branch", "b", "--branch", "a1"],
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [new] tracked
branch: b@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
c7d4bdcbc215 descr_for_b b
359a9a02457d descr_for_a1 a1
@ -830,7 +852,9 @@ fn test_git_fetch_undo() {
let (stdout, stderr) =
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "b"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: b@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
c7d4bdcbc215 descr_for_b b
ff36dc55760e descr_for_trunk1
@ -880,7 +904,9 @@ fn test_fetch_undo_what() {
// Fetch a branch
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--branch", "b"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: b@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
c7d4bdcbc215 descr_for_b b
ff36dc55760e descr_for_trunk1
@ -967,7 +993,9 @@ fn test_git_fetch_remove_fetch() {
// Check that origin@origin is properly recreated
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: origin@origin [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
origin (conflicted):
+ qpvuntsm 230dd059 (empty) (no description set)
@ -1050,7 +1078,12 @@ fn test_git_fetch_removed_branch() {
// Fetch all branches
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [new] tracked
branch: a2@origin [new] tracked
branch: b@origin [new] tracked
branch: trunk1@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
c7d4bdcbc215 descr_for_b b
decaa3966c83 descr_for_a2 a2
@ -1090,6 +1123,7 @@ fn test_git_fetch_removed_branch() {
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "a2"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a2@origin [deleted] untracked
Abandoned 1 commits that are no longer reachable.
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
@ -1136,7 +1170,12 @@ fn test_git_fetch_removed_parent_branch() {
// Fetch all branches
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [new] tracked
branch: a2@origin [new] tracked
branch: b@origin [new] tracked
branch: trunk1@origin [new] tracked
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
c7d4bdcbc215 descr_for_b b
decaa3966c83 descr_for_a2 a2
@ -1163,6 +1202,8 @@ fn test_git_fetch_removed_parent_branch() {
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a1@origin [deleted] untracked
branch: trunk1@origin [deleted] untracked
Abandoned 1 commits that are no longer reachable.
"###);
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"

View file

@ -148,7 +148,9 @@ fn test_git_import_undo() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
a: qpvuntsm 230dd059 (empty) (no description set)
@git: qpvuntsm 230dd059 (empty) (no description set)
@ -162,7 +164,9 @@ fn test_git_import_undo() {
// Try "git import" again, which should re-import the branch "a".
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
a: qpvuntsm 230dd059 (empty) (no description set)
@git: qpvuntsm 230dd059 (empty) (no description set)
@ -191,7 +195,9 @@ fn test_git_import_move_export_with_default_undo() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
a: qpvuntsm 230dd059 (empty) (no description set)
@git: qpvuntsm 230dd059 (empty) (no description set)
@ -237,7 +243,9 @@ fn test_git_import_move_export_with_default_undo() {
// intuitive result here.
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stderr, @r###"
branch: a [new] tracked
"###);
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
a: yqosqzyt 096dc80d (empty) (no description set)
@git: yqosqzyt 096dc80d (empty) (no description set)

View file

@ -201,10 +201,13 @@ impl GitImportError {
}
/// Describes changes made by `import_refs()` or `fetch()`.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct GitImportStats {
/// Commits superseded by newly imported commits.
pub abandoned_commits: Vec<CommitId>,
/// Remote `(ref_name, (old_remote_ref, new_target))`s to be merged in to
/// the local refs.
pub changed_remote_refs: BTreeMap<RefName, (RemoteRef, RefTarget)>,
}
#[derive(Debug)]
@ -326,7 +329,10 @@ pub fn import_some_refs(
} else {
vec![]
};
let stats = GitImportStats { abandoned_commits };
let stats = GitImportStats {
abandoned_commits,
changed_remote_refs,
};
Ok(stats)
}
@ -1089,7 +1095,7 @@ pub enum GitFetchError {
}
/// Describes successful `fetch()` result.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct GitFetchStats {
/// Remote's default branch.
pub default_branch: Option<String>,
@ -1135,12 +1141,7 @@ pub fn fetch(
.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![],
},
};
let stats = GitFetchStats::default();
return Ok(stats);
}
tracing::debug!("remote.download");