forked from mirrors/jj
git init: add revset alias for trunk()
when intializing with existing git repository
This commit is contained in:
parent
d8899e1ae7
commit
0c0e001262
5 changed files with 100 additions and 7 deletions
|
@ -20,8 +20,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
individually instead of being passed a directory by setting
|
individually instead of being passed a directory by setting
|
||||||
`merge-tools.$TOOL.diff-invocation-mode="file-by-file"` in config.toml.
|
`merge-tools.$TOOL.diff-invocation-mode="file-by-file"` in config.toml.
|
||||||
|
|
||||||
* `jj git clone` adds the default branch of the remote as repository
|
* `jj git clone` and `jj git init` with an existing git repository adds the
|
||||||
settings for `revset-aliases."trunk()"`.`
|
default branch of the remote as repository settings for
|
||||||
|
`revset-aliases."trunk()"`.`
|
||||||
|
|
||||||
### Fixed bugs
|
### Fixed bugs
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use jj_lib::git::{parse_git_ref, RefName};
|
||||||
use jj_lib::repo::{ReadonlyRepo, Repo};
|
use jj_lib::repo::{ReadonlyRepo, Repo};
|
||||||
use jj_lib::workspace::Workspace;
|
use jj_lib::workspace::Workspace;
|
||||||
use jj_lib::{file_util, git};
|
use jj_lib::{file_util, git};
|
||||||
|
@ -23,8 +24,9 @@ use jj_lib::{file_util, git};
|
||||||
use crate::cli_util::{print_trackable_remote_branches, start_repo_transaction, CommandHelper};
|
use crate::cli_util::{print_trackable_remote_branches, start_repo_transaction, CommandHelper};
|
||||||
use crate::command_error::{user_error_with_hint, user_error_with_message, CommandError};
|
use crate::command_error::{user_error_with_hint, user_error_with_message, CommandError};
|
||||||
use crate::commands::git::maybe_add_gitignore;
|
use crate::commands::git::maybe_add_gitignore;
|
||||||
|
use crate::config::{write_config_value_to_file, ConfigNamePathBuf};
|
||||||
use crate::git_util::{
|
use crate::git_util::{
|
||||||
is_colocated_git_workspace, print_failed_git_export, print_git_import_stats,
|
get_git_repo, is_colocated_git_workspace, print_failed_git_export, print_git_import_stats,
|
||||||
};
|
};
|
||||||
use crate::ui::Ui;
|
use crate::ui::Ui;
|
||||||
|
|
||||||
|
@ -152,6 +154,7 @@ pub fn do_init(
|
||||||
let mut workspace_command = command.for_loaded_repo(ui, workspace, repo)?;
|
let mut workspace_command = command.for_loaded_repo(ui, workspace, repo)?;
|
||||||
maybe_add_gitignore(&workspace_command)?;
|
maybe_add_gitignore(&workspace_command)?;
|
||||||
workspace_command.maybe_snapshot(ui)?;
|
workspace_command.maybe_snapshot(ui)?;
|
||||||
|
maybe_set_repository_level_trunk_alias(ui, workspace_command.repo())?;
|
||||||
if !workspace_command.working_copy_shared_with_git() {
|
if !workspace_command.working_copy_shared_with_git() {
|
||||||
let mut tx = workspace_command.start_transaction();
|
let mut tx = workspace_command.start_transaction();
|
||||||
jj_lib::git::import_head(tx.mut_repo())?;
|
jj_lib::git::import_head(tx.mut_repo())?;
|
||||||
|
@ -210,3 +213,33 @@ fn init_git_refs(
|
||||||
)?;
|
)?;
|
||||||
Ok(repo)
|
Ok(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set repository level `trunk()` alias to the default branch for "origin".
|
||||||
|
pub fn maybe_set_repository_level_trunk_alias(
|
||||||
|
ui: &Ui,
|
||||||
|
repo: &Arc<ReadonlyRepo>,
|
||||||
|
) -> Result<(), CommandError> {
|
||||||
|
let git_repo = get_git_repo(repo.store())?;
|
||||||
|
if let Ok(reference) = git_repo.find_reference("refs/remotes/origin/HEAD") {
|
||||||
|
if let Some(reference_name) = reference.symbolic_target() {
|
||||||
|
if let Some(RefName::RemoteBranch {
|
||||||
|
branch: default_branch,
|
||||||
|
..
|
||||||
|
}) = parse_git_ref(reference_name)
|
||||||
|
{
|
||||||
|
let config_path = repo.repo_path().join("config.toml");
|
||||||
|
write_config_value_to_file(
|
||||||
|
&ConfigNamePathBuf::from_iter(["revset-aliases", "trunk()"]),
|
||||||
|
&format!("{default_branch}@origin"),
|
||||||
|
&config_path,
|
||||||
|
)?;
|
||||||
|
writeln!(
|
||||||
|
ui.status(),
|
||||||
|
"Setting the revset alias \"trunk()\" to \"{default_branch}@origin\"",
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -148,6 +148,65 @@ fn test_git_init_external(bare: bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_case(false; "full")]
|
||||||
|
#[test_case(true; "bare")]
|
||||||
|
fn test_git_init_external_import_trunk(bare: bool) {
|
||||||
|
let test_env = TestEnvironment::default();
|
||||||
|
let git_repo_path = test_env.env_root().join("git-repo");
|
||||||
|
let git_repo = init_git_repo(&git_repo_path, bare);
|
||||||
|
|
||||||
|
// Add remote branch "trunk" for remote "origin", and set it as "origin/HEAD"
|
||||||
|
let oid = git_repo
|
||||||
|
.find_reference("refs/heads/my-branch")
|
||||||
|
.unwrap()
|
||||||
|
.target()
|
||||||
|
.unwrap();
|
||||||
|
git_repo
|
||||||
|
.reference("refs/remotes/origin/trunk", oid, false, "")
|
||||||
|
.unwrap();
|
||||||
|
git_repo
|
||||||
|
.reference_symbolic(
|
||||||
|
"refs/remotes/origin/HEAD",
|
||||||
|
"refs/remotes/origin/trunk",
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||||
|
test_env.env_root(),
|
||||||
|
&[
|
||||||
|
"git",
|
||||||
|
"init",
|
||||||
|
"repo",
|
||||||
|
"--git-repo",
|
||||||
|
git_repo_path.to_str().unwrap(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
insta::allow_duplicates! {
|
||||||
|
insta::assert_snapshot!(stdout, @"");
|
||||||
|
insta::assert_snapshot!(stderr, @r###"
|
||||||
|
Done importing changes from the underlying Git repo.
|
||||||
|
Setting the revset alias "trunk()" to "trunk@origin"
|
||||||
|
Working copy now at: sqpuoqvx f6950fc1 (empty) (no description set)
|
||||||
|
Parent commit : mwrttmos 8d698d4a my-branch trunk@origin | My commit message
|
||||||
|
Added 1 files, modified 0 files, removed 0 files
|
||||||
|
Initialized repo in "repo"
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
|
// "trunk()" alias should be set to remote "origin"'s default branch "trunk"
|
||||||
|
let stdout = test_env.jj_cmd_success(
|
||||||
|
&test_env.env_root().join("repo"),
|
||||||
|
&["config", "list", "--repo", "revset-aliases.\"trunk()\""],
|
||||||
|
);
|
||||||
|
insta::allow_duplicates! {
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
revset-aliases."trunk()" = "trunk@origin"
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_git_init_external_non_existent_directory() {
|
fn test_git_init_external_non_existent_directory() {
|
||||||
let test_env = TestEnvironment::default();
|
let test_env = TestEnvironment::default();
|
||||||
|
|
|
@ -362,9 +362,9 @@ for a comprehensive list.
|
||||||
tried. If more than one potential trunk commit exists, the newest one is
|
tried. If more than one potential trunk commit exists, the newest one is
|
||||||
chosen. If none of the branches exist, the revset evaluates to `root()`.
|
chosen. If none of the branches exist, the revset evaluates to `root()`.
|
||||||
|
|
||||||
When working with an existing Git repository (via `jj git clone`),
|
When working with an existing Git repository (via `jj git clone` or
|
||||||
`trunk()` will be overridden at the repository level to the default branch of
|
`jj git init`), `trunk()` will be overridden at the repository level
|
||||||
the remote.
|
to the default branch of the remote `origin`.
|
||||||
|
|
||||||
You can [override](./config.md) this as appropriate. If you do, make sure it
|
You can [override](./config.md) this as appropriate. If you do, make sure it
|
||||||
always resolves to exactly one commit. For example:
|
always resolves to exactly one commit. For example:
|
||||||
|
|
|
@ -62,7 +62,7 @@ impl fmt::Display for RefName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_git_ref(ref_name: &str) -> Option<RefName> {
|
pub fn parse_git_ref(ref_name: &str) -> Option<RefName> {
|
||||||
if let Some(branch_name) = ref_name.strip_prefix("refs/heads/") {
|
if let Some(branch_name) = ref_name.strip_prefix("refs/heads/") {
|
||||||
// Git CLI says 'HEAD' is not a valid branch name
|
// Git CLI says 'HEAD' is not a valid branch name
|
||||||
(branch_name != "HEAD").then(|| RefName::LocalBranch(branch_name.to_string()))
|
(branch_name != "HEAD").then(|| RefName::LocalBranch(branch_name.to_string()))
|
||||||
|
|
Loading…
Reference in a new issue